1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::fs;
use std::path::PathBuf;
use anyhow::{bail, Context as AnyhowContext, Result};
use clap::Parser;
use crate::config::Config;
use crate::context::Context;
use crate::lockfile::{lock_context, write_lockfile};
use crate::metadata::{load_metadata, Annotations, Cargo};
use crate::rendering::{write_outputs, Renderer};
use crate::splicing::SplicingManifest;
#[derive(Parser, Debug)]
#[clap(about = "Command line options for the `generate` subcommand", version)]
pub struct GenerateOptions {
#[clap(long, env = "CARGO")]
pub cargo: Option<PathBuf>,
#[clap(long, env = "RUSTC")]
pub rustc: Option<PathBuf>,
#[clap(long)]
pub config: PathBuf,
#[clap(long)]
pub splicing_manifest: PathBuf,
#[clap(long)]
pub lockfile: Option<PathBuf>,
#[clap(long)]
pub cargo_lockfile: PathBuf,
#[clap(long)]
pub repository_dir: PathBuf,
#[clap(long)]
pub cargo_config: Option<PathBuf>,
#[clap(long)]
pub repin: bool,
#[clap(long)]
pub metadata: Option<PathBuf>,
#[clap(long)]
pub dry_run: bool,
}
pub fn generate(opt: GenerateOptions) -> Result<()> {
let config = Config::try_from_path(&opt.config)?;
if !opt.repin {
if let Some(lockfile) = &opt.lockfile {
let context = Context::try_from_path(lockfile)?;
let outputs = Renderer::new(config.rendering).render(&context)?;
write_outputs(outputs, &opt.repository_dir, opt.dry_run)?;
return Ok(());
}
}
let cargo_bin = Cargo::new(match opt.cargo {
Some(bin) => bin,
None => bail!("The `--cargo` argument is required when generating unpinned content"),
});
let rustc_bin = match &opt.rustc {
Some(bin) => bin,
None => bail!("The `--rustc` argument is required when generating unpinned content"),
};
let metadata_path = match &opt.metadata {
Some(path) => path,
None => bail!("The `--metadata` argument is required when generating unpinned content"),
};
let (cargo_metadata, cargo_lockfile) = load_metadata(metadata_path)?;
let render_config = config.rendering.clone();
let annotations = Annotations::new(cargo_metadata, cargo_lockfile.clone(), config.clone())?;
let context = Context::new(annotations)?;
let outputs = Renderer::new(render_config).render(&context)?;
write_outputs(outputs, &opt.repository_dir, opt.dry_run)?;
if let Some(lockfile) = opt.lockfile {
let splicing_manifest = SplicingManifest::try_from_path(&opt.splicing_manifest)?;
let lock_content =
lock_context(context, &config, &splicing_manifest, &cargo_bin, rustc_bin)?;
write_lockfile(lock_content, &lockfile, opt.dry_run)?;
}
fs::write(&opt.cargo_lockfile, cargo_lockfile.to_string())
.context("Failed to write Cargo.lock file back to the workspace.")?;
Ok(())
}