Skip to content

Commit

Permalink
cli: refactor git clone
Browse files Browse the repository at this point in the history
the `do_git_clone` function takes a lot of arguments and does a lot.
This commit reduces the complexity by splitting the functionality into two parts:
    - setting up the workspace
    - fetching the git repo
  • Loading branch information
bsdinis committed Jan 18, 2025
1 parent dc6ebe1 commit bae8568
Showing 1 changed file with 31 additions and 21 deletions.
52 changes: 31 additions & 21 deletions cli/src/commands/git/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ use std::io;
use std::io::Write;
use std::num::NonZeroU32;
use std::path::Path;
use std::sync::Arc;

use jj_lib::git;
use jj_lib::git::GitFetchError;
use jj_lib::git::GitFetchStats;
use jj_lib::repo::ReadonlyRepo;
use jj_lib::repo::Repo;
use jj_lib::str_util::StringPattern;
use jj_lib::workspace::Workspace;
Expand Down Expand Up @@ -115,15 +117,24 @@ pub fn cmd_git_clone(
// `/some/path/.`
let canonical_wc_path = dunce::canonicalize(&wc_path)
.map_err(|err| user_error_with_message(format!("Failed to create {wc_path_str}"), err))?;
let clone_result = do_git_clone(

let (workspace, repo, git_repo) = setup_workspace(command, args.colocate, &canonical_wc_path)?;
writeln!(
ui.status(),
r#"Fetching into new repo in "{}""#,
canonical_wc_path.display()
)?;
let mut workspace_command = command.for_workable_repo(ui, workspace, repo)?;
maybe_add_gitignore(&workspace_command)?;
let clone_result = fetch_new_repo(
ui,
command,
args.colocate,
&mut workspace_command,
git_repo,
args.depth,
remote_name,
&source,
&canonical_wc_path,
);

if clone_result.is_err() {
let clean_up_dirs = || -> io::Result<()> {
fs::remove_dir_all(canonical_wc_path.join(".jj"))?;
Expand All @@ -146,7 +157,7 @@ pub fn cmd_git_clone(
}
}

let (mut workspace_command, stats) = clone_result?;
let stats = clone_result?;
if let Some(default_branch) = &stats.default_branch {
write_repository_level_trunk_alias(
ui,
Expand Down Expand Up @@ -174,33 +185,32 @@ pub fn cmd_git_clone(
Ok(())
}

fn do_git_clone(
ui: &mut Ui,
fn setup_workspace(
command: &CommandHelper,
colocate: bool,
depth: Option<NonZeroU32>,
remote_name: &str,
source: &str,
wc_path: &Path,
) -> Result<(WorkspaceCommandHelper, GitFetchStats), CommandError> {
) -> Result<(Workspace, Arc<ReadonlyRepo>, git2::Repository), CommandError> {
let settings = command.settings_for_new_workspace(wc_path)?;
let (workspace, repo) = if colocate {
Workspace::init_colocated_git(&settings, wc_path)?
} else {
Workspace::init_internal_git(&settings, wc_path)?
};
let git_repo = get_git_repo(repo.store())?;
writeln!(
ui.status(),
r#"Fetching into new repo in "{}""#,
wc_path.display()
)?;
let mut workspace_command = command.for_workable_repo(ui, workspace, repo)?;
maybe_add_gitignore(&workspace_command)?;
git_repo.remote(remote_name, source).unwrap();
Ok((workspace, repo, git_repo))
}

fn fetch_new_repo(
ui: &mut Ui,
workspace_command: &mut WorkspaceCommandHelper,
git_repo: git2::Repository,
depth: Option<NonZeroU32>,
remote_name: &str,
source: &str,
) -> Result<GitFetchStats, CommandError> {
let git_settings = workspace_command.settings().git_settings()?;
let mut fetch_tx = workspace_command.start_transaction();

git_repo.remote(remote_name, source).unwrap();
let stats = with_remote_git_callbacks(ui, None, |cb| {
git::fetch(
fetch_tx.repo_mut(),
Expand All @@ -224,5 +234,5 @@ fn do_git_clone(
})?;
print_git_import_stats(ui, fetch_tx.repo(), &stats.import_stats, true)?;
fetch_tx.finish(ui, "fetch from git remote into empty repo")?;
Ok((workspace_command, stats))
Ok(stats)
}

0 comments on commit bae8568

Please sign in to comment.