Skip to content

Commit 755e81c

Browse files
committed
evolution: convert some functions to async
1 parent 4ee5cd4 commit 755e81c

3 files changed

Lines changed: 33 additions & 20 deletions

File tree

cli/src/commands/operation/diff.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ pub async fn show_op_diff(
177177
with_content_format: &LogContentFormat,
178178
diff_renderer: Option<&DiffRenderer<'_>>,
179179
) -> Result<(), CommandError> {
180-
let changes = compute_operation_commits_diff(current_repo, from_repo, to_repo)?;
180+
let changes = compute_operation_commits_diff(current_repo, from_repo, to_repo).await?;
181181
if !changes.is_empty() {
182182
let revset =
183183
RevsetExpression::commits(changes.keys().cloned().collect()).evaluate(current_repo)?;
@@ -528,7 +528,7 @@ impl ModifiedChange {
528528
/// Returns a map of [`ModifiedChange`]s containing the new and old commits. For
529529
/// created/rewritten commits, the map entries are indexed by new ids. For
530530
/// abandoned commits, the entries are indexed by old ids.
531-
fn compute_operation_commits_diff(
531+
async fn compute_operation_commits_diff(
532532
repo: &dyn Repo,
533533
from_repo: &ReadonlyRepo,
534534
to_repo: &ReadonlyRepo,
@@ -542,7 +542,8 @@ fn compute_operation_commits_diff(
542542
let predecessor_commits = accumulate_predecessors(
543543
slice::from_ref(to_repo.operation()),
544544
slice::from_ref(from_repo.operation()),
545-
)?;
545+
)
546+
.await?;
546547

547548
// Collect hidden commits to find abandoned/rewritten changes.
548549
let mut hidden_commits_by_change: HashMap<ChangeId, CommitId> = HashMap::new();

lib/src/evolution.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<I> WalkPredecessors<'_, I>
109109
where
110110
I: Stream<Item = OpStoreResult<Operation>> + Unpin,
111111
{
112-
fn try_next(&mut self) -> Result<Option<CommitEvolutionEntry>, WalkPredecessorsError> {
112+
async fn try_next(&mut self) -> Result<Option<CommitEvolutionEntry>, WalkPredecessorsError> {
113113
while !self.to_visit.is_empty() && self.queued.is_empty() {
114114
let Some(op) = self.op_ancestors.next().block_on().transpose()? else {
115115
// Scanned all operations, no fallback needed.
@@ -120,16 +120,16 @@ where
120120
// There may be concurrent ops, but let's simply switch to the
121121
// legacy commit traversal. Operation history should be mostly
122122
// linear.
123-
self.scan_commits()?;
123+
self.scan_commits().await?;
124124
break;
125125
}
126-
self.visit_op(&op)?;
126+
self.visit_op(&op).await?;
127127
}
128128
Ok(self.queued.pop_front())
129129
}
130130

131131
/// Looks for predecessors within the given operation.
132-
fn visit_op(&mut self, op: &Operation) -> Result<(), WalkPredecessorsError> {
132+
async fn visit_op(&mut self, op: &Operation) -> Result<(), WalkPredecessorsError> {
133133
let mut to_emit = Vec::new(); // transitive edges should be short
134134
let mut has_dup = false;
135135
let mut i = 0;
@@ -166,7 +166,7 @@ where
166166
async |&id| op.predecessors_for_commit(id).into_iter().flatten().map(Ok),
167167
|id| id, // Err(&CommitId) if graph has cycle
168168
)
169-
.block_on()
169+
.await
170170
.map_err(|id| WalkPredecessorsError::CycleDetected(id.clone()))?;
171171
for &id in &sorted_ids {
172172
if op.predecessors_for_commit(id).is_some() {
@@ -179,7 +179,7 @@ where
179179
}
180180

181181
/// Traverses predecessors from remainder commits.
182-
fn scan_commits(&mut self) -> Result<(), WalkPredecessorsError> {
182+
async fn scan_commits(&mut self) -> Result<(), WalkPredecessorsError> {
183183
let store = self.repo.store();
184184
let index = self.repo.index();
185185
let mut commit_predecessors: HashMap<CommitId, Vec<CommitId>> = HashMap::new();
@@ -222,7 +222,7 @@ where
222222
},
223223
|_| panic!("graph has cycle"),
224224
)
225-
.block_on()?;
225+
.await?;
226226
self.queued.extend(commits.into_iter().map(|commit| {
227227
let predecessors = commit_predecessors
228228
.remove(commit.id())
@@ -253,14 +253,15 @@ where
253253
}
254254
}
255255

256+
// TODO: Convert to `Stream`.
256257
impl<I> Iterator for WalkPredecessors<'_, I>
257258
where
258259
I: Stream<Item = OpStoreResult<Operation>> + Unpin,
259260
{
260261
type Item = Result<CommitEvolutionEntry, WalkPredecessorsError>;
261262

262263
fn next(&mut self) -> Option<Self::Item> {
263-
self.try_next().transpose()
264+
self.try_next().block_on().transpose()
264265
}
265266
}
266267

@@ -271,7 +272,7 @@ where
271272
/// between `old_ops` and `new_ops`. If `old_ops` and `new_ops` have ancestors
272273
/// and descendants each other, or if criss-crossed merges exist between these
273274
/// operations, the returned mapping would be lossy.
274-
pub fn accumulate_predecessors(
275+
pub async fn accumulate_predecessors(
275276
new_ops: &[Operation],
276277
old_ops: &[Operation],
277278
) -> Result<BTreeMap<CommitId, Vec<CommitId>>, WalkPredecessorsError> {
@@ -287,36 +288,38 @@ pub fn accumulate_predecessors(
287288
return Ok(BTreeMap::new());
288289
};
289290
return resolve_transitive_edges(map, map.keys())
291+
.await
290292
.map_err(|id| WalkPredecessorsError::CycleDetected(id.clone()));
291293
}
292294

293295
// Follow reverse edges from the common ancestor to old_ops. Here we use
294296
// BTreeMap to stabilize order of the reversed edges.
295297
let mut accumulated = BTreeMap::new();
296298
let reverse_ops = op_walk::walk_ancestors_range(old_ops, new_ops);
297-
if !try_collect_predecessors_into(&mut accumulated, reverse_ops)? {
299+
if !try_collect_predecessors_into(&mut accumulated, reverse_ops).await? {
298300
return Ok(BTreeMap::new());
299301
}
300302
let mut accumulated = reverse_edges(accumulated);
301303
// Follow forward edges from new_ops to the common ancestor.
302304
let forward_ops = op_walk::walk_ancestors_range(new_ops, old_ops);
303-
if !try_collect_predecessors_into(&mut accumulated, forward_ops)? {
305+
if !try_collect_predecessors_into(&mut accumulated, forward_ops).await? {
304306
return Ok(BTreeMap::new());
305307
}
306308
let new_commit_ids = new_ops
307309
.iter()
308310
.filter_map(|op| op.store_operation().commit_predecessors.as_ref())
309311
.flat_map(|map| map.keys());
310312
resolve_transitive_edges(&accumulated, new_commit_ids)
313+
.await
311314
.map_err(|id| WalkPredecessorsError::CycleDetected(id.clone()))
312315
}
313316

314-
fn try_collect_predecessors_into(
317+
async fn try_collect_predecessors_into(
315318
collected: &mut BTreeMap<CommitId, Vec<CommitId>>,
316319
ops: impl Stream<Item = OpStoreResult<Operation>>,
317320
) -> OpStoreResult<bool> {
318321
let mut ops = pin!(ops);
319-
while let Some(op) = ops.next().block_on() {
322+
while let Some(op) = ops.next().await {
320323
let op = op?;
321324
let Some(map) = &op.store_operation().commit_predecessors else {
322325
return Ok(false);
@@ -330,7 +333,7 @@ fn try_collect_predecessors_into(
330333
/// Resolves transitive edges in `graph` starting from the `start` nodes,
331334
/// returns new DAG. The returned DAG only includes edges reachable from the
332335
/// `start` nodes.
333-
fn resolve_transitive_edges<'a: 'b, 'b>(
336+
async fn resolve_transitive_edges<'a: 'b, 'b>(
334337
graph: &'a BTreeMap<CommitId, Vec<CommitId>>,
335338
start: impl IntoIterator<Item = &'b CommitId>,
336339
) -> Result<BTreeMap<CommitId, Vec<CommitId>>, &'b CommitId> {
@@ -341,7 +344,7 @@ fn resolve_transitive_edges<'a: 'b, 'b>(
341344
async |&id| graph.get(id).into_iter().flatten().map(Ok),
342345
|id| id, // Err(&CommitId) if graph has cycle
343346
)
344-
.block_on()?;
347+
.await?;
345348
for cur_id in sorted_ids {
346349
let Some(neighbors) = graph.get(cur_id) else {
347350
continue;

lib/tests/test_evolution_predecessors.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,16 +541,21 @@ fn test_accumulate_predecessors() {
541541
let repo_d = tx.commit("d").block_on().unwrap();
542542

543543
// Empty old/new ops
544-
let predecessors = accumulate_predecessors(&[], slice::from_ref(repo_c.operation())).unwrap();
544+
let predecessors = accumulate_predecessors(&[], slice::from_ref(repo_c.operation()))
545+
.block_on()
546+
.unwrap();
545547
assert!(predecessors.is_empty());
546-
let predecessors = accumulate_predecessors(slice::from_ref(repo_c.operation()), &[]).unwrap();
548+
let predecessors = accumulate_predecessors(slice::from_ref(repo_c.operation()), &[])
549+
.block_on()
550+
.unwrap();
547551
assert!(predecessors.is_empty());
548552

549553
// Empty range
550554
let predecessors = accumulate_predecessors(
551555
slice::from_ref(repo_c.operation()),
552556
slice::from_ref(repo_c.operation()),
553557
)
558+
.block_on()
554559
.unwrap();
555560
assert!(predecessors.is_empty());
556561

@@ -559,6 +564,7 @@ fn test_accumulate_predecessors() {
559564
slice::from_ref(repo_c.operation()),
560565
slice::from_ref(repo_b.operation()),
561566
)
567+
.block_on()
562568
.unwrap();
563569
assert_eq!(
564570
predecessors,
@@ -574,6 +580,7 @@ fn test_accumulate_predecessors() {
574580
slice::from_ref(repo_c.operation()),
575581
slice::from_ref(repo_a.operation()),
576582
)
583+
.block_on()
577584
.unwrap();
578585
assert_eq!(
579586
predecessors,
@@ -591,6 +598,7 @@ fn test_accumulate_predecessors() {
591598
slice::from_ref(repo_a.operation()),
592599
slice::from_ref(repo_c.operation()),
593600
)
601+
.block_on()
594602
.unwrap();
595603
assert_eq!(
596604
predecessors,
@@ -609,6 +617,7 @@ fn test_accumulate_predecessors() {
609617
slice::from_ref(repo_d.operation()),
610618
slice::from_ref(repo_c.operation()),
611619
)
620+
.block_on()
612621
.unwrap();
613622
assert_eq!(
614623
predecessors,

0 commit comments

Comments
 (0)