Skip to content

Commit 6ec7119

Browse files
Implement :lookup filter
1 parent 291f346 commit 6ec7119

File tree

4 files changed

+192
-0
lines changed

4 files changed

+192
-0
lines changed

josh-core/src/filter/mod.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ enum Op {
321321
Prefix(std::path::PathBuf),
322322
Subdir(std::path::PathBuf),
323323
Workspace(std::path::PathBuf),
324+
Lookup(std::path::PathBuf),
325+
Lookup2(git2::Oid),
324326
Stored(std::path::PathBuf),
325327

326328
Pattern(String),
@@ -656,6 +658,12 @@ fn spec2(op: &Op) -> String {
656658
Op::Workspace(path) => {
657659
format!(":workspace={}", parse::quote_if(&path.to_string_lossy()))
658660
}
661+
Op::Lookup(path) => {
662+
format!(":lookup={}", parse::quote_if(&path.to_string_lossy()))
663+
}
664+
Op::Lookup2(oid) => {
665+
format!(":lookup2={}", oid.to_string())
666+
}
659667
Op::Stored(path) => {
660668
format!(":+{}", parse::quote_if(&path.to_string_lossy()))
661669
}
@@ -987,6 +995,69 @@ fn apply_to_commit2(
987995

988996
apply(transaction, nf, Apply::from_commit(commit)?)?
989997
}
998+
Op::Lookup(lookup_path) => {
999+
let lookup_commit = if let Some(lookup_commit) =
1000+
apply_to_commit2(&Op::Subdir(lookup_path.clone()), &commit, transaction)?
1001+
{
1002+
lookup_commit
1003+
} else {
1004+
return Ok(None);
1005+
};
1006+
1007+
let op = Op::Lookup2(lookup_commit);
1008+
1009+
if let Some(start) = transaction.get(to_filter(op), commit.id()) {
1010+
transaction.insert(filter, commit.id(), start, true);
1011+
return Ok(Some(start));
1012+
} else {
1013+
return Ok(None);
1014+
}
1015+
}
1016+
1017+
Op::Lookup2(lookup_commit_id) => {
1018+
let lookup_commit = repo.find_commit(*lookup_commit_id)?;
1019+
for parent in lookup_commit.parents() {
1020+
let lookup_tree = lookup_commit.tree_id();
1021+
let cw = get_filter(
1022+
transaction,
1023+
&repo.find_tree(lookup_tree)?,
1024+
&std::path::PathBuf::new().join(commit.id().to_string()),
1025+
);
1026+
if cw != filter::empty() {
1027+
if let Some(start) =
1028+
apply_to_commit2(&Op::Lookup2(parent.id()), &commit, transaction)?
1029+
{
1030+
transaction.insert(filter, commit.id(), start, true);
1031+
return Ok(Some(start));
1032+
} else {
1033+
return Ok(None);
1034+
}
1035+
}
1036+
break;
1037+
}
1038+
let lookup_tree = lookup_commit.tree_id();
1039+
let cw = get_filter(
1040+
transaction,
1041+
&repo.find_tree(lookup_tree)?,
1042+
&std::path::PathBuf::new().join(commit.id().to_string()),
1043+
);
1044+
1045+
if cw == filter::empty() {
1046+
// FIXME empty filter or no entry in table?
1047+
for parent in commit.parents() {
1048+
if let Some(start) = apply_to_commit2(&op, &parent, transaction)? {
1049+
transaction.insert(filter, commit.id(), start, true);
1050+
return Ok(Some(start));
1051+
} else {
1052+
return Ok(None);
1053+
}
1054+
}
1055+
return Ok(None);
1056+
}
1057+
1058+
Apply::from_commit(commit)?
1059+
.with_tree(apply(transaction, cw, Apply::from_commit(commit)?)?.into_tree())
1060+
}
9901061
Op::Squash(Some(ids)) => {
9911062
if let Some(sq) = ids.get(&LazyRef::Resolved(commit.id())) {
9921063
let oid = if let Some(oid) =
@@ -1672,6 +1743,8 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
16721743
Ok(x.with_tree(result_tree))
16731744
}
16741745
Op::Rev(_) => Err(josh_error("not applicable to tree")),
1746+
Op::Lookup(_) => Err(josh_error("not applicable to tree")),
1747+
Op::Lookup2(_) => Err(josh_error("not applicable to tree")),
16751748
Op::Join(_) => Err(josh_error("not applicable to tree")),
16761749
Op::RegexReplace(replacements) => {
16771750
let mut t = x.tree().clone();

josh-core/src/filter/parse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ fn make_op(args: &[&str]) -> JoshResult<Op> {
1010
["author", author, email] => Ok(Op::Author(author.to_string(), email.to_string())),
1111
["committer", author, email] => Ok(Op::Committer(author.to_string(), email.to_string())),
1212
["workspace", arg] => Ok(Op::Workspace(Path::new(arg).to_owned())),
13+
["lookup", arg] => Ok(Op::Lookup(Path::new(arg).to_owned())),
1314
["prefix"] => Err(josh_error(indoc!(
1415
r#"
1516
Filter ":prefix" requires an argument.

josh-core/src/filter/persist.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ impl InMemoryBuilder {
328328
let params_tree = self.build_str_params(&[hook.as_ref()]);
329329
push_tree_entries(&mut entries, [("hook", params_tree)]);
330330
}
331+
&Op::Lookup(_) | &Op::Lookup2(_) => todo!(),
331332
}
332333

333334
let tree = gix_object::Tree { entries };

tests/filter/lookup.t

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
$ export TERM=dumb
2+
$ export RUST_LOG_STYLE=never
3+
4+
$ git init -q real_repo 1> /dev/null
5+
$ cd real_repo
6+
7+
$ mkdir sub1
8+
$ echo contents1 > sub1/file1
9+
$ git add sub1
10+
$ git commit -m "add file1" 1> /dev/null
11+
12+
$ mkdir sub1
13+
mkdir: cannot create directory 'sub1': File exists
14+
[1]
15+
$ echo contents2 > sub1/file2
16+
$ git add sub1
17+
$ git commit -m "add file2" 1> /dev/null
18+
19+
$ git log --graph --pretty=%H
20+
* 81b10fb4984d20142cd275b89c91c346e536876a
21+
* bb282e9cdc1b972fffd08fd21eead43bc0c83cb8
22+
23+
$ mkdir table
24+
$ echo ":prefix=x" > table/81b10fb4984d20142cd275b89c91c346e536876a
25+
$ echo ":prefix=y" > table/bb282e9cdc1b972fffd08fd21eead43bc0c83cb8
26+
$ git add table
27+
$ git commit -m "add lookup table" 1> /dev/null
28+
29+
30+
$ echo contents3 > sub1/file3
31+
$ git add sub1
32+
$ git commit -m "add file3" 1> /dev/null
33+
34+
$ git log --graph --pretty=%H
35+
* 26e4c43675b985689e280bc42264a9226af76943
36+
* 14c74c5eca73952b36d736034b388832748c49d6
37+
* 81b10fb4984d20142cd275b89c91c346e536876a
38+
* bb282e9cdc1b972fffd08fd21eead43bc0c83cb8
39+
40+
$ josh-filter -s ":lookup=table" --update refs/heads/filtered
41+
[1] :lookup=table
42+
[2] :/table
43+
[4] :lookup2=4880528e9d57aa5efc925e120a8077bfa37d778d
44+
45+
$ git log refs/heads/filtered --graph --pretty=%s
46+
* add file2
47+
* add file1
48+
$ git diff ${EMPTY_TREE}..refs/heads/filtered
49+
diff --git a/x/sub1/file1 b/x/sub1/file1
50+
new file mode 100644
51+
index 0000000..a024003
52+
--- /dev/null
53+
+++ b/x/sub1/file1
54+
@@ -0,0 +1 @@
55+
+contents1
56+
diff --git a/x/sub1/file2 b/x/sub1/file2
57+
new file mode 100644
58+
index 0000000..6b46faa
59+
--- /dev/null
60+
+++ b/x/sub1/file2
61+
@@ -0,0 +1 @@
62+
+contents2
63+
$ git diff ${EMPTY_TREE}..refs/heads/filtered~1
64+
diff --git a/y/sub1/file1 b/y/sub1/file1
65+
new file mode 100644
66+
index 0000000..a024003
67+
--- /dev/null
68+
+++ b/y/sub1/file1
69+
@@ -0,0 +1 @@
70+
+contents1
71+
72+
$ echo ":prefix=z" > table/14c74c5eca73952b36d736034b388832748c49d6
73+
$ echo ":prefix=z" > table/26e4c43675b985689e280bc42264a9226af76943
74+
$ git add table
75+
$ git commit -m "mod lookup table" 1> /dev/null
76+
$ tree table
77+
table
78+
|-- 14c74c5eca73952b36d736034b388832748c49d6
79+
|-- 26e4c43675b985689e280bc42264a9226af76943
80+
|-- 81b10fb4984d20142cd275b89c91c346e536876a
81+
`-- bb282e9cdc1b972fffd08fd21eead43bc0c83cb8
82+
83+
1 directory, 4 files
84+
85+
$ josh-filter -s ":lookup=table" --update refs/heads/filtered
86+
Warning: reference refs/heads/filtered wasn't updated
87+
[2] :lookup=table
88+
[3] :/table
89+
[4] :lookup2=4880528e9d57aa5efc925e120a8077bfa37d778d
90+
[5] :lookup2=ed934c124e28c83270d9cfbb011f3ceb46c0f69e
91+
$ git log refs/heads/filtered --graph --pretty=%s
92+
* add file2
93+
* add file1
94+
95+
$ git diff ${EMPTY_TREE}..refs/heads/filtered
96+
diff --git a/x/sub1/file1 b/x/sub1/file1
97+
new file mode 100644
98+
index 0000000..a024003
99+
--- /dev/null
100+
+++ b/x/sub1/file1
101+
@@ -0,0 +1 @@
102+
+contents1
103+
diff --git a/x/sub1/file2 b/x/sub1/file2
104+
new file mode 100644
105+
index 0000000..6b46faa
106+
--- /dev/null
107+
+++ b/x/sub1/file2
108+
@@ -0,0 +1 @@
109+
+contents2
110+
$ git diff ${EMPTY_TREE}..refs/heads/filtered~1
111+
diff --git a/y/sub1/file1 b/y/sub1/file1
112+
new file mode 100644
113+
index 0000000..a024003
114+
--- /dev/null
115+
+++ b/y/sub1/file1
116+
@@ -0,0 +1 @@
117+
+contents1

0 commit comments

Comments
 (0)