diff --git a/lib/src/tree.rs b/lib/src/tree.rs index 0a60295db..8cd66a54a 100644 --- a/lib/src/tree.rs +++ b/lib/src/tree.rs @@ -272,6 +272,14 @@ impl Diff { Diff::Removed(left) => (Some(left), None), } } + + pub fn into_options(self) -> (Option, Option) { + match self { + Diff::Modified(left, right) => (Some(left), Some(right)), + Diff::Added(right) => (None, Some(right)), + Diff::Removed(left) => (Some(left), None), + } + } } struct TreeEntryDiffIterator<'trees, 'matcher> { diff --git a/src/commands.rs b/src/commands.rs index 85d499386..1233c1082 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -39,7 +39,7 @@ use jujutsu_lib::evolution::{ use jujutsu_lib::files::DiffLine; use jujutsu_lib::git::GitFetchError; use jujutsu_lib::index::HexPrefix; -use jujutsu_lib::matchers::EverythingMatcher; +use jujutsu_lib::matchers::{EverythingMatcher, FilesMatcher, Matcher}; use jujutsu_lib::op_heads_store::OpHeadsStore; use jujutsu_lib::op_store::{OpStore, OpStoreError, OperationId}; use jujutsu_lib::operation::Operation; @@ -488,6 +488,21 @@ fn resolve_single_op_from_store( } } +fn matcher_from_values(values: Option) -> Box { + if let Some(values) = values { + // TODO: Interpret path relative to cwd (not repo root) + // TODO: Accept backslash separator on Windows + // TODO: Add support for matching directories (and probably globs and other + // formats) + let paths = values + .map(|path| RepoPath::from_internal_string(path)) + .collect(); + Box::new(FilesMatcher::new(paths)) + } else { + Box::new(EverythingMatcher) + } +} + fn update_working_copy( ui: &mut Ui, repo: &Arc, @@ -1794,11 +1809,10 @@ fn cmd_restore( tree_id = crate::diff_edit::edit_diff(ui, &from_commit.tree(), &to_commit.tree(), &instructions)?; } else if sub_matches.is_present("paths") { - let paths = sub_matches.values_of("paths").unwrap(); + let matcher = matcher_from_values(sub_matches.values_of("paths")); let mut tree_builder = repo.store().tree_builder(to_commit.tree().id().clone()); - for path in paths { - let repo_path = RepoPath::from_internal_string(path); - match from_commit.tree().path_value(&repo_path) { + for (repo_path, diff) in from_commit.tree().diff(&to_commit.tree(), matcher.as_ref()) { + match diff.into_options().0 { Some(value) => { tree_builder.set(repo_path, value); }