Find path to running app using [NSBundle bundlePath]

Max Brunsfeld created

Change summary

crates/auto_update/src/auto_update.rs    |  2 +-
crates/gpui/src/platform.rs              |  1 +
crates/gpui/src/platform/mac/platform.rs | 23 +++++++++++++++++++----
crates/gpui/src/platform/test.rs         |  4 ++++
4 files changed, 25 insertions(+), 5 deletions(-)

Detailed changes

crates/auto_update/src/auto_update.rs 🔗

@@ -166,7 +166,7 @@ impl AutoUpdater {
         mounted_app_path.push("/");
         let running_app_path = ZED_APP_PATH
             .clone()
-            .map_or_else(|| cx.platform().path_for_resource(None, None), Ok)?;
+            .map_or_else(|| cx.platform().app_path(), Ok)?;
 
         let mut dmg_file = File::create(&dmg_path).await?;
         let response = client

crates/gpui/src/platform.rs 🔗

@@ -57,6 +57,7 @@ pub trait Platform: Send + Sync {
     fn local_timezone(&self) -> UtcOffset;
 
     fn path_for_resource(&self, name: Option<&str>, extension: Option<&str>) -> Result<PathBuf>;
+    fn app_path(&self) -> Result<PathBuf>;
     fn app_version(&self) -> Result<AppVersion>;
 }
 

crates/gpui/src/platform/mac/platform.rs 🔗

@@ -615,15 +615,23 @@ impl platform::Platform for MacPlatform {
                 if path.is_null() {
                     Err(anyhow!("resource could not be found"))
                 } else {
-                    let len = msg_send![path, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
-                    let bytes = path.UTF8String() as *const u8;
-                    let path = str::from_utf8(slice::from_raw_parts(bytes, len)).unwrap();
-                    Ok(PathBuf::from(path))
+                    Ok(path_from_objc(path))
                 }
             }
         }
     }
 
+    fn app_path(&self) -> Result<PathBuf> {
+        unsafe {
+            let bundle: id = NSBundle::mainBundle();
+            if bundle.is_null() {
+                Err(anyhow!("app is not running inside a bundle"))
+            } else {
+                Ok(path_from_objc(msg_send![bundle, bundlePath]))
+            }
+        }
+    }
+
     fn app_version(&self) -> Result<platform::AppVersion> {
         unsafe {
             let bundle: id = NSBundle::mainBundle();
@@ -641,6 +649,13 @@ impl platform::Platform for MacPlatform {
     }
 }
 
+unsafe fn path_from_objc(path: id) -> PathBuf {
+    let len = msg_send![path, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
+    let bytes = path.UTF8String() as *const u8;
+    let path = str::from_utf8(slice::from_raw_parts(bytes, len)).unwrap();
+    PathBuf::from(path)
+}
+
 unsafe fn get_foreground_platform(object: &mut Object) -> &MacForegroundPlatform {
     let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR);
     assert!(!platform_ptr.is_null());

crates/gpui/src/platform/test.rs 🔗

@@ -165,6 +165,10 @@ impl super::Platform for Platform {
         Err(anyhow!("app not running inside a bundle"))
     }
 
+    fn app_path(&self) -> Result<PathBuf> {
+        Err(anyhow!("app not running inside a bundle"))
+    }
+
     fn app_version(&self) -> Result<AppVersion> {
         Ok(AppVersion {
             major: 1,