Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Commit

Permalink
remote-helper: Fix FETCH_HEAD setting on fetch
Browse files Browse the repository at this point in the history
The `git2` crate is not reliable at setting the `FETCH_HEAD` on fetch.
Therefore we disable that feature, and let the git command-line do its
thing.
  • Loading branch information
cloudhead committed Nov 22, 2023
1 parent 2fc65de commit e703bad
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 4 deletions.
31 changes: 31 additions & 0 deletions radicle-cli/examples/rad-patch-fetch-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
This is a simple test to ensure the behavior of our remote helper is correct.

``` ~alice
$ git rev-parse master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
$ git checkout -b alice/1 -q
$ git commit --allow-empty -m "Change #1" -q
$ git rev-parse HEAD
7461703ce0fda972df450d071d1d3702057a6352
$ git push rad HEAD:alice/1
```

``` ~bob
$ git status
On branch master
Your branch is up to date with 'rad/master'.
nothing to commit, working tree clean
$ git fetch --all
Fetching rad
Fetching alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ cat .git/FETCH_HEAD
7461703ce0fda972df450d071d1d3702057a6352 not-for-merge branch 'alice/1' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 not-for-merge branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ git merge FETCH_HEAD
Already up to date.
$ git rev-parse master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
$ git rev-parse HEAD
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
```
27 changes: 27 additions & 0 deletions radicle-cli/examples/rad-patch-fetch-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Ensure that we're able to pull our own branches if they happened to be deleted
in our working copy. This also applies to a situation with multiple working
copies.

```
$ git checkout -b alice/1 -q
$ git commit --allow-empty -m "Changes #1" -q
$ git push rad -o patch.message="Changes" HEAD:refs/patches
```

```
$ git checkout master -q
$ git branch -D alice/1 -q
$ git update-ref -d refs/remotes/rad/alice/1
$ git update-ref -d refs/remotes/rad/patches/34dff44b9e86f0bdb1a65ee5b6ef90ce6e7af70d
$ git gc --prune=now
$ git branch -r
rad/master
```

```
$ git pull
Already up to date.
$ git branch -r
rad/master
rad/patches/34dff44b9e86f0bdb1a65ee5b6ef90ce6e7af70d
```
81 changes: 81 additions & 0 deletions radicle-cli/examples/rad-push-and-pull-patches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Testing pulling, fetching and the `FETCH_HEAD`.

``` ~bob
$ git push rad
$ git checkout -b bob/1 -q
$ git commit --allow-empty -m "Changes #1" -q
$ git push -o patch.message="Changes" rad HEAD:refs/patches
$ rad sync -a
✓ Synced with 1 node(s)
```

``` ~alice
$ git checkout -b alice/1 -q
$ git rev-parse HEAD
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
$ git checkout master -q
$ rad patch checkout 0fd67a0
✓ Switched to branch patch/0fd67a0
✓ Branch patch/0fd67a0 setup to track rad/patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21
$ rad remote add z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
✓ Remote bob@z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk added
✓ Remote-tracking branch bob@z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk/master created for z6Mkt67…v4N1tRk
$ git checkout master -q
$ git fetch --all -q
$ cat .git/FETCH_HEAD
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 not-for-merge branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ git rev-parse master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
```

``` ~alice (stderr)
$ git checkout patch/0fd67a0 -q
$ git commit --allow-empty -m "Changes #2" -q
$ git push
✓ Patch 0fd67a0 updated to c360232989049f6d95efe3512e68608317333a5e
✓ Synced with 1 node(s)
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] patch/0fd67a0 -> patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21
```

``` ~bob
$ git commit --allow-empty -m "Changes #2" -q
$ git push
```

``` ~alice (stderr)
$ git checkout master -q
$ git pull
✓ Synced with 1 peer(s)
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+ c2aaf1c...8d5f1ba patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21 -> rad/patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21 (forced update)
$ git checkout - -q
$ git commit --allow-empty -m "Changes #3" -q
$ git push
✓ Patch 0fd67a0 updated to c4115970191cd0e67212b6d26ad9e3bd992dce35
✓ Synced with 1 node(s)
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
c2aaf1c..d9f8caf patch/0fd67a0 -> patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21
```

``` ~alice
$ cat .git/FETCH_HEAD
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
```

``` ~bob (stderr)
$ git checkout master -q
$ git pull
✓ Synced with 1 peer(s)
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+ c2aaf1c...8d5f1ba patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21 -> rad/patches/0fd67a0364af1f79ed8770a35ed09d85571d4c21 (forced update)
```

``` ~bob
$ git rev-parse master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
```
108 changes: 106 additions & 2 deletions radicle-cli/tests/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1530,7 +1530,111 @@ fn git_push_diverge() {
}

#[test]
fn git_push_and_pull() {
fn rad_push_and_pull_patches() {
let mut environment = Environment::new();
let alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob")));
let working = environment.tmp().join("working");

fixtures::repository(working.join("alice"));

test(
"examples/rad-init.md",
working.join("alice"),
Some(&alice.home),
[],
)
.unwrap();

let alice = alice.spawn();
let mut bob = bob.spawn();

bob.connect(&alice).converge([&alice]);

logger::init(log::Level::Debug);

test(
"examples/rad-clone.md",
working.join("bob"),
Some(&bob.home),
[],
)
.unwrap();

formula(&environment.tmp(), "examples/rad-push-and-pull-patches.md")
.unwrap()
.home(
"alice",
working.join("alice"),
[("RAD_HOME", alice.home.path().display())],
)
.home(
"bob",
working.join("bob").join("heartwood"),
[("RAD_HOME", bob.home.path().display())],
)
.run()
.unwrap();
}

#[test]
fn rad_patch_fetch_1() {
let mut environment = Environment::new();
let mut alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob")));
let working = environment.tmp().join("working");
let (repo, _) = fixtures::repository(working.join("alice"));
let rid = alice.project_from("heartwood", "Radicle Heartwood Protocol & Stack", &repo);

let alice = alice.spawn();
let mut bob = bob.spawn();

bob.connect(&alice).converge([&alice]);
bob.clone(rid, working.join("bob")).unwrap();

formula(&environment.tmp(), "examples/rad-patch-fetch-1.md")
.unwrap()
.home(
"alice",
working.join("alice"),
[("RAD_HOME", alice.home.path().display())],
)
.home(
"bob",
working.join("bob").join("heartwood"),
[("RAD_HOME", bob.home.path().display())],
)
.run()
.unwrap();
}

#[test]
fn rad_patch_fetch_2() {
let mut environment = Environment::new();
let alice = environment.node(Config::test(Alias::new("alice")));
let working = environment.tmp().join("working");

fixtures::repository(working.join("alice"));

test(
"examples/rad-init.md",
working.join("alice"),
Some(&alice.home),
[],
)
.unwrap();

test(
"examples/rad-patch-fetch-2.md",
working.join("alice"),
Some(&alice.home),
[],
)
.unwrap();
}

#[test]
fn git_push_and_fetch() {
let mut environment = Environment::new();
let alice = environment.node(Config::test(Alias::new("alice")));
let bob = environment.node(Config::test(Alias::new("bob")));
Expand Down Expand Up @@ -1566,7 +1670,7 @@ fn git_push_and_pull() {
)
.unwrap();
test(
"examples/git/git-pull.md",
"examples/git/git-fetch.md",
&working.join("bob"),
Some(&bob.home),
[],
Expand Down
16 changes: 15 additions & 1 deletion radicle-node/src/test/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
}
}

/// Clone a repo into a directory.
pub fn clone<P: AsRef<Path>>(&self, rid: Id, cwd: P) -> io::Result<()> {
self.rad("clone", &[rid.to_string().as_str()], cwd)
}

/// Run a `rad` CLI command.
pub fn rad<P: AsRef<Path>>(&self, cmd: &str, args: &[&str], cwd: P) -> io::Result<()> {
let cwd = cwd.as_ref();
Expand Down Expand Up @@ -402,11 +407,12 @@ impl<G: cyphernet::Ecdh<Pk = NodeId> + Signer + Clone> Node<G> {
) -> Id {
transport::local::register(self.storage.clone());

let branch = refname!("master");
let id = rad::init(
repo,
name,
description,
refname!("master"),
branch.clone(),
Visibility::default(),
&self.signer,
&self.storage,
Expand Down Expand Up @@ -437,6 +443,14 @@ impl<G: cyphernet::Ecdh<Pk = NodeId> + Signer + Clone> Node<G> {
}
git::push(repo, "rad", refs.iter().map(|(a, b)| (a, b))).unwrap();

radicle::git::set_upstream(
repo,
&*radicle::rad::REMOTE_NAME,
branch.clone(),
radicle::git::refs::workdir::branch(&branch),
)
.unwrap();

self.storage
.repository(id)
.unwrap()
Expand Down
6 changes: 5 additions & 1 deletion radicle-remote-helper/src/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ pub fn run<R: ReadRepository>(
};
}

let mut opts = git::raw::FetchOptions::new();
// Setting this to false ensures that the FETCH_HEAD is set correctly. Go figure.
opts.update_fetchhead(false);

git::raw::Repository::open(working)?
.remote_anonymous(&git::url::File::new(stored.path()).to_string())?
.fetch(&refspecs, None, None)?;
.fetch(&refspecs, Some(&mut opts), None)?;

// Nb. An empty line means we're done.
println!();
Expand Down

0 comments on commit e703bad

Please sign in to comment.