Skip to content

Commit a282003

Browse files
Fix base (#555)
* Add a test for creating new branch from a workspace * Fix base option Co-authored-by: Vladislav Ivanov <[email protected]>
1 parent 3292dd7 commit a282003

File tree

3 files changed

+262
-13
lines changed

3 files changed

+262
-13
lines changed

src/history.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,11 @@ fn find_unapply_base(
7878
filtered: git2::Oid,
7979
) -> super::JoshResult<git2::Oid> {
8080
if contained_in == git2::Oid::zero() {
81+
tracing::info!("contained in zero",);
8182
return Ok(git2::Oid::zero());
8283
}
8384
if let Some(original) = bm.get(&filtered) {
85+
tracing::info!("Found in bm",);
8486
return Ok(*original);
8587
}
8688
let contained_in_commit = transaction.repo().find_commit(contained_in)?;
@@ -96,10 +98,12 @@ fn find_unapply_base(
9698
let original = transaction.repo().find_commit(original?)?;
9799
if filtered == filter::apply_to_commit(filter, &original, transaction)? {
98100
bm.insert(filtered, original.id());
101+
tracing::info!("found original properly",);
99102
return Ok(original.id());
100103
}
101104
}
102105

106+
tracing::info!("Didn't find original",);
103107
Ok(git2::Oid::zero())
104108
}
105109

@@ -199,6 +203,71 @@ fn all_equal(a: git2::Parents, b: &[&git2::Commit]) -> bool {
199203
true
200204
}
201205

206+
fn find_oldest_similar_commit(
207+
transaction: &cache::Transaction,
208+
filter: filter::Filter,
209+
unfiltered: git2::Oid,
210+
) -> super::JoshResult<git2::Oid> {
211+
let walk = {
212+
let mut walk = transaction.repo().revwalk()?;
213+
walk.set_sorting(git2::Sort::TOPOLOGICAL)?;
214+
walk.push(unfiltered)?;
215+
walk
216+
};
217+
tracing::info!("oldest similar?");
218+
let unfiltered_commit = transaction.repo().find_commit(unfiltered)?;
219+
let filtered = filter::apply_to_commit(filter, &unfiltered_commit, transaction)?;
220+
let mut prev_rev = unfiltered;
221+
for rev in walk {
222+
let rev = rev?;
223+
tracing::info!("next");
224+
let rev_commit = transaction.repo().find_commit(rev)?;
225+
if filtered != filter::apply_to_commit(filter, &rev_commit, transaction)? {
226+
tracing::info!("diff! {}", prev_rev);
227+
return Ok(prev_rev);
228+
}
229+
prev_rev = rev;
230+
}
231+
tracing::info!("bottom");
232+
return Ok(unfiltered);
233+
}
234+
235+
fn find_new_branch_base(
236+
transaction: &cache::Transaction,
237+
bm: &mut std::collections::HashMap<git2::Oid, git2::Oid>,
238+
filter: filter::Filter,
239+
contained_in: git2::Oid,
240+
filtered: git2::Oid,
241+
) -> super::JoshResult<git2::Oid> {
242+
let walk = {
243+
let mut walk = transaction.repo().revwalk()?;
244+
walk.set_sorting(git2::Sort::TOPOLOGICAL)?;
245+
walk.push(filtered)?;
246+
walk
247+
};
248+
tracing::info!("new branch base?");
249+
250+
for rev in walk {
251+
let rev = rev?;
252+
if let Ok(base) = find_unapply_base(transaction, bm, filter, contained_in, rev) {
253+
if base != git2::Oid::zero() {
254+
tracing::info!("new branch base: {:?}", base);
255+
let base =
256+
if let Ok(new_base) = find_oldest_similar_commit(transaction, filter, base) {
257+
new_base
258+
} else {
259+
base
260+
};
261+
tracing::info!("inserting in bm {}, {}", rev, base);
262+
bm.insert(rev, base);
263+
return Ok(rev);
264+
}
265+
}
266+
}
267+
tracing::info!("new branch base not found");
268+
return Ok(git2::Oid::zero());
269+
}
270+
202271
#[tracing::instrument(skip(transaction))]
203272
pub fn unapply_filter(
204273
transaction: &cache::Transaction,
@@ -213,12 +282,30 @@ pub fn unapply_filter(
213282
let mut bm = std::collections::HashMap::new();
214283
let mut ret = original_target;
215284

285+
let old = if old == git2::Oid::zero() {
286+
match find_new_branch_base(transaction, &mut bm, filterobj, original_target, new) {
287+
Ok(res) => {
288+
tracing::info!("No error, branch base {} ", res);
289+
res
290+
}
291+
Err(_) => {
292+
tracing::info!("Error in new branch base");
293+
old
294+
}
295+
}
296+
} else {
297+
tracing::info!("Old not zero");
298+
old
299+
};
300+
301+
tracing::info!("before walk");
302+
216303
let walk = {
217304
let mut walk = transaction.repo().revwalk()?;
218305
walk.set_sorting(git2::Sort::REVERSE | git2::Sort::TOPOLOGICAL)?;
219306
walk.push(new)?;
220307
if walk.hide(old).is_ok() {
221-
tracing::trace!("walk: hidden {}", old);
308+
tracing::info!("walk: hidden {}", old);
222309
} else {
223310
tracing::warn!("walk: can't hide");
224311
}
@@ -230,6 +317,7 @@ pub fn unapply_filter(
230317

231318
let s = tracing::span!(tracing::Level::TRACE, "walk commit", ?rev);
232319
let _e = s.enter();
320+
tracing::info!("walk commit: {:?}", rev);
233321

234322
let module_commit = transaction.repo().find_commit(rev)?;
235323

tests/proxy/push_new_branch.t

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
Setup
2+
3+
$ . ${TESTDIR}/setup_test_env.sh
4+
$ cd ${TESTTMP}
5+
6+
Clone an empty repo
7+
8+
$ git clone -q http://localhost:8001/real_repo.git >/dev/null 2>&1
9+
$ cd real_repo
10+
11+
Commit a file in a root folder
12+
13+
$ echo contents1 > file1
14+
$ git add file1
15+
$ git commit -m "add file1"
16+
[master (root-commit) 0b4cf6c] add file1
17+
1 file changed, 1 insertion(+)
18+
create mode 100644 file1
19+
20+
Commit a file in a subfolder and push
21+
22+
$ mkdir sub
23+
$ echo contents2 > sub/file2
24+
$ git add sub
25+
$ git commit -m "add file2" 1> /dev/null
26+
$ git push 1> /dev/null
27+
To http://localhost:8001/real_repo.git
28+
* [new branch] master -> master
29+
30+
Check commit SHA1
31+
$ SHA1=$(git log --max-count=1 --format="%H")
32+
$ echo "${SHA1}"
33+
37c3f9a18f21fe53e0be9ea657220ba4537dbca7
34+
35+
Clone subfolder as a workspace
36+
37+
$ cd ${TESTTMP}
38+
$ git clone -q http://localhost:8002/real_repo.git:/sub.git
39+
$ cd sub
40+
41+
Check workspace contents
42+
43+
$ ls
44+
file2
45+
46+
Create a new branch and push it
47+
48+
$ git switch -c new-branch
49+
Switched to a new branch 'new-branch'
50+
$ git push origin new-branch -o base=refs/heads/master 1> /dev/null
51+
remote: josh-proxy
52+
remote: response from upstream:
53+
remote: To http://localhost:8001/real_repo.git
54+
remote: * [new branch] JOSH_PUSH -> new-branch
55+
remote:
56+
remote:
57+
To http://localhost:8002/real_repo.git:/sub.git
58+
* [new branch] new-branch -> new-branch
59+
Check the branch pushed
60+
$ cd ${TESTTMP}/real_repo
61+
$ git fetch
62+
From http://localhost:8001/real_repo
63+
* [new branch] new-branch -> origin/new-branch
64+
$ [ "${SHA1}" = "$(git log --max-count=1 --format='%H' origin/new-branch)" ] || echo "SHA1 differs after push!"
65+
66+
Add one more commit in the workspace
67+
68+
$ cd ${TESTTMP}/sub
69+
$ echo test > test.txt
70+
$ git add test.txt
71+
$ git commit -m "test commit"
72+
[new-branch 751ef45] test commit
73+
1 file changed, 1 insertion(+)
74+
create mode 100644 test.txt
75+
$ git push origin new-branch -o base=refs/heads/master
76+
remote: josh-proxy
77+
remote: response from upstream:
78+
remote: To http://localhost:8001/real_repo.git
79+
remote: 37c3f9a..56dc1f7 JOSH_PUSH -> new-branch
80+
remote:
81+
remote:
82+
To http://localhost:8002/real_repo.git:/sub.git
83+
28d2085..751ef45 new-branch -> new-branch
84+
85+
Check the branch again
86+
87+
$ cd ${TESTTMP}/real_repo
88+
$ git fetch
89+
From http://localhost:8001/real_repo
90+
37c3f9a..56dc1f7 new-branch -> origin/new-branch
91+
$ [ "${SHA1}" = "$(git log --max-count=1 --skip=1 --format='%H' origin/new-branch)" ] || echo "SHA1 differs after push!"
92+
93+
$ bash ${TESTDIR}/destroy_test_env.sh
94+
"real_repo.git" = [':/sub']
95+
refs
96+
|-- heads
97+
|-- josh
98+
| |-- filtered
99+
| | `-- real_repo.git
100+
| | `-- %3A%2Fsub
101+
| | `-- HEAD
102+
| `-- upstream
103+
| `-- real_repo.git
104+
| |-- HEAD
105+
| `-- refs
106+
| `-- heads
107+
| |-- master
108+
| `-- new-branch
109+
|-- namespaces
110+
`-- tags
111+
112+
11 directories, 4 files

tests/proxy/unrelated_leak.t

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ Flushed credential cache
4141
$ echo contents2 > file4
4242
$ git add .
4343
$ git commit -m "add file4" 1> /dev/null
44+
45+
$ echo contents3 > file4
46+
$ git add .
47+
$ git commit -m "edit file4" 1> /dev/null
4448
$ git push -o base=refs/heads/master origin master:refs/heads/from_filtered 2>&1 >/dev/null | sed -e 's/[ ]*$//g'
4549
remote: josh-proxy
4650
remote: response from upstream:
@@ -55,27 +59,72 @@ Flushed credential cache
5559
remote: josh-proxy
5660
remote: response from upstream:
5761
remote: To http://localhost:8001/real_repo.git
58-
remote: db0fd21..3f7ab67 JOSH_PUSH -> master
62+
remote: db0fd21..e170e96 JOSH_PUSH -> master
5963
remote:
6064
remote:
6165
To http://localhost:8002/real_repo.git:/sub1.git
62-
0b4cf6c..37fad4a master -> master
66+
0b4cf6c..da0d1f3 master -> master
6367

6468
$ cd ${TESTTMP}/real_repo
6569
$ git fetch
6670
From http://localhost:8001/real_repo
67-
db0fd21..3f7ab67 master -> origin/master
71+
db0fd21..e170e96 master -> origin/master
6872
* [new branch] from_filtered -> origin/from_filtered
6973

70-
$ git log --graph --pretty=%s origin/master
71-
* add file4
72-
* unrelated on master
73-
* add file1
74-
* initial
75-
$ git log --graph --pretty=%s origin/from_filtered
76-
* add file4
77-
* add file1
78-
74+
$ git log origin/master
75+
commit e170e962d0fb4b94a491a176a7f39a6207ada3e8
76+
Author: Josh <[email protected]>
77+
Date: Thu Apr 7 22:13:13 2005 +0000
78+
79+
edit file4
80+
81+
commit 3f7ab67d01db03914916161b51dbda1a4635f8d2
82+
Author: Josh <[email protected]>
83+
Date: Thu Apr 7 22:13:13 2005 +0000
84+
85+
add file4
86+
87+
commit db0fd21be0dea377057285e6119361753587f667
88+
Author: Josh <[email protected]>
89+
Date: Thu Apr 7 22:13:13 2005 +0000
90+
91+
unrelated on master
92+
93+
commit a11885ec53fe483199d9515bf4662e5cf94d9a9e
94+
Author: Josh <[email protected]>
95+
Date: Thu Apr 7 22:13:13 2005 +0000
96+
97+
add file1
98+
99+
commit 66472b80301b889cf27a92d43fc2c2d8fbf4729d
100+
Author: Josh <[email protected]>
101+
Date: Thu Apr 7 22:13:13 2005 +0000
102+
103+
initial
104+
$ git log origin/from_filtered
105+
commit 865c34e9a2c40198324cdc2fc796827653cb11df
106+
Author: Josh <[email protected]>
107+
Date: Thu Apr 7 22:13:13 2005 +0000
108+
109+
edit file4
110+
111+
commit 42e0161c1ad82c05895e0f2caeae95925ac5ae6a
112+
Author: Josh <[email protected]>
113+
Date: Thu Apr 7 22:13:13 2005 +0000
114+
115+
add file4
116+
117+
commit a11885ec53fe483199d9515bf4662e5cf94d9a9e
118+
Author: Josh <[email protected]>
119+
Date: Thu Apr 7 22:13:13 2005 +0000
120+
121+
add file1
122+
123+
commit 66472b80301b889cf27a92d43fc2c2d8fbf4729d
124+
Author: Josh <[email protected]>
125+
Date: Thu Apr 7 22:13:13 2005 +0000
126+
127+
initial
79128
$ . ${TESTDIR}/destroy_test_env.sh
80129
"real_repo.git" = [
81130
':/sub1',

0 commit comments

Comments
 (0)