diff --git a/radicle-cli/examples/git/git-tag.md b/radicle-cli/examples/git/git-tag.md index f9b4dd79..6768f8c9 100644 --- a/radicle-cli/examples/git/git-tag.md +++ b/radicle-cli/examples/git/git-tag.md @@ -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//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 ``` diff --git a/radicle-cli/examples/rad-checkout-repo-config-linux.md b/radicle-cli/examples/rad-checkout-repo-config-linux.md index 69c6f10e..ace75c51 100644 --- a/radicle-cli/examples/rad-checkout-repo-config-linux.md +++ b/radicle-cli/examples/rad-checkout-repo-config-linux.md @@ -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 diff --git a/radicle-cli/examples/rad-checkout-repo-config-macos.md b/radicle-cli/examples/rad-checkout-repo-config-macos.md index 42acc436..ff7bc1f3 100644 --- a/radicle-cli/examples/rad-checkout-repo-config-macos.md +++ b/radicle-cli/examples/rad-checkout-repo-config-macos.md @@ -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 diff --git a/radicle/src/git.rs b/radicle/src/git.rs index 19da1c6d..09fe8ced 100644 --- a/radicle/src/git.rs +++ b/radicle/src/git.rs @@ -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.] /// url = /// pushurl = -/// fetch +refs/heads/*:refs/remotes//* +/// fetch = +refs/heads/*:refs/remotes//* +/// fetch = +refs/tags/*:refs/remotes//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()))?; }