Skip to content

Commit

Permalink
first rough sketch of gix clone (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Oct 17, 2022
1 parent 63947ae commit 23a5e8b
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
15 changes: 15 additions & 0 deletions git-repository/src/clone/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ pub mod main_worktree {
}
}

/// Access
impl PrepareCheckout {
/// Get access to the repository while the checkout isn't yet completed.
///
/// # Panics
///
/// If the checkout is completed and the [`Repository`] was already passed on to the caller.
pub fn repo(&self) -> &Repository {
self.repo
.as_ref()
.take()
.expect("present as checkout operation isn't complete")
}
}

/// Consumption
impl PrepareCheckout {
/// Persist the contained repository as is even if an error may have occurred when checking out the main working tree.
Expand Down
102 changes: 102 additions & 0 deletions gitoxide-core/src/repository/clone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use crate::OutputFormat;

pub struct Options {
pub format: OutputFormat,
pub bare: bool,
pub handshake_info: bool,
}

pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 1..=3;

pub(crate) mod function {
use anyhow::bail;
use git_repository as git;
use git_repository::remote::fetch::Status;
use std::ffi::OsStr;

use super::Options;
use crate::repository::fetch::function::print_updates;
use crate::OutputFormat;

pub fn clone(
remote: impl AsRef<OsStr>,
directory: impl AsRef<std::path::Path>,
mut progress: impl git::Progress,
mut out: impl std::io::Write,
err: impl std::io::Write,
Options {
format,
handshake_info,
bare,
}: Options,
) -> anyhow::Result<()> {
if format != OutputFormat::Human {
bail!("JSON output isn't yet supported for fetching.");
}

let mut prepare = git::clone::PrepareFetch::new(
remote.as_ref(),
directory,
git::create::Options {
bare,
fs_capabilities: None,
},
{
let mut opts = git::open::Options::default();
opts.permissions.config.git_binary = true;
opts
},
)?;
let (mut checkout, fetch_outcome) =
prepare.fetch_then_checkout(progress.add_child("fetch"), &git::interrupt::IS_INTERRUPTED)?;

if handshake_info {
writeln!(out, "Handshake Information")?;
writeln!(out, "\t{:?}", fetch_outcome.ref_map.handshake)?;
}

match fetch_outcome.status {
Status::NoChange => {
unreachable!("clone always has changes")
}
Status::DryRun { .. } => unreachable!("dry-run unsupported"),
Status::Change {
update_refs,
write_pack_bundle,
} => {
let repo = checkout.repo();
let remote = repo
.find_default_remote(git::remote::Direction::Fetch)
.expect("one origin remote")?;
let ref_specs = remote.refspecs(git::remote::Direction::Fetch);
print_updates(
checkout.repo(),
update_refs,
ref_specs,
fetch_outcome.ref_map,
&mut out,
err,
)?;
if let Some(data_path) = write_pack_bundle.data_path {
writeln!(out, "pack file: \"{}\"", data_path.display()).ok();
}
if let Some(index_path) = write_pack_bundle.index_path {
writeln!(out, "index file: \"{}\"", index_path.display()).ok();
}
}
};

let repo = if bare {
checkout.persist()
} else {
checkout.main_worktree(progress.add_child("clone"), &git::interrupt::IS_INTERRUPTED)?
};
writeln!(
out,
"clone (bare = {}) successful at \"{}\"",
bare,
repo.work_dir().unwrap_or_else(|| repo.git_dir()).display()
)?;
Ok(())
}
}
4 changes: 4 additions & 0 deletions gitoxide-core/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ pub mod commit;
pub mod config;
mod credential;
pub use credential::function as credential;
#[cfg(feature = "blocking-client")]
pub mod clone;
pub mod exclude;
#[cfg(feature = "blocking-client")]
pub mod fetch;
#[cfg(feature = "blocking-client")]
pub use clone::function::clone;
#[cfg(feature = "blocking-client")]
pub use fetch::function::fetch;
pub mod index;
pub mod mailmap;
Expand Down
21 changes: 21 additions & 0 deletions src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,27 @@ pub fn main() -> Result<()> {
})?;

match cmd {
#[cfg(feature = "gitoxide-core-blocking-client")]
Subcommands::Clone(crate::plumbing::options::clone::Platform {
handshake_info,
bare,
remote,
directory,
}) => {
let opts = core::repository::clone::Options {
format,
bare,
handshake_info,
};
prepare_and_run(
"clone",
verbose,
progress,
progress_keep_open,
core::repository::fetch::PROGRESS_RANGE,
move |progress, out, err| core::repository::clone(remote, directory, progress, out, err, opts),
)
}
#[cfg(feature = "gitoxide-core-blocking-client")]
Subcommands::Fetch(crate::plumbing::options::fetch::Platform {
dry_run,
Expand Down
25 changes: 25 additions & 0 deletions src/plumbing/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub enum Subcommands {
/// Fetch data from remotes and store it in the repository
#[cfg(feature = "gitoxide-core-blocking-client")]
Fetch(fetch::Platform),
#[cfg(feature = "gitoxide-core-blocking-client")]
Clone(clone::Platform),
/// Interact with the mailmap.
#[clap(subcommand)]
Mailmap(mailmap::Subcommands),
Expand Down Expand Up @@ -142,6 +144,29 @@ pub mod fetch {
}
}

#[cfg(feature = "gitoxide-core-blocking-client")]
pub mod clone {
use std::ffi::OsString;
use std::path::PathBuf;

#[derive(Debug, clap::Parser)]
pub struct Platform {
/// Output additional typically information provided by the server as part of the connection handshake.
#[clap(long, short = 'H')]
pub handshake_info: bool,

/// If set, the clone will be bare and a working tree checkout won't be available.
#[clap(long)]
pub bare: bool,

/// The url of the remote to connect to, like `https://github.com/byron/gitoxide`.
pub remote: OsString,

/// The directory to initialize with the new repository and to which all data should be written.
pub directory: PathBuf,
}
}

#[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))]
pub mod remote {
use git_repository as git;
Expand Down

0 comments on commit 23a5e8b

Please sign in to comment.