From b4ee69db67db5c45afdf7af09726b68d9959e73b Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Thu, 30 May 2024 20:40:31 +0800 Subject: [PATCH 1/5] fix: handle Windows path correctly We need to make truncate_registry_path can handle Windows path as well. Because tokio-console can connect to any server from different platforms, so we use the same path separator to have same experience. Signed-off-by: hi-rustin --- tokio-console/src/state/mod.rs | 64 ++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/tokio-console/src/state/mod.rs b/tokio-console/src/state/mod.rs index d40dac014..48fd2d576 100644 --- a/tokio-console/src/state/mod.rs +++ b/tokio-console/src/state/mod.rs @@ -511,15 +511,20 @@ fn truncate_registry_path(s: String) -> String { static REGEX: OnceCell = OnceCell::new(); let regex = REGEX.get_or_init(|| { - Regex::new(r".*/\.cargo(/registry/src/[^/]*/|/git/checkouts/)") - .expect("failed to compile regex") + Regex::new( + r".*(/|\\)\.cargo(/|\\)(registry(/|\\)src(/|\\)[^/\\]*(/|\\)|git(/|\\)checkouts(/|\\))", + ) + .expect("failed to compile regex") }); - return match regex.replace(&s, "/") { + let s = match regex.replace(&s, "/") { Cow::Owned(s) => s, // String was not modified, return the original. - Cow::Borrowed(_) => s.to_string(), + Cow::Borrowed(_) => s, }; + + // This help use the same path separator on all platforms. + s.replace('\\', "/") } fn format_location(loc: Option) -> String { @@ -586,30 +591,69 @@ mod tests { #[test] fn test_format_location_macos() { // macOS style paths. - let location4 = proto::Location { + let location1 = proto::Location { file: Some("/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.0.1/src/lib.rs".to_string()), ..Default::default() }; - let location5 = proto::Location { + let location2 = proto::Location { file: Some("/Users/user/.cargo/git/checkouts/tokio-1.0.1/src/lib.rs".to_string()), ..Default::default() }; - let location6 = proto::Location { + let location3 = proto::Location { file: Some("/Users/user/projects/tokio-1.0.1/src/lib.rs".to_string()), ..Default::default() }; assert_eq!( - format_location(Some(location4)), + format_location(Some(location1)), "/tokio-1.0.1/src/lib.rs" ); assert_eq!( - format_location(Some(location5)), + format_location(Some(location2)), "/tokio-1.0.1/src/lib.rs" ); assert_eq!( - format_location(Some(location6)), + format_location(Some(location3)), "/Users/user/projects/tokio-1.0.1/src/lib.rs" ); } + + #[test] + fn test_format_location_windows() { + // Windows style paths. + let location1 = proto::Location { + file: Some( + "C:\\Users\\user\\.cargo\\registry\\src\\github.com-1ecc6299db9ec823\\tokio-1.0.1\\src\\lib.rs" + .to_string(), + ), + ..Default::default() + }; + + let location2 = proto::Location { + file: Some( + "C:\\Users\\user\\.cargo\\git\\checkouts\\tokio-1.0.1\\src\\lib.rs".to_string(), + ), + ..Default::default() + }; + + let location3 = proto::Location { + file: Some("C:\\Users\\user\\projects\\tokio-1.0.1\\src\\lib.rs".to_string()), + ..Default::default() + }; + + assert_eq!( + format_location(Some(location1)), + "/tokio-1.0.1/src/lib.rs" + ); + + assert_eq!( + format_location(Some(location2)), + "/tokio-1.0.1/src/lib.rs" + ); + + assert_eq!( + format_location(Some(location3)), + "C:/Users/user/projects/tokio-1.0.1/src/lib.rs" + ); + } } From 081ba385841d919bfb7180529bedf3db94e45c01 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sun, 16 Jun 2024 21:15:55 +0800 Subject: [PATCH 2/5] refactor: better regex expression Signed-off-by: hi-rustin --- tokio-console/src/state/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tokio-console/src/state/mod.rs b/tokio-console/src/state/mod.rs index 48fd2d576..affffdd5c 100644 --- a/tokio-console/src/state/mod.rs +++ b/tokio-console/src/state/mod.rs @@ -511,10 +511,8 @@ fn truncate_registry_path(s: String) -> String { static REGEX: OnceCell = OnceCell::new(); let regex = REGEX.get_or_init(|| { - Regex::new( - r".*(/|\\)\.cargo(/|\\)(registry(/|\\)src(/|\\)[^/\\]*(/|\\)|git(/|\\)checkouts(/|\\))", - ) - .expect("failed to compile regex") + Regex::new(r".*[/\\]\.cargo[/\\](registry[/\\]src[/\\][^/\\]*[/\\]|git[/\\]checkouts[/\\])") + .expect("failed to compile regex") }); let s = match regex.replace(&s, "/") { From 2adc9843e405fd0756675b3202c542621149d319 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Mon, 1 Jul 2024 21:35:54 +0800 Subject: [PATCH 3/5] fix: keep the windows separator --- tokio-console/src/state/mod.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tokio-console/src/state/mod.rs b/tokio-console/src/state/mod.rs index affffdd5c..61c555c78 100644 --- a/tokio-console/src/state/mod.rs +++ b/tokio-console/src/state/mod.rs @@ -504,6 +504,11 @@ impl Attribute { } } +fn is_windows_path(path: &str) -> bool { + let re = regex::Regex::new(r"^[a-zA-Z]:\\").unwrap(); + re.is_match(path) +} + fn truncate_registry_path(s: String) -> String { use once_cell::sync::OnceCell; use regex::Regex; @@ -515,14 +520,17 @@ fn truncate_registry_path(s: String) -> String { .expect("failed to compile regex") }); - let s = match regex.replace(&s, "/") { + let rep = if is_windows_path(&s) { + "\\" + } else { + "/" + }; + + match regex.replace(&s, rep) { Cow::Owned(s) => s, // String was not modified, return the original. Cow::Borrowed(_) => s, - }; - - // This help use the same path separator on all platforms. - s.replace('\\', "/") + } } fn format_location(loc: Option) -> String { @@ -641,17 +649,17 @@ mod tests { assert_eq!( format_location(Some(location1)), - "/tokio-1.0.1/src/lib.rs" + "\\tokio-1.0.1\\src\\lib.rs" ); assert_eq!( format_location(Some(location2)), - "/tokio-1.0.1/src/lib.rs" + "\\tokio-1.0.1\\src\\lib.rs" ); assert_eq!( format_location(Some(location3)), - "C:/Users/user/projects/tokio-1.0.1/src/lib.rs" + "C:\\Users\\user\\projects\\tokio-1.0.1\\src\\lib.rs" ); } } From cf78c6c3ab0c6fe6f8bc474316c9155ae21f2131 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Mon, 1 Jul 2024 21:41:51 +0800 Subject: [PATCH 4/5] refactor: better code --- tokio-console/src/state/mod.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tokio-console/src/state/mod.rs b/tokio-console/src/state/mod.rs index 61c555c78..be10f5f3b 100644 --- a/tokio-console/src/state/mod.rs +++ b/tokio-console/src/state/mod.rs @@ -504,9 +504,18 @@ impl Attribute { } } +// A naive way to determine if a path is a Windows path. +// If the path has a drive letter and more backslashes than forward slashes, it's a Windows path. fn is_windows_path(path: &str) -> bool { - let re = regex::Regex::new(r"^[a-zA-Z]:\\").unwrap(); - re.is_match(path) + use once_cell::sync::OnceCell; + use regex::Regex; + + static REGEX: OnceCell = OnceCell::new(); + let regex = REGEX.get_or_init(|| Regex::new(r"^[a-zA-Z]:\\").expect("failed to compile regex")); + let has_drive_letter = regex.is_match(path); + let slash_count = path.find('/').iter().count(); + let backslash_count = path.find('\\').iter().count(); + has_drive_letter && backslash_count > slash_count } fn truncate_registry_path(s: String) -> String { From a36c277b6219e284cdb9c350528be5bbfce2e781 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Wed, 3 Jul 2024 20:28:53 +0800 Subject: [PATCH 5/5] refactor: use filter instead of find --- tokio-console/src/state/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tokio-console/src/state/mod.rs b/tokio-console/src/state/mod.rs index be10f5f3b..4b9928a8f 100644 --- a/tokio-console/src/state/mod.rs +++ b/tokio-console/src/state/mod.rs @@ -513,8 +513,8 @@ fn is_windows_path(path: &str) -> bool { static REGEX: OnceCell = OnceCell::new(); let regex = REGEX.get_or_init(|| Regex::new(r"^[a-zA-Z]:\\").expect("failed to compile regex")); let has_drive_letter = regex.is_match(path); - let slash_count = path.find('/').iter().count(); - let backslash_count = path.find('\\').iter().count(); + let slash_count = path.chars().filter(|&c| c == '/').count(); + let backslash_count = path.chars().filter(|&c| c == '\\').count(); has_drive_letter && backslash_count > slash_count }