make revision optional

implement fetching the latest revision for github and gitlab
This commit is contained in:
figsoda 2023-01-08 12:10:03 -05:00
parent c7a3c95197
commit 1e8389c104
7 changed files with 303 additions and 11 deletions

215
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.68"
@ -39,6 +45,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -57,6 +69,12 @@ dependencies = [
"serde",
]
[[package]]
name = "bumpalo"
version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "cc"
version = "1.0.78"
@ -154,6 +172,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
@ -275,6 +302,16 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "flate2"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "form_urlencoded"
version = "1.1.0"
@ -408,6 +445,15 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.139"
@ -420,6 +466,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
@ -435,6 +490,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "nom8"
version = "0.2.0"
@ -484,6 +548,7 @@ dependencies = [
"serde",
"serde_json",
"trycmd",
"ureq",
"url",
]
@ -639,6 +704,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "roff"
version = "0.2.1"
@ -665,6 +745,18 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "rustls"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "ryu"
version = "1.0.12"
@ -686,6 +778,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "serde"
version = "1.0.152"
@ -757,6 +859,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "485e65c1203eb37244465e857d15a26d3a85a5410648ccb53b18bd44cb3a7336"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "strsim"
version = "0.10.0"
@ -912,6 +1020,30 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "ureq"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "733b5ad78377302af52c0dbcb2623d78fe50e4b3bf215948ff29e9ee031d8566"
dependencies = [
"base64",
"flate2",
"log",
"once_cell",
"rustls",
"serde",
"serde_json",
"url",
"webpki",
"webpki-roots",
]
[[package]]
name = "url"
version = "2.3.1"
@ -949,6 +1081,89 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "web-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
dependencies = [
"webpki",
]
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -20,6 +20,7 @@ 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"
ureq = { version = "2.6.1", features = ["json"] }
url = "2.3.1"
[dependencies.clap]

View File

@ -15,12 +15,7 @@ pub struct Opts {
pub url: Url,
/// the revision or reference to be fetched
#[arg(
required_unless_present = "command",
default_value_t,
hide_default_value = true
)]
pub rev: String,
pub rev: Option<String>,
/// specify the fetcher function instead of inferring from the URL
#[arg(short, long)]

View File

@ -1,3 +1,6 @@
use anyhow::{anyhow, Result};
use serde::Deserialize;
use crate::{
impl_fetcher,
simple::{SimpleFetcher, SimpleFlakeFetcher},
@ -6,6 +9,11 @@ use crate::{
pub struct FetchFromGitHub<'a>(pub Option<&'a str>);
impl_fetcher!(FetchFromGitHub<'a>);
#[derive(Deserialize)]
struct Commit {
sha: String,
}
impl<'a> SimpleFetcher<'a, 2> for FetchFromGitHub<'a> {
const HOST_KEY: &'static str = "githubBase";
const KEYS: [&'static str; 2] = ["owner", "repo"];
@ -14,6 +22,20 @@ impl<'a> SimpleFetcher<'a, 2> for FetchFromGitHub<'a> {
fn host(&'a self) -> Option<&'a str> {
self.0
}
fn fetch_rev(&self, [owner, repo]: &[&str; 2]) -> Result<String> {
let host = self.0.unwrap_or("github.com");
Ok(
ureq::get(&format!("https://api.{host}/repos/{owner}/{repo}/commits"))
.call()?
.into_json::<Vec<Commit>>()?
.into_iter()
.next()
.ok_or_else(|| anyhow!("no commits found for https://{host}/{owner}/{repo}"))?
.sha,
)
}
}
impl<'a> SimpleFlakeFetcher<'a, 2> for FetchFromGitHub<'a> {

View File

@ -1,6 +1,10 @@
use anyhow::{anyhow, Result};
use once_cell::unsync::OnceCell;
use serde::Deserialize;
use url::Url;
use std::fmt::Write;
use crate::{
impl_fetcher,
simple::{SimpleFetcher, SimpleFlakeFetcher},
@ -21,6 +25,11 @@ impl<'a> FetchFromGitLab<'a> {
}
}
#[derive(Deserialize)]
struct Commit {
id: String,
}
impl<'a> SimpleFetcher<'a, 2> for FetchFromGitLab<'a> {
const KEYS: [&'static str; 2] = ["owner", "repo"];
const NAME: &'static str = "fetchFromGitLab";
@ -45,6 +54,35 @@ impl<'a> SimpleFetcher<'a, 2> for FetchFromGitLab<'a> {
}
})
}
fn fetch_rev(&self, [owner, repo]: &[&str; 2]) -> Result<String> {
let host = self.host.unwrap_or("gitlab.com");
let mut url = format!("https://{host}/api/v4/projects/");
if let Some(group) = self.group.get() {
url.push_str(group);
url.push_str("%2F");
}
write!(url, "{owner}%2F{repo}/repository/commits")?;
Ok(ureq::get(&url)
.call()?
.into_json::<Vec<Commit>>()?
.into_iter()
.next()
.ok_or_else(|| {
let mut msg = format!("no commits found for https://{host}/");
if let Some(group) = self.group.get() {
msg.push_str(group);
msg.push('/');
}
msg.push_str(owner);
msg.push('/');
msg.push_str(repo);
anyhow!(msg)
})?
.id)
}
}
impl<'a> SimpleFlakeFetcher<'a, 2> for FetchFromGitLab<'a> {

View File

@ -33,7 +33,7 @@ pub trait Fetcher<'a> {
&'a self,
out: &mut impl Write,
url: &'a Url,
rev: String,
rev: Option<String>,
args: Vec<(String, String)>,
args_str: Vec<(String, String)>,
overwrites: FxHashMap<String, String>,
@ -44,7 +44,7 @@ pub trait Fetcher<'a> {
&'a self,
out: &mut impl Write,
url: &'a Url,
rev: String,
rev: Option<String>,
args: Vec<(String, String)>,
args_str: Vec<(String, String)>,
overwrites: Vec<(String, String)>,
@ -74,7 +74,7 @@ macro_rules! impl_fetcher {
&'a self,
out: &mut impl ::std::io::Write,
url: &'a ::url::Url,
rev: String,
rev: Option<String>,
args: Vec<(String, String)>,
args_str: Vec<(String, String)>,
overwrites: ::rustc_hash::FxHashMap<String, String>,
@ -85,7 +85,14 @@ macro_rules! impl_fetcher {
let values = &self
.get_values(url)
.with_context(|| format!("failed to parse {url}"))?;
let rev = match rev {
Some(rev) => rev,
None => self.fetch_rev(values)?,
};
let hash = self.fetch(values, &rev, &args, &args_str)?;
self.write_nix(out, values, rev, hash, args, args_str, overwrites, indent)
}
@ -93,7 +100,7 @@ macro_rules! impl_fetcher {
&'a self,
out: &mut impl ::std::io::Write,
url: &'a ::url::Url,
rev: String,
rev: Option<String>,
args: Vec<(String, String)>,
args_str: Vec<(String, String)>,
overwrites: Vec<(String, String)>,
@ -104,7 +111,14 @@ macro_rules! impl_fetcher {
let values = &self
.get_values(url)
.with_context(|| format!("failed to parse {url}"))?;
let rev = match rev {
Some(rev) => rev,
None => self.fetch_rev(values)?,
};
let hash = self.fetch(values, &rev, &args, &args_str)?;
self.write_json(
out,
values,

View File

@ -1,4 +1,4 @@
use anyhow::Result;
use anyhow::{bail, Result};
use itertools::Itertools;
use rustc_hash::FxHashMap;
use serde_json::json;
@ -35,6 +35,13 @@ pub trait SimpleFetcher<'a, const N: usize> {
Some(xs)
}
fn fetch_rev(&self, _: &[&str; N]) -> Result<String> {
bail!(
"{} does not support fetching the latest revision",
Self::NAME,
);
}
fn fetch_fod(
&'a self,
values: &[&str; N],