Skip to main content

grit_lib/
transport_path.rs

1//! Safety checks for local transport URLs (matches Git `connect.c` / `path.c`).
2
3use thiserror::Error;
4
5/// Errors returned while validating local transport paths.
6#[derive(Clone, Debug, Error, PartialEq, Eq)]
7pub enum TransportPathError {
8    /// A repository path begins with `-` and could be interpreted as a command option.
9    #[error("fatal: strange pathname '{0}' blocked")]
10    OptionLikePath(String),
11}
12
13/// Returns true when `s` is non-empty and begins with `-`, matching Git's
14/// `looks_like_command_line_option` (used before quoting a path for shell-backed transport).
15#[must_use]
16pub fn looks_like_command_line_option(s: &str) -> bool {
17    !s.is_empty() && s.starts_with('-')
18}
19
20/// Rejects repository path strings that could be mistaken for options when passed to a shell.
21///
22/// Git dies with `strange pathname '%s' blocked` when the parsed local path starts with `-`.
23/// Absolute paths like `/tmp/-repo.git` are allowed because the path string begins with `/`.
24pub fn check_local_url_path_not_option_like(url: &str) -> Result<(), TransportPathError> {
25    let path = url
26        .strip_prefix("file://")
27        .unwrap_or(url)
28        .split('?')
29        .next()
30        .unwrap_or("");
31    if looks_like_command_line_option(path) {
32        return Err(TransportPathError::OptionLikePath(path.to_owned()));
33    }
34    Ok(())
35}