Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
remote-helper: Fix `FETCH_HEAD` setting on fetch
cloudhead committed 2 years ago
commit e703bad294cc89358da319ac5f94cb89f22b897a
parent 2fc65def46564de46e9b1f5b2b7a81e4029b6058
8 files changed +296 -35
added radicle-cli/examples/git/git-fetch.md
@@ -0,0 +1,31 @@
+
```
+
$ cd heartwood
+
$ git branch -r
+
  alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
+
  rad/master
+
```
+

+
```
+
$ git ls-remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/heads/*'
+
145e1e69bef3ad93d14946ea212249c2fa9b9828	refs/heads/alice/1
+
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354	refs/heads/master
+
```
+

+
``` (stderr)
+
$ git fetch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
✓ Synced with 1 peer(s)
+
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
 * [new branch]      alice/1    -> alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
+
```
+

+
```
+
$ git branch -r
+
  alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
+
  alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
+
  rad/master
+
```
+

+
```
+
$ git rev-parse alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
+
145e1e69bef3ad93d14946ea212249c2fa9b9828
+
```
deleted radicle-cli/examples/git/git-pull.md
@@ -1,31 +0,0 @@
-
```
-
$ cd heartwood
-
$ git branch -r
-
  alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
-
  rad/master
-
```
-

-
```
-
$ git ls-remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/heads/*'
-
145e1e69bef3ad93d14946ea212249c2fa9b9828	refs/heads/alice/1
-
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354	refs/heads/master
-
```
-

-
``` (stderr)
-
$ git fetch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
✓ Synced with 1 peer(s)
-
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
 * [new branch]      alice/1    -> alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
-
```
-

-
```
-
$ git branch -r
-
  alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
-
  alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
-
  rad/master
-
```
-

-
```
-
$ git rev-parse alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
-
145e1e69bef3ad93d14946ea212249c2fa9b9828
-
```
added radicle-cli/examples/rad-patch-fetch-1.md
@@ -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
+
```
added radicle-cli/examples/rad-patch-fetch-2.md
@@ -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
+
```
added radicle-cli/examples/rad-push-and-pull-patches.md
@@ -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
+
```
modified radicle-cli/tests/commands.rs
@@ -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")));
@@ -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),
        [],
modified radicle-node/src/test/environment.rs
@@ -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();
@@ -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,
@@ -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()
modified radicle-remote-helper/src/fetch.rs
@@ -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!();