Repository: TabbyML/tabby
File: crates/tabby-common/src/config.rs (Rust)

Code before:
        &self.git_url
    }

    pub fn canonicalize_url(url: &str) -> String {
        let url = url.strip_suffix(".git").unwrap_or(url);
        url::Url::parse(url)
            .map(|mut url| {
                let _ = url.set_password(None);
                let _ = url.set_username("");
                url.to_string()
            })
            .unwrap_or_else(|_| url.to_string())
    }

    pub fn dir(&self) -> PathBuf {
        Self::resolve_dir(&self.git_url)
    }

    pub fn display_name(&self) -> String {
        Self::resolve_dir_name(&self.git_url)
    }

    pub fn resolve_dir(git_url: &str) -> PathBuf {
        if Self::resolve_is_local_dir(git_url) {
            // Parse the URL and convert to a file path in a platform-aware way
            let url = Url::parse(git_url)
                .unwrap_or_else(|e| panic!("Invalid file:// URL: {}, error: {}", git_url, e));

            url.to_file_path().unwrap_or_else(|_| {
                panic!(
                    "Failed to convert file URL to path: {}. \
                     Please ensure the URL has a valid format for your platform (e.g., \
                     'file:///C:/path' for Windows or 'file:///path' for Unix)",
                    git_url
                )
            })
        } else {
            repositories_dir().join(Self::resolve_dir_name(git_url))
        }
    }

    pub fn resolve_dir_name(git_url: &str) -> String {
        sanitize_name(&Self::canonicalize_url(git_url))
    }

    pub fn resolve_is_local_dir(git_url: &str) -> bool {
        git_url.starts_with("file://")
    }
}

fn sanitize_name(s: &str) -> String {

Review comment (suggestion):
```
url::Url::parse(git_url)
    .ok()
    .and_then(|url| url.to_file_path().ok())
    .unwrap_or_else(|| {
        let path = git_url.strip_prefix("file://").unwrap_or(git_url);
        PathBuf::from(path)
    })
```
For example

Code after:
    }

    pub fn canonicalize_url(url: &str) -> String {
        let url = url.strip_suffix(".git").unwrap_or(url);
        url::Url::parse(url)
            .map(|mut url| {
                let _ = url.set_password(None);
                let _ = url.set_username("");
                url.to_string()
            })
            .unwrap_or_else(|_| url.to_string())
    }

    pub fn dir(&self) -> PathBuf {
        Self::resolve_dir(&self.git_url)
    }

    pub fn display_name(&self) -> String {
        Self::resolve_dir_name(&self.git_url)
    }

    pub fn resolve_dir(git_url: &str) -> PathBuf {
        if Self::resolve_is_local_dir(git_url) {
            url::Url::parse(git_url)
                .ok()
                .and_then(|url| url.to_file_path().ok())
                .unwrap_or_else(|| {
                    let path = git_url.strip_prefix("file://").unwrap_or(git_url);
                    PathBuf::from(path)
                })
        } else {
            repositories_dir().join(Self::resolve_dir_name(git_url))
        }
    }

    pub fn resolve_dir_name(git_url: &str) -> String {
        sanitize_name(&Self::canonicalize_url(git_url))
    }

    pub fn resolve_is_local_dir(git_url: &str) -> bool {
        git_url.starts_with("file://")
    }
}

fn sanitize_name(s: &str) -> String {
    let mut sanitized: Vec<char> = s
        .chars()
        .map(|c| match c {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '-' => c,
            _ => '_',
        })