use super::{OwnedEditAction, execute};
use crate::cmd;
use crate::config::Config;
use crate::diagnostic::{DiagnosticResult, Diagnostics};
use crate::model::{ChangelogCategory, ClauseKind, RfcPhase, WorkItemStatus};
use crate::write::{BumpLevel, WriteOp};
use crate::{FinalizeStatus, ListTarget, OutputFormat, RenderTarget};
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Scope {
Global,
Collection {
target: ListTarget,
},
Artifact {
artifact: cmd::edit::ArtifactType,
id: String,
},
Target {
artifact: cmd::edit::ArtifactType,
id: String,
target: cmd::edit::engine::ResolvedTarget,
},
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct EditExtras {
pub category: Option<ChangelogCategory>,
pub scope: Option<String>,
pub pros: Vec<String>,
pub cons: Vec<String>,
pub reject_reason: Option<String>,
}
#[derive(Debug, Clone)]
pub enum BuiltinOp {
Init {
force: bool,
},
InitSkills {
force: bool,
format: crate::SkillFormat,
dir: Option<std::path::PathBuf>,
},
Check {
has_active: bool,
},
Status,
RenderGlobal {
target: RenderTarget,
dry_run: bool,
force: bool,
},
Migrate,
Verify {
guard_ids: Vec<String>,
work: Option<String>,
},
Search {
query: Vec<String>,
types: Vec<ListTarget>,
tags: Vec<String>,
limit: Option<usize>,
output: OutputFormat,
reindex: bool,
},
Describe {
context: bool,
},
Completions {
shell: clap_complete::Shell,
},
SelfUpdate {
check: bool,
},
#[cfg(feature = "tui")]
Tui,
ReleaseCut {
version: String,
date: Option<String>,
},
TagNew {
tag: String,
},
TagDelete {
tag: String,
},
TagList {
output: crate::OutputFormat,
},
LoopStart {
loop_id: Option<String>,
work_ids: Vec<String>,
},
LoopList {
filter: Option<String>,
limit: Option<usize>,
output: crate::OutputFormat,
},
LoopShow {
loop_id: String,
},
LoopResume {
loop_id: String,
},
LoopReplan {
loop_id: String,
},
LoopAdd {
loop_id: String,
field: String,
value: String,
},
LoopRemove {
loop_id: String,
field: String,
value: String,
},
LoopRun {
loop_id: String,
target_work_ids: Vec<String>,
max_rounds: u32,
},
}
impl BuiltinOp {
fn is_lock_free(&self) -> bool {
match self {
Self::Check { .. }
| Self::Status
| Self::Verify { .. }
| Self::Describe { .. }
| Self::Completions { .. }
| Self::SelfUpdate { .. }
| Self::TagList { .. }
| Self::LoopList { .. }
| Self::LoopShow { .. }
| Self::LoopResume { .. } => true,
Self::Search { .. } => true,
#[cfg(feature = "tui")]
Self::Tui => true,
_ => false,
}
}
}
#[derive(Debug, Clone)]
pub enum CreateOp {
Rfc {
title: String,
id: Option<String>,
},
Clause {
clause_id: String,
title: String,
section: String,
kind: ClauseKind,
},
Adr {
title: String,
},
Work {
title: String,
active: bool,
},
Guard {
title: String,
},
}
#[derive(Debug, Clone)]
pub enum EditOp {
Field {
action: OwnedEditAction,
extras: EditExtras,
},
ClauseLegacy {
text: Option<String>,
text_file: Option<PathBuf>,
stdin: bool,
},
}
#[derive(Debug, Clone)]
pub enum LifecycleOp {
Bump {
level: Option<BumpLevel>,
summary: Option<String>,
changes: Vec<String>,
},
Finalize {
status: FinalizeStatus,
},
Advance {
phase: RfcPhase,
},
Deprecate {
force: bool,
},
Supersede {
by: String,
force: bool,
},
AcceptAdr {
force: bool,
},
RejectAdr,
MoveWork {
file_or_id: PathBuf,
status: WorkItemStatus,
},
}
#[derive(Debug, Clone)]
pub enum Op {
Builtin(BuiltinOp),
Create(CreateOp),
List {
filter: Option<String>,
limit: Option<usize>,
output: OutputFormat,
tags: Vec<String>,
},
Get,
Show {
output: OutputFormat,
},
Edit(EditOp),
Lifecycle(LifecycleOp),
Delete {
force: bool,
},
RenderArtifact {
dry_run: bool,
},
}
impl Op {
fn is_lock_free(&self) -> bool {
match self {
Self::Builtin(builtin) => builtin.is_lock_free(),
Self::Get | Self::List { .. } | Self::Show { .. } => true,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LockDisposition {
None,
GovRootExclusive,
}
#[derive(Debug, Clone)]
pub struct CommandPlan {
pub scope: Scope,
pub op: Op,
}
impl CommandPlan {
pub(super) fn new(scope: Scope, op: Op) -> Self {
Self { scope, op }
}
pub fn lock_disposition(&self) -> LockDisposition {
if self.op.is_lock_free() {
LockDisposition::None
} else {
LockDisposition::GovRootExclusive
}
}
pub fn execute(&self, config: &Config, op: WriteOp) -> DiagnosticResult<Diagnostics> {
execute::execute_plan(self, config, op)
}
}