cli: Create `rad patch ready` command
Allows for converting patches to and from draft mode.
This commit is contained in:
parent
f111681dd6
commit
12a91bd0ae
|
|
@ -0,0 +1,69 @@
|
|||
Let's say we have some changes in a branch:
|
||||
|
||||
```
|
||||
$ git checkout -b cloudhead/draft
|
||||
$ git commit -a -m "Nothing to see here.." -q --allow-empty
|
||||
```
|
||||
|
||||
To open a patch in draft mode, we use the `--draft` option:
|
||||
|
||||
```
|
||||
$ rad patch open --draft -m "Nothing yet" --quiet
|
||||
3bdbfc4f85b942293ba7adb8e47bf3202a602e8b
|
||||
```
|
||||
|
||||
We can confirm it's a draft by running `show`:
|
||||
|
||||
```
|
||||
$ rad patch show 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Title Nothing yet │
|
||||
│ Patch 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b │
|
||||
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
|
||||
│ Head 2a465832b5a76abe25be44a3a5d224bbd7741ba7 │
|
||||
│ Branches cloudhead/draft │
|
||||
│ Commits ahead 1, behind 0 │
|
||||
│ Status draft │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) [ ... ] │
|
||||
╰─────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Once the patch is ready for review, we can use the `ready` command:
|
||||
|
||||
```
|
||||
$ rad patch ready 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b
|
||||
```
|
||||
|
||||
```
|
||||
$ rad patch show 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Title Nothing yet │
|
||||
│ Patch 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b │
|
||||
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
|
||||
│ Head 2a465832b5a76abe25be44a3a5d224bbd7741ba7 │
|
||||
│ Branches cloudhead/draft │
|
||||
│ Commits ahead 1, behind 0 │
|
||||
│ Status open │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) [ ... ] │
|
||||
╰─────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
If for whatever reason, it needed to go back into draft mode, we could use
|
||||
the `--undo` flag:
|
||||
|
||||
```
|
||||
$ rad patch ready --undo 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b
|
||||
$ rad patch show 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Title Nothing yet │
|
||||
│ Patch 3bdbfc4f85b942293ba7adb8e47bf3202a602e8b │
|
||||
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
|
||||
│ Head 2a465832b5a76abe25be44a3a5d224bbd7741ba7 │
|
||||
│ Branches cloudhead/draft │
|
||||
│ Commits ahead 1, behind 0 │
|
||||
│ Status draft │
|
||||
├─────────────────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● opened by did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (you) [ ... ] │
|
||||
╰─────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
|
|
@ -10,6 +10,8 @@ mod create;
|
|||
mod delete;
|
||||
#[path = "patch/list.rs"]
|
||||
mod list;
|
||||
#[path = "patch/ready.rs"]
|
||||
mod ready;
|
||||
#[path = "patch/show.rs"]
|
||||
mod show;
|
||||
#[path = "patch/update.rs"]
|
||||
|
|
@ -45,6 +47,7 @@ Usage
|
|||
rad patch update <patch-id> [<option>...]
|
||||
rad patch checkout <patch-id> [<option>...]
|
||||
rad patch delete <patch-id> [<option>...]
|
||||
rad patch ready <patch-id> [--undo] [<option>...]
|
||||
|
||||
Show options
|
||||
|
||||
|
|
@ -66,6 +69,10 @@ List options
|
|||
--merged Show only merged patches
|
||||
--open Show only open patches (default)
|
||||
|
||||
Ready options
|
||||
|
||||
--undo Convert a patch back to a draft
|
||||
|
||||
Other options
|
||||
|
||||
--help Print help
|
||||
|
|
@ -80,6 +87,7 @@ pub enum OperationName {
|
|||
Archive,
|
||||
Delete,
|
||||
Checkout,
|
||||
Ready,
|
||||
#[default]
|
||||
List,
|
||||
}
|
||||
|
|
@ -103,6 +111,10 @@ pub enum Operation {
|
|||
Archive {
|
||||
patch_id: Rev,
|
||||
},
|
||||
Ready {
|
||||
patch_id: Rev,
|
||||
undo: bool,
|
||||
},
|
||||
Delete {
|
||||
patch_id: Rev,
|
||||
},
|
||||
|
|
@ -138,6 +150,7 @@ impl Args for Options {
|
|||
let mut filter = Some(patch::State::Open);
|
||||
let mut diff = false;
|
||||
let mut draft = false;
|
||||
let mut undo = false;
|
||||
let mut quiet = false;
|
||||
|
||||
while let Some(arg) = parser.next()? {
|
||||
|
|
@ -187,6 +200,11 @@ impl Args for Options {
|
|||
diff = true;
|
||||
}
|
||||
|
||||
// Ready options.
|
||||
Long("undo") if op == Some(OperationName::Ready) => {
|
||||
undo = true;
|
||||
}
|
||||
|
||||
// List options.
|
||||
Long("all") => {
|
||||
filter = None;
|
||||
|
|
@ -217,6 +235,7 @@ impl Args for Options {
|
|||
"d" | "delete" => op = Some(OperationName::Delete),
|
||||
"c" | "checkout" => op = Some(OperationName::Checkout),
|
||||
"a" | "archive" => op = Some(OperationName::Archive),
|
||||
"y" | "ready" => op = Some(OperationName::Ready),
|
||||
unknown => anyhow::bail!("unknown operation '{}'", unknown),
|
||||
},
|
||||
Value(val)
|
||||
|
|
@ -226,6 +245,7 @@ impl Args for Options {
|
|||
Some(OperationName::Update),
|
||||
Some(OperationName::Delete),
|
||||
Some(OperationName::Archive),
|
||||
Some(OperationName::Ready),
|
||||
Some(OperationName::Checkout),
|
||||
]
|
||||
.contains(&op) =>
|
||||
|
|
@ -262,6 +282,10 @@ impl Args for Options {
|
|||
OperationName::Checkout => Operation::Checkout {
|
||||
patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
|
||||
},
|
||||
OperationName::Ready => Operation::Ready {
|
||||
patch_id: patch_id.ok_or_else(|| anyhow!("a patch must be provided"))?,
|
||||
undo,
|
||||
},
|
||||
};
|
||||
|
||||
Ok((
|
||||
|
|
@ -336,6 +360,10 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
let patch_id = patch_id.resolve::<PatchId>(&repository.backend)?;
|
||||
archive::run(&repository, &profile, &patch_id)?;
|
||||
}
|
||||
Operation::Ready { ref patch_id, undo } => {
|
||||
let patch_id = patch_id.resolve::<PatchId>(&repository.backend)?;
|
||||
ready::run(&repository, &profile, &patch_id, undo)?;
|
||||
}
|
||||
Operation::Delete { patch_id } => {
|
||||
let patch_id = patch_id.resolve(&repository.backend)?;
|
||||
delete::run(&repository, &profile, &patch_id)?;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
use super::*;
|
||||
|
||||
use radicle::cob::patch;
|
||||
use radicle::prelude::*;
|
||||
use radicle::storage::git::Repository;
|
||||
|
||||
pub fn run(
|
||||
repository: &Repository,
|
||||
profile: &Profile,
|
||||
patch_id: &PatchId,
|
||||
undo: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
let signer = term::signer(profile)?;
|
||||
let mut patches = patch::Patches::open(repository)?;
|
||||
let Ok(mut patch) = patches.get_mut(patch_id) else {
|
||||
anyhow::bail!("Patch `{patch_id}` not found");
|
||||
};
|
||||
|
||||
if undo {
|
||||
patch.unready(&signer)?;
|
||||
} else {
|
||||
patch.ready(&signer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -271,6 +271,26 @@ fn rad_patch() {
|
|||
test("examples/rad-patch.md", working.path(), Some(home), []).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rad_patch_draft() {
|
||||
let mut environment = Environment::new();
|
||||
let profile = environment.profile("alice");
|
||||
let working = tempfile::tempdir().unwrap();
|
||||
let home = &profile.home;
|
||||
|
||||
// Setup a test repository.
|
||||
fixtures::repository(working.path());
|
||||
|
||||
test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
|
||||
test(
|
||||
"examples/rad-patch-draft.md",
|
||||
working.path(),
|
||||
Some(home),
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rad_rm() {
|
||||
let mut environment = Environment::new();
|
||||
|
|
|
|||
|
|
@ -980,6 +980,26 @@ impl<'a, 'g> PatchMut<'a, 'g> {
|
|||
self.lifecycle(State::Archived, signer)
|
||||
}
|
||||
|
||||
/// Mark a patch as ready to be reviewed. Returns `false` if the patch was not a draft.
|
||||
pub fn ready<G: Signer>(&mut self, signer: &G) -> Result<bool, Error> {
|
||||
if self.state() != State::Draft {
|
||||
return Ok(false);
|
||||
}
|
||||
self.lifecycle(State::Open, signer)?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Mark an open patch as a draft. Returns `false` if the patch was not open.
|
||||
pub fn unready<G: Signer>(&mut self, signer: &G) -> Result<bool, Error> {
|
||||
if self.state() != State::Open {
|
||||
return Ok(false);
|
||||
}
|
||||
self.lifecycle(State::Draft, signer)?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Tag a patch.
|
||||
pub fn tag<G: Signer>(
|
||||
&mut self,
|
||||
|
|
|
|||
Loading…
Reference in New Issue