Improve command logging and log_err module paths (#39674)
Prior we only logged the crate in `log_err`, which is not too helpful. We now assemble the module path from the file system path. Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
@@ -41,12 +41,9 @@ impl StdioTransport {
|
||||
command.current_dir(working_directory);
|
||||
}
|
||||
|
||||
let mut server = command.spawn().with_context(|| {
|
||||
format!(
|
||||
"failed to spawn command. (path={:?}, args={:?})",
|
||||
binary.executable, &binary.args
|
||||
)
|
||||
})?;
|
||||
let mut server = command
|
||||
.spawn()
|
||||
.with_context(|| format!("failed to spawn command {command:?})",))?;
|
||||
|
||||
let stdin = server.stdin.take().unwrap();
|
||||
let stdout = server.stdout.take().unwrap();
|
||||
|
||||
@@ -674,13 +674,7 @@ impl StdioTransport {
|
||||
command.args(&binary.arguments);
|
||||
command.envs(&binary.envs);
|
||||
|
||||
let mut process = Child::spawn(command, Stdio::piped()).with_context(|| {
|
||||
format!(
|
||||
"failed to spawn command `{} {}`.",
|
||||
binary_command,
|
||||
binary.arguments.join(" ")
|
||||
)
|
||||
})?;
|
||||
let mut process = Child::spawn(command, Stdio::piped())?;
|
||||
|
||||
let err_task = process.stderr.take().map(|stderr| {
|
||||
cx.background_spawn(TransportDelegate::handle_adapter_log(
|
||||
@@ -1058,11 +1052,13 @@ impl Child {
|
||||
#[cfg(not(windows))]
|
||||
fn spawn(mut command: std::process::Command, stdin: Stdio) -> Result<Self> {
|
||||
util::set_pre_exec_to_start_new_session(&mut command);
|
||||
let process = smol::process::Command::from(command)
|
||||
let mut command = smol::process::Command::from(command);
|
||||
let process = command
|
||||
.stdin(stdin)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?;
|
||||
.spawn()
|
||||
.with_context(|| format!("failed to spawn command `{command:?}`",))?;
|
||||
Ok(Self { process })
|
||||
}
|
||||
|
||||
@@ -1070,11 +1066,13 @@ impl Child {
|
||||
fn spawn(command: std::process::Command, stdin: Stdio) -> Result<Self> {
|
||||
// TODO(windows): create a job object and add the child process handle to it,
|
||||
// see https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects
|
||||
let process = smol::process::Command::from(command)
|
||||
let mut command = smol::process::Command::from(command);
|
||||
let process = command
|
||||
.stdin(stdin)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?;
|
||||
.spawn()
|
||||
.with_context(|| format!("failed to spawn command `{command:?}`",))?;
|
||||
Ok(Self { process })
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ use ui::{
|
||||
};
|
||||
use vim_mode_setting::VimModeSetting;
|
||||
use workspace::{
|
||||
Workspace, WorkspaceId,
|
||||
Workspace,
|
||||
item::{Item, ItemEvent},
|
||||
};
|
||||
use zed_actions::ExtensionCategoryFilter;
|
||||
@@ -1551,15 +1551,6 @@ impl Item for ExtensionsPage {
|
||||
false
|
||||
}
|
||||
|
||||
fn clone_on_split(
|
||||
&self,
|
||||
_workspace_id: Option<WorkspaceId>,
|
||||
_window: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
|
||||
f(*event)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::sync::LazyLock;
|
||||
use anyhow::Result;
|
||||
use collections::{FxHashMap, FxHashSet};
|
||||
use itertools::Itertools;
|
||||
use util::ResultExt;
|
||||
use windows::Win32::{
|
||||
Foundation::{HANDLE, HGLOBAL},
|
||||
System::{
|
||||
@@ -76,14 +75,18 @@ enum ClipboardFormatType {
|
||||
}
|
||||
|
||||
pub(crate) fn write_to_clipboard(item: ClipboardItem) {
|
||||
write_to_clipboard_inner(item).log_err();
|
||||
unsafe { CloseClipboard().log_err() };
|
||||
with_clipboard(|| write_to_clipboard_inner(item));
|
||||
}
|
||||
|
||||
pub(crate) fn read_from_clipboard() -> Option<ClipboardItem> {
|
||||
let result = read_from_clipboard_inner();
|
||||
unsafe { CloseClipboard().log_err() };
|
||||
result
|
||||
with_clipboard(|| {
|
||||
with_best_match_format(|item_format| match format_to_type(item_format) {
|
||||
ClipboardFormatType::Text => read_string_from_clipboard(),
|
||||
ClipboardFormatType::Image => read_image_from_clipboard(item_format),
|
||||
ClipboardFormatType::Files => read_files_from_clipboard(),
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub(crate) fn with_file_names<F>(hdrop: HDROP, mut f: F)
|
||||
@@ -96,11 +99,33 @@ where
|
||||
let mut buffer = vec![0u16; filename_length + 1];
|
||||
let ret = unsafe { DragQueryFileW(hdrop, file_index, Some(buffer.as_mut_slice())) };
|
||||
if ret == 0 {
|
||||
log::error!("unable to read file name");
|
||||
log::error!("unable to read file name of dragged file");
|
||||
continue;
|
||||
}
|
||||
if let Some(file_name) = String::from_utf16(&buffer[0..filename_length]).log_err() {
|
||||
f(file_name);
|
||||
match String::from_utf16(&buffer[0..filename_length]) {
|
||||
Ok(file_name) => f(file_name),
|
||||
Err(e) => {
|
||||
log::error!("dragged file name is not UTF-16: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_clipboard<F, T>(f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
match unsafe { OpenClipboard(None) } {
|
||||
Ok(()) => {
|
||||
let result = f();
|
||||
if let Err(e) = unsafe { CloseClipboard() } {
|
||||
log::error!("Failed to close clipboard: {e}",);
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to open clipboard: {e}",);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +149,6 @@ fn format_to_type(item_format: u32) -> &'static ClipboardFormatType {
|
||||
// Currently, we only write the first item.
|
||||
fn write_to_clipboard_inner(item: ClipboardItem) -> Result<()> {
|
||||
unsafe {
|
||||
OpenClipboard(None)?;
|
||||
EmptyClipboard()?;
|
||||
}
|
||||
match item.entries().first() {
|
||||
@@ -215,15 +239,6 @@ fn convert_image_to_png_format(bytes: &[u8], image_format: ImageFormat) -> Resul
|
||||
Ok(output_buf)
|
||||
}
|
||||
|
||||
fn read_from_clipboard_inner() -> Option<ClipboardItem> {
|
||||
unsafe { OpenClipboard(None) }.log_err()?;
|
||||
with_best_match_format(|item_format| match format_to_type(item_format) {
|
||||
ClipboardFormatType::Text => read_string_from_clipboard(),
|
||||
ClipboardFormatType::Image => read_image_from_clipboard(item_format),
|
||||
ClipboardFormatType::Files => read_files_from_clipboard(),
|
||||
})
|
||||
}
|
||||
|
||||
// Here, we enumerate all formats on the clipboard and find the first one that we can process.
|
||||
// The reason we don't use `GetPriorityClipboardFormat` is that it sometimes returns the
|
||||
// wrong format.
|
||||
@@ -266,7 +281,7 @@ where
|
||||
}
|
||||
|
||||
fn read_string_from_clipboard() -> Option<ClipboardEntry> {
|
||||
let text = with_clipboard_data(CF_UNICODETEXT.0 as u32, |data_ptr| {
|
||||
let text = with_clipboard_data(CF_UNICODETEXT.0 as u32, |data_ptr, _| {
|
||||
let pcwstr = PCWSTR(data_ptr as *const u16);
|
||||
String::from_utf16_lossy(unsafe { pcwstr.as_wide() })
|
||||
})?;
|
||||
@@ -290,20 +305,22 @@ fn read_hash_from_clipboard() -> Option<u64> {
|
||||
if unsafe { IsClipboardFormatAvailable(*CLIPBOARD_HASH_FORMAT).is_err() } {
|
||||
return None;
|
||||
}
|
||||
with_clipboard_data(*CLIPBOARD_HASH_FORMAT, |data_ptr| {
|
||||
with_clipboard_data(*CLIPBOARD_HASH_FORMAT, |data_ptr, size| {
|
||||
if size < 8 {
|
||||
return None;
|
||||
}
|
||||
let hash_bytes: [u8; 8] = unsafe {
|
||||
std::slice::from_raw_parts(data_ptr.cast::<u8>(), 8)
|
||||
.to_vec()
|
||||
.try_into()
|
||||
.log_err()
|
||||
.ok()
|
||||
}?;
|
||||
Some(u64::from_ne_bytes(hash_bytes))
|
||||
})?
|
||||
}
|
||||
|
||||
fn read_metadata_from_clipboard() -> Option<String> {
|
||||
unsafe { IsClipboardFormatAvailable(*CLIPBOARD_METADATA_FORMAT).log_err()? };
|
||||
with_clipboard_data(*CLIPBOARD_METADATA_FORMAT, |data_ptr| {
|
||||
unsafe { IsClipboardFormatAvailable(*CLIPBOARD_METADATA_FORMAT).ok()? };
|
||||
with_clipboard_data(*CLIPBOARD_METADATA_FORMAT, |data_ptr, _size| {
|
||||
let pcwstr = PCWSTR(data_ptr as *const u16);
|
||||
String::from_utf16_lossy(unsafe { pcwstr.as_wide() })
|
||||
})
|
||||
@@ -320,7 +337,7 @@ fn format_number_to_image_format(format_number: u32) -> Option<&'static ImageFor
|
||||
}
|
||||
|
||||
fn read_image_for_type(format_number: u32, format: ImageFormat) -> Option<ClipboardEntry> {
|
||||
let (bytes, id) = with_clipboard_data_and_size(format_number, |data_ptr, size| {
|
||||
let (bytes, id) = with_clipboard_data(format_number, |data_ptr, size| {
|
||||
let bytes = unsafe { std::slice::from_raw_parts(data_ptr as *mut u8 as _, size).to_vec() };
|
||||
let id = hash(&bytes);
|
||||
(bytes, id)
|
||||
@@ -329,7 +346,7 @@ fn read_image_for_type(format_number: u32, format: ImageFormat) -> Option<Clipbo
|
||||
}
|
||||
|
||||
fn read_files_from_clipboard() -> Option<ClipboardEntry> {
|
||||
let text = with_clipboard_data(CF_HDROP.0 as u32, |data_ptr| {
|
||||
let text = with_clipboard_data(CF_HDROP.0 as u32, |data_ptr, _size| {
|
||||
let hdrop = HDROP(data_ptr);
|
||||
let mut filenames = String::new();
|
||||
with_file_names(hdrop, |file_name| {
|
||||
@@ -344,25 +361,14 @@ fn read_files_from_clipboard() -> Option<ClipboardEntry> {
|
||||
}
|
||||
|
||||
fn with_clipboard_data<F, R>(format: u32, f: F) -> Option<R>
|
||||
where
|
||||
F: FnOnce(*mut std::ffi::c_void) -> R,
|
||||
{
|
||||
let global = HGLOBAL(unsafe { GetClipboardData(format).log_err() }?.0);
|
||||
let data_ptr = unsafe { GlobalLock(global) };
|
||||
let result = f(data_ptr);
|
||||
unsafe { GlobalUnlock(global).log_err() };
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn with_clipboard_data_and_size<F, R>(format: u32, f: F) -> Option<R>
|
||||
where
|
||||
F: FnOnce(*mut std::ffi::c_void, usize) -> R,
|
||||
{
|
||||
let global = HGLOBAL(unsafe { GetClipboardData(format).log_err() }?.0);
|
||||
let global = HGLOBAL(unsafe { GetClipboardData(format).ok() }?.0);
|
||||
let size = unsafe { GlobalSize(global) };
|
||||
let data_ptr = unsafe { GlobalLock(global) };
|
||||
let result = f(data_ptr, size);
|
||||
unsafe { GlobalUnlock(global).log_err() };
|
||||
unsafe { GlobalUnlock(global).ok() };
|
||||
Some(result)
|
||||
}
|
||||
|
||||
|
||||
@@ -336,21 +336,18 @@ impl LanguageServer {
|
||||
&binary.arguments
|
||||
);
|
||||
|
||||
let mut server = util::command::new_smol_command(&binary.path)
|
||||
let mut command = util::command::new_smol_command(&binary.path);
|
||||
command
|
||||
.current_dir(working_dir)
|
||||
.args(&binary.arguments)
|
||||
.envs(binary.env.clone().unwrap_or_default())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.kill_on_drop(true)
|
||||
.kill_on_drop(true);
|
||||
let mut server = command
|
||||
.spawn()
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"failed to spawn command. path: {:?}, working directory: {:?}, args: {:?}",
|
||||
binary.path, working_dir, &binary.arguments
|
||||
)
|
||||
})?;
|
||||
.with_context(|| format!("failed to spawn command {command:?}",))?;
|
||||
|
||||
let stdin = server.stdin.take().unwrap();
|
||||
let stdout = server.stdout.take().unwrap();
|
||||
|
||||
@@ -5,7 +5,7 @@ use gpui::{
|
||||
use menu::{SelectNext, SelectPrevious};
|
||||
use ui::{ButtonLike, Divider, DividerColor, KeyBinding, Vector, VectorName, prelude::*};
|
||||
use workspace::{
|
||||
NewFile, Open, WorkspaceId,
|
||||
NewFile, Open,
|
||||
item::{Item, ItemEvent},
|
||||
with_active_or_new_workspace,
|
||||
};
|
||||
@@ -339,15 +339,6 @@ impl Item for WelcomePage {
|
||||
false
|
||||
}
|
||||
|
||||
fn clone_on_split(
|
||||
&self,
|
||||
_workspace_id: Option<WorkspaceId>,
|
||||
_: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
|
||||
f(*event)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use gpui::{
|
||||
use project::ProjectItem as _;
|
||||
use ui::{ButtonLike, ElevationIndex, KeyBinding, prelude::*};
|
||||
use util::ResultExt as _;
|
||||
use workspace::WorkspaceId;
|
||||
use workspace::item::ItemEvent;
|
||||
use workspace::{Workspace, item::Item};
|
||||
|
||||
@@ -192,15 +191,6 @@ impl Item for ReplSessionsPage {
|
||||
false
|
||||
}
|
||||
|
||||
fn clone_on_split(
|
||||
&self,
|
||||
_workspace_id: Option<WorkspaceId>,
|
||||
_window: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
) -> Option<Entity<Self>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
|
||||
f(*event)
|
||||
}
|
||||
|
||||
@@ -605,13 +605,15 @@ where
|
||||
// so discard the prefix up to that segment to find the crate name
|
||||
let target = file
|
||||
.split_once("crates/")
|
||||
.and_then(|(_, s)| s.split_once('/'))
|
||||
.map(|(p, _)| p);
|
||||
.and_then(|(_, s)| s.split_once("/src/"));
|
||||
|
||||
let module_path = target.map(|(krate, module)| {
|
||||
krate.to_owned() + "::" + &module.trim_end_matches(".rs").replace('/', "::")
|
||||
});
|
||||
log::logger().log(
|
||||
&log::Record::builder()
|
||||
.target(target.unwrap_or(""))
|
||||
.module_path(target)
|
||||
.target(target.map_or("", |(krate, _)| krate))
|
||||
.module_path(module_path.as_deref())
|
||||
.args(format_args!("{:?}", error))
|
||||
.file(Some(caller.file()))
|
||||
.line(Some(caller.line()))
|
||||
|
||||
@@ -4106,11 +4106,11 @@ impl Workspace {
|
||||
pane.add_item(clone, true, true, None, window, cx)
|
||||
});
|
||||
self.center.split(&pane, &new_pane, direction).unwrap();
|
||||
cx.notify();
|
||||
Some(new_pane)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
cx.notify();
|
||||
maybe_pane_handle
|
||||
}
|
||||
|
||||
|
||||
+42
-39
@@ -1231,55 +1231,58 @@ pub fn handle_settings_file_changes(
|
||||
MigrationNotification::set_global(cx.new(|_| MigrationNotification), cx);
|
||||
|
||||
// Helper function to process settings content
|
||||
let process_settings = move |content: String,
|
||||
is_user: bool,
|
||||
store: &mut SettingsStore,
|
||||
cx: &mut App|
|
||||
-> bool {
|
||||
let id = NotificationId::Named("failed-to-migrate-settings".into());
|
||||
// Apply migrations to both user and global settings
|
||||
let (processed_content, content_migrated) = match migrate_settings(&content) {
|
||||
Ok(result) => {
|
||||
dismiss_app_notification(&id, cx);
|
||||
if let Some(migrated_content) = result {
|
||||
(migrated_content, true)
|
||||
} else {
|
||||
(content, false)
|
||||
let process_settings =
|
||||
move |content: String, is_user: bool, store: &mut SettingsStore, cx: &mut App| -> bool {
|
||||
let id = NotificationId::Named("failed-to-migrate-settings".into());
|
||||
// Apply migrations to both user and global settings
|
||||
let (processed_content, content_migrated) = match migrate_settings(&content) {
|
||||
Ok(result) => {
|
||||
dismiss_app_notification(&id, cx);
|
||||
if let Some(migrated_content) = result {
|
||||
(migrated_content, true)
|
||||
} else {
|
||||
(content, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
show_app_notification(id, cx, move |cx| {
|
||||
cx.new(|cx| {
|
||||
MessageNotification::new(format!("Failed to migrate settings\n{err}"), cx)
|
||||
Err(err) => {
|
||||
show_app_notification(id, cx, move |cx| {
|
||||
cx.new(|cx| {
|
||||
MessageNotification::new(
|
||||
format!(
|
||||
"Failed to migrate settings\n\
|
||||
{err}"
|
||||
),
|
||||
cx,
|
||||
)
|
||||
.primary_message("Open Settings File")
|
||||
.primary_icon(IconName::Settings)
|
||||
.primary_on_click(|window, cx| {
|
||||
window.dispatch_action(zed_actions::OpenSettings.boxed_clone(), cx);
|
||||
cx.emit(DismissEvent);
|
||||
})
|
||||
})
|
||||
});
|
||||
// notify user here
|
||||
(content, false)
|
||||
})
|
||||
});
|
||||
// notify user here
|
||||
(content, false)
|
||||
}
|
||||
};
|
||||
|
||||
let result = if is_user {
|
||||
store.set_user_settings(&processed_content, cx)
|
||||
} else {
|
||||
store.set_global_settings(&processed_content, cx)
|
||||
};
|
||||
|
||||
if let Err(err) = &result {
|
||||
let settings_type = if is_user { "user" } else { "global" };
|
||||
log::error!("Failed to load {} settings: {err}", settings_type);
|
||||
}
|
||||
|
||||
settings_changed(result.err(), cx);
|
||||
|
||||
content_migrated
|
||||
};
|
||||
|
||||
let result = if is_user {
|
||||
store.set_user_settings(&processed_content, cx)
|
||||
} else {
|
||||
store.set_global_settings(&processed_content, cx)
|
||||
};
|
||||
|
||||
if let Err(err) = &result {
|
||||
let settings_type = if is_user { "user" } else { "global" };
|
||||
log::error!("Failed to load {} settings: {err}", settings_type);
|
||||
}
|
||||
|
||||
settings_changed(result.err(), cx);
|
||||
|
||||
content_migrated
|
||||
};
|
||||
|
||||
// Initial load of both settings files
|
||||
let global_content = cx
|
||||
.background_executor()
|
||||
|
||||
Reference in New Issue
Block a user