Skip to main content

release_kit/cli/
depend.rs

1//! Arguments for `rk depend`.
2
3use camino::Utf8PathBuf;
4use clap::{Args, Subcommand, ValueEnum};
5use serde::Serialize;
6
7/// Add another project as a dependency of a target, from how the source distributes itself.
8#[derive(Debug, Args)]
9pub struct DependArgs {
10    /// What to do with the dependency.
11    #[command(subcommand)]
12    pub action: DependAction,
13}
14
15/// The depend operations.
16#[derive(Debug, Subcommand)]
17pub enum DependAction {
18    /// Read the source and the target, offline, and report every way the dependency can land.
19    Assess(AssessArgs),
20    /// Serve the fragment or the native command for one way; seed a manager file only where the target has none.
21    Add(AddArgs),
22}
23
24/// Arguments for `rk depend assess`.
25#[derive(Debug, Args)]
26pub struct AssessArgs {
27    /// The dependency's checkout: a local directory, never a URL.
28    #[arg(long)]
29    pub source: Utf8PathBuf,
30
31    /// The project that takes the dependency.
32    #[arg(long, default_value = ".")]
33    pub target: Utf8PathBuf,
34
35    /// Emit one JSON object on stdout instead of the human report.
36    #[arg(long)]
37    pub json: bool,
38}
39
40/// Arguments for `rk depend add`.
41#[derive(Debug, Args)]
42pub struct AddArgs {
43    /// The dependency's checkout: a local directory, never a URL.
44    #[arg(long)]
45    pub source: Utf8PathBuf,
46
47    /// The project that takes the dependency.
48    #[arg(long, default_value = ".")]
49    pub target: Utf8PathBuf,
50
51    /// dev: a tool on PATH in the development environment; prod: a library the code imports.
52    #[arg(long, value_enum)]
53    pub kind: Kind,
54
55    /// The target's tool manager; required when the target carries several, or none.
56    #[arg(long, value_enum)]
57    pub manager: Option<Manager>,
58
59    /// How the source is fetched; the first viable channel for the manager by default.
60    #[arg(long, value_enum)]
61    pub channel: Option<Channel>,
62
63    /// The version to pin: 1.2.3, v1.2.3, or the release URL; the source tree's declared version by default.
64    #[arg(long)]
65    pub pin: Option<String>,
66
67    /// Write the seed file; without it the fragment or command is printed and nothing is written.
68    #[arg(long)]
69    pub apply: bool,
70
71    /// Emit one JSON object on stdout instead of the human report.
72    #[arg(long)]
73    pub json: bool,
74}
75
76/// What kind of dependency the target takes.
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, ValueEnum)]
78#[serde(rename_all = "kebab-case")]
79#[value(rename_all = "kebab-case")]
80pub enum Kind {
81    /// A tool on PATH in the development environment.
82    Dev,
83    /// A library the code imports, through the technology's own manifest.
84    Prod,
85}
86
87impl Kind {
88    /// The wire form.
89    #[must_use]
90    pub const fn as_str(self) -> &'static str {
91        match self {
92            Self::Dev => "dev",
93            Self::Prod => "prod",
94        }
95    }
96}
97
98/// The target's tool manager.
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, ValueEnum)]
100#[serde(rename_all = "kebab-case")]
101#[value(rename_all = "kebab-case")]
102pub enum Manager {
103    /// A Nix flake: an input pinned at a tag and its package in the devshell.
104    Flake,
105    /// mise: one `[tools]` entry in its configuration file.
106    Mise,
107    /// asdf: one line in `.tool-versions`.
108    Asdf,
109    /// devbox: one entry in the `packages` array of `devbox.json`.
110    Devbox,
111}
112
113impl Manager {
114    /// The wire form.
115    #[must_use]
116    pub const fn as_str(self) -> &'static str {
117        match self {
118            Self::Flake => "flake",
119            Self::Mise => "mise",
120            Self::Asdf => "asdf",
121            Self::Devbox => "devbox",
122        }
123    }
124
125    /// Every manager, in the order the reports list them.
126    pub const ALL: [Self; 4] = [Self::Flake, Self::Mise, Self::Asdf, Self::Devbox];
127}
128
129/// Where the source is fetched from.
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, ValueEnum)]
131#[serde(rename_all = "kebab-case")]
132#[value(rename_all = "kebab-case")]
133pub enum Channel {
134    /// The crate on crates.io.
135    Crates,
136    /// The flake the source repository serves, at a tag.
137    Flake,
138    /// The project on the Python package index.
139    Pypi,
140    /// The package on the npm registry.
141    Npm,
142    /// The prebuilt archives attached to a GitHub release.
143    GithubRelease,
144}
145
146impl Channel {
147    /// The wire form.
148    #[must_use]
149    pub const fn as_str(self) -> &'static str {
150        match self {
151            Self::Crates => "crates",
152            Self::Flake => "flake",
153            Self::Pypi => "pypi",
154            Self::Npm => "npm",
155            Self::GithubRelease => "github-release",
156        }
157    }
158
159    /// Every channel, in the order the reports list them.
160    pub const ALL: [Self; 5] = [
161        Self::Crates,
162        Self::Flake,
163        Self::Pypi,
164        Self::Npm,
165        Self::GithubRelease,
166    ];
167}