Skip to content

Commit 1b6ba5d

Browse files
authored
feat(cli): Add --target-dir option (#7350)
1 parent 31becc6 commit 1b6ba5d

File tree

7 files changed

+52
-17
lines changed

7 files changed

+52
-17
lines changed

cspell.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
"envrc",
9494
"EXPONENTIATE",
9595
"Flamegraph",
96+
"flamegraphs",
9697
"flate",
9798
"fmtstr",
9899
"foldl",
@@ -120,6 +121,7 @@
120121
"impls",
121122
"indexmap",
122123
"injective",
124+
"interners",
123125
"Inlines",
124126
"instrumenter",
125127
"interner",
@@ -227,6 +229,7 @@
227229
"tempdir",
228230
"tempfile",
229231
"termcolor",
232+
"termion",
230233
"thiserror",
231234
"tslog",
232235
"turbofish",

tooling/lsp/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ pub(crate) fn resolve_workspace_for_source_path(file_path: &Path) -> Result<Work
316316
members: vec![assumed_package],
317317
selected_package_index: Some(0),
318318
is_assumed: true,
319+
target_dir: None,
319320
};
320321
Ok(workspace)
321322
}

tooling/lsp/src/requests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ pub(crate) fn find_all_references_in_workspace(
598598
));
599599
}
600600

601-
// The LSP client usually removes duplicate loctions, but we do it here just in case they don't
601+
// The LSP client usually removes duplicate locations, but we do it here just in case they don't
602602
locations.sort_by_key(|location| {
603603
(
604604
location.uri.to_string(),

tooling/nargo/src/workspace.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use crate::{
2020
#[derive(Clone)]
2121
pub struct Workspace {
2222
pub root_dir: PathBuf,
23+
/// Optional target directory override.
24+
pub target_dir: Option<PathBuf>,
2325
pub members: Vec<Package>,
2426
// If `Some()`, the `selected_package_index` is used to select the only `Package` when iterating a Workspace
2527
pub selected_package_index: Option<usize>,
@@ -34,7 +36,7 @@ impl Workspace {
3436
}
3537

3638
pub fn target_directory_path(&self) -> PathBuf {
37-
self.root_dir.join(TARGET_DIR)
39+
self.target_dir.as_ref().cloned().unwrap_or_else(|| self.root_dir.join(TARGET_DIR))
3840
}
3941

4042
pub fn export_directory_path(&self) -> PathBuf {

tooling/nargo_cli/benches/criterion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn criterion_test_execution(c: &mut Criterion, test_program_dir: &Path, force_br
156156
});
157157
}
158158

159-
/// Go through all the selected tests and executem with and without Brillig.
159+
/// Go through all the selected tests and execute them with and without Brillig.
160160
fn criterion_selected_tests_execution(c: &mut Criterion) {
161161
for test_program_dir in get_selected_tests() {
162162
for force_brillig in [false, true] {

tooling/nargo_cli/src/cli/mod.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@ struct NargoCli {
5656
#[derive(Args, Clone, Debug)]
5757
pub(crate) struct NargoConfig {
5858
// REMINDER: Also change this flag in the LSP test lens if renamed
59-
#[arg(long, hide = true, global = true, default_value = "./")]
59+
#[arg(long, hide = true, global = true, default_value = "./", value_parser = parse_path)]
6060
program_dir: PathBuf,
61+
62+
/// Override the default target directory.
63+
#[arg(long, hide = true, global = true, value_parser = parse_path)]
64+
target_dir: Option<PathBuf>,
6165
}
6266

6367
/// Options for commands that work on either workspace or package scope.
@@ -130,14 +134,7 @@ enum LockType {
130134
#[cfg(not(feature = "codegen-docs"))]
131135
#[tracing::instrument(level = "trace")]
132136
pub(crate) fn start_cli() -> eyre::Result<()> {
133-
use fm::NormalizePath;
134-
135-
let NargoCli { command, mut config } = NargoCli::parse();
136-
137-
// If the provided `program_dir` is relative, make it absolute by joining it to the current directory.
138-
if !config.program_dir.is_absolute() {
139-
config.program_dir = std::env::current_dir().unwrap().join(config.program_dir).normalize();
140-
}
137+
let NargoCli { command, config } = NargoCli::parse();
141138

142139
match command {
143140
NargoCommand::New(args) => new_cmd::run(args, config),
@@ -194,14 +191,17 @@ where
194191
// or a specific package; if that's the case then parse the package name to select it in the workspace.
195192
let selection = match cmd.package_selection() {
196193
PackageSelection::DefaultOrAll if workspace_dir != package_dir => {
197-
let workspace = read_workspace(&package_dir, PackageSelection::DefaultOrAll)?;
198-
let package = workspace.into_iter().next().expect("there should be exactly 1 package");
194+
let package = read_workspace(&package_dir, PackageSelection::DefaultOrAll)?;
195+
let package = package.into_iter().next().expect("there should be exactly 1 package");
199196
PackageSelection::Selected(package.name.clone())
200197
}
201198
other => other,
202199
};
203200
// Parse the top level workspace with the member selected.
204-
let workspace = read_workspace(&workspace_dir, selection)?;
201+
let mut workspace = read_workspace(&workspace_dir, selection)?;
202+
// Optionally override the target directory. It's only done here because most commands like the LSP and DAP
203+
// don't read or write artifacts, so they don't use the target directory.
204+
workspace.target_dir = config.target_dir.clone();
205205
// Lock manifests if the command needs it.
206206
let _locks = match cmd.lock_type() {
207207
LockType::None => None,
@@ -249,18 +249,44 @@ fn lock_workspace(workspace: &Workspace, exclusive: bool) -> Result<Vec<impl Dro
249249
Ok(locks)
250250
}
251251

252+
/// Parses a path and turns it into an absolute one by joining to the current directory.
253+
fn parse_path(path: &str) -> Result<PathBuf, String> {
254+
use fm::NormalizePath;
255+
let mut path: PathBuf = path.parse().map_err(|e| format!("failed to parse path: {e}"))?;
256+
if !path.is_absolute() {
257+
path = std::env::current_dir().unwrap().join(path).normalize();
258+
}
259+
Ok(path)
260+
}
261+
252262
#[cfg(test)]
253263
mod tests {
264+
use super::NargoCli;
254265
use clap::Parser;
266+
255267
#[test]
256268
fn test_parse_invalid_expression_width() {
257269
let cmd = "nargo --program-dir . compile --expression-width 1";
258-
let res = super::NargoCli::try_parse_from(cmd.split_ascii_whitespace());
270+
let res = NargoCli::try_parse_from(cmd.split_ascii_whitespace());
259271

260272
let err = res.expect_err("should fail because of invalid width");
261273
assert!(err.to_string().contains("expression-width"));
262274
assert!(err
263275
.to_string()
264276
.contains(acvm::compiler::MIN_EXPRESSION_WIDTH.to_string().as_str()));
265277
}
278+
279+
#[test]
280+
fn test_parse_target_dir() {
281+
let cmd = "nargo --program-dir . --target-dir ../foo/bar execute";
282+
let cli = NargoCli::try_parse_from(cmd.split_ascii_whitespace()).expect("should parse");
283+
284+
let target_dir = cli.config.target_dir.expect("should parse target dir");
285+
assert!(target_dir.is_absolute(), "should be made absolute");
286+
assert!(target_dir.ends_with("foo/bar"));
287+
288+
let cmd = "nargo --program-dir . execute";
289+
let cli = NargoCli::try_parse_from(cmd.split_ascii_whitespace()).expect("should parse");
290+
assert!(cli.config.target_dir.is_none());
291+
}
266292
}

tooling/nargo_toml/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ fn toml_to_workspace(
396396
selected_package_index: Some(0),
397397
members: vec![member],
398398
is_assumed: false,
399+
target_dir: None,
399400
},
400401
}
401402
}
@@ -448,6 +449,7 @@ fn toml_to_workspace(
448449
members,
449450
selected_package_index,
450451
is_assumed: false,
452+
target_dir: None,
451453
}
452454
}
453455
};
@@ -514,14 +516,15 @@ pub enum PackageSelection {
514516
}
515517

516518
/// Resolves a Nargo.toml file into a `Workspace` struct as defined by our `nargo` core.
519+
///
520+
/// As a side effect it downloads project dependencies as well.
517521
pub fn resolve_workspace_from_toml(
518522
toml_path: &Path,
519523
package_selection: PackageSelection,
520524
current_compiler_version: Option<String>,
521525
) -> Result<Workspace, ManifestError> {
522526
let nargo_toml = read_toml(toml_path)?;
523527
let workspace = toml_to_workspace(nargo_toml, package_selection)?;
524-
525528
if let Some(current_compiler_version) = current_compiler_version {
526529
semver::semver_check_workspace(&workspace, current_compiler_version)?;
527530
}

0 commit comments

Comments
 (0)