forked from mirrors/jj
cli: extract a function for importing Git refs and HEAD (#44)
`WorkspaceCommandHelper::for_loaded_repo()` was getting a bit long.
This commit is contained in:
parent
47b3abd0f7
commit
cd0192e1b3
2 changed files with 86 additions and 32 deletions
|
@ -422,9 +422,53 @@ fn test_export_refs_current_branch_changed() {
|
|||
);
|
||||
test_data.repo = tx.commit();
|
||||
assert_eq!(git::export_refs(&test_data.repo, &git_repo), Ok(()));
|
||||
assert_eq!(
|
||||
git_repo
|
||||
.find_reference("refs/heads/main")
|
||||
.unwrap()
|
||||
.peel_to_commit()
|
||||
.unwrap()
|
||||
.id(),
|
||||
Oid::from_bytes(new_commit.id().as_bytes()).unwrap()
|
||||
);
|
||||
assert!(git_repo.head_detached().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_export_refs_unborn_git_branch() {
|
||||
// Can export to an empty Git repo (we can handle Git's "unborn branch" state)
|
||||
let mut test_data = GitRepoData::create();
|
||||
let git_repo = test_data.git_repo;
|
||||
git_repo.set_head("refs/heads/main").unwrap();
|
||||
let mut tx = test_data.repo.start_transaction("test");
|
||||
git::import_refs(tx.mut_repo(), &git_repo).unwrap();
|
||||
test_data.repo = tx.commit();
|
||||
|
||||
assert_eq!(git::export_refs(&test_data.repo, &git_repo), Ok(()));
|
||||
let mut tx = test_data.repo.start_transaction("test");
|
||||
let new_commit = testutils::create_random_commit(&test_data.settings, &test_data.repo)
|
||||
.write_to_repo(tx.mut_repo());
|
||||
tx.mut_repo().set_local_branch(
|
||||
"main".to_string(),
|
||||
RefTarget::Normal(new_commit.id().clone()),
|
||||
);
|
||||
test_data.repo = tx.commit();
|
||||
assert_eq!(git::export_refs(&test_data.repo, &git_repo), Ok(()));
|
||||
assert_eq!(
|
||||
git_repo
|
||||
.find_reference("refs/heads/main")
|
||||
.unwrap()
|
||||
.peel_to_commit()
|
||||
.unwrap()
|
||||
.id(),
|
||||
Oid::from_bytes(new_commit.id().as_bytes()).unwrap()
|
||||
);
|
||||
// It's weird that the head is still pointing to refs/heads/main, but
|
||||
// it doesn't seem that Git lets you be on an "unborn branch" while
|
||||
// also being in a "detached HEAD" state.
|
||||
assert!(!git_repo.head_detached().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_init() {
|
||||
let settings = testutils::user_settings();
|
||||
|
|
|
@ -31,6 +31,7 @@ use std::{fs, io};
|
|||
|
||||
use clap::{crate_version, App, Arg, ArgMatches, SubCommand};
|
||||
use criterion::Criterion;
|
||||
use git2::Repository;
|
||||
use itertools::Itertools;
|
||||
use jujutsu_lib::backend::{BackendError, CommitId, Timestamp, TreeValue};
|
||||
use jujutsu_lib::commit::Commit;
|
||||
|
@ -233,45 +234,19 @@ struct WorkspaceCommandHelper {
|
|||
impl WorkspaceCommandHelper {
|
||||
fn for_loaded_repo(
|
||||
ui: &Ui,
|
||||
mut workspace: Workspace,
|
||||
workspace: Workspace,
|
||||
string_args: Vec<String>,
|
||||
root_args: &ArgMatches,
|
||||
mut repo: Arc<ReadonlyRepo>,
|
||||
repo: Arc<ReadonlyRepo>,
|
||||
) -> Result<Self, CommandError> {
|
||||
let loaded_at_head = root_args.value_of("at_op").unwrap() == "@";
|
||||
let mut working_copy_shared_with_git = false;
|
||||
if let Some(git_repo) = repo.store().git_repo() {
|
||||
let maybe_git_repo = repo.store().git_repo();
|
||||
if let Some(git_repo) = &maybe_git_repo {
|
||||
working_copy_shared_with_git =
|
||||
git_repo.workdir() == Some(workspace.workspace_root().as_path());
|
||||
if working_copy_shared_with_git && loaded_at_head {
|
||||
let mut tx = repo.start_transaction("import git refs");
|
||||
git::import_refs(tx.mut_repo(), &git_repo)?;
|
||||
if tx.mut_repo().has_changes() {
|
||||
let old_git_head = repo.view().git_head();
|
||||
let new_git_head = tx.mut_repo().view().git_head();
|
||||
// If the Git HEAD has changed, abandon our old checkout and check out the new
|
||||
// Git HEAD.
|
||||
let mut new_wc_commit = None;
|
||||
if new_git_head != old_git_head && new_git_head.is_some() {
|
||||
tx.mut_repo()
|
||||
.record_abandoned_commit(repo.view().checkout().clone());
|
||||
let new_checkout =
|
||||
repo.store().get_commit(new_git_head.as_ref().unwrap())?;
|
||||
let new_checkout = tx.mut_repo().check_out(ui.settings(), &new_checkout);
|
||||
new_wc_commit = Some(new_checkout);
|
||||
tx.mut_repo()
|
||||
.create_descendant_rebaser(ui.settings())
|
||||
.rebase_all();
|
||||
}
|
||||
repo = tx.commit();
|
||||
if let Some(new_wc_commit) = new_wc_commit {
|
||||
let locked_working_copy = workspace.working_copy_mut().write_tree();
|
||||
locked_working_copy.finish(new_wc_commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self {
|
||||
let mut helper = Self {
|
||||
string_args,
|
||||
settings: ui.settings().clone(),
|
||||
workspace,
|
||||
|
@ -280,7 +255,42 @@ impl WorkspaceCommandHelper {
|
|||
working_copy_shared_with_git,
|
||||
working_copy_committed: false,
|
||||
rebase_descendants: true,
|
||||
})
|
||||
};
|
||||
if working_copy_shared_with_git && loaded_at_head {
|
||||
helper.import_git_refs_and_head(maybe_git_repo.as_ref().unwrap())?;
|
||||
}
|
||||
Ok(helper)
|
||||
}
|
||||
|
||||
fn import_git_refs_and_head(&mut self, git_repo: &Repository) -> Result<(), CommandError> {
|
||||
let mut tx = self.start_transaction("import git refs");
|
||||
git::import_refs(tx.mut_repo(), git_repo)?;
|
||||
if tx.mut_repo().has_changes() {
|
||||
let old_git_head = self.repo.view().git_head();
|
||||
let new_git_head = tx.mut_repo().view().git_head();
|
||||
// If the Git HEAD has changed, abandon our old checkout and check out the new
|
||||
// Git HEAD.
|
||||
let mut new_wc_commit = None;
|
||||
if new_git_head != old_git_head && new_git_head.is_some() {
|
||||
tx.mut_repo()
|
||||
.record_abandoned_commit(self.repo.view().checkout().clone());
|
||||
let new_checkout = self
|
||||
.repo
|
||||
.store()
|
||||
.get_commit(new_git_head.as_ref().unwrap())?;
|
||||
let new_checkout = tx.mut_repo().check_out(&self.settings, &new_checkout);
|
||||
new_wc_commit = Some(new_checkout);
|
||||
tx.mut_repo()
|
||||
.create_descendant_rebaser(&self.settings)
|
||||
.rebase_all();
|
||||
}
|
||||
self.repo = tx.commit();
|
||||
if let Some(new_wc_commit) = new_wc_commit {
|
||||
let locked_working_copy = self.workspace.working_copy_mut().write_tree();
|
||||
locked_working_copy.finish(new_wc_commit);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rebase_descendants(mut self, value: bool) -> Self {
|
||||
|
|
Loading…
Reference in a new issue