remote-helper: Simplify handling of `GIT_DIR`
The contract for Git remote handlers says that we can expect `GIT_DIR` to be set, and this also simplifies logic regarding bare vs. non-bare repositories.
This commit is contained in:
parent
354565c579
commit
606882f01f
|
|
@ -7,6 +7,14 @@
|
||||||
//! Usage of standard streams:
|
//! Usage of standard streams:
|
||||||
//! - Standard Error ([`eprintln`]) is used for communicating with the user.
|
//! - Standard Error ([`eprintln`]) is used for communicating with the user.
|
||||||
//! - Standard Output ([`println`]) is used for communicating with Git tooling.
|
//! - Standard Output ([`println`]) is used for communicating with Git tooling.
|
||||||
|
//!
|
||||||
|
//! This process assumes that the environment variable `GIT_DIR` is set
|
||||||
|
//! appropriately (to the repository being pushed from or fetched to), as
|
||||||
|
//! mentioned in the documentation on Git remote helpers.
|
||||||
|
//!
|
||||||
|
//! For example, the following two mechanisms rely on `GIT_DIR` being set:
|
||||||
|
//! - [`git::raw::Repository::open_from_env`] to open the repository
|
||||||
|
//! - [`radicle::git::run`] (with [`None`] as first argument) to invoke `git`
|
||||||
|
|
||||||
mod fetch;
|
mod fetch;
|
||||||
mod list;
|
mod list;
|
||||||
|
|
@ -89,12 +97,6 @@ pub enum Error {
|
||||||
/// I/O error.
|
/// I/O error.
|
||||||
#[error("i/o error: {0}")]
|
#[error("i/o error: {0}")]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
/// The `GIT_DIR` env var is not set.
|
|
||||||
#[error("the `GIT_DIR` environment variable is not set")]
|
|
||||||
NoGitDir,
|
|
||||||
/// No parent of `GIT_DIR` was found.
|
|
||||||
#[error("expected parent of .git but found {path:?}")]
|
|
||||||
NoWorkingCopy { path: PathBuf },
|
|
||||||
/// Git error.
|
/// Git error.
|
||||||
#[error("git: {0}")]
|
#[error("git: {0}")]
|
||||||
Git(#[from] git::raw::Error),
|
Git(#[from] git::raw::Error),
|
||||||
|
|
@ -185,13 +187,14 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Assume the default remote if there was no remote.
|
||||||
|
let remote = remote.unwrap_or_else(|| (*radicle::rad::REMOTE_NAME).clone());
|
||||||
|
|
||||||
let stored = profile.storage.repository_mut(url.repo)?;
|
let stored = profile.storage.repository_mut(url.repo)?;
|
||||||
if stored.is_empty()? {
|
if stored.is_empty()? {
|
||||||
return Err(Error::RepositoryNotFound(stored.path().to_path_buf()));
|
return Err(Error::RepositoryNotFound(stored.path().to_path_buf()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// `GIT_DIR` is set by Git tooling, if we're in a working copy.
|
|
||||||
let working = env::var("GIT_DIR").map(PathBuf::from);
|
|
||||||
// Whether we should output debug logs.
|
// Whether we should output debug logs.
|
||||||
let debug = radicle::profile::env::debug();
|
let debug = radicle::profile::env::debug();
|
||||||
|
|
||||||
|
|
@ -243,25 +246,23 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
|
||||||
let oid = git::Oid::from_str(oid)?;
|
let oid = git::Oid::from_str(oid)?;
|
||||||
let refstr = git::RefString::try_from(*refstr)?;
|
let refstr = git::RefString::try_from(*refstr)?;
|
||||||
|
|
||||||
return fetch::run(vec![(oid, refstr)], stored, &stdin, opts.verbosity)
|
return Ok(fetch::run(
|
||||||
.map_err(Error::from);
|
vec![(oid, refstr)],
|
||||||
|
stored,
|
||||||
|
&stdin,
|
||||||
|
opts.verbosity,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
["push", refspec] => {
|
["push", refspec] => {
|
||||||
// We have to be in a working copy to push.
|
return Ok(push::run(
|
||||||
let working = working.map_err(|_| Error::NoGitDir)?;
|
|
||||||
|
|
||||||
return push::run(
|
|
||||||
vec![refspec.to_string()],
|
vec![refspec.to_string()],
|
||||||
&working,
|
remote,
|
||||||
// N.b. assume the default remote if there was no remote
|
|
||||||
remote.unwrap_or((*radicle::rad::REMOTE_NAME).clone()),
|
|
||||||
url,
|
url,
|
||||||
&stored,
|
&stored,
|
||||||
&profile,
|
&profile,
|
||||||
&stdin,
|
&stdin,
|
||||||
opts,
|
opts,
|
||||||
)
|
)?);
|
||||||
.map_err(Error::from);
|
|
||||||
}
|
}
|
||||||
["list"] => {
|
["list"] => {
|
||||||
list::for_fetch(&url, &profile, &stored)?;
|
list::for_fetch(&url, &profile, &stored)?;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ mod error;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::IsTerminal;
|
use std::io::IsTerminal;
|
||||||
use std::path::Path;
|
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{assert_eq, io};
|
use std::{assert_eq, io};
|
||||||
|
|
@ -247,7 +246,6 @@ impl PushAction {
|
||||||
/// Run a git push command.
|
/// Run a git push command.
|
||||||
pub fn run(
|
pub fn run(
|
||||||
mut specs: Vec<String>,
|
mut specs: Vec<String>,
|
||||||
working: &Path,
|
|
||||||
remote: git::RefString,
|
remote: git::RefString,
|
||||||
url: Url,
|
url: Url,
|
||||||
stored: &storage::git::Repository,
|
stored: &storage::git::Repository,
|
||||||
|
|
@ -292,7 +290,9 @@ pub fn run(
|
||||||
let canonical_ref = git::refs::branch(project.default_branch());
|
let canonical_ref = git::refs::branch(project.default_branch());
|
||||||
let mut set_canonical_refs: Vec<(git::Qualified, git::canonical::Object)> =
|
let mut set_canonical_refs: Vec<(git::Qualified, git::canonical::Object)> =
|
||||||
Vec::with_capacity(specs.len());
|
Vec::with_capacity(specs.len());
|
||||||
let working = git::raw::Repository::open(working)?;
|
|
||||||
|
// Rely on the environment variable `GIT_DIR`.
|
||||||
|
let working = git::raw::Repository::open_from_env()?;
|
||||||
|
|
||||||
// For each refspec, push a ref or delete a ref.
|
// For each refspec, push a ref or delete a ref.
|
||||||
for spec in specs {
|
for spec in specs {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue