//! Smart-HTTP and SSH service selection and command construction. use std::path::Path; use crate::command::{GitCommand, GitEnv}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum GitService { UploadPack, ReceivePack, } impl GitService { /// Accepts `git-upload-pack` or `git-receive-pack`. pub fn from_name(s: &str) -> Option { match s { "git-upload-pack" => Some(GitService::UploadPack), "git-receive-pack" => Some(GitService::ReceivePack), _ => None, } } /// `git-upload-pack` or `git-receive-pack`. pub fn name(&self) -> &'static str { match self { GitService::UploadPack => "git-upload-pack", GitService::ReceivePack => "git-receive-pack", } } /// The `git` subcommand, without the `git-` prefix. fn subcommand(&self) -> &'static str { match self { GitService::UploadPack => "upload-pack", GitService::ReceivePack => "receive-pack", } } } /// Builds `git [--stateless-rpc] [--advertise-refs] -- `. /// `git_protocol` is passed as `GIT_PROTOCOL`. For SSH, pass `stateless_rpc=false` and /// `advertise_refs=false` to get no flags. pub fn service_command( env: &GitEnv, svc: GitService, repo: &Path, stateless_rpc: bool, advertise_refs: bool, git_protocol: Option<&str>, ) -> GitCommand { let mut cmd = GitCommand::new(env, svc.subcommand()); if stateless_rpc { cmd = cmd.arg("--stateless-rpc"); } if advertise_refs { cmd = cmd.arg("--advertise-refs"); } let repo_str = repo.to_string_lossy(); cmd = cmd.paths(&[repo_str.as_ref()]); if let Some(proto) = git_protocol { cmd = cmd.env("GIT_PROTOCOL", proto); } cmd }