Skip to content

Commit 3934461

Browse files
committed
refactor: Simplify extract_binary_path_from_wrapper with shared parsing logic
- Create shared utility function extract_quoted_strings() in desktop_file.rs - Extract strings enclosed in specified quote characters - Refactor extract_binary_path_from_wrapper() to use shared parsing logic - Reduce code duplication from 6 lines to 1 line for extraction logic - Add comprehensive tests for the utility function - Maintain identical functionality and behavior
1 parent dade483 commit 3934461

2 files changed

Lines changed: 57 additions & 10 deletions

File tree

src/backends/desktop_file.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ pub struct DesktopEntry {
55
pub icon: String,
66
}
77

8+
/// Extracts the first string enclosed in the specified quote character from a line of text.
9+
/// Returns the extracted string without quotes, or None if no quoted string is found.
10+
///
11+
/// This is useful for parsing shell scripts and config files that use quoted strings.
12+
///
13+
/// # Examples
14+
/// ```
15+
/// let line = "exec '/usr/bin/vim' \"$@\"";
16+
/// assert_eq!(extract_quoted_string(line, '\''), Some("/usr/bin/vim"));
17+
/// ```
18+
pub fn extract_quoted_string(line: &str, quote_char: char) -> Option<String> {
19+
let start = line.find(quote_char)?;
20+
let end = line[start + 1..].find(quote_char)?;
21+
Some(line[start + 1..start + 1 + end].to_string())
22+
}
23+
824
pub fn parse_desktop_file(content: &str) -> anyhow::Result<DesktopEntry> {
925
let mut name = None;
1026
let mut exec = None;
@@ -118,4 +134,34 @@ Icon=test-icon
118134
assert_eq!(&entry.name, "Test=App");
119135
assert_eq!(&entry.exec, "/usr/bin/test --param=value");
120136
}
137+
138+
#[test]
139+
fn test_extract_quoted_string_single_quotes() {
140+
let line = "exec '/usr/bin/vim' \"$@\"";
141+
assert_eq!(extract_quoted_string(line, '\''), Some("/usr/bin/vim".to_string()));
142+
}
143+
144+
#[test]
145+
fn test_extract_quoted_string_double_quotes() {
146+
let line = r#"exec "distrobox-enter" -n test"#;
147+
assert_eq!(extract_quoted_string(line, '"'), Some("distrobox-enter".to_string()));
148+
}
149+
150+
#[test]
151+
fn test_extract_quoted_string_no_quotes() {
152+
let line = "exec /usr/bin/vim";
153+
assert_eq!(extract_quoted_string(line, '\''), None);
154+
}
155+
156+
#[test]
157+
fn test_extract_quoted_string_incomplete_quotes() {
158+
let line = "exec '/usr/bin/vim";
159+
assert_eq!(extract_quoted_string(line, '\''), None);
160+
}
161+
162+
#[test]
163+
fn test_extract_quoted_string_empty() {
164+
let line = "exec ''";
165+
assert_eq!(extract_quoted_string(line, '\''), Some("".to_string()));
166+
}
121167
}

src/backends/distrobox/distrobox.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,9 @@ impl Distrobox {
848848

849849
/// Extracts the original binary path from a distrobox exported wrapper script.
850850
/// The wrapper script contains lines like: exec '/usr/bin/binary' "$@"
851+
///
852+
/// Uses the shared `extract_quoted_string` utility from desktop_file module for
853+
/// consistent string parsing across the codebase.
851854
async fn extract_binary_path_from_wrapper(&self, wrapper_path: &str) -> Option<String> {
852855
// Read the wrapper script content
853856
let cmd = Command::new_with_args("cat", [wrapper_path]);
@@ -856,17 +859,15 @@ impl Distrobox {
856859
// Look for the pattern: exec ... '/path/to/binary' or exec '/path/to/binary'
857860
// The binary path is typically in single quotes in the else branch
858861
for line in output.lines() {
859-
let line = line.trim();
862+
let trimmed = line.trim();
860863
// Look for lines with exec that contain a quoted path
861-
if line.starts_with("exec") {
862-
// Try to extract path between single quotes
863-
if let Some(start) = line.find('\'') {
864-
if let Some(end) = line[start + 1..].find('\'') {
865-
let path = &line[start + 1..start + 1 + end];
866-
// Validate it looks like a path
867-
if path.starts_with('/') && !path.contains("distrobox") {
868-
return Some(path.to_string());
869-
}
864+
if trimmed.starts_with("exec") {
865+
// Reuse the shared quoted string extraction logic from desktop_file module
866+
if let Some(path) = extract_quoted_string(trimmed, '\'') {
867+
// Validate it looks like an absolute path to the actual binary
868+
// (not a distrobox wrapper command)
869+
if path.starts_with('/') && !path.contains("distrobox") {
870+
return Some(path);
870871
}
871872
}
872873
}

0 commit comments

Comments
 (0)