8000 Headless mode by figsoda · Pull Request #665 · nix-community/nix-init · GitHub
[go: up one dir, main page]

Skip to content
7FFF
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ askalono.workspace = true
bstr = "1.12.1"
cargo = "0.93.0"
chumsky = "=1.0.0-alpha.8"
enum_dispatch = "0.3.13"
expand = "0.3.0"
flate2 = "1.1.5"
heck = "0.5.0"
Expand Down Expand Up @@ -93,3 +94,6 @@ vendored = ["cargo/vendored-libgit2", "cargo/vendored-openssl"]
lto = true
panic = "abort"
codegen-units = 1

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(not_build)"] }
7 changes: 5 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ use clap::{CommandFactory, ValueEnum};
use clap_complete::{Shell, generate_to};
use clap_mangen::Man;

include!("src/cli.rs");
mod cli {
include!("src/cli.rs");
}

fn main() {
println!("cargo:rerun-if-env-changed=GEN_ARTIFACTS");
println!("cargo:rustc-cfg=not_build");

if let Some(dir) = env::var_os("GEN_ARTIFACTS") {
let out = &Path::new(&dir);
create_dir_all(out).unwrap();
let cmd = &mut Opts::command();
let cmd = &mut cli::Opts::command();

Man::new(cmd.clone())
.render(&mut File::create(out.join("nix-init.1")).unwrap())
Expand Down
31 changes: 12 additions & 19 deletions src/build.rs → src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,30 @@
use std::fmt::{self, Display, Formatter};

use parse_display::Display;
use crate::cli::CargoVendor;

#[derive(Clone, Copy)]
pub enum BuildType {
pub enum Builder {
BuildGoModule,
BuildPythonPackage {
application: bool,
rust: Option<RustVendor>,
rust: Option<CargoVendor>,
},
BuildRustPackage {
vendor: RustVendor,
vendor: CargoVendor,
},
MkDerivation {
rust: Option<RustVendor>,
rust: Option<CargoVendor>,
},
}

#[derive(Clone, Copy, Display)]
#[display(style = "camelCase")]
pub enum RustVendor {
FetchCargoVendor,
ImportCargoLock,
}

impl Display for BuildType {
impl Display for Builder {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
BuildType::BuildGoModule => {
Builder::BuildGoModule => {
write!(f, "buildGoModule")?;
}

BuildType::BuildPythonPackage { application, rust } => {
Builder::BuildPythonPackage { application, rust } => {
write!(
f,
"buildPython{}",
Expand All @@ -46,18 +39,18 @@ impl Display for BuildType {
}
}

BuildType::BuildRustPackage { vendor } => {
Builder::BuildRustPackage { vendor } => {
write!(
f,
"buildRustPackage - {}",
match vendor {
RustVendor::FetchCargoVendor => "cargoHash",
RustVendor::ImportCargoLock => "cargoLock",
CargoVendor::FetchCargoVendor => "cargoHash",
CargoVendor::ImportCargoLock => "cargoLock",
}
)?;
}

BuildType::MkDerivation { rust } => {
Builder::MkDerivation { rust } => {
write!(f, "stdenv.mkDerivation")?;
if let Some(rust) = rust {
write!(f, " + {rust}")?;
Expand Down
62 changes: 60 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::path::PathBuf;

use clap::Parser;
use clap::{Parser, ValueEnum};

/// Generate Nix packages with hash prefetching, license detection, and more
/// https://github.com/nix-community/nix-init
#[derive(Parser)]
#[command(version, verbatim_doc_comment)]
#[command(verbatim_doc_comment)]
pub struct Opts {
/// The path or directory to output the generated file to
pub output: Option<PathBuf>,
Expand All @@ -14,6 +14,42 @@ pub struct Opts {
#[arg(short, long)]
pub url: Option<String>,

/// Specify the tag or revision
#[arg(long)]
pub rev: Option<String>,

/// Always fetch submodules when possible
///
/// use --submodules=false to never fetch submodules
#[arg(short = 'S', long, num_args=0..=1, require_equals = true, default_missing_value = "true")]
pub submodules: Option<bool>,

/// Specify the version of the package, or print nix-init version if no arguments are present
#[arg(short = 'V', long)]
pub version: Option<Option<String>>,

/// Specify the pname
#[arg(long)]
pub pname: Option<String>,

/// Specify the builder
#[arg(long)]
pub builder: Option<BuilderFunction>,

/// Specify how the cargo dependencies are vendored
#[arg(long)]
pub cargo_vendor: Option<CargoVendor>,

/// Always overwrite files
///
/// use --overwrite=false to never overwrite files
#[arg(short = 'y', long, num_args=0..=1, require_equals = true, default_missing_value = "true")]
pub overwrite: Option<bool>,

/// Don't prompt for anything (requires --url)
#[arg(long)]
pub headless: bool,

/// Path to nixpkgs (in nix)
///
/// Examples:
Expand All @@ -33,3 +69,25 @@ pub struct Opts {
#[arg(short, long)]
pub config: Option<PathBuf>,
}

#[derive(Clone, ValueEnum)]
#[clap(rename_all = "camelCase")]
pub enum BuilderFunction {
BuildGoModule,
BuildPythonApplication,
BuildPythonPackage,
BuildRustPackage,
MkDerivation,
}

#[derive(Clone, Copy, ValueEnum)]
#[clap(rename_all = "camelCase")]
#[cfg_attr(
not_build,
derive(parse_display::Display),
display(style = "camelCase")
)]
pub enum CargoVendor {
FetchCargoVendor,
ImportCargoLock,
}
58 changes: 58 additions & 0 deletions src/frontend/headless.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use std::path::{Path, PathBuf};

use anyhow::{Result, bail};
use tracing::error;

use crate::{
builder::Builder,
fetcher::{Revisions, Version},
frontend::Frontend,
utils::by_name_path,
};

pub struct Headless;

impl Frontend for Headless {
fn url(&mut self) -> Result<String> {
bail!("specifyi 10000 ng a URL with --url is required in headless mode");
}

fn rev(&mut self, revs: Option<Revisions>) -> Result<(String, Option<Version>)> {
Ok(if let Some(mut revs) = revs {
(revs.latest.clone(), revs.versions.remove(&revs.latest))
} else {
(String::new(), None)
})
}

fn fetch_submodules(&mut self) -> Result<bool> {
Ok(true)
}

fn version(&mut self, version: &str) -> Result<String> {
Ok(version.to_owned())
}

fn pname(&mut self, pname: Option<String>) -> Result<String> {
Ok(pname.unwrap_or_default())
}

fn builder(&mut self, builders: Vec<Builder>) -> Result<Builder> {
Ok(builders[0])
}

fn output(&mut self, pname: &str, builder: &Builder) -> Result<PathBuf> {
Ok(match by_name_path(pname, builder) {
Some(path) => path.into(),
None => PathBuf::from("."),
})
}

fn overwrite(&mut self, path: &Path) -> Result<bool> {
error!(
"path {} already exists, use --overwrite to overwrite to always overwrite files",
path.display()
);
Ok(false)
}
}
55 changes: 55 additions & 0 deletions src/frontend/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
mod headless;
mod readline;

use std::path::{Path, PathBuf};

use anyhow::Result;
use enum_dispatch::enum_dispatch;

use crate::{
builder::Builder,
fetcher::{Revisions, Version},
frontend::{headless::Headless, readline::Readline},
};

#[enum_dispatch]
pub trait Frontend {
fn url(&mut self) -> Result<String>;

fn rev(&mut self, revs: Option<Revisions>) -> Result<(String, Option<Version>)>;

fn fetch_submodules(&mut self) -> Result<bool>;

fn version(&mut self, version: &str) -> Result<String>;

fn pname(&mut self, pname: Option<String>) -> Result<String>;

fn builder(&mut self, builders: Vec<Builder>) -> Result<Builder>;

fn output(&mut self, pname: &str, builder: &Builder) -> Result<PathBuf>;

fn overwrite(&mut self, path: &Path) -> Result<bool>;
}

#[enum_dispatch(Frontend)]
pub enum FrontendDispatch {
Headless(Headless),
Readline(Readline),
}

impl FrontendDispatch {
pub fn should_overwrite(&mut self, path: &Path, opt_overwrite: Option<bool>) -> Result<bool> {
match opt_overwrite {
Some(b) => Ok(b),
None => self.overwrite(path),
}
}
}

pub fn headless() -> FrontendDispatch {
Headless.into()
}

pub fn readline() -> Result<FrontendDispatch> {
Readline::new().map(Into::into)
}
Loading
0