99#include < optional>
1010#include < string>
1111#include < string_view>
12+ #include < sys/stat.h>
1213#include < unistd.h>
1314#include < vector>
1415
@@ -96,7 +97,11 @@ namespace {
9697 const fs::path root = fs::temp_directory_path () / (" noctalia-appimage-origin-" + std::to_string (getpid ()));
9798 const fs::path applications = root / " data/applications" ;
9899 const fs::path executable = root / " PortableApp" ;
100+ const fs::path bin = root / " bin" ;
101+ const fs::path workingDirectory = root / " cwd" ;
99102 fs::create_directories (applications);
103+ fs::create_directories (bin);
104+ fs::create_directories (workingDirectory);
100105 {
101106 std::ofstream binary (executable, std::ios::binary);
102107 binary.write (
@@ -120,15 +125,36 @@ namespace {
120125 std::ofstream entry (applications / " suffix.desktop" );
121126 entry << " [Desktop Entry]\n Type=Application\n Name=Suffixed AppImage\n Exec=/opt/Suffixed.AppImage\n " ;
122127 }
128+ {
129+ std::ofstream binary (bin / " native-app" );
130+ binary << " #!/bin/sh\n exit 0\n " ;
131+ chmod ((bin / " native-app" ).c_str (), 0700 );
132+ fs::create_symlink (executable, bin / " path-appimage" );
133+ fs::create_symlink (executable, workingDirectory / " native-app" );
134+ }
135+ {
136+ std::ofstream entry (applications / " native.desktop" );
137+ entry << " [Desktop Entry]\n Type=Application\n Name=Native App\n Exec=native-app\n " ;
138+ }
139+ {
140+ std::ofstream entry (applications / " path.desktop" );
141+ entry << " [Desktop Entry]\n Type=Application\n Name=PATH AppImage\n Exec=path-appimage\n " ;
142+ }
123143
124144 const char * oldDataHome = std::getenv (" XDG_DATA_HOME" );
125145 const char * oldDataDirs = std::getenv (" XDG_DATA_DIRS" );
146+ const char * oldPath = std::getenv (" PATH" );
126147 const std::optional<std::string> savedDataHome =
127148 oldDataHome == nullptr ? std::nullopt : std::optional<std::string>(oldDataHome);
128149 const std::optional<std::string> savedDataDirs =
129150 oldDataDirs == nullptr ? std::nullopt : std::optional<std::string>(oldDataDirs);
151+ const std::optional<std::string> savedPath =
152+ oldPath == nullptr ? std::nullopt : std::optional<std::string>(oldPath);
153+ const fs::path savedWorkingDirectory = fs::current_path ();
130154 setenv (" XDG_DATA_HOME" , (root / " data" ).c_str (), 1 );
131155 setenv (" XDG_DATA_DIRS" , (root / " empty" ).c_str (), 1 );
156+ setenv (" PATH" , bin.c_str (), 1 );
157+ fs::current_path (workingDirectory);
132158
133159 const auto entries = scanDesktopEntries ();
134160 const auto findOrigin = [&](std::string_view id) {
@@ -138,6 +164,10 @@ namespace {
138164 TEST_CHECK (findOrigin (" metadata" ) == DesktopEntryOrigin::AppImage);
139165 TEST_CHECK (findOrigin (" portable" ) == DesktopEntryOrigin::AppImage);
140166 TEST_CHECK (findOrigin (" suffix" ) == DesktopEntryOrigin::AppImage);
167+ TEST_CHECK (findOrigin (" native" ) == DesktopEntryOrigin::System);
168+ TEST_CHECK (findOrigin (" path" ) == DesktopEntryOrigin::AppImage);
169+
170+ fs::current_path (savedWorkingDirectory);
141171
142172 if (savedDataHome.has_value ()) {
143173 setenv (" XDG_DATA_HOME" , savedDataHome->c_str (), 1 );
@@ -149,6 +179,11 @@ namespace {
149179 } else {
150180 unsetenv (" XDG_DATA_DIRS" );
151181 }
182+ if (savedPath.has_value ()) {
183+ setenv (" PATH" , savedPath->c_str (), 1 );
184+ } else {
185+ unsetenv (" PATH" );
186+ }
152187 fs::remove_all (root);
153188 }
154189
0 commit comments