mirror of
https://github.com/nix-community/nurl.git
synced 2024-09-11 18:39:19 +03:00
switch to git-url to support git urls without a scheme
This commit is contained in:
parent
b97a16d0e0
commit
af7bce854e
82
Cargo.lock
generated
82
Cargo.lock
generated
@ -321,6 +321,50 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git-features"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0019327672cb759f851d1b18fdcc36bb797dc62b925cb93c8c881b54735eb2c2"
|
||||
dependencies = [
|
||||
"git-hash",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git-hash"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1532d82bf830532f8d545c5b7b568e311e3593f16cf7ee9dd0ce03c74b12b99d"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git-path"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e40e68481a06da243d3f4dfd86a4be39c24eefb535017a862e845140dcdb878a"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git-url"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc9a3df0498c511cf34739eab2692352939b54075c2fc96e8f688d402f3f1250"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"git-features",
|
||||
"git-path",
|
||||
"home",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
@ -357,6 +401,21 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
@ -536,10 +595,12 @@ version = "0.3.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
"bstr",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"clap_mangen",
|
||||
"enum_dispatch",
|
||||
"git-url",
|
||||
"itertools",
|
||||
"nu-glob",
|
||||
"once_cell",
|
||||
@ -549,7 +610,6 @@ dependencies = [
|
||||
"serde_json",
|
||||
"trycmd",
|
||||
"ureq",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -931,6 +991,26 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
|
@ -13,7 +13,9 @@ categories = ["command-line-utilities"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.68"
|
||||
bstr = "1.1.0"
|
||||
enum_dispatch = "0.3.11"
|
||||
git-url = "0.13.1"
|
||||
itertools = "0.10.5"
|
||||
once_cell = "1.17.0"
|
||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||
@ -21,7 +23,6 @@ rustc-hash = "1.1.0"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.91"
|
||||
ureq = { version = "2.6.2", features = ["json"] }
|
||||
url = "2.3.1"
|
||||
|
||||
[dependencies.clap]
|
||||
version = "4.1.1"
|
||||
@ -31,7 +32,6 @@ features = ["cargo", "derive", "unicode", "wrap_help"]
|
||||
clap = { version = "4.1.1", features = ["derive"] }
|
||||
clap_complete = "4.1.0"
|
||||
clap_mangen = "0.2.7"
|
||||
url = "2.3.1"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2.0.8"
|
||||
|
@ -1,5 +1,4 @@
|
||||
use clap::{Parser, ValueEnum};
|
||||
use url::Url;
|
||||
|
||||
/// Generate Nix fetcher calls from repository URLs
|
||||
/// https://github.com/nix-community/nurl
|
||||
@ -9,10 +8,10 @@ pub struct Opts {
|
||||
/// URL to the repository to be fetched
|
||||
#[arg(
|
||||
required_unless_present = "command",
|
||||
default_value = "x:", // placeholder value, will not be accessed
|
||||
default_value_t, // placeholder, will not be accessed
|
||||
hide_default_value = true
|
||||
)]
|
||||
pub url: Url,
|
||||
pub url: String,
|
||||
|
||||
/// The revision or reference to be fetched
|
||||
pub rev: Option<String>,
|
||||
|
@ -1,11 +1,10 @@
|
||||
use anyhow::{bail, Context, Result};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde_json::json;
|
||||
use url::Url;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use crate::fetcher::Fetcher;
|
||||
use crate::{fetcher::Fetcher, Url};
|
||||
|
||||
pub struct BuiltinsFetchGit;
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleUrlFetcher},
|
||||
Url,
|
||||
};
|
||||
|
||||
pub struct FetchCrate(pub bool);
|
||||
@ -14,7 +13,7 @@ impl<'a> SimpleFetcher<'a, 1> for FetchCrate {
|
||||
const REV_KEY: &'static str = "version";
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 1]> {
|
||||
let mut xs = url.path_segments()?;
|
||||
let mut xs = url.path_segments();
|
||||
Some([if self.0 {
|
||||
xs.nth(1)?
|
||||
} else {
|
||||
|
@ -1,9 +1,7 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleFlakeFetcher},
|
||||
GitScheme,
|
||||
GitScheme, Url,
|
||||
};
|
||||
|
||||
pub struct Fetchgit(pub GitScheme);
|
||||
@ -15,9 +13,9 @@ impl<'a> SimpleFetcher<'a, 1> for Fetchgit {
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 1]> {
|
||||
Some([if matches!(self.0, GitScheme::Plus) {
|
||||
url.as_ref().strip_prefix("git+")?
|
||||
url.as_str().strip_prefix("git+")?
|
||||
} else {
|
||||
url.as_ref()
|
||||
url.as_str()
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleUrlFetcher},
|
||||
Url,
|
||||
};
|
||||
|
||||
pub struct FetchFromGitiles;
|
||||
@ -12,8 +11,8 @@ impl<'a> SimpleFetcher<'a, 1> for FetchFromGitiles {
|
||||
const KEYS: [&'static str; 1] = ["url"];
|
||||
const NAME: &'static str = "fetchFromGitiles";
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 1]> {
|
||||
Some([url.as_ref()])
|
||||
fn get_values(&self, url: &'a Url<'a>) -> Option<[&'a str; 1]> {
|
||||
Some([url.as_str()])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
use anyhow::{Context, Result};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use serde::Deserialize;
|
||||
use url::Url;
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleFlakeFetcher},
|
||||
Url,
|
||||
};
|
||||
|
||||
pub struct FetchFromGitLab<'a> {
|
||||
@ -42,8 +42,8 @@ impl<'a> SimpleFetcher<'a, 2> for FetchFromGitLab<'a> {
|
||||
self.group.get().copied()
|
||||
}
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 2]> {
|
||||
let mut xs = url.path_segments()?;
|
||||
fn get_values(&self, url: &'a Url<'a>) -> Option<[&'a str; 2]> {
|
||||
let mut xs = url.path_segments();
|
||||
let x = xs.next()?;
|
||||
let y = xs.next()?;
|
||||
Some(match xs.next() {
|
||||
|
@ -1,8 +1,7 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleUrlFetcher},
|
||||
Url,
|
||||
};
|
||||
|
||||
pub struct FetchHex;
|
||||
@ -14,8 +13,8 @@ impl<'a> SimpleFetcher<'a, 1> for FetchHex {
|
||||
const NAME: &'static str = "fetchHex";
|
||||
const REV_KEY: &'static str = "version";
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 1]> {
|
||||
Some([url.path_segments()?.nth(1)?])
|
||||
fn get_values(&self, url: &'a Url<'a>) -> Option<[&'a str; 1]> {
|
||||
Some([url.path_segments().nth(1)?])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleFlakeFetcher},
|
||||
Url,
|
||||
};
|
||||
|
||||
pub struct Fetchhg(pub bool);
|
||||
@ -13,11 +12,11 @@ impl<'a> SimpleFetcher<'a, 1> for Fetchhg {
|
||||
const KEYS: [&'static str; 1] = ["url"];
|
||||
const NAME: &'static str = "fetchhg";
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 1]> {
|
||||
fn get_values(&self, url: &'a Url<'a>) -> Option<[&'a str; 1]> {
|
||||
Some([if self.0 {
|
||||
url.as_ref().strip_prefix("hg+")?
|
||||
url.as_str().strip_prefix("hg+")?
|
||||
} else {
|
||||
url.as_ref()
|
||||
url.as_str()
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,10 @@ pub use repo_or_cz::FetchFromRepoOrCz;
|
||||
pub use sourcehut::FetchFromSourcehut;
|
||||
pub use svn::Fetchsvn;
|
||||
|
||||
use crate::Url;
|
||||
use anyhow::Result;
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use rustc_hash::FxHashMap;
|
||||
use url::Url;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
@ -49,7 +49,7 @@ pub trait Fetcher<'a> {
|
||||
fn fetch_hash(
|
||||
&'a self,
|
||||
out: &mut impl ::std::io::Write,
|
||||
url: &'a Url,
|
||||
url: &'a Url<'a>,
|
||||
rev: Option<String>,
|
||||
args: Vec<(String, String)>,
|
||||
args_str: Vec<(String, String)>,
|
||||
@ -58,7 +58,7 @@ pub trait Fetcher<'a> {
|
||||
fn fetch_json(
|
||||
&'a self,
|
||||
out: &mut impl Write,
|
||||
url: &'a Url,
|
||||
url: &'a Url<'a>,
|
||||
rev: Option<String>,
|
||||
args: Vec<(String, String)>,
|
||||
args_str: Vec<(String, String)>,
|
||||
@ -69,7 +69,7 @@ pub trait Fetcher<'a> {
|
||||
fn to_json(
|
||||
&'a self,
|
||||
out: &mut impl ::std::io::Write,
|
||||
url: &'a ::url::Url,
|
||||
url: &'a Url<'a>,
|
||||
rev: Option<String>,
|
||||
) -> ::anyhow::Result<()>;
|
||||
}
|
||||
@ -98,7 +98,7 @@ macro_rules! impl_fetcher {
|
||||
fn fetch_nix(
|
||||
&'a self,
|
||||
out: &mut impl ::std::io::Write,
|
||||
url: &'a ::url::Url,
|
||||
url: &'a $crate::Url<'a>,
|
||||
rev: Option<String>,
|
||||
args: Vec<(String, String)>,
|
||||
args_str: Vec<(String, String)>,
|
||||
@ -124,7 +124,7 @@ macro_rules! impl_fetcher {
|
||||
fn fetch_hash(
|
||||
&'a self,
|
||||
out: &mut impl ::std::io::Write,
|
||||
url: &'a ::url::Url,
|
||||
url: &'a $crate::Url<'a>,
|
||||
rev: Option<String>,
|
||||
args: Vec<(String, String)>,
|
||||
args_str: Vec<(String, String)>,
|
||||
@ -149,7 +149,7 @@ macro_rules! impl_fetcher {
|
||||
fn fetch_json(
|
||||
&'a self,
|
||||
out: &mut impl ::std::io::Write,
|
||||
url: &'a ::url::Url,
|
||||
url: &'a $crate::Url<'a>,
|
||||
rev: Option<String>,
|
||||
args: Vec<(String, String)>,
|
||||
args_str: Vec<(String, String)>,
|
||||
@ -184,7 +184,7 @@ macro_rules! impl_fetcher {
|
||||
fn to_json(
|
||||
&'a self,
|
||||
out: &mut impl ::std::io::Write,
|
||||
url: &'a ::url::Url,
|
||||
url: &'a $crate::Url<'a>,
|
||||
rev: Option<String>,
|
||||
) -> ::anyhow::Result<()> {
|
||||
use anyhow::Context;
|
||||
|
@ -1,8 +1,7 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
impl_fetcher,
|
||||
simple::{SimpleFetcher, SimpleFodFetcher},
|
||||
Url,
|
||||
};
|
||||
|
||||
pub struct Fetchsvn;
|
||||
@ -14,7 +13,7 @@ impl<'a> SimpleFetcher<'a, 1> for Fetchsvn {
|
||||
const NAME: &'static str = "fetchsvn";
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; 1]> {
|
||||
Some([url.as_ref()])
|
||||
Some([url.as_str()])
|
||||
}
|
||||
}
|
||||
|
||||
|
60
src/main.rs
60
src/main.rs
@ -6,7 +6,9 @@ mod prefetch;
|
||||
mod simple;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use bstr::ByteSlice;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use git_url::Scheme;
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
@ -19,7 +21,32 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use std::io::{stdout, Write};
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
io::{stdout, Write},
|
||||
str::Split,
|
||||
};
|
||||
|
||||
pub struct Url<'a> {
|
||||
url: &'a str,
|
||||
path: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Url<'a> {
|
||||
fn as_str(&'a self) -> &str {
|
||||
self.url
|
||||
}
|
||||
|
||||
fn path_segments(&self) -> Split<char> {
|
||||
self.path.split('/')
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Display for Url<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum GitScheme {
|
||||
Yes,
|
||||
@ -56,7 +83,9 @@ fn main() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let fetcher: FetcherDispatch = match (opts.fetcher, opts.url.host_str(), opts.url.scheme()) {
|
||||
let url: git_url::Url = opts.url.try_into()?;
|
||||
|
||||
let fetcher: FetcherDispatch = match (opts.fetcher, url.host(), &url.scheme) {
|
||||
(Some(FetcherFunction::BuiltinsFetchGit), ..) => BuiltinsFetchGit.into(),
|
||||
|
||||
(None | Some(FetcherFunction::FetchCrate), Some("crates.io"), _) => FetchCrate(true).into(),
|
||||
@ -136,32 +165,43 @@ fn main() -> Result<()> {
|
||||
bail!("fetchHex only supports hex.pm");
|
||||
}
|
||||
|
||||
(None | Some(FetcherFunction::Fetchgit), _, "git") => Fetchgit(GitScheme::Yes).into(),
|
||||
(None | Some(FetcherFunction::Fetchgit), _, scheme) if scheme.starts_with("git+") => {
|
||||
(None | Some(FetcherFunction::Fetchgit), _, Scheme::Git) => Fetchgit(GitScheme::Yes).into(),
|
||||
(None | Some(FetcherFunction::Fetchgit), _, Scheme::Ext(scheme))
|
||||
if scheme.starts_with("git+") =>
|
||||
{
|
||||
Fetchgit(GitScheme::Plus).into()
|
||||
}
|
||||
(Some(FetcherFunction::Fetchgit), ..) => Fetchgit(GitScheme::No).into(),
|
||||
|
||||
(None | Some(FetcherFunction::Fetchhg), _, scheme) if scheme.starts_with("hg+") => {
|
||||
(None | Some(FetcherFunction::Fetchhg), _, Scheme::Ext(scheme))
|
||||
if scheme.starts_with("hg+") =>
|
||||
{
|
||||
Fetchhg(true).into()
|
||||
}
|
||||
(Some(FetcherFunction::Fetchhg), ..) => Fetchhg(false).into(),
|
||||
|
||||
(None, _, "svn") => Fetchsvn.into(),
|
||||
(None, _, Scheme::Ext(scheme)) if scheme == "svn" => Fetchsvn.into(),
|
||||
(Some(FetcherFunction::Fetchsvn), ..) => Fetchsvn.into(),
|
||||
|
||||
(None, ..) => Fetchgit(GitScheme::No).into(),
|
||||
};
|
||||
|
||||
let url_bstring = url.to_bstring();
|
||||
let path = url.path.to_str()?;
|
||||
let url = Url {
|
||||
url: url_bstring.to_str()?,
|
||||
path: path.strip_prefix('/').unwrap_or(path),
|
||||
};
|
||||
|
||||
let out = &mut stdout().lock();
|
||||
let args = opts.args.into_iter().tuples().collect();
|
||||
let args_str = opts.args_str.into_iter().tuples().collect();
|
||||
if opts.hash {
|
||||
fetcher.fetch_hash(out, &opts.url, opts.rev, args, args_str)
|
||||
fetcher.fetch_hash(out, &url, opts.rev, args, args_str)
|
||||
} else if opts.json {
|
||||
fetcher.fetch_json(
|
||||
out,
|
||||
&opts.url,
|
||||
&url,
|
||||
opts.rev,
|
||||
args,
|
||||
args_str,
|
||||
@ -169,7 +209,7 @@ fn main() -> Result<()> {
|
||||
opts.overwrites_str.into_iter().tuples().collect(),
|
||||
)
|
||||
} else if opts.parse {
|
||||
fetcher.to_json(out, &opts.url, opts.rev)
|
||||
fetcher.to_json(out, &url, opts.rev)
|
||||
} else {
|
||||
let mut overwrites: FxHashMap<_, _> = opts.overwrites.into_iter().tuples().collect();
|
||||
|
||||
@ -179,7 +219,7 @@ fn main() -> Result<()> {
|
||||
|
||||
fetcher.fetch_nix(
|
||||
out,
|
||||
&opts.url,
|
||||
&url,
|
||||
opts.rev,
|
||||
args,
|
||||
args_str,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::Url;
|
||||
use anyhow::{bail, Result};
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde_json::{json, Value};
|
||||
use url::Url;
|
||||
|
||||
use std::{fmt::Write as _, io::Write};
|
||||
|
||||
@ -23,9 +23,9 @@ pub trait SimpleFetcher<'a, const N: usize> {
|
||||
None
|
||||
}
|
||||
|
||||
fn get_values(&self, url: &'a Url) -> Option<[&'a str; N]> {
|
||||
fn get_values(&self, url: &'a Url<'a>) -> Option<[&'a str; N]> {
|
||||
let mut xs: [_; N] = url
|
||||
.path_segments()?
|
||||
.path_segments()
|
||||
.chunks(N)
|
||||
.into_iter()
|
||||
.next()?
|
||||
|
Loading…
Reference in New Issue
Block a user