mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
debug-tree: allow looking up tree by path and id, not just revision
Sometimes only a tree has been created, so we shouldn't require a commit for `jj debug tree`.
This commit is contained in:
parent
3bbc3e5715
commit
3bb9fd412a
2 changed files with 107 additions and 4 deletions
|
@ -17,9 +17,13 @@ use std::fmt::Debug;
|
|||
use std::io::Write as _;
|
||||
|
||||
use clap::Subcommand;
|
||||
use jj_lib::backend::TreeId;
|
||||
use jj_lib::default_index::{AsCompositeIndex as _, DefaultIndexStore, DefaultReadonlyIndex};
|
||||
use jj_lib::local_working_copy::LocalWorkingCopy;
|
||||
use jj_lib::merged_tree::MergedTree;
|
||||
use jj_lib::object_id::ObjectId;
|
||||
use jj_lib::repo::Repo;
|
||||
use jj_lib::repo_path::RepoPathBuf;
|
||||
use jj_lib::working_copy::WorkingCopy;
|
||||
use jj_lib::{op_walk, revset};
|
||||
|
||||
|
@ -94,8 +98,12 @@ pub enum DebugOperationDisplay {
|
|||
/// List the recursive entries of a tree.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct DebugTreeArgs {
|
||||
#[arg(long, short = 'r', default_value = "@")]
|
||||
revision: RevisionArg,
|
||||
#[arg(long, short = 'r')]
|
||||
revision: Option<RevisionArg>,
|
||||
#[arg(long, conflicts_with = "revision")]
|
||||
id: Option<String>,
|
||||
#[arg(long, requires = "id")]
|
||||
dir: Option<String>,
|
||||
paths: Vec<String>,
|
||||
// TODO: Add an option to include trees that are ancestors of the matched paths
|
||||
}
|
||||
|
@ -293,8 +301,22 @@ fn cmd_debug_tree(
|
|||
args: &DebugTreeArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
let commit = workspace_command.resolve_single_rev(&args.revision)?;
|
||||
let tree = commit.tree()?;
|
||||
let tree = if let Some(tree_id_hex) = &args.id {
|
||||
let tree_id =
|
||||
TreeId::try_from_hex(tree_id_hex).map_err(|_| user_error("Invalid tree id"))?;
|
||||
let dir = if let Some(dir_str) = &args.dir {
|
||||
workspace_command.parse_file_path(dir_str)?
|
||||
} else {
|
||||
RepoPathBuf::root()
|
||||
};
|
||||
let store = workspace_command.repo().store();
|
||||
let tree = store.get_tree(&dir, &tree_id)?;
|
||||
MergedTree::resolved(tree)
|
||||
} else {
|
||||
let commit =
|
||||
workspace_command.resolve_single_rev(args.revision.as_deref().unwrap_or("@"))?;
|
||||
commit.tree()?
|
||||
};
|
||||
let matcher = workspace_command.matcher_from_values(&args.paths)?;
|
||||
for (path, value) in tree.entries_matching(matcher.as_ref()) {
|
||||
let ui_path = workspace_command.format_file_path(&path);
|
||||
|
|
|
@ -117,6 +117,87 @@ fn test_debug_reindex() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_tree() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
|
||||
let workspace_path = test_env.env_root().join("repo");
|
||||
let subdir = workspace_path.join("dir").join("subdir");
|
||||
std::fs::create_dir_all(&subdir).unwrap();
|
||||
std::fs::write(subdir.join("file1"), "contents 1").unwrap();
|
||||
test_env.jj_cmd_ok(&workspace_path, &["new"]);
|
||||
std::fs::write(subdir.join("file2"), "contents 2").unwrap();
|
||||
|
||||
// Defaults to showing the tree at the current commit
|
||||
let stdout = test_env.jj_cmd_success(&workspace_path, &["debug", "tree"]);
|
||||
assert_snapshot!(stdout.replace('\\',"/"), @r###"
|
||||
dir/subdir/file1: Resolved(Some(File { id: FileId("498e9b01d79cb8d31cdf0df1a663cc1fcefd9de3"), executable: false }))
|
||||
dir/subdir/file2: Resolved(Some(File { id: FileId("b2496eaffe394cd50a9db4de5787f45f09fd9722"), executable: false }))
|
||||
"###
|
||||
);
|
||||
|
||||
// Can show the tree at another commit
|
||||
let stdout = test_env.jj_cmd_success(&workspace_path, &["debug", "tree", "-r@-"]);
|
||||
assert_snapshot!(stdout.replace('\\',"/"), @r###"
|
||||
dir/subdir/file1: Resolved(Some(File { id: FileId("498e9b01d79cb8d31cdf0df1a663cc1fcefd9de3"), executable: false }))
|
||||
"###
|
||||
);
|
||||
|
||||
// Can filter by paths
|
||||
let stdout = test_env.jj_cmd_success(&workspace_path, &["debug", "tree", "dir/subdir/file2"]);
|
||||
assert_snapshot!(stdout.replace('\\',"/"), @r###"
|
||||
dir/subdir/file2: Resolved(Some(File { id: FileId("b2496eaffe394cd50a9db4de5787f45f09fd9722"), executable: false }))
|
||||
"###
|
||||
);
|
||||
|
||||
// Can a show the root tree by id
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&workspace_path,
|
||||
&[
|
||||
"debug",
|
||||
"tree",
|
||||
"--id=0958358e3f80e794f032b25ed2be96cf5825da6c",
|
||||
],
|
||||
);
|
||||
assert_snapshot!(stdout.replace('\\',"/"), @r###"
|
||||
dir/subdir/file1: Resolved(Some(File { id: FileId("498e9b01d79cb8d31cdf0df1a663cc1fcefd9de3"), executable: false }))
|
||||
dir/subdir/file2: Resolved(Some(File { id: FileId("b2496eaffe394cd50a9db4de5787f45f09fd9722"), executable: false }))
|
||||
"###
|
||||
);
|
||||
|
||||
// Can a show non-root tree by id
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&workspace_path,
|
||||
&[
|
||||
"debug",
|
||||
"tree",
|
||||
"--dir=dir",
|
||||
"--id=6ac232efa713535ae518a1a898b77e76c0478184",
|
||||
],
|
||||
);
|
||||
assert_snapshot!(stdout.replace('\\',"/"), @r###"
|
||||
dir/subdir/file1: Resolved(Some(File { id: FileId("498e9b01d79cb8d31cdf0df1a663cc1fcefd9de3"), executable: false }))
|
||||
dir/subdir/file2: Resolved(Some(File { id: FileId("b2496eaffe394cd50a9db4de5787f45f09fd9722"), executable: false }))
|
||||
"###
|
||||
);
|
||||
|
||||
// Can filter by paths when showing non-root tree (matcher applies from root)
|
||||
let stdout = test_env.jj_cmd_success(
|
||||
&workspace_path,
|
||||
&[
|
||||
"debug",
|
||||
"tree",
|
||||
"--dir=dir",
|
||||
"--id=6ac232efa713535ae518a1a898b77e76c0478184",
|
||||
"dir/subdir/file2",
|
||||
],
|
||||
);
|
||||
assert_snapshot!(stdout.replace('\\',"/"), @r###"
|
||||
dir/subdir/file2: Resolved(Some(File { id: FileId("b2496eaffe394cd50a9db4de5787f45f09fd9722"), executable: false }))
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_operation_id() {
|
||||
let test_env = TestEnvironment::default();
|
||||
|
|
Loading…
Reference in a new issue