From d5b0aa20cb3fd99a3a241f7664d9e6bbdf7a1e8f Mon Sep 17 00:00:00 2001 From: JDSeiler Date: Sat, 21 Dec 2024 13:02:31 -0500 Subject: [PATCH] evolog: Implement --reversed flag Adds some additional helper functions for converting between jj_lib's GraphEdge and the graphlog's Edge type. --- CHANGELOG.md | 2 + cli/src/commands/evolog.rs | 48 +++++++++++++++++++---- cli/src/graphlog.rs | 24 ++++++++++++ cli/tests/cli-reference@.md.snap | 1 + cli/tests/test_evolog_command.rs | 67 ++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77c9ad9a64..69963939a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New features +* `jj evolog` now accepts `--reversed`. + ### Fixed bugs ## [0.25.0] - 2025-01-01 diff --git a/cli/src/commands/evolog.rs b/cli/src/commands/evolog.rs index 985a566ab2..e555f8a3ed 100644 --- a/cli/src/commands/evolog.rs +++ b/cli/src/commands/evolog.rs @@ -12,10 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::convert::Infallible; + use clap_complete::ArgValueCandidates; use itertools::Itertools; +use jj_lib::backend::BackendError; +use jj_lib::backend::CommitId; use jj_lib::commit::Commit; use jj_lib::dag_walk::topo_order_reverse_ok; +use jj_lib::graph::reverse_graph; +use jj_lib::graph::GraphEdge; +use jj_lib::graph::GraphNode; use jj_lib::matchers::EverythingMatcher; use tracing::instrument; @@ -28,6 +35,7 @@ use crate::command_error::CommandError; use crate::commit_templater::CommitTemplateLanguage; use crate::complete; use crate::diff_util::DiffFormatArgs; +use crate::graphlog::convert_edge_type; use crate::graphlog::get_graphlog; use crate::graphlog::Edge; use crate::graphlog::GraphStyle; @@ -57,6 +65,9 @@ pub(crate) struct EvologArgs { value_name = "LIMIT" )] deprecated_limit: Option, + /// Show revisions in the opposite order (older revisions first) + #[arg(long)] + reversed: bool, /// Don't show the graph, show a flat list of revisions #[arg(long)] no_graph: bool, @@ -151,14 +162,31 @@ pub(crate) fn cmd_evolog( if !args.no_graph { let mut raw_output = formatter.raw()?; let mut graph = get_graphlog(graph_style, raw_output.as_mut()); - for commit in commits { - let edges = commit - .predecessor_ids() - .iter() - .map(|id| Edge::Direct(id.clone())) - .collect_vec(); + + let commit_dag: Vec> = commits + .into_iter() + .map(|c| -> Result<_, BackendError> { + let edges = c.predecessors().map_ok(GraphEdge::direct).try_collect()?; + Ok((c, edges)) + }) + .try_collect()?; + + let iter_nodes = if args.reversed { + reverse_graph(commit_dag.into_iter().map(Result::<_, Infallible>::Ok)).unwrap() + } else { + commit_dag + }; + + for node in iter_nodes { + let (commit, edges) = node; + // Slightly different edge type used for display. + let graphlog_edges: Vec> = edges + .into_iter() + .map(|e| convert_edge_type(e).map(|e| e.id().clone())) + .collect(); let mut buffer = vec![]; - let within_graph = with_content_format.sub_width(graph.width(commit.id(), &edges)); + let within_graph = + with_content_format.sub_width(graph.width(commit.id(), &graphlog_edges)); within_graph.write(ui.new_formatter(&mut buffer).as_mut(), |formatter| { template.format(&commit, formatter) })?; @@ -180,12 +208,16 @@ pub(crate) fn cmd_evolog( let node_symbol = format_template(ui, &Some(commit.clone()), &node_template); graph.add_node( commit.id(), - &edges, + &graphlog_edges, &node_symbol, &String::from_utf8_lossy(&buffer), )?; } } else { + if args.reversed { + commits.reverse(); + } + for commit in commits { with_content_format .write(formatter, |formatter| template.format(&commit, formatter))?; diff --git a/cli/src/graphlog.rs b/cli/src/graphlog.rs index de168e43dc..bdfc636681 100644 --- a/cli/src/graphlog.rs +++ b/cli/src/graphlog.rs @@ -18,6 +18,8 @@ use std::io::Write; use itertools::Itertools; use jj_lib::config::ConfigGetError; +use jj_lib::graph::GraphEdge; +use jj_lib::graph::GraphEdgeType; use jj_lib::settings::UserSettings; use renderdag::Ancestor; use renderdag::GraphRowRenderer; @@ -31,6 +33,28 @@ pub enum Edge { Missing, } +impl Edge { + pub fn map(self, f: impl FnOnce(T) -> U) -> Edge { + match self { + Edge::Direct(inner) => Edge::Direct(f(inner)), + Edge::Indirect(inner) => Edge::Indirect(f(inner)), + Edge::Missing => Edge::Missing, + } + } +} + +/// Used to convert a jj_lib GraphEdge into a graphlog Edge. +pub fn convert_edge_type(e: GraphEdge) -> Edge { + // TODO: Is it possible for the ClI to use the GraphEdge type directly? + // These two types seem to correspond exactly, only differing in minor + // implementation details. + match e.edge_type { + GraphEdgeType::Missing => Edge::Missing, + GraphEdgeType::Direct => Edge::Direct(e.target), + GraphEdgeType::Indirect => Edge::Indirect(e.target), + } +} + pub trait GraphLog { fn add_node( &mut self, diff --git a/cli/tests/cli-reference@.md.snap b/cli/tests/cli-reference@.md.snap index 49fe4c2156..99b7b571de 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -797,6 +797,7 @@ Lists the previous commits which a change has pointed to. The current commit of Default value: `@` * `-n`, `--limit ` — Limit number of revisions to show +* `--reversed` — Show revisions in the opposite order (older revisions first) * `--no-graph` — Don't show the graph, show a flat list of revisions * `-T`, `--template