use std::{ path::Path, process::{Command, Stdio}, }; use bstr::{BString, ByteSlice, ByteVec}; use crate::{Program, helper}; /// Correctly quotes `git_progarm`, while assuming `name_and_args` are good to be put into a script. fn external_name_command( git_program: &Path, name_and_args: &bstr::BStr, action: &helper::Action, ) -> std::process::Command { let git_program = gix_path::to_unix_separators_on_windows(gix_path::into_bstr(git_program)); let mut args = gix_quote::single(git_program.as_ref()); args.push_str(" credential-"); args.push_str(name_and_args); gix_command::prepare(gix_path::from_bstr(args.as_bstr()).into_owned()) .arg(action.as_arg(true)) .command_may_be_shell_script_allow_manual_argument_splitting() .into() } /// The kind of helper program to use. #[derive(Debug, Clone, Eq, PartialEq)] pub enum Kind { /// The built-in `git credential` helper program, part of any `git` distribution. Builtin, /// A custom credentials helper, as identified just by the name with optional arguments ExternalName { /// The name like `foo` along with optional args, like `foo --arg --bar="a b"`, with arguments using `sh` shell quoting rules. /// The program executed will be `git-credential-foo [args]` if `name_and_args` starts with `foo [args]`. /// Note that a shell is only used if it's needed. name_and_args: BString, }, /// A custom credentials helper, as identified just by the absolute path to the program and optional arguments. The program is executed through a shell. ExternalPath { /// The absolute path to the executable, like `/path/to/exe` along with optional args, like `/path/to/exe --arg --bar="a b"`, with arguments using `sh` /// shell quoting rules. path_and_args: BString, }, /// A script to execute with `sh`. ExternalShellScript(BString), } /// Initialization impl Program { /// Create a new program of the given `kind`. pub fn from_kind(kind: Kind) -> Self { Program { kind, child: None, stderr: true, } } /// Parse the given input as per the custom helper definition, supporting `!