Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli/clone: Add flag `--bare`
Lorenz Leutgeb committed 7 months ago
commit 3795bdff78c2d7a45112a571dc9b0bac5b07de53
parent 48f7949b41b480ae751d934fc23e4fe109b98b30
4 files changed +136 -5
modified CHANGELOG.md
@@ -13,6 +13,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## New Features

+
- `rad clone` now supports the flag `--bare` which works analoguously to 
+
  `git clone --bare`.
+

+
## Fixed Bugs
+

+
## 1.4.0
+

+
## Release Highlights
+

+
## Deprecations
+

+
## New Features
+

- `rad cob log` now supports the arguments `--from` and `--to` which can be used
  to range over particular operations on a COB.

added crates/radicle-cli/examples/rad-clone-bare.md
@@ -0,0 +1,81 @@
+
To create a local bare copy of a repository on the radicle network, we use the
+
`clone` command, followed by the identifier or *RID* of the repository:
+

+
```
+
$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed --bare
+
✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
+
Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found [..] potential seed(s).
+
✓ Target met: [..] seed(s)
+
✓ Creating checkout in ./heartwood..
+
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
+
✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
✓ Repository successfully cloned under [..]/heartwood/
+
╭────────────────────────────────────╮
+
│ heartwood                          │
+
│ Radicle Heartwood Protocol & Stack │
+
│ 0 issues · 0 patches               │
+
╰────────────────────────────────────╯
+
Run `cd ./heartwood` to go to the repository directory.
+
```
+

+
We can now have a look at the new directory that was created from the cloned
+
repository:
+

+
```
+
$ cd heartwood
+
$ ls
+
FETCH_HEAD
+
HEAD
+
config
+
description
+
hooks
+
info
+
objects
+
refs
+
```
+

+
As expected, some `git` commands fail:
+
``` (stderr) (fail)
+
$ git status
+
fatal: this operation must be run in a work tree
+
```
+

+
Let's check that the remote tracking branch was setup correctly:
+

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

+
The first branch is ours, and the second points to the repository delegate.
+
We can also take a look at the remotes:
+

+
```
+
$ git remote -v
+
alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi	rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (fetch)
+
alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi	rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
+
rad	rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji (fetch)
+
rad	rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (push)
+
```
+

+
Let's check the last commit!
+

+
```
+
$ git log -n 1
+
commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
+
Author: anonymous <anonymous@radicle.xyz>
+
Date:   Mon Jan 1 14:39:16 2018 +0000
+

+
    Second commit
+
```
+

+
Cloned repositories show up in `rad ls`:
+
```
+
$ rad ls --seeded
+
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+
│ Name        RID                                 Visibility   Head      Description                        │
+
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
+
│ heartwood   rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji   public       f2de534   Radicle Heartwood Protocol & Stack │
+
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
+
```
modified crates/radicle-cli/src/commands/clone.rs
@@ -46,6 +46,7 @@ Usage

Options

+
        --bare              Make a bare repository
        --scope <scope>     Follow scope: `followed` or `all` (default: all)
    -s, --seed <nid>        Clone from this seed (may be specified multiple times)
        --timeout <secs>    Timeout for fetching repository (default: 9)
@@ -64,6 +65,7 @@ pub struct Options {
    scope: Scope,
    /// Sync settings.
    sync: SyncSettings,
+
    bare: bool,
}

impl Args for Options {
@@ -75,6 +77,7 @@ impl Args for Options {
        let mut scope = Scope::All;
        let mut sync = SyncSettings::default();
        let mut directory = None;
+
        let mut bare = false;

        while let Some(arg) = parser.next()? {
            match arg {
@@ -99,6 +102,9 @@ impl Args for Options {
                    // We keep this flag here for consistency though it doesn't have any effect,
                    // since the command is fully non-interactive.
                }
+
                Long("bare") => {
+
                    bare = true;
+
                }
                Long("help") | Short('h') => {
                    return Err(Error::Help.into());
                }
@@ -125,6 +131,7 @@ impl Args for Options {
                directory,
                scope,
                sync,
+
                bare,
            },
            vec![],
        ))
@@ -153,6 +160,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        options.sync.with_profile(&profile),
        &mut node,
        &profile,
+
        options.bare,
    )?
    .print_or_success()
    .ok_or_else(|| anyhow::anyhow!("failed to clone {}", options.id))?;
@@ -163,7 +171,11 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        .filter(|id| id != profile.id())
        .collect::<Vec<_>>();
    let default_branch = proj.default_branch().clone();
-
    let path = working.workdir().unwrap(); // SAFETY: The working copy is not bare.
+
    let path = if !options.bare {
+
        working.workdir().unwrap()
+
    } else {
+
        working.path()
+
    };

    // Configure repository and setup tracking for repository delegates.
    radicle::git::configure_repository(&working)?;
@@ -229,6 +241,7 @@ struct Checkout {
    repository: storage::git::Repository,
    doc: Doc,
    project: Project,
+
    bare: bool,
}

impl Checkout {
@@ -236,6 +249,7 @@ impl Checkout {
        repository: storage::git::Repository,
        profile: &Profile,
        directory: Option<PathBuf>,
+
        bare: bool,
    ) -> Result<Self, CheckoutFailure> {
        let rid = repository.rid();
        let doc = repository
@@ -257,6 +271,7 @@ impl Checkout {
            repository,
            doc: doc.doc,
            project: proj,
+
            bare,
        })
    }

@@ -274,7 +289,7 @@ impl Checkout {
            "Creating checkout in ./{}..",
            term::format::tertiary(destination.display())
        ));
-
        match rad::checkout(self.id, &self.remote, self.path, storage, false) {
+
        match rad::checkout(self.id, &self.remote, self.path, storage, self.bare) {
            Err(err) => {
                spinner.message(format!(
                    "Failed to checkout in ./{}",
@@ -303,6 +318,7 @@ fn clone(
    settings: SyncSettings,
    node: &mut Node,
    profile: &Profile,
+
    bare: bool,
) -> Result<CloneResult, CloneError> {
    // Seed repository.
    if node.seed(id, scope)? {
@@ -322,7 +338,7 @@ fn clone(
                node::sync::FetcherResult::TargetReached(_) => {
                    profile.storage.repository(id).map_or_else(
                        |err| Ok(CloneResult::RepositoryMissing { rid: id, err }),
-
                        |repository| Ok(perform_checkout(repository, profile, directory)?),
+
                        |repository| Ok(perform_checkout(repository, profile, directory, bare)?),
                    )
                }
                node::sync::FetcherResult::TargetError(failure) => {
@@ -330,7 +346,7 @@ fn clone(
                }
            }
        }
-
        Ok(repository) => Ok(perform_checkout(repository, profile, directory)?),
+
        Ok(repository) => Ok(perform_checkout(repository, profile, directory, bare)?),
    }
}

@@ -338,8 +354,9 @@ fn perform_checkout(
    repository: storage::git::Repository,
    profile: &Profile,
    directory: Option<PathBuf>,
+
    bare: bool,
) -> Result<CloneResult, rad::CheckoutError> {
-
    Checkout::new(repository, profile, directory).map_or_else(
+
    Checkout::new(repository, profile, directory, bare).map_or_else(
        |failure| Ok(CloneResult::Failure(failure)),
        |checkout| checkout.run(&profile.storage),
    )
modified crates/radicle-cli/tests/commands.rs
@@ -1156,6 +1156,26 @@ fn rad_clone() {
}

#[test]
+
fn rad_clone_bare() {
+
    let mut environment = Environment::new();
+
    let mut alice = environment.node("alice");
+
    let bob = environment.node("bob");
+
    let working = environment.tempdir().join("working");
+

+
    // Setup a test project.
+
    let acme = alice.project("heartwood", "Radicle Heartwood Protocol & Stack");
+

+
    let mut alice = alice.spawn();
+
    let mut bob = bob.spawn();
+
    // Prevent Alice from fetching Bob's fork, as we're not testing that and it may cause errors.
+
    alice.handle.seed(acme, Scope::Followed).unwrap();
+

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

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

+
#[test]
fn rad_clone_directory() {
    let mut environment = Environment::new();
    let mut alice = environment.node("alice");