Skip to content

Commit 17788e9

Browse files
committed
[spr] initial version
Created using spr 1.3.6-beta.1
1 parent 570f7cb commit 17788e9

File tree

5 files changed

+57
-567
lines changed

5 files changed

+57
-567
lines changed

bin/src/dispatch.rs

Lines changed: 43 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
use anyhow::{Context, Result, bail};
66
use camino::Utf8PathBuf;
77
use chrono::{DateTime, Utc};
8-
use clap::{CommandFactory, Parser};
9-
use semver::Version;
10-
use tufaceous_artifact::{
11-
ArtifactKind, ArtifactVersion, ArtifactsDocument, KnownArtifactKind,
12-
};
8+
use clap::Parser;
9+
use tufaceous_artifact::{ArtifactsDocument, KnownArtifactKind};
1310
use tufaceous_lib::assemble::{ArtifactManifest, OmicronRepoAssembler};
14-
use tufaceous_lib::{AddArtifact, ArchiveExtractor, Key, OmicronRepo};
11+
use tufaceous_lib::{ArchiveExtractor, Key, OmicronRepo};
1512

1613
#[derive(Debug, Parser)]
1714
pub struct Args {
@@ -38,117 +35,44 @@ pub struct Args {
3835
impl Args {
3936
/// Executes these arguments.
4037
pub async fn exec(self, log: &slog::Logger) -> Result<()> {
41-
let repo_path = match self.repo {
42-
Some(repo) => repo,
43-
None => std::env::current_dir()?.try_into()?,
44-
};
45-
4638
match self.command {
47-
// TODO-cleanup: we no longer use the init and add commands in
48-
// production. We should get rid of these options and direct users
49-
// towards assemble. (If necessary, we should build tooling for
50-
// making it easy to build up a manifest that can then be
51-
// assembled.)
52-
Command::Init { system_version, no_generate_key } => {
53-
let keys = maybe_generate_keys(self.keys, no_generate_key)?;
54-
let root =
55-
tufaceous_lib::root::new_root(keys.clone(), self.expiry)
56-
.await?;
57-
58-
let repo = OmicronRepo::initialize(
59-
log,
60-
&repo_path,
61-
system_version,
62-
keys,
63-
root,
64-
self.expiry,
65-
true,
66-
)
67-
.await?;
68-
slog::info!(
69-
log,
70-
"Initialized TUF repository in {}",
71-
repo.repo_path()
72-
);
73-
Ok(())
74-
}
75-
Command::Add {
76-
kind,
77-
allow_unknown_kinds,
78-
path,
79-
name,
80-
version,
39+
Command::Assemble {
40+
manifest_path,
41+
output_path,
42+
build_dir,
43+
no_generate_key,
44+
skip_all_present,
8145
allow_non_semver,
46+
no_installinator_document,
8247
} => {
83-
if !allow_unknown_kinds {
84-
// Try converting kind to a known kind.
85-
if kind.to_known().is_none() {
86-
// Simulate a failure to parse (though ideally there would
87-
// be a way to also specify the underlying error -- there
88-
// doesn't appear to be a public API to do so in clap 4).
89-
let mut error = clap::Error::new(
90-
clap::error::ErrorKind::ValueValidation,
91-
)
92-
.with_cmd(&Args::command());
93-
error.insert(
94-
clap::error::ContextKind::InvalidArg,
95-
clap::error::ContextValue::String(
96-
"<KIND>".to_owned(),
97-
),
98-
);
99-
error.insert(
100-
clap::error::ContextKind::InvalidValue,
101-
clap::error::ContextValue::String(kind.to_string()),
102-
);
103-
error.exit();
104-
}
48+
// The filename must end with "zip".
49+
if output_path.extension() != Some("zip") {
50+
bail!("output path `{output_path}` must end with .zip");
10551
}
10652

53+
let manifest = ArtifactManifest::from_path(&manifest_path)
54+
.context("error reading manifest")?;
10755
if !allow_non_semver {
108-
if let Err(error) = version.as_str().parse::<Version>() {
109-
let error = Args::command().error(
110-
clap::error::ErrorKind::ValueValidation,
111-
format!(
112-
"version `{version}` is not valid semver \
113-
(pass in --allow-non-semver to override): {error}"
114-
),
115-
);
116-
error.exit();
117-
}
56+
manifest.verify_all_semver()?;
57+
}
58+
if !skip_all_present {
59+
manifest.verify_all_present()?;
11860
}
11961

120-
let repo = OmicronRepo::load_untrusted_ignore_expiration(
121-
log, &repo_path,
122-
)
123-
.await?;
124-
let mut editor = repo.into_editor().await?;
125-
126-
let new_artifact =
127-
AddArtifact::from_path(kind, name, version, path)?;
128-
129-
editor
130-
.add_artifact(&new_artifact)
131-
.context("error adding artifact")?;
132-
editor.sign_and_finish(self.keys, self.expiry, true).await?;
133-
println!(
134-
"added {} {}, version {}",
135-
new_artifact.kind(),
136-
new_artifact.name(),
137-
new_artifact.version()
62+
let keys = maybe_generate_keys(self.keys, no_generate_key)?;
63+
let mut assembler = OmicronRepoAssembler::new(
64+
log,
65+
manifest,
66+
keys,
67+
self.expiry,
68+
!no_installinator_document,
69+
output_path,
13870
);
139-
Ok(())
140-
}
141-
Command::Archive { output_path } => {
142-
// The filename must end with "zip".
143-
if output_path.extension() != Some("zip") {
144-
bail!("output path `{output_path}` must end with .zip");
71+
if let Some(dir) = build_dir {
72+
assembler.set_build_dir(dir);
14573
}
14674

147-
let repo = OmicronRepo::load_untrusted_ignore_expiration(
148-
log, &repo_path,
149-
)
150-
.await?;
151-
repo.archive(&output_path)?;
75+
assembler.build().await?;
15276

15377
Ok(())
15478
}
@@ -166,7 +90,7 @@ impl Args {
16690
.with_context(|| {
16791
format!(
16892
"error loading extracted repository at `{dest}` \
169-
(extracted files are still available)"
93+
(extracted files are still available)"
17094
)
17195
})?;
17296
let artifacts =
@@ -207,46 +131,6 @@ impl Args {
207131
})?;
208132
}
209133

210-
Ok(())
211-
}
212-
Command::Assemble {
213-
manifest_path,
214-
output_path,
215-
build_dir,
216-
no_generate_key,
217-
skip_all_present,
218-
allow_non_semver,
219-
no_installinator_document,
220-
} => {
221-
// The filename must end with "zip".
222-
if output_path.extension() != Some("zip") {
223-
bail!("output path `{output_path}` must end with .zip");
224-
}
225-
226-
let manifest = ArtifactManifest::from_path(&manifest_path)
227-
.context("error reading manifest")?;
228-
if !allow_non_semver {
229-
manifest.verify_all_semver()?;
230-
}
231-
if !skip_all_present {
232-
manifest.verify_all_present()?;
233-
}
234-
235-
let keys = maybe_generate_keys(self.keys, no_generate_key)?;
236-
let mut assembler = OmicronRepoAssembler::new(
237-
log,
238-
manifest,
239-
keys,
240-
self.expiry,
241-
!no_installinator_document,
242-
output_path,
243-
);
244-
if let Some(dir) = build_dir {
245-
assembler.set_build_dir(dir);
246-
}
247-
248-
assembler.build().await?;
249-
250134
Ok(())
251135
}
252136
}
@@ -255,60 +139,6 @@ impl Args {
255139

256140
#[derive(Debug, Parser)]
257141
enum Command {
258-
/// Create a new rack update TUF repository
259-
Init {
260-
/// The system version.
261-
system_version: Version,
262-
263-
/// Disable random key generation and exit if no keys are provided
264-
#[clap(long)]
265-
no_generate_key: bool,
266-
},
267-
Add {
268-
/// The kind of artifact this is.
269-
kind: ArtifactKind,
270-
271-
/// Allow artifact kinds that aren't known to tufaceous
272-
#[clap(long)]
273-
allow_unknown_kinds: bool,
274-
275-
/// Path to the artifact.
276-
path: Utf8PathBuf,
277-
278-
/// Override the name for this artifact (default: filename with extension stripped)
279-
#[clap(long)]
280-
name: Option<String>,
281-
282-
/// Artifact version.
283-
///
284-
/// This is required to be semver by default, but can be overridden with
285-
/// --allow-non-semver.
286-
version: ArtifactVersion,
287-
288-
/// Allow versions to be non-semver.
289-
///
290-
/// Transitional option for v13 -> v14. After v14, versions will be
291-
/// allowed to be non-semver by default.
292-
#[clap(long)]
293-
allow_non_semver: bool,
294-
},
295-
/// Archives this repository to a zip file.
296-
Archive {
297-
/// The path to write the archive to (must end with .zip).
298-
output_path: Utf8PathBuf,
299-
},
300-
/// Validates and extracts a repository created by the `archive` command.
301-
Extract {
302-
/// The file to extract.
303-
archive_file: Utf8PathBuf,
304-
305-
/// The destination to extract the file to.
306-
dest: Utf8PathBuf,
307-
308-
/// Indicate that the file does not contain an installinator document.
309-
#[clap(long)]
310-
no_installinator_document: bool,
311-
},
312142
/// Assembles a repository from a provided manifest.
313143
Assemble {
314144
/// Path to artifact manifest.
@@ -342,6 +172,18 @@ enum Command {
342172
#[clap(long)]
343173
no_installinator_document: bool,
344174
},
175+
/// Validates and extracts a repository created by the `assemble` command.
176+
Extract {
177+
/// The file to extract.
178+
archive_file: Utf8PathBuf,
179+
180+
/// The destination to extract the file to.
181+
dest: Utf8PathBuf,
182+
183+
/// Indicate that the file does not contain an installinator document.
184+
#[clap(long)]
185+
no_installinator_document: bool,
186+
},
345187
}
346188

347189
fn maybe_generate_keys(

0 commit comments

Comments
 (0)