Implement package specs files
This commit is contained in:
parent
bc1f1ed082
commit
46336cfaff
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
/target
|
||||
tags
|
||||
package.specs
|
||||
|
254
Cargo.lock
generated
254
Cargo.lock
generated
@ -2,6 +2,15 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -47,6 +56,12 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
@ -62,6 +77,22 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.11"
|
||||
@ -91,6 +122,22 @@ dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.5"
|
||||
@ -153,6 +200,50 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn 2.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.4"
|
||||
@ -304,6 +395,7 @@ checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
name = "hpk"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"cli",
|
||||
"rayon",
|
||||
@ -316,6 +408,30 @@ dependencies = [
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@ -374,18 +490,45 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
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"
|
||||
@ -401,6 +544,25 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
@ -531,6 +693,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.158"
|
||||
@ -634,6 +802,17 @@ dependencies = [
|
||||
"syn 2.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
@ -693,6 +872,12 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
@ -721,6 +906,66 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
@ -752,6 +997,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
@ -26,6 +26,10 @@ tar = { path = "tar" }
|
||||
walkdir = "2.3"
|
||||
zstd = "0.12"
|
||||
|
||||
[dependencies.chrono]
|
||||
version = "0.4"
|
||||
features = ["serde"]
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive"]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use clap::{Arg, ArgAction, Command, ValueHint, value_parser};
|
||||
use clap::{value_parser, Arg, ArgAction, Command, ValueHint};
|
||||
|
||||
pub fn cli() -> Command {
|
||||
Command::new("hpk")
|
||||
@ -9,6 +9,7 @@ pub fn cli() -> Command {
|
||||
.arg_required_else_help(true)
|
||||
.subcommands([
|
||||
create(),
|
||||
init(),
|
||||
search(),
|
||||
info(),
|
||||
install(),
|
||||
@ -42,6 +43,35 @@ fn create() -> Command {
|
||||
.long("package-version")
|
||||
.num_args(1)
|
||||
.required_unless_present("specs"),
|
||||
Arg::new("release")
|
||||
.help("release number")
|
||||
.short('r')
|
||||
.long("release")
|
||||
.default_value("1")
|
||||
.value_parser(value_parser!(u8)),
|
||||
Arg::new("dependencies")
|
||||
.help("a comma separated list of dependencies")
|
||||
.short('d')
|
||||
.long("dependencies")
|
||||
.value_delimiter(',')
|
||||
.num_args(1..),
|
||||
])
|
||||
}
|
||||
|
||||
fn init() -> Command {
|
||||
Command::new("init")
|
||||
.about("Initialize a package `specs.ron` file in the current directory")
|
||||
.args([
|
||||
Arg::new("name")
|
||||
.help("package name")
|
||||
.short('n')
|
||||
.long("name")
|
||||
.num_args(1),
|
||||
Arg::new("package-version")
|
||||
.help("package version")
|
||||
.short('v')
|
||||
.long("package-version")
|
||||
.num_args(1),
|
||||
Arg::new("release")
|
||||
.help("release number")
|
||||
.short('r')
|
||||
@ -78,17 +108,14 @@ fn search() -> Command {
|
||||
.short('n')
|
||||
.long("names")
|
||||
.action(ArgAction::SetTrue),
|
||||
Arg::new("query")
|
||||
.use_value_delimiter(false)
|
||||
.required(true),
|
||||
Arg::new("query").use_value_delimiter(false).required(true),
|
||||
])
|
||||
}
|
||||
|
||||
fn info() -> Command {
|
||||
Command::new("info")
|
||||
.about("Display information about a specific package")
|
||||
.arg(Arg::new("name")
|
||||
.required(true))
|
||||
.arg(Arg::new("name").required(true))
|
||||
}
|
||||
|
||||
fn install() -> Command {
|
||||
@ -114,9 +141,7 @@ fn remove() -> Command {
|
||||
Command::new("remove")
|
||||
.about("Remove packages")
|
||||
.visible_aliases(["rm", "del"])
|
||||
.arg(Arg::new("package")
|
||||
.required(true)
|
||||
.num_args(1..))
|
||||
.arg(Arg::new("package").required(true).num_args(1..))
|
||||
}
|
||||
|
||||
fn upgrade() -> Command {
|
||||
|
@ -1,14 +1,40 @@
|
||||
use std::error::Error;
|
||||
use std::{
|
||||
io,
|
||||
process::{Command, Output},
|
||||
};
|
||||
|
||||
#[non_exhaustive]
|
||||
/// Defines a set of commands to be run in order to finish package installation
|
||||
pub enum Hooks {
|
||||
/// Runs `makewhatis` to update the mandoc database if the package contains
|
||||
/// any Unix man pages
|
||||
Man,
|
||||
/// Runs `glib-compile-schemas` if the package contains any GLib schema files
|
||||
GlibSchema,
|
||||
Info,
|
||||
/// runs `install-info` to update the GNU Texinfo database
|
||||
Info(String),
|
||||
}
|
||||
|
||||
impl Hooks {
|
||||
pub fn run(&self) -> Result<(), Box<dyn Error>> {
|
||||
unimplemented!();
|
||||
pub fn run(&self) -> Result<Output, io::Error> {
|
||||
match self {
|
||||
Self::Man => makeinfo(),
|
||||
Self::GlibSchema => compile_schemas(),
|
||||
Self::Info(path) => install_info(&path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn makeinfo() -> Result<Output, io::Error> {
|
||||
Command::new("makewhatis").output()
|
||||
}
|
||||
|
||||
fn compile_schemas() -> Result<Output, io::Error> {
|
||||
Command::new("glib-compile-schemas")
|
||||
.arg("/usr/share/glib-2.0/schemas")
|
||||
.output()
|
||||
}
|
||||
|
||||
fn install_info(path: &str) -> Result<Output, io::Error> {
|
||||
Command::new("install-info").arg(path).output()
|
||||
}
|
||||
|
18
src/hpk.rs
18
src/hpk.rs
@ -1,13 +1,19 @@
|
||||
use {
|
||||
clap::ArgMatches,
|
||||
cli::cli,
|
||||
std::error::Error,
|
||||
hpk::Specs,
|
||||
ron::ser::{to_writer_pretty, PrettyConfig},
|
||||
std::{error::Error, fs::File, io::BufWriter, path::PathBuf},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let matches = cli().get_matches();
|
||||
match matches.subcommand() {
|
||||
Some(("create", matches)) => create(matches)?,
|
||||
Some(("init", matches)) => {
|
||||
let specsfile = init(matches)?;
|
||||
println!("Created specsfile {}", specsfile.display());
|
||||
}
|
||||
Some(("search", matches)) => search(matches)?,
|
||||
Some(("install", matches)) => install(matches)?,
|
||||
Some(("remove", matches)) => remove(matches)?,
|
||||
@ -21,6 +27,16 @@ fn create(_matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn init(matches: &ArgMatches) -> Result<PathBuf, Box<dyn Error>> {
|
||||
let specsfile = PathBuf::from("package.specs");
|
||||
let cfg = PrettyConfig::new().struct_names(true);
|
||||
let buf = File::create(&specsfile)?;
|
||||
let writer = BufWriter::new(buf);
|
||||
let specs = Specs::try_from(matches)?;
|
||||
to_writer_pretty(writer, &specs, cfg)?;
|
||||
Ok(specsfile)
|
||||
}
|
||||
|
||||
fn search(_matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
use crate::Entry;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{error::Error, fmt::Write, fs, path::{Path, PathBuf}, io::Read, os::unix::fs::MetadataExt};
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt::Write,
|
||||
fs,
|
||||
io::Read,
|
||||
os::unix::fs::MetadataExt,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use tar::{Node, Owner};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -28,7 +35,12 @@ impl Item {
|
||||
}
|
||||
let mode = meta.mode();
|
||||
Ok(Self {
|
||||
entry: Entry::File { path, sha256sum, mode, size },
|
||||
entry: Entry::File {
|
||||
path,
|
||||
sha256sum,
|
||||
mode,
|
||||
size,
|
||||
},
|
||||
node: Node::read_data_to_tar(&data, &filename, &meta, owner)?,
|
||||
})
|
||||
} else if meta.is_dir() {
|
||||
|
@ -1,15 +1,15 @@
|
||||
#![warn(clippy::all, clippy::pedantic)]
|
||||
mod item;
|
||||
mod hooks;
|
||||
mod item;
|
||||
mod package;
|
||||
mod plist;
|
||||
mod repository;
|
||||
mod version;
|
||||
|
||||
pub use {
|
||||
item::Item,
|
||||
hooks::Hooks,
|
||||
package::{Dependency, Package},
|
||||
item::Item,
|
||||
package::{Dependency, Package, Specs},
|
||||
plist::*,
|
||||
repository::Repository,
|
||||
version::*,
|
||||
|
@ -6,8 +6,8 @@ use {
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Dependency {
|
||||
name: String,
|
||||
version: (Option<Version>, Option<Version>),
|
||||
pub name: String,
|
||||
pub version: (Option<Version>, Option<Version>),
|
||||
}
|
||||
|
||||
impl Dependency {
|
||||
|
@ -1,9 +1,10 @@
|
||||
mod dependency;
|
||||
pub use dependency::Dependency;
|
||||
mod specs;
|
||||
use {
|
||||
crate::{Plist, Version},
|
||||
serde::{Deserialize, Serialize},
|
||||
};
|
||||
pub use {dependency::Dependency, specs::Specs};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct User {
|
||||
@ -24,7 +25,7 @@ pub struct Package {
|
||||
/// The `Version` of the package
|
||||
pub version: Version,
|
||||
/// The release number for this package
|
||||
pub release: u32,
|
||||
pub release: u8,
|
||||
/// a single line description of the package
|
||||
pub description: String,
|
||||
/// a more verbose description of the package
|
||||
|
81
src/package/specs.rs
Normal file
81
src/package/specs.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use {
|
||||
super::{Group, User},
|
||||
crate::{Dependency, Version},
|
||||
clap::ArgMatches,
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{env, error::Error},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Specs {
|
||||
/// The name of the package minus all version information
|
||||
pub name: String,
|
||||
/// The `Version` of the package
|
||||
pub version: Version,
|
||||
/// The release number for this package
|
||||
pub release: u8,
|
||||
/// a single line description of the package
|
||||
pub description: String,
|
||||
/// a more verbose description of the package
|
||||
pub long_description: String,
|
||||
/// an optional link to an
|
||||
/// [AppStream](https://www.freedesktop.org/wiki/Distributions/AppStream/)
|
||||
/// metadata file
|
||||
pub appstream_data: Option<String>,
|
||||
/// all of this package's runtime dependencies
|
||||
pub dependencies: Vec<Dependency>,
|
||||
/// an optional list of users to be created upon installation
|
||||
pub users: Option<Vec<User>>,
|
||||
/// an optional list of groups to be created upon installation
|
||||
pub groups: Option<Vec<Group>>,
|
||||
/// an optional post installation shell script to be run
|
||||
pub post_install: Option<String>,
|
||||
}
|
||||
|
||||
impl TryFrom<&ArgMatches> for Specs {
|
||||
type Error = Box<dyn Error>;
|
||||
|
||||
fn try_from(matches: &ArgMatches) -> Result<Self, Self::Error> {
|
||||
let mut specs = Specs::default();
|
||||
let mut name: Option<String> = None;
|
||||
let mut version: Option<Version> = None;
|
||||
let cwd = env::current_dir()?;
|
||||
if let Some(dir) = cwd.file_name() {
|
||||
if let Some(n) = dir.to_str() {
|
||||
if let Some((n, v)) = n.split_once('-') {
|
||||
name = Some(n.to_string());
|
||||
if let Ok(v) = v.parse() {
|
||||
version = Some(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(name) = matches.get_one::<String>("name") {
|
||||
specs.name = name.to_string();
|
||||
} else {
|
||||
if let Some(n) = name {
|
||||
specs.name = n;
|
||||
}
|
||||
}
|
||||
if let Some(version) = matches.get_one::<String>("package-version") {
|
||||
specs.version = version.parse()?;
|
||||
} else {
|
||||
if let Some(v) = version {
|
||||
specs.version = v;
|
||||
}
|
||||
}
|
||||
if let Some(release) = matches.get_one::<usize>("release") {
|
||||
specs.release = *release as u8;
|
||||
}
|
||||
if let Some(deps) = matches.get_many::<String>("dependencies") {
|
||||
let deps = deps
|
||||
.map(|d| Dependency {
|
||||
name: d.to_string(),
|
||||
version: (None, None),
|
||||
})
|
||||
.collect::<Vec<Dependency>>();
|
||||
specs.dependencies = deps;
|
||||
}
|
||||
Ok(specs)
|
||||
}
|
||||
}
|
@ -89,4 +89,3 @@ impl TryFrom<&Path> for Entry {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,21 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use {
|
||||
chrono::{offset::Utc, DateTime},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{cmp::Ordering, error::Error, fmt, str::FromStr},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct GitRev {
|
||||
hash: String,
|
||||
datetime: u64,
|
||||
/// the short revision hash
|
||||
pub hash: String,
|
||||
/// the time of the revision commit
|
||||
pub datetime: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl fmt::Display for GitRev {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "git_{}.{}", self.hash, self.datetime.format("%Y%m%d"))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for GitRev {
|
||||
@ -19,3 +29,39 @@ impl Ord for GitRev {
|
||||
self.datetime.cmp(&other.datetime)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseGitRevError;
|
||||
|
||||
impl fmt::Display for ParseGitRevError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Error parsing git version")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseGitRevError {}
|
||||
|
||||
impl From<chrono::ParseError> for ParseGitRevError {
|
||||
fn from(_value: chrono::ParseError) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for GitRev {
|
||||
type Err = ParseGitRevError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if let Some(gitrev) = s.strip_prefix("git_") {
|
||||
if let Some((hash, date)) = gitrev.split_once('_') {
|
||||
if hash.len() == 7 {
|
||||
let datetime = DateTime::parse_from_str(date, "%Y%m%d")?;
|
||||
return Ok(Self {
|
||||
hash: hash.to_string(),
|
||||
datetime: datetime.into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ParseGitRevError)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use {
|
||||
chrono::{offset::Utc, DateTime},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{error::Error, fmt, str::FromStr},
|
||||
};
|
||||
|
||||
mod gitrev;
|
||||
mod semver;
|
||||
@ -8,17 +12,103 @@ pub use {gitrev::GitRev, semver::SemVer};
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub enum Version {
|
||||
Number(u32),
|
||||
SemVer(SemVer),
|
||||
Git(GitRev),
|
||||
SemVer {
|
||||
major: u8,
|
||||
minor: u8,
|
||||
patch: u8,
|
||||
},
|
||||
Git {
|
||||
hash: String,
|
||||
datetime: DateTime<Utc>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for Version {
|
||||
fn default() -> Self {
|
||||
Self::SemVer {
|
||||
major: 0,
|
||||
minor: 1,
|
||||
patch: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SemVer> for Version {
|
||||
fn from(value: SemVer) -> Self {
|
||||
Self::SemVer {
|
||||
major: value.major,
|
||||
minor: value.minor,
|
||||
patch: value.patch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GitRev> for Version {
|
||||
fn from(value: GitRev) -> Self {
|
||||
Self::Git { hash: value.hash, datetime: value.datetime }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Version {
|
||||
fn from(value: u32) -> Self {
|
||||
Self::Number(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Version {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
match (self, other) {
|
||||
(Self::Number(s), Self::Number(o)) => s.partial_cmp(o),
|
||||
(Self::SemVer(s), Self::SemVer(o)) => s.partial_cmp(o),
|
||||
(Self::Git(s), Self::Git(o)) => s.partial_cmp(o),
|
||||
(
|
||||
Self::SemVer {
|
||||
major: a,
|
||||
minor: b,
|
||||
patch: c,
|
||||
},
|
||||
Self::SemVer {
|
||||
major: d,
|
||||
minor: e,
|
||||
patch: f,
|
||||
},
|
||||
) => (a, b, c).partial_cmp(&(d, e, f)),
|
||||
(
|
||||
Self::Git {
|
||||
hash: a,
|
||||
datetime: b,
|
||||
},
|
||||
Self::Git {
|
||||
hash: c,
|
||||
datetime: d,
|
||||
},
|
||||
) => (a, b).partial_cmp(&(c, d)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParseVersionError;
|
||||
|
||||
impl fmt::Display for ParseVersionError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "error parsing version")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseVersionError {}
|
||||
|
||||
impl FromStr for Version {
|
||||
type Err = ParseVersionError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if let Ok(v) = s.parse::<SemVer>() {
|
||||
Ok(v.into())
|
||||
} else if let Ok(v) = s.parse::<GitRev>() {
|
||||
Ok(v.into())
|
||||
} else if let Ok(v) = s.parse::<u32>() {
|
||||
Ok(v.into())
|
||||
} else {
|
||||
Err(ParseVersionError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,19 @@
|
||||
use {
|
||||
serde::{Deserialize, Serialize},
|
||||
std::cmp::Ordering,
|
||||
std::{cmp::Ordering, error::Error, fmt, num::ParseIntError, str::FromStr},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct SemVer {
|
||||
pub major: u32,
|
||||
pub minor: u32,
|
||||
pub patch: u32,
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
pub patch: u8,
|
||||
}
|
||||
|
||||
impl fmt::Display for SemVer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for SemVer {
|
||||
@ -39,3 +45,58 @@ impl Ord for SemVer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ParseSemVerError;
|
||||
|
||||
impl fmt::Display for ParseSemVerError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Error parsing SemVer")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseSemVerError {}
|
||||
|
||||
impl From<ParseIntError> for ParseSemVerError {
|
||||
fn from(_value: ParseIntError) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for SemVer {
|
||||
type Err = ParseSemVerError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let split = s.split('.').collect::<Vec<_>>();
|
||||
match split.len() {
|
||||
3 => {
|
||||
let major = split.get(0).unwrap().parse::<u8>()?;
|
||||
let minor = split.get(1).unwrap().parse::<u8>()?;
|
||||
let patch = split.get(2).unwrap().parse::<u8>()?;
|
||||
Ok(Self {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
})
|
||||
}
|
||||
_ => Err(ParseSemVerError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_semver() {
|
||||
assert_eq!(
|
||||
"1.0.3".parse::<SemVer>(),
|
||||
Ok(SemVer {
|
||||
major: 1,
|
||||
minor: 0,
|
||||
patch: 3
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user