Skip to main content

worktree_io/git/
remote.rs

1use anyhow::{bail, Context, Result};
2
3/// Get the URL of a named remote from a git repository.
4///
5/// # Errors
6///
7/// Returns an error if `git remote get-url` fails or the output is not valid UTF-8.
8pub fn get_remote_url(repo: &std::path::Path, remote: &str) -> Result<String> {
9    let output = super::git_cmd()
10        .args(["-C"])
11        .arg(repo)
12        .args(["remote", "get-url", remote])
13        .output()
14        .context("Failed to run `git remote get-url`")?; // LLVM_COV_EXCL_LINE
15
16    if !output.status.success() {
17        bail!(
18            "git remote get-url {remote} failed: {}",
19            String::from_utf8_lossy(&output.stderr).trim()
20        );
21    }
22
23    Ok(String::from_utf8(output.stdout)
24        .context("Remote URL is not valid UTF-8")? // LLVM_COV_EXCL_LINE
25        .trim()
26        .to_string())
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32    use std::process::Command;
33
34    fn git(dir: &std::path::Path, args: &[&str]) {
35        Command::new("git")
36            .args(["-C"])
37            .arg(dir)
38            .args(args)
39            .env_remove("GIT_DIR")
40            .status()
41            .unwrap();
42    }
43
44    #[test]
45    fn get_remote_url_success() {
46        let dir = tempfile::tempdir().unwrap();
47        git(dir.path(), &["init"]);
48        git(
49            dir.path(),
50            &["remote", "add", "origin", "https://github.com/acme/api.git"],
51        );
52        let url = get_remote_url(dir.path(), "origin").unwrap();
53        assert_eq!(url, "https://github.com/acme/api.git");
54    }
55
56    #[test]
57    fn get_remote_url_no_remote() {
58        let dir = tempfile::tempdir().unwrap();
59        git(dir.path(), &["init"]);
60        let err = get_remote_url(dir.path(), "origin").unwrap_err();
61        assert!(err.to_string().contains("git remote get-url origin failed"));
62    }
63}