Compare commits

...

9 Commits

Author SHA1 Message Date
Joseph T. Lyons
eab4bd5720 v0.91.x stable 2023-06-21 13:58:53 -04:00
Antonio Scandurra
707bd7c156 zed 0.91.3 2023-06-16 17:27:42 +02:00
Antonio Scandurra
656f68dc69 Activate screen-sharing when leader activates a panel (#2614)
Fixes
https://linear.app/zed-industries/issue/Z-1875/screen-sharing-tab-is-not-activated-when-leader-is-on-a-panel

Release Notes:

- Fixed a bug that caused followers to not see the leader's screen when
they activated a panel.
2023-06-16 17:26:33 +02:00
Max Brunsfeld
186334bb12 zed 0.91.2 2023-06-15 15:34:43 -07:00
Max Brunsfeld
b1324ebe1f Fix failure to upload panics when multiple panics happen at the same time (#2616)
When multiple panics occur at the same time (usually because one thread
panics, and another thread joins it), multiple panic JSON objects can
get written to the same panic file. The resulting file won't be valid
JSON.

This PR addresses that problem via two changes:
* Format panic files as single-line JSON objects
* When a panic file  isn't valid JSON, try taking the first line

In the future, we could try combining all of the backtraces, but for
now, I just want to avoid a problem of not reporting a panic at all.

Release Notes:

- Fixed a problem with Zed's internal crash reporting.
2023-06-15 15:34:09 -07:00
Max Brunsfeld
e9aec1d67a Don't rely on debug symbols for panic reporting (#2615)
This fixes a regression introduced in
https://github.com/zed-industries/zed/pull/2560, where panic reports did
not include backtraces. The problem was that in that PR, I assumed we
could retrieve file paths for symbols in our backtraces. But actually,
that functionality only works when the app is built locally, and a
`.dSYM` file can be magically found by the OS. We don't ship those dSYM
files with Zed, so panic symbols do not have file paths available.

Panic backtraces will still be more useful and less noisy than before
though: we will strip out frames for which we don't have symbol names,
and remove leading panic-handling stack frames from the backtraces.

Release Notes:

- N/A
2023-06-15 15:34:01 -07:00
Mikayla Maki
32ed547c2c zed 0.91.1 2023-06-14 18:10:16 -07:00
Mikayla Maki
39915f7c96 Add entitlements file to bundle step (#2611)
This completes the bundle changes that will be needed to access voice,
as well as adds permissions for accessing other MacOS services, the
camera, and the necessary permissions for plugins. This was developed by
combining the entitlements of iTerm and VSCode, cross-referenced with
the entitlements of Firefox. 

Release Notes:

- Fixed a bug in enabling authorization for macOS services (preview
only)
2023-06-14 18:09:15 -07:00
Joseph Lyons
2c2cea1c92 v0.91.x preview 2023-06-14 13:27:18 -04:00
10 changed files with 169 additions and 118 deletions

2
Cargo.lock generated
View File

@@ -8795,7 +8795,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.91.0"
version = "0.91.3"
dependencies = [
"activity_indicator",
"ai",

View File

@@ -39,7 +39,12 @@ use std::{
},
};
use unindent::Unindent as _;
use workspace::{item::ItemHandle as _, shared_screen::SharedScreen, SplitDirection, Workspace};
use workspace::{
dock::{test::TestPanel, DockPosition},
item::{test::TestItem, ItemHandle as _},
shared_screen::SharedScreen,
SplitDirection, Workspace,
};
#[ctor::ctor]
fn init_logger() {
@@ -6847,12 +6852,43 @@ async fn test_basic_following(
)
});
// Client B activates an external window again, and the previously-opened screen-sharing item
// gets activated.
active_call_b
.update(cx_b, |call, cx| call.set_location(None, cx))
.await
.unwrap();
// Client B activates a panel, and the previously-opened screen-sharing item gets activated.
let panel = cx_b.add_view(workspace_b.window_id(), |_| {
TestPanel::new(DockPosition::Left)
});
workspace_b.update(cx_b, |workspace, cx| {
workspace.add_panel(panel, cx);
workspace.toggle_panel_focus::<TestPanel>(cx);
});
deterministic.run_until_parked();
assert_eq!(
workspace_a.read_with(cx_a, |workspace, cx| workspace
.active_item(cx)
.unwrap()
.id()),
shared_screen.id()
);
// Toggling the focus back to the pane causes client A to return to the multibuffer.
workspace_b.update(cx_b, |workspace, cx| {
workspace.toggle_panel_focus::<TestPanel>(cx);
});
deterministic.run_until_parked();
workspace_a.read_with(cx_a, |workspace, cx| {
assert_eq!(
workspace.active_item(cx).unwrap().id(),
multibuffer_editor_a.id()
)
});
// Client B activates an item that doesn't implement following,
// so the previously-opened screen-sharing item gets activated.
let unfollowable_item = cx_b.add_view(workspace_b.window_id(), |_| TestItem::new());
workspace_b.update(cx_b, |workspace, cx| {
workspace.active_pane().update(cx, |pane, cx| {
pane.add_item(Box::new(unfollowable_item), true, true, None, cx)
})
});
deterministic.run_until_parked();
assert_eq!(
workspace_a.read_with(cx_a, |workspace, cx| workspace

View File

@@ -598,8 +598,8 @@ impl StatusItemView for PanelButtons {
}
}
#[cfg(test)]
pub(crate) mod test {
#[cfg(any(test, feature = "test-support"))]
pub mod test {
use super::*;
use gpui::{ViewContext, WindowContext};

View File

@@ -710,8 +710,8 @@ impl<T: FollowableItem> FollowableItemHandle for ViewHandle<T> {
}
}
#[cfg(test)]
pub(crate) mod test {
#[cfg(any(test, feature = "test-support"))]
pub mod test {
use super::{Item, ItemEvent};
use crate::{ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId};
use gpui::{

View File

@@ -919,6 +919,7 @@ impl Workspace {
this.zoomed = None;
this.zoomed_position = None;
}
this.update_active_view_for_followers(cx);
cx.notify();
}
}
@@ -1946,18 +1947,7 @@ impl Workspace {
self.zoomed = None;
}
self.zoomed_position = None;
self.update_followers(
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
id: self.active_item(cx).and_then(|item| {
item.to_followable_item_handle(cx)?
.remote_id(&self.app_state.client, cx)
.map(|id| id.to_proto())
}),
leader_id: self.leader_for_pane(&pane),
}),
cx,
);
self.update_active_view_for_followers(cx);
cx.notify();
}
@@ -2646,6 +2636,30 @@ impl Workspace {
Ok(())
}
fn update_active_view_for_followers(&self, cx: &AppContext) {
if self.active_pane.read(cx).has_focus() {
self.update_followers(
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
id: self.active_item(cx).and_then(|item| {
item.to_followable_item_handle(cx)?
.remote_id(&self.app_state.client, cx)
.map(|id| id.to_proto())
}),
leader_id: self.leader_for_pane(&self.active_pane),
}),
cx,
);
} else {
self.update_followers(
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
id: None,
leader_id: None,
}),
cx,
);
}
}
fn update_followers(
&self,
update: proto::update_followers::Variant,
@@ -2693,12 +2707,10 @@ impl Workspace {
.and_then(|id| state.items_by_leader_view_id.get(&id))
{
items_to_activate.push((pane.clone(), item.boxed_clone()));
} else {
if let Some(shared_screen) =
self.shared_screen_for_peer(leader_id, pane, cx)
{
items_to_activate.push((pane.clone(), Box::new(shared_screen)));
}
} else if let Some(shared_screen) =
self.shared_screen_for_peer(leader_id, pane, cx)
{
items_to_activate.push((pane.clone(), Box::new(shared_screen)));
}
}
}

View File

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
description = "The fast, collaborative code editor."
edition = "2021"
name = "zed"
version = "0.91.0"
version = "0.91.3"
publish = false
[lib]

View File

@@ -1 +1 @@
dev
stable

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.personal-information.addressbook</key>
<true/>
<key>com.apple.security.personal-information.calendars</key>
<true/>
<key>com.apple.security.personal-information.location</key>
<true/>
<key>com.apple.security.personal-information.photos-library</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

View File

@@ -31,7 +31,6 @@ use std::{
ffi::OsStr,
fs::OpenOptions,
io::Write as _,
ops::Not,
os::unix::prelude::OsStrExt,
panic,
path::{Path, PathBuf},
@@ -373,7 +372,6 @@ struct Panic {
os_version: Option<String>,
architecture: String,
panicked_on: u128,
identifying_backtrace: Option<Vec<String>>,
}
#[derive(Serialize)]
@@ -401,61 +399,18 @@ fn init_panic_hook(app: &App) {
.unwrap_or_else(|| "Box<Any>".to_string());
let backtrace = Backtrace::new();
let backtrace = backtrace
let mut backtrace = backtrace
.frames()
.iter()
.filter_map(|frame| {
let symbol = frame.symbols().first()?;
let path = symbol.filename()?;
Some((path, symbol.lineno(), format!("{:#}", symbol.name()?)))
})
.filter_map(|frame| Some(format!("{:#}", frame.symbols().first()?.name()?)))
.collect::<Vec<_>>();
let this_file_path = Path::new(file!());
// Find the first frame in the backtrace for this panic hook itself. Exclude
// that frame and all frames before it.
let mut start_frame_ix = 0;
let mut codebase_root_path = None;
for (ix, (path, _, _)) in backtrace.iter().enumerate() {
if path.ends_with(this_file_path) {
start_frame_ix = ix + 1;
codebase_root_path = path.ancestors().nth(this_file_path.components().count());
break;
}
}
// Exclude any subsequent frames inside of rust's panic handling system.
while let Some((path, _, _)) = backtrace.get(start_frame_ix) {
if path.starts_with("/rustc") {
start_frame_ix += 1;
} else {
break;
}
}
// Build two backtraces:
// * one for display, which includes symbol names for all frames, and files
// and line numbers for symbols in this codebase
// * one for identification and de-duplication, which only includes symbol
// names for symbols in this codebase.
let mut display_backtrace = Vec::new();
let mut identifying_backtrace = Vec::new();
for (path, line, symbol) in &backtrace[start_frame_ix..] {
display_backtrace.push(symbol.clone());
if let Some(codebase_root_path) = &codebase_root_path {
if let Ok(suffix) = path.strip_prefix(&codebase_root_path) {
identifying_backtrace.push(symbol.clone());
let display_path = suffix.to_string_lossy();
if let Some(line) = line {
display_backtrace.push(format!(" {display_path}:{line}"));
} else {
display_backtrace.push(format!(" {display_path}"));
}
}
}
// Strip out leading stack frames for rust panic-handling.
if let Some(ix) = backtrace
.iter()
.position(|name| name == "rust_begin_unwind")
{
backtrace.drain(0..=ix);
}
let panic_data = Panic {
@@ -477,29 +432,27 @@ fn init_panic_hook(app: &App) {
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis(),
backtrace: display_backtrace,
identifying_backtrace: identifying_backtrace
.is_empty()
.not()
.then_some(identifying_backtrace),
backtrace,
};
if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() {
if is_pty {
if is_pty {
if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() {
eprintln!("{}", panic_data_json);
return;
}
let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
let panic_file_path = paths::LOGS_DIR.join(format!("zed-{}.panic", timestamp));
let panic_file = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(&panic_file_path)
.log_err();
if let Some(mut panic_file) = panic_file {
write!(&mut panic_file, "{}", panic_data_json).log_err();
panic_file.flush().log_err();
} else {
if let Some(panic_data_json) = serde_json::to_string(&panic_data).log_err() {
let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
let panic_file_path = paths::LOGS_DIR.join(format!("zed-{}.panic", timestamp));
let panic_file = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(&panic_file_path)
.log_err();
if let Some(mut panic_file) = panic_file {
writeln!(&mut panic_file, "{}", panic_data_json).log_err();
panic_file.flush().log_err();
}
}
}
}));
@@ -531,23 +484,45 @@ fn upload_previous_panics(http: Arc<dyn HttpClient>, cx: &mut AppContext) {
}
if telemetry_settings.diagnostics {
let panic_data_text = smol::fs::read_to_string(&child_path)
let panic_file_content = smol::fs::read_to_string(&child_path)
.await
.context("error reading panic file")?;
let body = serde_json::to_string(&PanicRequest {
panic: serde_json::from_str(&panic_data_text)?,
token: ZED_SECRET_CLIENT_TOKEN.into(),
})
.unwrap();
let panic = serde_json::from_str(&panic_file_content)
.ok()
.or_else(|| {
panic_file_content
.lines()
.next()
.and_then(|line| serde_json::from_str(line).ok())
})
.unwrap_or_else(|| {
log::error!(
"failed to deserialize panic file {:?}",
panic_file_content
);
None
});
let request = Request::post(&panic_report_url)
.redirect_policy(isahc::config::RedirectPolicy::Follow)
.header("Content-Type", "application/json")
.body(body.into())?;
let response = http.send(request).await.context("error sending panic")?;
if !response.status().is_success() {
log::error!("Error uploading panic to server: {}", response.status());
if let Some(panic) = panic {
let body = serde_json::to_string(&PanicRequest {
panic,
token: ZED_SECRET_CLIENT_TOKEN.into(),
})
.unwrap();
let request = Request::post(&panic_report_url)
.redirect_policy(isahc::config::RedirectPolicy::Follow)
.header("Content-Type", "application/json")
.body(body.into())?;
let response =
http.send(request).await.context("error sending panic")?;
if !response.status().is_success() {
log::error!(
"Error uploading panic to server: {}",
response.status()
);
}
}
}

View File

@@ -81,12 +81,12 @@ if [[ -n $MACOS_CERTIFICATE && -n $MACOS_CERTIFICATE_PASSWORD && -n $APPLE_NOTAR
security import /tmp/zed-certificate.p12 -k zed.keychain -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
rm /tmp/zed-certificate.p12
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CERTIFICATE_PASSWORD" zed.keychain
/usr/bin/codesign --force --deep --timestamp --options runtime --sign "Zed Industries, Inc." "${app_path}" -v
/usr/bin/codesign --force --deep --timestamp --options runtime --entitlements crates/zed/resources/zed.entitlements --sign "Zed Industries, Inc." "${app_path}" -v
security default-keychain -s login.keychain
else
echo "One or more of the following variables are missing: MACOS_CERTIFICATE, MACOS_CERTIFICATE_PASSWORD, APPLE_NOTARIZATION_USERNAME, APPLE_NOTARIZATION_PASSWORD"
echo "Performing an ad-hoc signature, but this bundle should not be distributed"
codesign --force --deep --sign - "${app_path}" -v
codesign --force --deep --entitlements crates/zed/resources/zed.entitlements --sign - "${app_path}" -v
fi
if [ "$target_dir" = "debug" ]; then