feat: add local diff review workflow
This commit is contained in:
@@ -1058,6 +1058,7 @@ struct PreparedComparison {
|
||||
id: u64,
|
||||
selected: [Revision; 2],
|
||||
selected_ids: [Option<String>; 2],
|
||||
revisions: [String; 2],
|
||||
mode: ComparisonMode,
|
||||
left: Snapshot,
|
||||
right: Snapshot,
|
||||
@@ -2284,6 +2285,34 @@ impl Repository {
|
||||
}
|
||||
Ok(snapshot)
|
||||
}
|
||||
fn snapshot_revision(
|
||||
&mut self,
|
||||
target: &RevisionTarget,
|
||||
snapshot: &Snapshot,
|
||||
) -> Result<String, String> {
|
||||
if let RevisionTarget::Commit(id) = target {
|
||||
return Ok(id.clone());
|
||||
}
|
||||
self.ensure_private()?;
|
||||
let store = &self.private.as_ref().unwrap().1;
|
||||
let mut input = b"vamp-working-snapshot-v1\0".to_vec();
|
||||
for (path, file) in snapshot {
|
||||
self.check_cancelled()?;
|
||||
for field in [
|
||||
path.as_os_str().as_encoded_bytes(),
|
||||
file.mode.as_bytes(),
|
||||
file.bytes.as_slice(),
|
||||
file.notice.as_deref().unwrap_or("").as_bytes(),
|
||||
] {
|
||||
input.extend_from_slice(&(field.len() as u64).to_be_bytes());
|
||||
input.extend_from_slice(field);
|
||||
}
|
||||
}
|
||||
let mut command = git_command(store);
|
||||
command.args(["hash-object", "--no-filters", "--stdin"]);
|
||||
let id = text(checked(run(command, input, &self.cancelled)?)?)?;
|
||||
Ok(format!("working:{}", id.trim()))
|
||||
}
|
||||
fn snapshot(&mut self, target: &RevisionTarget) -> Result<Snapshot, String> {
|
||||
if *target == RevisionTarget::Working {
|
||||
self.working_snapshot(&[])
|
||||
@@ -2454,10 +2483,17 @@ impl Repository {
|
||||
let (store, id) = pinned.as_ref().unwrap();
|
||||
self.commit_snapshot(store, id)?
|
||||
};
|
||||
let before_revision = self.snapshot_revision(before_target, &left)?;
|
||||
let after_revision = if same {
|
||||
before_revision.clone()
|
||||
} else {
|
||||
self.snapshot_revision(after_target, &right)?
|
||||
};
|
||||
let mut prepared = PreparedComparison {
|
||||
id: comparison_id,
|
||||
selected: [before.clone(), after.clone()],
|
||||
selected_ids,
|
||||
revisions: [before_revision, after_revision],
|
||||
mode,
|
||||
left,
|
||||
right,
|
||||
@@ -2574,9 +2610,11 @@ impl Repository {
|
||||
return Ok(None);
|
||||
}
|
||||
let right = self.working_snapshot(buffers)?;
|
||||
let revision = self.snapshot_revision(&RevisionTarget::Working, &right)?;
|
||||
let mut prepared = self.comparison.take().unwrap();
|
||||
let previous_right = std::mem::replace(&mut prepared.right, right);
|
||||
let previous_files = std::mem::take(&mut prepared.files);
|
||||
let previous_revision = std::mem::replace(&mut prepared.revisions[1], revision);
|
||||
let result = self
|
||||
.build_comparison(&mut prepared, false)
|
||||
.and_then(|comparison| {
|
||||
@@ -2598,6 +2636,7 @@ impl Repository {
|
||||
} else {
|
||||
prepared.right = previous_right;
|
||||
prepared.files = previous_files;
|
||||
prepared.revisions[1] = previous_revision;
|
||||
}
|
||||
self.comparison = Some(prepared);
|
||||
result.map(|comparison| Some(CheckoutRefresh::Checkout(comparison)))
|
||||
@@ -2628,11 +2667,14 @@ impl Repository {
|
||||
let advance_working = working_after
|
||||
&& follow_working
|
||||
&& self.working_advanced(prepared.working_anchor.as_deref(), anchor.as_deref())?;
|
||||
let mut revisions = prepared.revisions.clone();
|
||||
let (left, before_label) = if branch {
|
||||
let base = self.merge_base(ids[0].as_deref().unwrap(), ids[1].as_deref().unwrap())?;
|
||||
let label = format!("merge base of {label} and {after_label} · {base}");
|
||||
revisions[0] = base.clone();
|
||||
(Some(self.snapshot(&RevisionTarget::Commit(base))?), label)
|
||||
} else if changed_before {
|
||||
revisions[0] = ids[0].clone().unwrap();
|
||||
(
|
||||
Some(self.snapshot(&RevisionTarget::Commit(ids[0].clone().unwrap()))?),
|
||||
label,
|
||||
@@ -2647,6 +2689,13 @@ impl Repository {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(right) = &right {
|
||||
revisions[1] = if advance_working {
|
||||
self.snapshot_revision(&RevisionTarget::Working, right)?
|
||||
} else {
|
||||
ids[1].clone().unwrap()
|
||||
};
|
||||
}
|
||||
let pinned_checkout = ids[1]
|
||||
.as_deref()
|
||||
.map(|id| self.pinned_checkout(id))
|
||||
@@ -2658,6 +2707,7 @@ impl Repository {
|
||||
let previous_files = std::mem::take(&mut prepared.files);
|
||||
let previous_before = std::mem::replace(&mut prepared.before, before_label);
|
||||
let previous_editable = prepared.editable_after;
|
||||
let previous_revisions = std::mem::replace(&mut prepared.revisions, revisions);
|
||||
prepared.editable_after =
|
||||
working_after || (pinned_checkout.is_some() && pinned_checkout == anchor);
|
||||
let result = self
|
||||
@@ -2693,6 +2743,7 @@ impl Repository {
|
||||
prepared.files = previous_files;
|
||||
prepared.before = previous_before;
|
||||
prepared.editable_after = previous_editable;
|
||||
prepared.revisions = previous_revisions;
|
||||
}
|
||||
self.comparison = Some(prepared);
|
||||
result
|
||||
@@ -2810,6 +2861,7 @@ impl Repository {
|
||||
BTreeSet::new()
|
||||
};
|
||||
Comparison {
|
||||
revisions: prepared.revisions.clone(),
|
||||
before: prepared.before.clone(),
|
||||
after: prepared.after.clone(),
|
||||
files,
|
||||
|
||||
Reference in New Issue
Block a user