codetether_agent/a2a/git_credentials/
script.rs1use anyhow::{Context, Result};
13use std::fs;
14#[cfg(unix)]
15use std::os::unix::fs::PermissionsExt;
16use std::path::Path;
17
18pub fn write_git_credential_helper_script(script_path: &Path, workspace_id: &str) -> Result<()> {
28 if let Some(parent) = script_path.parent() {
29 fs::create_dir_all(parent).with_context(|| {
30 format!(
31 "Failed to create helper script directory {}",
32 parent.display()
33 )
34 })?;
35 }
36 let current_exe = std::env::current_exe()
37 .context("Failed to determine current CodeTether binary path for credential helper")?;
38 let script = format!(
39 "#!/bin/sh\nexec {} git-credential-helper --workspace-id {} \"$@\"\n",
40 shell_single_quote(current_exe.to_string_lossy().as_ref()),
41 shell_single_quote(workspace_id)
42 );
43 fs::write(script_path, script).with_context(|| {
44 format!(
45 "Failed to write Git credential helper script {}",
46 script_path.display()
47 )
48 })?;
49 #[cfg(unix)]
50 mark_executable(script_path)?;
51 Ok(())
52}
53
54#[cfg(unix)]
55fn mark_executable(script_path: &Path) -> Result<()> {
56 let mut permissions = fs::metadata(script_path)
57 .with_context(|| {
58 format!(
59 "Failed to stat Git credential helper script {}",
60 script_path.display()
61 )
62 })?
63 .permissions();
64 permissions.set_mode(0o700);
65 fs::set_permissions(script_path, permissions).with_context(|| {
66 format!(
67 "Failed to mark Git credential helper script executable {}",
68 script_path.display()
69 )
70 })
71}
72
73fn shell_single_quote(value: &str) -> String {
74 format!("'{}'", value.replace('\'', "'\\''"))
75}