mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 02:04:19 +00:00
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();
|
test_data.repo = tx.commit();
|
||||||
assert_eq!(git::export_refs(&test_data.repo, &git_repo), Ok(()));
|
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());
|
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]
|
#[test]
|
||||||
fn test_init() {
|
fn test_init() {
|
||||||
let settings = testutils::user_settings();
|
let settings = testutils::user_settings();
|
||||||
|
|
|
@ -31,6 +31,7 @@ use std::{fs, io};
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg, ArgMatches, SubCommand};
|
use clap::{crate_version, App, Arg, ArgMatches, SubCommand};
|
||||||
use criterion::Criterion;
|
use criterion::Criterion;
|
||||||
|
use git2::Repository;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use jujutsu_lib::backend::{BackendError, CommitId, Timestamp, TreeValue};
|
use jujutsu_lib::backend::{BackendError, CommitId, Timestamp, TreeValue};
|
||||||
use jujutsu_lib::commit::Commit;
|
use jujutsu_lib::commit::Commit;
|
||||||
|
@ -233,45 +234,19 @@ struct WorkspaceCommandHelper {
|
||||||
impl WorkspaceCommandHelper {
|
impl WorkspaceCommandHelper {
|
||||||
fn for_loaded_repo(
|
fn for_loaded_repo(
|
||||||
ui: &Ui,
|
ui: &Ui,
|
||||||
mut workspace: Workspace,
|
workspace: Workspace,
|
||||||
string_args: Vec<String>,
|
string_args: Vec<String>,
|
||||||
root_args: &ArgMatches,
|
root_args: &ArgMatches,
|
||||||
mut repo: Arc<ReadonlyRepo>,
|
repo: Arc<ReadonlyRepo>,
|
||||||
) -> Result<Self, CommandError> {
|
) -> Result<Self, CommandError> {
|
||||||
let loaded_at_head = root_args.value_of("at_op").unwrap() == "@";
|
let loaded_at_head = root_args.value_of("at_op").unwrap() == "@";
|
||||||
let mut working_copy_shared_with_git = false;
|
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 =
|
working_copy_shared_with_git =
|
||||||
git_repo.workdir() == Some(workspace.workspace_root().as_path());
|
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,
|
string_args,
|
||||||
settings: ui.settings().clone(),
|
settings: ui.settings().clone(),
|
||||||
workspace,
|
workspace,
|
||||||
|
@ -280,7 +255,42 @@ impl WorkspaceCommandHelper {
|
||||||
working_copy_shared_with_git,
|
working_copy_shared_with_git,
|
||||||
working_copy_committed: false,
|
working_copy_committed: false,
|
||||||
rebase_descendants: true,
|
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 {
|
fn rebase_descendants(mut self, value: bool) -> Self {
|
||||||
|
|
Loading…
Reference in a new issue