mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-04 10:51:37 +00:00
cli: extract a function for checking for stale working copy
Similar to the previous commit, the checking for stale working copy is a big part of `commit_working_copy()` and it's logically quite separated from the rest, so let's extract it to a function.
This commit is contained in:
parent
2282047d3b
commit
f7d0c196c1
1 changed files with 72 additions and 63 deletions
135
src/cli_util.rs
135
src/cli_util.rs
|
@ -678,70 +678,8 @@ impl WorkspaceCommandHelper {
|
||||||
};
|
};
|
||||||
let base_ignores = self.base_ignores();
|
let base_ignores = self.base_ignores();
|
||||||
let mut locked_wc = self.workspace.working_copy_mut().start_mutation();
|
let mut locked_wc = self.workspace.working_copy_mut().start_mutation();
|
||||||
// Check if the working copy commit matches the repo's view. It's fine if it
|
|
||||||
// doesn't, but we'll need to reload the repo so the new commit is
|
|
||||||
// in the index and view, and so we don't cause unnecessary
|
|
||||||
// divergence.
|
|
||||||
let wc_commit = repo.store().get_commit(&wc_commit_id)?;
|
let wc_commit = repo.store().get_commit(&wc_commit_id)?;
|
||||||
let wc_tree_id = locked_wc.old_tree_id().clone();
|
self.repo = check_stale_working_copy(ui, &mut locked_wc, &wc_commit, repo)?;
|
||||||
if *wc_commit.tree_id() != wc_tree_id {
|
|
||||||
let wc_operation_data = self
|
|
||||||
.repo
|
|
||||||
.op_store()
|
|
||||||
.read_operation(locked_wc.old_operation_id())
|
|
||||||
.unwrap();
|
|
||||||
let wc_operation = Operation::new(
|
|
||||||
repo.op_store().clone(),
|
|
||||||
locked_wc.old_operation_id().clone(),
|
|
||||||
wc_operation_data,
|
|
||||||
);
|
|
||||||
let repo_operation = repo.operation();
|
|
||||||
let maybe_ancestor_op = dag_walk::closest_common_node(
|
|
||||||
[wc_operation.clone()],
|
|
||||||
[repo_operation.clone()],
|
|
||||||
&|op: &Operation| op.parents(),
|
|
||||||
&|op: &Operation| op.id().clone(),
|
|
||||||
);
|
|
||||||
if let Some(ancestor_op) = maybe_ancestor_op {
|
|
||||||
if ancestor_op.id() == repo_operation.id() {
|
|
||||||
// The working copy was updated since we loaded the repo. We reload the repo
|
|
||||||
// at the working copy's operation.
|
|
||||||
self.repo = repo.reload_at(&wc_operation);
|
|
||||||
} else if ancestor_op.id() == wc_operation.id() {
|
|
||||||
// The working copy was not updated when some repo operation committed,
|
|
||||||
// meaning that it's stale compared to the repo view. We update the working
|
|
||||||
// copy to what the view says.
|
|
||||||
writeln!(
|
|
||||||
ui,
|
|
||||||
"The working copy is stale (not updated since operation {}), now updating \
|
|
||||||
to operation {}",
|
|
||||||
short_operation_hash(wc_operation.id()),
|
|
||||||
short_operation_hash(repo_operation.id()),
|
|
||||||
)?;
|
|
||||||
locked_wc.check_out(&wc_commit.tree()).map_err(|err| {
|
|
||||||
CommandError::InternalError(format!(
|
|
||||||
"Failed to check out commit {}: {}",
|
|
||||||
wc_commit.id().hex(),
|
|
||||||
err
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
} else {
|
|
||||||
return Err(CommandError::InternalError(format!(
|
|
||||||
"The repo was loaded at operation {}, which seems to be a sibling of the \
|
|
||||||
working copy's operation {}",
|
|
||||||
short_operation_hash(repo_operation.id()),
|
|
||||||
short_operation_hash(wc_operation.id())
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(CommandError::InternalError(format!(
|
|
||||||
"The repo was loaded at operation {}, which seems unrelated to the working \
|
|
||||||
copy's operation {}",
|
|
||||||
short_operation_hash(repo_operation.id()),
|
|
||||||
short_operation_hash(wc_operation.id())
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let new_tree_id = locked_wc.snapshot(base_ignores)?;
|
let new_tree_id = locked_wc.snapshot(base_ignores)?;
|
||||||
if new_tree_id != *wc_commit.tree_id() {
|
if new_tree_id != *wc_commit.tree_id() {
|
||||||
let mut tx = self
|
let mut tx = self
|
||||||
|
@ -915,6 +853,77 @@ impl WorkspaceCommandHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_stale_working_copy(
|
||||||
|
ui: &mut Ui,
|
||||||
|
locked_wc: &mut LockedWorkingCopy,
|
||||||
|
wc_commit: &Commit,
|
||||||
|
mut repo: Arc<ReadonlyRepo>,
|
||||||
|
) -> Result<Arc<ReadonlyRepo>, CommandError> {
|
||||||
|
// Check if the working copy commit matches the repo's view. It's fine if it
|
||||||
|
// doesn't, but we'll need to reload the repo so the new commit is
|
||||||
|
// in the index and view, and so we don't cause unnecessary
|
||||||
|
// divergence.
|
||||||
|
let wc_tree_id = locked_wc.old_tree_id().clone();
|
||||||
|
if *wc_commit.tree_id() != wc_tree_id {
|
||||||
|
let wc_operation_data = repo
|
||||||
|
.op_store()
|
||||||
|
.read_operation(locked_wc.old_operation_id())
|
||||||
|
.unwrap();
|
||||||
|
let wc_operation = Operation::new(
|
||||||
|
repo.op_store().clone(),
|
||||||
|
locked_wc.old_operation_id().clone(),
|
||||||
|
wc_operation_data,
|
||||||
|
);
|
||||||
|
let repo_operation = repo.operation();
|
||||||
|
let maybe_ancestor_op = dag_walk::closest_common_node(
|
||||||
|
[wc_operation.clone()],
|
||||||
|
[repo_operation.clone()],
|
||||||
|
&|op: &Operation| op.parents(),
|
||||||
|
&|op: &Operation| op.id().clone(),
|
||||||
|
);
|
||||||
|
if let Some(ancestor_op) = maybe_ancestor_op {
|
||||||
|
if ancestor_op.id() == repo_operation.id() {
|
||||||
|
// The working copy was updated since we loaded the repo. We reload the repo
|
||||||
|
// at the working copy's operation.
|
||||||
|
repo = repo.reload_at(&wc_operation);
|
||||||
|
} else if ancestor_op.id() == wc_operation.id() {
|
||||||
|
// The working copy was not updated when some repo operation committed,
|
||||||
|
// meaning that it's stale compared to the repo view. We update the working
|
||||||
|
// copy to what the view says.
|
||||||
|
writeln!(
|
||||||
|
ui,
|
||||||
|
"The working copy is stale (not updated since operation {}), now updating to \
|
||||||
|
operation {}",
|
||||||
|
short_operation_hash(wc_operation.id()),
|
||||||
|
short_operation_hash(repo_operation.id()),
|
||||||
|
)?;
|
||||||
|
locked_wc.check_out(&wc_commit.tree()).map_err(|err| {
|
||||||
|
CommandError::InternalError(format!(
|
||||||
|
"Failed to check out commit {}: {}",
|
||||||
|
wc_commit.id().hex(),
|
||||||
|
err
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
} else {
|
||||||
|
return Err(CommandError::InternalError(format!(
|
||||||
|
"The repo was loaded at operation {}, which seems to be a sibling of the \
|
||||||
|
working copy's operation {}",
|
||||||
|
short_operation_hash(repo_operation.id()),
|
||||||
|
short_operation_hash(wc_operation.id())
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(CommandError::InternalError(format!(
|
||||||
|
"The repo was loaded at operation {}, which seems unrelated to the working copy's \
|
||||||
|
operation {}",
|
||||||
|
short_operation_hash(repo_operation.id()),
|
||||||
|
short_operation_hash(wc_operation.id())
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(repo)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_checkout_stats(ui: &mut Ui, stats: CheckoutStats) -> Result<(), std::io::Error> {
|
pub fn print_checkout_stats(ui: &mut Ui, stats: CheckoutStats) -> Result<(), std::io::Error> {
|
||||||
if stats.added_files > 0 || stats.updated_files > 0 || stats.removed_files > 0 {
|
if stats.added_files > 0 || stats.updated_files > 0 || stats.removed_files > 0 {
|
||||||
writeln!(
|
writeln!(
|
||||||
|
|
Loading…
Reference in a new issue