From 63b8dd9ae0ec695dec5fea822131dbf182880a24 Mon Sep 17 00:00:00 2001 From: Ackerman Date: Wed, 23 Jul 2025 18:53:25 +0900 Subject: [PATCH] Handle git config failures --- src/config.rs | 16 +++++++++++++--- tests/cli.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/config.rs b/src/config.rs index dd728ff..7e7d545 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, path::Path, process::Command}; @@ -68,22 +69,31 @@ impl Config { pub fn save(&self, repo_root: &Path) -> anyhow::Result<()> { for (name, m) in &self.mappings { let key_remote = format!("{CONFIG_PREFIX}.{}.remote", name); - Command::new("git") + let status = Command::new("git") .args(["config", "--local", "--replace-all", &key_remote, &m.remote]) .current_dir(repo_root) .status()?; + if !status.success() { + return Err(anyhow!("git config failed to set {key_remote}")); + } let key_url = format!("{CONFIG_PREFIX}.{}.url", name); - Command::new("git") + let status = Command::new("git") .args(["config", "--local", "--replace-all", &key_url, &m.url]) .current_dir(repo_root) .status()?; + if !status.success() { + return Err(anyhow!("git config failed to set {key_url}")); + } let key_branch = format!("{CONFIG_PREFIX}.{}.branch", name); - Command::new("git") + let status = Command::new("git") .args(["config", "--local", "--replace-all", &key_branch, &m.branch]) .current_dir(repo_root) .status()?; + if !status.success() { + return Err(anyhow!("git config failed to set {key_branch}")); + } } Ok(()) diff --git a/tests/cli.rs b/tests/cli.rs index 510ede9..e0696d5 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -58,6 +58,22 @@ fi shim } +/// `git config` が失敗するシム +fn fake_git_fail_config(dir: &tempfile::TempDir) -> std::path::PathBuf { + let shim = dir.path().join("git"); + fs::write( + &shim, + "#!/usr/bin/env sh\nif [ \"$1\" = \"config\" ]; then\n exit 1\nelse\n echo git \"$@\"\n exit 0\nfi\n", + ) + .unwrap(); + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + fs::set_permissions(&shim, fs::Permissions::from_mode(0o755)).unwrap(); + } + shim +} + #[test] fn connect_and_list_roundtrip() { let repo = setup_repo(); @@ -189,3 +205,24 @@ fn remove_mapping() { .success() .stdout(predicate::str::contains("No mappings")); } + +#[test] +fn connect_fails_on_git_config_error() { + let repo = setup_repo(); + let git_shim = fake_git_fail_config(&repo); + + let path_env = format!( + "{}:{}", + git_shim.parent().unwrap().display(), + std::env::var("PATH").unwrap() + ); + + Command::cargo_bin("gh-sync") + .unwrap() + .current_dir(repo.path()) + .env("PATH", &path_env) + .args(&["connect", "web-app", "git@github.com:a/b.git"]) + .assert() + .failure() + .stderr(predicate::str::contains("git config")); +}