radicle: add tags fetch refspec

Add a fetch refspec to fetch tags from a Radicle remote. The
`--no-tag` option is also included. This is to ensure that it is easy
to collaborate by having tags placed in the remote namespace of
another peer. However, if the namespace is the default `rad` remote,
then tags are expected to be allowed -- this is to pave way for the
feature of canonical tags.

In the tests, the `--tags` option is removed -- and is generally
recommended that it is not used. This is to ensure that it does not
override the `--no-tag` option.
This commit is contained in:
Fintan Halpenny 2024-07-18 09:53:42 +01:00 committed by cloudhead
parent 6763bf31e1
commit 46c2637f77
No known key found for this signature in database
4 changed files with 41 additions and 8 deletions

View File

@ -11,12 +11,26 @@ $ git tag v1.0 -a -m "Release v1.0"
```
``` ~alice (stderr)
$ git push rad v1.0 --tags
$ git push rad v1.0
✓ Synced with 1 node(s)
To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v1.0 -> v1.0
```
Since the `rad` remote is setup to push `tags` using the refspec:
~~~
fetch = +refs/tags/*:refs/remotes/<name>/tags/*
~~~
there's no need to use the `--tags` flag. In fact, we avoid fetching tags into
the global `tags` namespace to keep tags for each remote separate. This is
achieved by also adding the following option to the remote configuration:
~~~
tagOpt = --no-tags
~~~
Bob fetches the tag from Alice, by adding her as a remote:
``` ~bob
@ -28,13 +42,13 @@ $ rad remote add z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --name alice
✓ Remote-tracking branch alice/master created for z6MknSL…StBU8Vi
```
Bob is able to fetch Alice's tag into his working copy by using the
`--tags` flag:
Bob is able to fetch Alice's tag into his working copy, and they're fetched
under the `alice` remote:
``` ~bob (stderr)
$ git fetch alice --tags
$ git fetch alice
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v1.0 -> v1.0
* [new tag] v1.0 -> alice/tags/v1.0
```
Alice forcefully creates a new version of the tag (let's say she made
@ -64,7 +78,7 @@ $ rad sync -f
```
``` ~bob (stderr)
$ git fetch alice --tags -f
$ git fetch alice -f
From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
t [tag update] v1.0 -> v1.0
62d19fd..9dbdebc v1.0 -> alice/tags/v1.0
```

View File

@ -16,6 +16,7 @@ $ cat .git/config
[remote "rad"]
url = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
fetch = +refs/heads/*:refs/remotes/rad/*
fetch = +refs/tags/*:refs/remotes/rad/tags/*
pushurl = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
[branch "master"]
remote = rad

View File

@ -18,6 +18,7 @@ $ cat .git/config
[remote "rad"]
url = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
fetch = +refs/heads/*:refs/remotes/rad/*
fetch = +refs/tags/*:refs/remotes/rad/tags/*
pushurl = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
[branch "master"]
remote = rad

View File

@ -11,6 +11,7 @@ use once_cell::sync::Lazy;
use crate::collections::RandomMap;
use crate::crypto::PublicKey;
use crate::node::Alias;
use crate::rad;
use crate::storage;
use crate::storage::refs::Refs;
use crate::storage::RemoteId;
@ -532,7 +533,9 @@ pub fn configure_repository(repo: &git2::Repository) -> Result<(), git2::Error>
/// [remote.<name>]
/// url = <fetch>
/// pushurl = <push>
/// fetch +refs/heads/*:refs/remotes/<name>/*
/// fetch = +refs/heads/*:refs/remotes/<name>/*
/// fetch = +refs/tags/*:refs/remotes/<name>/tags/*
/// tagOpt = --no-tags
/// ```
pub fn configure_remote<'r>(
repo: &'r git2::Repository,
@ -543,6 +546,20 @@ pub fn configure_remote<'r>(
let fetchspec = format!("+refs/heads/*:refs/remotes/{name}/*");
let remote = repo.remote_with_fetch(name, fetch.to_string().as_str(), &fetchspec)?;
// We want to be able fetch tags from a peer's namespace and this is
// necessary to do so, since Git assumes that tags should always be fetched
// from the top-level `refs/tags` namespace
let tags = format!("+refs/tags/*:refs/remotes/{name}/tags/*");
repo.remote_add_fetch(name, &tags)?;
// Because of the above, if we don't set `--no-tags` then the tags will be
// fetched into `refs/tags` as well. We don't want to do this *unless* it's
// the `rad` remote, which will have the canonical tags
if name != (*rad::REMOTE_NAME).as_str() {
let mut config = repo.config()?;
config.set_str(&format!("remote.{name}.tagOpt"), "--no-tags")?;
}
if push != fetch {
repo.remote_set_pushurl(name, Some(push.to_string().as_str()))?;
}