From 94fc32ab471960b461f7f802e87358dc6d6b3546 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sun, 31 Dec 2023 10:21:47 +0900 Subject: [PATCH] op_walk: extract walk_ancestors() to new module I'm going to extract fake "opset" resolution functions there, and I think walk_ancestors() belongs to the same category. --- cli/src/commands/operation.rs | 4 +-- lib/src/lib.rs | 1 + lib/src/op_walk.rs | 54 +++++++++++++++++++++++++++++++++++ lib/src/operation.rs | 35 +---------------------- 4 files changed, 58 insertions(+), 36 deletions(-) create mode 100644 lib/src/op_walk.rs diff --git a/cli/src/commands/operation.rs b/cli/src/commands/operation.rs index cf010523f..1cf951dd6 100644 --- a/cli/src/commands/operation.rs +++ b/cli/src/commands/operation.rs @@ -14,7 +14,7 @@ use clap::Subcommand; use jj_lib::backend::ObjectId; -use jj_lib::operation; +use jj_lib::op_walk; use jj_lib::repo::Repo; use crate::cli_util::{user_error, CommandError, CommandHelper, LogContentFormat}; @@ -125,7 +125,7 @@ fn cmd_op_log( ui.request_pager(); let mut formatter = ui.stdout_formatter(); let formatter = formatter.as_mut(); - let iter = operation::walk_ancestors(&head_op).take(args.limit.unwrap_or(usize::MAX)); + let iter = op_walk::walk_ancestors(&head_op).take(args.limit.unwrap_or(usize::MAX)); if !args.no_graph { let mut graph = get_graphlog(command.settings(), formatter.raw()); let default_node_symbol = graph.default_node_symbol().to_owned(); diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 4b5dd5e38..193acde14 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -49,6 +49,7 @@ pub mod merge; pub mod merged_tree; pub mod op_heads_store; pub mod op_store; +pub mod op_walk; pub mod operation; #[allow(missing_docs)] pub mod protos; diff --git a/lib/src/op_walk.rs b/lib/src/op_walk.rs new file mode 100644 index 000000000..1d10ece75 --- /dev/null +++ b/lib/src/op_walk.rs @@ -0,0 +1,54 @@ +// Copyright 2020-2023 The Jujutsu Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Utility for operation id resolution and traversal. + +use std::cmp::Ordering; + +use itertools::Itertools as _; + +use crate::dag_walk; +use crate::op_store::OpStoreResult; +use crate::operation::Operation; + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +struct OperationByEndTime(Operation); + +impl Ord for OperationByEndTime { + fn cmp(&self, other: &Self) -> Ordering { + let self_end_time = &self.0.store_operation().metadata.end_time; + let other_end_time = &other.0.store_operation().metadata.end_time; + self_end_time + .cmp(other_end_time) + .then_with(|| self.0.cmp(&other.0)) // to comply with Eq + } +} + +impl PartialOrd for OperationByEndTime { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +/// Walks `head_op` and its ancestors in reverse topological order. +pub fn walk_ancestors(head_op: &Operation) -> impl Iterator> { + // Lazily load operations based on timestamp-based heuristic. This works so long + // as the operation history is mostly linear. + dag_walk::topo_order_reverse_lazy_ok( + [Ok(OperationByEndTime(head_op.clone()))], + |OperationByEndTime(op)| op.id().clone(), + |OperationByEndTime(op)| op.parents().map_ok(OperationByEndTime).collect_vec(), + ) + .map_ok(|OperationByEndTime(op)| op) +} diff --git a/lib/src/operation.rs b/lib/src/operation.rs index 8c1e5f4a7..510db0b97 100644 --- a/lib/src/operation.rs +++ b/lib/src/operation.rs @@ -20,11 +20,9 @@ use std::fmt::{Debug, Error, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use itertools::Itertools as _; - use crate::backend::CommitId; +use crate::op_store; use crate::op_store::{OpStore, OpStoreResult, OperationId, ViewId}; -use crate::{dag_walk, op_store}; #[derive(Clone)] pub struct Operation { @@ -165,34 +163,3 @@ impl View { &self.data.head_ids } } - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -struct OperationByEndTime(Operation); - -impl Ord for OperationByEndTime { - fn cmp(&self, other: &Self) -> Ordering { - let self_end_time = &self.0.store_operation().metadata.end_time; - let other_end_time = &other.0.store_operation().metadata.end_time; - self_end_time - .cmp(other_end_time) - .then_with(|| self.0.cmp(&other.0)) // to comply with Eq - } -} - -impl PartialOrd for OperationByEndTime { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -/// Walks `head_op` and its ancestors in reverse topological order. -pub fn walk_ancestors(head_op: &Operation) -> impl Iterator> { - // Lazily load operations based on timestamp-based heuristic. This works so long - // as the operation history is mostly linear. - dag_walk::topo_order_reverse_lazy_ok( - [Ok(OperationByEndTime(head_op.clone()))], - |OperationByEndTime(op)| op.id().clone(), - |OperationByEndTime(op)| op.parents().map_ok(OperationByEndTime).collect_vec(), - ) - .map_ok(|OperationByEndTime(op)| op) -}