Skip to content

Commit

Permalink
reindeer [-c reindeer.toml] reads manifest_path + third_party_dir fro…
Browse files Browse the repository at this point in the history
…m config

Creates third party dir if it doesn't exist.
  • Loading branch information
cormacrelf committed Jan 14, 2025
1 parent 30d0c2d commit 43dc5b4
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub(crate) fn run_cargo(
let mut cargo_command = if let Some(cargo_path) = args.cargo_path.as_ref() {
Command::new(cargo_path)
} else if let Some(bin) = config.cargo.cargo.as_ref() {
Command::new(config.config_path.join(bin))
Command::new(config.config_dir.join(bin))
} else {
Command::new("cargo")
};
Expand All @@ -143,7 +143,7 @@ pub(crate) fn run_cargo(
}
}
} else if let Some(bin) = config.cargo.rustc.as_ref() {
cargo_command.env("RUSTC", config.config_path.join(bin));
cargo_command.env("RUSTC", config.config_dir.join(bin));
}

if let Some(cargo_home) = cargo_home {
Expand Down
20 changes: 16 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,17 @@ use crate::universe::UniverseName;
pub struct Config {
/// Path the config was read from
#[serde(skip)]
pub config_path: PathBuf,
pub config_dir: PathBuf,

/// Path to the Cargo.toml we are buckifying
#[serde(default)]
pub manifest_path: Option<PathBuf>,

/// Where to write the output.
///
/// (Default = "", i.e. current directory)
#[serde(default)]
pub third_party_dir: Option<PathBuf>,

/// Try to compute a precise list of sources rather than using globbing
#[serde(default)]
Expand Down Expand Up @@ -325,11 +335,13 @@ where
deserializer.deserialize_any(VendorConfigVisitor)
}

pub fn read_config(dir: &Path) -> anyhow::Result<Config> {
let reindeer_toml = dir.join("reindeer.toml");
pub fn read_config(reindeer_toml: &Path) -> anyhow::Result<Config> {
let dir = reindeer_toml
.parent()
.context("Invalid path to reindeer.toml")?;
let mut config = try_read_config(&reindeer_toml)?;

config.config_path = dir.to_path_buf();
config.config_dir = dir.to_path_buf();

if config.buck.buckfile_imports.is_default {
// Fill in some prelude imports so Reindeer generates working targets
Expand Down
100 changes: 83 additions & 17 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
//!
//! (TBD - rest of it)
use std::path::Path;
use std::path::PathBuf;

use anyhow::Context;
use clap::Parser;
use clap::Subcommand;

Expand Down Expand Up @@ -56,14 +58,23 @@ pub struct Args {
/// Extra cargo options
#[arg(long, value_name = "ARGUMENT")]
cargo_options: Vec<String>,
/// Path to third-party dir
#[arg(long, default_value = ".", value_name = "PATH")]
third_party_dir: PathBuf,
/// Path to third-party dir. Overrides configuration from `reindeer.toml`.
///
/// Path is relative to current dir, whereas the one in `reindeer.toml` is relative to the
/// parent directory of the `reindeer.toml` file.
#[arg(long, value_name = "PATH")]
third_party_dir: Option<PathBuf>,
#[command(subcommand)]
subcommand: SubCommand,
/// Path to the `Cargo.toml to generate from
/// Path to the `Cargo.toml to generate from. Overrides configuration from `reindeer.toml`.
///
/// Path is relative to current dir, whereas the one in `reindeer.toml` is relative to the
/// parent directory of the `reindeer.toml` file.
#[arg(long, value_name = "PATH")]
manifest_path: Option<PathBuf>,
/// Path to a `reindeer.toml` file to read configuration from.
#[arg(short = 'c', long, value_name = "PATH")]
config: Option<PathBuf>,
}

#[derive(Debug, Subcommand)]
Expand Down Expand Up @@ -110,19 +121,74 @@ pub struct Paths {
fn try_main() -> anyhow::Result<()> {
let args = Args::parse();

let third_party_dir = dunce::canonicalize(&args.third_party_dir)?;
let mut config = config::read_config(&third_party_dir)?;

let manifest_path = args
.manifest_path
.clone()
.unwrap_or_else(|| third_party_dir.join("Cargo.toml"));
let paths = Paths {
lockfile_path: manifest_path.with_file_name("Cargo.lock"),
manifest_path,
cargo_home: third_party_dir.join(".cargo"),
third_party_dir,
};
let paths;
let mut config;

if let Some(from_args) = args.third_party_dir.as_deref() {
let third_party_dir = dunce::canonicalize(&from_args)?;
config = config::read_config(&third_party_dir.join("reindeer.toml"))?;

let manifest_path = args
.manifest_path
.clone()
.unwrap_or_else(|| third_party_dir.join("Cargo.toml"));

paths = Paths {
lockfile_path: manifest_path.with_file_name("Cargo.lock"),
manifest_path,
cargo_home: third_party_dir.join(".cargo"),
third_party_dir,
};
} else {
let config_path = args.config.as_deref().unwrap_or(Path::new("reindeer.toml"));
config = config::read_config(config_path)?;

// These unwrap sequences look gnarly, but essentially
// - `reindeer` (no flags) == `reindeer -c reindeer.toml`
// - config.third_party_dir and config.manifest_path are new, and many projects
// don't have them
// - third_party_dir defaulted to . before, and remains so
// - manifest_path was not configurable before, so absent configuration remains
// {third_party_dir}/Cargo.toml
let third_party_dir = args
.third_party_dir
.clone()
.or_else(|| Some(config.config_dir.join(config.third_party_dir.as_deref()?)))
.unwrap_or_else(|| ".".into());
let third_party_dir = dunce::canonicalize(&third_party_dir)?;

let manifest_path = args
.manifest_path
.clone()
.or_else(|| Some(config.config_dir.join(config.manifest_path.as_deref()?)))
.unwrap_or_else(|| third_party_dir.join("Cargo.toml"));

let lockfile_path = manifest_path.with_file_name("Cargo.lock");

paths = Paths {
lockfile_path,
manifest_path,
cargo_home: third_party_dir.join(".cargo"),
third_party_dir,
};
}

if !paths.manifest_path.is_file() {
return Err(anyhow::anyhow!(
"Path {} is not a file",
paths.manifest_path.display()
));
}

if !paths.third_party_dir.exists() {
std::fs::create_dir_all(&paths.third_party_dir)
.with_context(|| format!("Creating directory {}", paths.third_party_dir.display()))?;
} else if !paths.third_party_dir.is_dir() {
return Err(anyhow::anyhow!(
"Path {} must be a directory",
paths.manifest_path.display()
));
}

log::debug!("Args = {:#?}, paths {:#?}", args, paths);

Expand Down

0 comments on commit 43dc5b4

Please sign in to comment.