Skip to content

Commit b54968a

Browse files
Implement workspace redirect (#1278)
1 parent 2934d82 commit b54968a

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

josh-core/src/filter/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,27 @@ pub fn apply_to_commit(
375375
}
376376
}
377377

378+
// Handle workspace.josh files that contain ":workspace=..." as their only filter as
379+
// a "redirect" to that other workspace. We chain an exclude of the redirecting workspace
380+
// in front to prevent infinite recursion.
381+
fn resolve_workspace_redirect<'a>(
382+
repo: &'a git2::Repository,
383+
tree: &'a git2::Tree<'a>,
384+
path: &Path,
385+
) -> Option<Filter> {
386+
let f = parse::parse(&tree::get_blob(repo, tree, &path.join("workspace.josh")))
387+
.unwrap_or_else(|_| to_filter(Op::Empty));
388+
389+
if let Op::Workspace(_) = to_op(f) {
390+
Some(chain(
391+
to_filter(Op::Exclude(to_filter(Op::File(path.to_owned())))),
392+
f,
393+
))
394+
} else {
395+
None
396+
}
397+
}
398+
378399
fn get_workspace<'a>(repo: &'a git2::Repository, tree: &'a git2::Tree<'a>, path: &Path) -> Filter {
379400
let f = parse::parse(&tree::get_blob(repo, tree, &path.join("workspace.josh")))
380401
.unwrap_or_else(|_| to_filter(Op::Empty));
@@ -568,6 +589,10 @@ fn apply_to_commit2(
568589
.map(|parent| transaction.get(filter, parent))
569590
.collect::<Option<Vec<git2::Oid>>>();
570591

592+
if let Some(redirect) = resolve_workspace_redirect(repo, &commit.tree()?, ws_path) {
593+
return apply_to_commit2(&to_op(redirect), &commit, transaction);
594+
}
595+
571596
let normal_parents = some_or!(normal_parents, { return Ok(None) });
572597

573598
let cw = get_workspace(repo, &commit.tree()?, ws_path);

tests/filter/workspace_redirect.t

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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+
$ echo contents4 > sub1/file4
10+
$ git add sub1
11+
$ git commit -m "add file1" 1> /dev/null
12+
13+
$ mkdir -p sub2/subsub
14+
$ echo contents1 > sub2/subsub/file2
15+
$ git add sub2
16+
$ git commit -m "add file2" 1> /dev/null
17+
18+
$ mkdir ws
19+
$ cat > ws/workspace.josh <<EOF
20+
> ::sub2/subsub/
21+
> a = :/sub1
22+
> EOF
23+
$ echo "foobar" > ws/extra_file
24+
$ git add ws
25+
$ git commit -m "add ws" 1> /dev/null
26+
27+
$ mkdir ws_new
28+
$ echo "foobar" > ws_new/extra_file_new
29+
$ cat > ws_new/workspace.josh <<EOF
30+
> :workspace=ws
31+
> EOF
32+
$ git add ws_new
33+
$ git commit -m "add ws_new" 1> /dev/null
34+
35+
$ josh-filter -s :workspace=ws master --update refs/heads/filtered
36+
[1] :/sub1
37+
[1] :/subsub
38+
[1] :prefix=a
39+
[1] :prefix=sub2
40+
[1] :prefix=subsub
41+
[2] :/sub2
42+
[2] :[
43+
a = :/sub1
44+
::sub2/subsub/
45+
]
46+
[2] :workspace=ws
47+
$ josh-filter -s :workspace=ws_new master --update refs/heads/filtered_new
48+
[1] :/sub1
49+
[1] :/subsub
50+
[1] :prefix=a
51+
[1] :prefix=sub2
52+
[1] :prefix=subsub
53+
[2] :/sub2
54+
[2] ::ws_new
55+
[2] :[
56+
a = :/sub1
57+
::sub2/subsub/
58+
]
59+
[2] :workspace=ws
60+
[3] :exclude[::ws_new]
61+
62+
$ git log --graph --pretty=%s refs/heads/filtered
63+
* add ws
64+
* add file2
65+
* add file1
66+
$ git log --graph --pretty=%s refs/heads/filtered_new
67+
* add ws
68+
* add file2
69+
* add file1
70+
71+
$ git diff ${EMPTY_TREE}..refs/heads/filtered
72+
diff --git a/a/file1 b/a/file1
73+
new file mode 100644
74+
index 0000000..a024003
75+
--- /dev/null
76+
+++ b/a/file1
77+
@@ -0,0 +1 @@
78+
+contents1
79+
diff --git a/a/file4 b/a/file4
80+
new file mode 100644
81+
index 0000000..288746e
82+
--- /dev/null
83+
+++ b/a/file4
84+
@@ -0,0 +1 @@
85+
+contents4
86+
diff --git a/extra_file b/extra_file
87+
new file mode 100644
88+
index 0000000..323fae0
89+
--- /dev/null
90+
+++ b/extra_file
91+
@@ -0,0 +1 @@
92+
+foobar
93+
diff --git a/sub2/subsub/file2 b/sub2/subsub/file2
94+
new file mode 100644
95+
index 0000000..a024003
96+
--- /dev/null
97+
+++ b/sub2/subsub/file2
98+
@@ -0,0 +1 @@
99+
+contents1
100+
diff --git a/workspace.josh b/workspace.josh
101+
new file mode 100644
102+
index 0000000..68bf391
103+
--- /dev/null
104+
+++ b/workspace.josh
105+
@@ -0,0 +1,2 @@
106+
+::sub2/subsub/
107+
+a = :/sub1
108+
$ git diff ${EMPTY_TREE}..refs/heads/filtered_new
109+
diff --git a/a/file1 b/a/file1
110+
new file mode 100644
111+
index 0000000..a024003
112+
--- /dev/null
113+
+++ b/a/file1
114+
@@ -0,0 +1 @@
115+
+contents1
116+
diff --git a/a/file4 b/a/file4
117+
new file mode 100644
118+
index 0000000..288746e
119+
--- /dev/null
120+
+++ b/a/file4
121+
@@ -0,0 +1 @@
122+
+contents4
123+
diff --git a/extra_file b/extra_file
124+
new file mode 100644
125+
index 0000000..323fae0
126+
--- /dev/null
127+
+++ b/extra_file
128+
@@ -0,0 +1 @@
129+
+foobar
130+
diff --git a/sub2/subsub/file2 b/sub2/subsub/file2
131+
new file mode 100644
132+
index 0000000..a024003
133+
--- /dev/null
134+
+++ b/sub2/subsub/file2
135+
@@ -0,0 +1 @@
136+
+contents1
137+
diff --git a/workspace.josh b/workspace.josh
138+
new file mode 100644
139+
index 0000000..68bf391
140+
--- /dev/null
141+
+++ b/workspace.josh
142+
@@ -0,0 +1,2 @@
143+
+::sub2/subsub/
144+
+a = :/sub1
145+
146+
147+
$ cat > ws/workspace.josh <<EOF
148+
> :workspace=ws_new
149+
> EOF
150+
$ git add ws
151+
$ git commit -m "add ws recursion" 1> /dev/null
152+
153+
$ josh-filter -s :workspace=ws master --update refs/heads/filtered
154+
[1] :/sub1
155+
[1] :/subsub
156+
[1] :prefix=a
157+
[1] :prefix=sub2
158+
[1] :prefix=subsub
159+
[2] :/sub2
160+
[2] :[
161+
a = :/sub1
162+
::sub2/subsub/
163+
]
164+
[2] :workspace=ws
165+
[3] ::ws
166+
[3] ::ws_new
167+
[3] :exclude[::ws]
168+
[3] :exclude[::ws_new]

0 commit comments

Comments
 (0)