Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 89 additions & 1 deletion src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ fn find_unapply_base(
filtered: git2::Oid,
) -> super::JoshResult<git2::Oid> {
if contained_in == git2::Oid::zero() {
tracing::info!("contained in zero",);
return Ok(git2::Oid::zero());
}
if let Some(original) = bm.get(&filtered) {
tracing::info!("Found in bm",);
return Ok(*original);
}
let contained_in_commit = transaction.repo().find_commit(contained_in)?;
Expand All @@ -96,10 +98,12 @@ fn find_unapply_base(
let original = transaction.repo().find_commit(original?)?;
if filtered == filter::apply_to_commit(filter, &original, transaction)? {
bm.insert(filtered, original.id());
tracing::info!("found original properly",);
return Ok(original.id());
}
}

tracing::info!("Didn't find original",);
Ok(git2::Oid::zero())
}

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

fn find_oldest_similar_commit(
transaction: &cache::Transaction,
filter: filter::Filter,
unfiltered: git2::Oid,
) -> super::JoshResult<git2::Oid> {
let walk = {
let mut walk = transaction.repo().revwalk()?;
walk.set_sorting(git2::Sort::TOPOLOGICAL)?;
walk.push(unfiltered)?;
walk
};
tracing::info!("oldest similar?");
let unfiltered_commit = transaction.repo().find_commit(unfiltered)?;
let filtered = filter::apply_to_commit(filter, &unfiltered_commit, transaction)?;
let mut prev_rev = unfiltered;
for rev in walk {
let rev = rev?;
tracing::info!("next");
let rev_commit = transaction.repo().find_commit(rev)?;
if filtered != filter::apply_to_commit(filter, &rev_commit, transaction)? {
tracing::info!("diff! {}", prev_rev);
return Ok(prev_rev);
}
prev_rev = rev;
}
tracing::info!("bottom");
return Ok(unfiltered);
}

fn find_new_branch_base(
transaction: &cache::Transaction,
bm: &mut std::collections::HashMap<git2::Oid, git2::Oid>,
filter: filter::Filter,
contained_in: git2::Oid,
filtered: git2::Oid,
) -> super::JoshResult<git2::Oid> {
let walk = {
let mut walk = transaction.repo().revwalk()?;
walk.set_sorting(git2::Sort::TOPOLOGICAL)?;
walk.push(filtered)?;
walk
};
tracing::info!("new branch base?");

for rev in walk {
let rev = rev?;
if let Ok(base) = find_unapply_base(transaction, bm, filter, contained_in, rev) {
if base != git2::Oid::zero() {
tracing::info!("new branch base: {:?}", base);
let base =
if let Ok(new_base) = find_oldest_similar_commit(transaction, filter, base) {
new_base
} else {
base
};
tracing::info!("inserting in bm {}, {}", rev, base);
bm.insert(rev, base);
return Ok(rev);
}
}
}
tracing::info!("new branch base not found");
return Ok(git2::Oid::zero());
}

#[tracing::instrument(skip(transaction))]
pub fn unapply_filter(
transaction: &cache::Transaction,
Expand All @@ -213,12 +282,30 @@ pub fn unapply_filter(
let mut bm = std::collections::HashMap::new();
let mut ret = original_target;

let old = if old == git2::Oid::zero() {
match find_new_branch_base(transaction, &mut bm, filterobj, original_target, new) {
Ok(res) => {
tracing::info!("No error, branch base {} ", res);
res
}
Err(_) => {
tracing::info!("Error in new branch base");
old
}
}
} else {
tracing::info!("Old not zero");
old
};

tracing::info!("before walk");

let walk = {
let mut walk = transaction.repo().revwalk()?;
walk.set_sorting(git2::Sort::REVERSE | git2::Sort::TOPOLOGICAL)?;
walk.push(new)?;
if walk.hide(old).is_ok() {
tracing::trace!("walk: hidden {}", old);
tracing::info!("walk: hidden {}", old);
} else {
tracing::warn!("walk: can't hide");
}
Expand All @@ -230,6 +317,7 @@ pub fn unapply_filter(

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

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

Expand Down
112 changes: 112 additions & 0 deletions tests/proxy/push_new_branch.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
Setup

$ . ${TESTDIR}/setup_test_env.sh
$ cd ${TESTTMP}

Clone an empty repo

$ git clone -q http://localhost:8001/real_repo.git >/dev/null 2>&1
$ cd real_repo

Commit a file in a root folder

$ echo contents1 > file1
$ git add file1
$ git commit -m "add file1"
[master (root-commit) 0b4cf6c] add file1
1 file changed, 1 insertion(+)
create mode 100644 file1

Commit a file in a subfolder and push

$ mkdir sub
$ echo contents2 > sub/file2
$ git add sub
$ git commit -m "add file2" 1> /dev/null
$ git push 1> /dev/null
To http://localhost:8001/real_repo.git
* [new branch] master -> master

Check commit SHA1
$ SHA1=$(git log --max-count=1 --format="%H")
$ echo "${SHA1}"
37c3f9a18f21fe53e0be9ea657220ba4537dbca7

Clone subfolder as a workspace

$ cd ${TESTTMP}
$ git clone -q http://localhost:8002/real_repo.git:/sub.git
$ cd sub

Check workspace contents

$ ls
file2

Create a new branch and push it

$ git switch -c new-branch
Switched to a new branch 'new-branch'
$ git push origin new-branch -o base=refs/heads/master 1> /dev/null
remote: josh-proxy
remote: response from upstream:
remote: To http://localhost:8001/real_repo.git
remote: * [new branch] JOSH_PUSH -> new-branch
remote:
remote:
To http://localhost:8002/real_repo.git:/sub.git
* [new branch] new-branch -> new-branch
Check the branch pushed
$ cd ${TESTTMP}/real_repo
$ git fetch
From http://localhost:8001/real_repo
* [new branch] new-branch -> origin/new-branch
$ [ "${SHA1}" = "$(git log --max-count=1 --format='%H' origin/new-branch)" ] || echo "SHA1 differs after push!"

Add one more commit in the workspace

$ cd ${TESTTMP}/sub
$ echo test > test.txt
$ git add test.txt
$ git commit -m "test commit"
[new-branch 751ef45] test commit
1 file changed, 1 insertion(+)
create mode 100644 test.txt
$ git push origin new-branch -o base=refs/heads/master
remote: josh-proxy
remote: response from upstream:
remote: To http://localhost:8001/real_repo.git
remote: 37c3f9a..56dc1f7 JOSH_PUSH -> new-branch
remote:
remote:
To http://localhost:8002/real_repo.git:/sub.git
28d2085..751ef45 new-branch -> new-branch

Check the branch again

$ cd ${TESTTMP}/real_repo
$ git fetch
From http://localhost:8001/real_repo
37c3f9a..56dc1f7 new-branch -> origin/new-branch
$ [ "${SHA1}" = "$(git log --max-count=1 --skip=1 --format='%H' origin/new-branch)" ] || echo "SHA1 differs after push!"

$ bash ${TESTDIR}/destroy_test_env.sh
"real_repo.git" = [':/sub']
refs
|-- heads
|-- josh
| |-- filtered
| | `-- real_repo.git
| | `-- %3A%2Fsub
| | `-- HEAD
| `-- upstream
| `-- real_repo.git
| |-- HEAD
| `-- refs
| `-- heads
| |-- master
| `-- new-branch
|-- namespaces
`-- tags

11 directories, 4 files
73 changes: 61 additions & 12 deletions tests/proxy/unrelated_leak.t
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Flushed credential cache
$ echo contents2 > file4
$ git add .
$ git commit -m "add file4" 1> /dev/null

$ echo contents3 > file4
$ git add .
$ git commit -m "edit file4" 1> /dev/null
$ git push -o base=refs/heads/master origin master:refs/heads/from_filtered 2>&1 >/dev/null | sed -e 's/[ ]*$//g'
remote: josh-proxy
remote: response from upstream:
Expand All @@ -55,27 +59,72 @@ Flushed credential cache
remote: josh-proxy
remote: response from upstream:
remote: To http://localhost:8001/real_repo.git
remote: db0fd21..3f7ab67 JOSH_PUSH -> master
remote: db0fd21..e170e96 JOSH_PUSH -> master
remote:
remote:
To http://localhost:8002/real_repo.git:/sub1.git
0b4cf6c..37fad4a master -> master
0b4cf6c..da0d1f3 master -> master

$ cd ${TESTTMP}/real_repo
$ git fetch
From http://localhost:8001/real_repo
db0fd21..3f7ab67 master -> origin/master
db0fd21..e170e96 master -> origin/master
* [new branch] from_filtered -> origin/from_filtered

$ git log --graph --pretty=%s origin/master
* add file4
* unrelated on master
* add file1
* initial
$ git log --graph --pretty=%s origin/from_filtered
* add file4
* add file1

$ git log origin/master
commit e170e962d0fb4b94a491a176a7f39a6207ada3e8
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

edit file4

commit 3f7ab67d01db03914916161b51dbda1a4635f8d2
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

add file4

commit db0fd21be0dea377057285e6119361753587f667
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

unrelated on master

commit a11885ec53fe483199d9515bf4662e5cf94d9a9e
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

add file1

commit 66472b80301b889cf27a92d43fc2c2d8fbf4729d
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

initial
$ git log origin/from_filtered
commit 865c34e9a2c40198324cdc2fc796827653cb11df
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

edit file4

commit 42e0161c1ad82c05895e0f2caeae95925ac5ae6a
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

add file4

commit a11885ec53fe483199d9515bf4662e5cf94d9a9e
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

add file1

commit 66472b80301b889cf27a92d43fc2c2d8fbf4729d
Author: Josh <josh@example.com>
Date: Thu Apr 7 22:13:13 2005 +0000

initial
$ . ${TESTDIR}/destroy_test_env.sh
"real_repo.git" = [
':/sub1',
Expand Down