mirror of
https://github.com/nix-community/nurl.git
synced 2024-08-15 13:00:22 +03:00
add --overwrite and --overwrite-str
This commit is contained in:
parent
834bb2cedc
commit
6dc540c192
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -172,12 +172,6 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780"
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.3"
|
||||
@ -242,9 +236,9 @@ dependencies = [
|
||||
"clap_complete",
|
||||
"clap_mangen",
|
||||
"enum_dispatch",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"owo-colors",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
@ -325,6 +319,12 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.6"
|
||||
|
@ -14,9 +14,9 @@ categories = ["command-line-utilities"]
|
||||
[dependencies]
|
||||
anyhow = "1.0.68"
|
||||
enum_dispatch = "0.3.9"
|
||||
indoc = "1.0.8"
|
||||
itertools = "0.10.5"
|
||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||
rustc-hash = "1.1.0"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.91"
|
||||
url = "2.3.1"
|
||||
|
21
src/cli.rs
21
src/cli.rs
@ -38,6 +38,27 @@ pub struct Opts {
|
||||
#[arg(short, long = "arg", num_args = 2, value_names = ["KEY", "VALUE"])]
|
||||
pub args: Vec<String>,
|
||||
|
||||
/// overwrite arguments in the final output,
|
||||
/// not taken into consideration when fetching the hash
|
||||
///
|
||||
/// Note that nurl does not verify any of the overwrites,
|
||||
/// for the final output to be valid,
|
||||
/// the user should not overwrite anything that would change the hash
|
||||
///
|
||||
/// examples:
|
||||
/// {n} --overwrite repo pname
|
||||
/// {n} --overwrite rev version
|
||||
#[arg(short, long = "overwrite", num_args = 2, value_names = ["NAME", "EXPR"])]
|
||||
pub overwrites: Vec<String>,
|
||||
|
||||
/// same as --overwrite, but accepts strings instead Nix expressions
|
||||
///
|
||||
/// examples:
|
||||
/// {n} --overwrite-str rev 'v${version}'
|
||||
/// {n} --overwrite-str meta.homepage https://example.org
|
||||
#[arg(short = 'O', long = "overwrite-str", num_args = 2, value_names = ["NAME", "STRING"])]
|
||||
pub overwrites_str: Vec<String>,
|
||||
|
||||
/// List all available fetchers
|
||||
#[arg(short, long, group = "command")]
|
||||
pub list_fetchers: bool,
|
||||
|
@ -20,6 +20,7 @@ pub use sourcehut::FetchFromSourcehut;
|
||||
|
||||
use anyhow::Result;
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use rustc_hash::FxHashMap;
|
||||
use url::Url;
|
||||
|
||||
use std::io::Write;
|
||||
@ -32,6 +33,7 @@ pub trait Fetcher {
|
||||
url: &Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: FxHashMap<String, String>,
|
||||
indent: String,
|
||||
) -> Result<()>;
|
||||
fn fetch_json(
|
||||
@ -40,6 +42,8 @@ pub trait Fetcher {
|
||||
url: &Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: Vec<(String, String)>,
|
||||
overwrites_str: Vec<(String, String)>,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
||||
@ -66,9 +70,10 @@ macro_rules! impl_fetcher {
|
||||
url: &::url::Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: ::rustc_hash::FxHashMap<String, String>,
|
||||
indent: String,
|
||||
) -> ::anyhow::Result<()> {
|
||||
self.fetch_nix_impl(out, url, rev, args, indent)
|
||||
self.fetch_nix_impl(out, url, rev, args, overwrites, indent)
|
||||
}
|
||||
|
||||
fn fetch_json(
|
||||
@ -77,8 +82,10 @@ macro_rules! impl_fetcher {
|
||||
url: &::url::Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: Vec<(String, String)>,
|
||||
overwrites_str: Vec<(String, String)>,
|
||||
) -> ::anyhow::Result<()> {
|
||||
self.fetch_json_impl(out, url, rev, args)
|
||||
self.fetch_json_impl(out, url, rev, args, overwrites, overwrites_str)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
25
src/main.rs
25
src/main.rs
@ -8,6 +8,7 @@ mod simple;
|
||||
use anyhow::{bail, Result};
|
||||
use clap::{Parser, ValueEnum};
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::{
|
||||
cli::{FetcherFunction, Opts},
|
||||
@ -100,9 +101,29 @@ fn main() -> Result<()> {
|
||||
let out = &mut stdout().lock();
|
||||
let args = opts.args.into_iter().tuples().collect();
|
||||
if opts.json {
|
||||
fetcher.fetch_json(out, &opts.url, opts.rev, args)
|
||||
fetcher.fetch_json(
|
||||
out,
|
||||
&opts.url,
|
||||
opts.rev,
|
||||
args,
|
||||
opts.overwrites.into_iter().tuples().collect(),
|
||||
opts.overwrites_str.into_iter().tuples().collect(),
|
||||
)
|
||||
} else {
|
||||
fetcher.fetch_nix(out, &opts.url, opts.rev, args, " ".repeat(opts.indent))
|
||||
let mut overwrites: FxHashMap<_, _> = opts.overwrites.into_iter().tuples().collect();
|
||||
|
||||
for (key, value) in opts.overwrites_str.into_iter().tuples() {
|
||||
overwrites.insert(key, format!(r#""{value}""#));
|
||||
}
|
||||
|
||||
fetcher.fetch_nix(
|
||||
out,
|
||||
&opts.url,
|
||||
opts.rev,
|
||||
args,
|
||||
overwrites,
|
||||
" ".repeat(opts.indent),
|
||||
)
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
|
@ -1,6 +1,6 @@
|
||||
use anyhow::{Context, Result};
|
||||
use indoc::writedoc;
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde_json::json;
|
||||
use url::Url;
|
||||
|
||||
@ -73,27 +73,43 @@ pub trait SimpleFetcher<'a, const N: usize = 2> {
|
||||
rev: String,
|
||||
hash: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: FxHashMap<String, String>,
|
||||
indent: String,
|
||||
) -> Result<()> {
|
||||
let mut overwrites = overwrites;
|
||||
|
||||
writeln!(out, "{} {{", Self::NAME)?;
|
||||
|
||||
if let Some(host) = self.host() {
|
||||
if let Some(host) = overwrites.remove(Self::HOST_KEY) {
|
||||
writeln!(out, r#"{indent} {} = {host};"#, Self::HOST_KEY)?;
|
||||
} else if let Some(host) = self.host() {
|
||||
writeln!(out, r#"{indent} {} = "{host}";"#, Self::HOST_KEY)?;
|
||||
}
|
||||
|
||||
for (key, value) in Self::KEYS.iter().zip(values) {
|
||||
writeln!(out, r#"{indent} {key} = "{value}";"#)?;
|
||||
if let Some(value) = overwrites.remove(*key) {
|
||||
writeln!(out, r#"{indent} {key} = {value};"#)?;
|
||||
} else {
|
||||
writeln!(out, r#"{indent} {key} = "{value}";"#)?;
|
||||
}
|
||||
}
|
||||
|
||||
writedoc!(
|
||||
out,
|
||||
r#"
|
||||
{indent} rev = "{rev}";
|
||||
{indent} hash = "{hash}";
|
||||
"#
|
||||
)?;
|
||||
if let Some(rev) = overwrites.remove("rev") {
|
||||
writeln!(out, "{indent} rev = {rev};")?;
|
||||
} else {
|
||||
writeln!(out, r#"{indent} rev = "{rev}";"#)?;
|
||||
}
|
||||
if let Some(hash) = overwrites.remove("hash") {
|
||||
writeln!(out, "{indent} hash = {hash};")?;
|
||||
} else {
|
||||
writeln!(out, r#"{indent} hash = "{hash}";"#)?;
|
||||
}
|
||||
|
||||
for (key, value) in args {
|
||||
let value = overwrites.remove(&key).unwrap_or(value);
|
||||
writeln!(out, "{indent} {key} = {value};")?;
|
||||
}
|
||||
for (key, value) in overwrites {
|
||||
writeln!(out, "{indent} {key} = {value};")?;
|
||||
}
|
||||
|
||||
@ -109,6 +125,8 @@ pub trait SimpleFetcher<'a, const N: usize = 2> {
|
||||
rev: String,
|
||||
hash: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: Vec<(String, String)>,
|
||||
overwrites_str: Vec<(String, String)>,
|
||||
) -> Result<()> {
|
||||
let mut fetcher_args = json! ({
|
||||
"rev": rev,
|
||||
@ -130,6 +148,16 @@ pub trait SimpleFetcher<'a, const N: usize = 2> {
|
||||
});
|
||||
}
|
||||
|
||||
for (key, value) in overwrites {
|
||||
fetcher_args[key] = json!({
|
||||
"type": "nix",
|
||||
"value": value,
|
||||
})
|
||||
}
|
||||
for (key, value) in overwrites_str {
|
||||
fetcher_args[key] = json!(value);
|
||||
}
|
||||
|
||||
serde_json::to_writer(
|
||||
out,
|
||||
&json!({
|
||||
@ -149,10 +177,11 @@ pub trait SimpleFodFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
url: &'a Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: FxHashMap<String, String>,
|
||||
indent: String,
|
||||
) -> Result<()> {
|
||||
let (values, hash) = self.fetch_fod(url, &rev, &args)?;
|
||||
self.write_nix(out, values, rev, hash, args, indent)
|
||||
self.write_nix(out, values, rev, hash, args, overwrites, indent)
|
||||
}
|
||||
|
||||
fn fetch_json_impl(
|
||||
@ -161,9 +190,11 @@ pub trait SimpleFodFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
url: &'a Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: Vec<(String, String)>,
|
||||
overwrites_str: Vec<(String, String)>,
|
||||
) -> Result<()> {
|
||||
let (values, hash) = self.fetch_fod(url, &rev, &args)?;
|
||||
self.write_json(out, values, rev, hash, args)
|
||||
self.write_json(out, values, rev, hash, args, overwrites, overwrites_str)
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,6 +229,7 @@ pub trait SimpleFlakeFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
url: &'a Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: FxHashMap<String, String>,
|
||||
indent: String,
|
||||
) -> Result<()> {
|
||||
let (values, hash) = if args.is_empty() {
|
||||
@ -206,7 +238,7 @@ pub trait SimpleFlakeFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
self.fetch_fod(url, &rev, &args)?
|
||||
};
|
||||
|
||||
self.write_nix(out, values, rev, hash, args, indent)
|
||||
self.write_nix(out, values, rev, hash, args, overwrites, indent)
|
||||
}
|
||||
|
||||
fn fetch_json_impl(
|
||||
@ -215,13 +247,15 @@ pub trait SimpleFlakeFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
url: &'a Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: Vec<(String, String)>,
|
||||
overwrites_str: Vec<(String, String)>,
|
||||
) -> Result<()> {
|
||||
let (values, hash) = if args.is_empty() {
|
||||
self.fetch(url, &rev)?
|
||||
} else {
|
||||
self.fetch_fod(url, &rev, &args)?
|
||||
};
|
||||
self.write_json(out, values, rev, hash, args)
|
||||
self.write_json(out, values, rev, hash, args, overwrites, overwrites_str)
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,6 +276,7 @@ pub trait SimpleUrlFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
url: &'a Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: FxHashMap<String, String>,
|
||||
indent: String,
|
||||
) -> Result<()> {
|
||||
let (values, hash) = if args.is_empty() {
|
||||
@ -250,7 +285,7 @@ pub trait SimpleUrlFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
self.fetch_fod(url, &rev, &args)?
|
||||
};
|
||||
|
||||
self.write_nix(out, values, rev, hash, args, indent)
|
||||
self.write_nix(out, values, rev, hash, args, overwrites, indent)
|
||||
}
|
||||
|
||||
fn fetch_json_impl(
|
||||
@ -259,12 +294,14 @@ pub trait SimpleUrlFetcher<'a, const N: usize = 2>: SimpleFetcher<'a, N> {
|
||||
url: &'a Url,
|
||||
rev: String,
|
||||
args: Vec<(String, String)>,
|
||||
overwrites: Vec<(String, String)>,
|
||||
overwrites_str: Vec<(String, String)>,
|
||||
) -> Result<()> {
|
||||
let (values, hash) = if args.is_empty() {
|
||||
self.fetch(url, &rev)?
|
||||
} else {
|
||||
self.fetch_fod(url, &rev, &args)?
|
||||
};
|
||||
self.write_json(out, values, rev, hash, args)
|
||||
self.write_json(out, values, rev, hash, args, overwrites, overwrites_str)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user