git-next/src/server/gitforge/forgejo/branch/fetch.rs
Paul Campbell 5ba5a126c3
Some checks failed
ci/woodpecker/cron/cron-docker-builder Pipeline was successful
ci/woodpecker/cron/push-next Pipeline was successful
ci/woodpecker/cron/tag-created Pipeline was successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
ci/woodpecker/push/push-next Pipeline failed
fix(gitforge): use local repo or clone to allow git push
The `git push` command requires a git directory (bare at a minimum)
before it can work.
The git dir must also be up-to-date with the relevant references from
the remote, so
we do a `git fetch` before a `git push`.

Closes kemitix/git-next#51
2024-05-03 19:08:58 +01:00

72 lines
2.4 KiB
Rust

use std::ops::Deref;
use tracing::info;
use crate::server::config::RepoDetails;
#[derive(Debug, derive_more::From, derive_more::Display)]
pub enum Error {
UnableToOpenRepo(Box<gix::open::Error>),
NoFetchRemoteFound,
Connect(Box<gix::remote::connect::Error>),
Fetch(String),
}
impl std::error::Error for Error {}
#[tracing::instrument]
pub fn fetch(repo_details: &RepoDetails) -> Result<(), Error> {
// INFO: gitdir validate tests that the default fetch remote matches the configured remote
let repository = gix::ThreadSafeRepository::open(repo_details.gitdir.deref())
.map_err(Box::new)?
.to_thread_local();
info!(?repository, "opened repo");
let Some(remote) = repository.find_default_remote(gix::remote::Direction::Fetch) else {
return Err(Error::NoFetchRemoteFound);
};
info!(?remote, "fetch remote");
remote
.map_err(|e| Error::Fetch(e.to_string()))?
.connect(gix::remote::Direction::Fetch)
.map_err(Box::new)?
.prepare_fetch(gix::progress::Discard, Default::default())
.map_err(|e| Error::Fetch(e.to_string()))?
.receive(gix::progress::Discard, &Default::default())
.map_err(|e| Error::Fetch(e.to_string()))?;
info!("fetched");
Ok(())
// INFO: never log the command as it contains the API token within the 'origin'
// let command: secrecy::Secret<String> = format!(
// "/usr/bin/git push {} {to_commit}:{branch_name} {force}",
// origin.expose_secret()
// )
// .into();
// info!("Resetting {branch_name} to {to_commit}");
// let ctx = gix::diff::command::Context {
// git_dir: Some(repo_details.gitdir.deref().clone()),
// ..Default::default()
// };
// // info!(?ctx, command = command.expose_secret(), "prepare");
// match gix::command::prepare(command.expose_secret())
// .with_context(ctx)
// .with_shell_allow_argument_splitting()
// // .stdout(std::process::Stdio::null())
// // .stderr(std::process::Stdio::null())
// .spawn()
// {
// Ok(mut child) => match child.wait() {
// Ok(_) => Ok(()),
// Err(err) => {
// warn!(?err, "Failed (wait)");
// Err(())
// }
// },
// Err(err) => {
// warn!(?err, "Failed (spawn)");
// Err(())
// }
// }
}