Skip to content

Commit

Permalink
Merge pull request rust-lang#114 from notriddle/master
Browse files Browse the repository at this point in the history
Bump to clap 3
  • Loading branch information
Mark-Simulacrum authored Jun 18, 2022
2 parents ed86e91 + b3a4b38 commit ae02ae4
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 273 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ num_cpus = "1"
remove_dir_all = "0.5"

[dependencies.clap]
features = ["yaml"]
version = "2.19.0"
features = ["derive"]
version = "3.1"

[target."cfg(windows)".dependencies]
lazy_static = "1"
Expand Down
12 changes: 11 additions & 1 deletion src/combiner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,44 @@ actor! {
#[derive(Debug)]
pub struct Combiner {
/// The name of the product, for display.
#[clap(value_name = "NAME")]
product_name: String = "Product",

/// The name of the package tarball.
#[clap(value_name = "NAME")]
package_name: String = "package",

/// The directory under lib/ where the manifest lives.
#[clap(value_name = "DIR")]
rel_manifest_dir: String = "packagelib",

/// The string to print after successful installation.
#[clap(value_name = "MESSAGE")]
success_message: String = "Installed.",

/// Places to look for legacy manifests to uninstall.
#[clap(value_name = "DIRS")]
legacy_manifest_dirs: String = "",

/// Installers to combine.
#[clap(value_name = "FILE,FILE")]
input_tarballs: String = "",

/// Directory containing files that should not be installed.
#[clap(value_name = "DIR")]
non_installed_overlay: String = "",

/// The directory to do temporary work.
#[clap(value_name = "DIR")]
work_dir: String = "./workdir",

/// The location to put the final image and tarball.
#[clap(value_name = "DIR")]
output_dir: String = "./dist",

/// The formats used to compress the tarball
compression_formats: CompressionFormats = CompressionFormats::default(),
#[clap(value_name = "FORMAT", default_value_t)]
compression_formats: CompressionFormats,
}
}

Expand Down
25 changes: 24 additions & 1 deletion src/compression.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{Context, Error};
use flate2::{read::GzDecoder, write::GzEncoder};
use rayon::prelude::*;
use std::{convert::TryFrom, io::Read, io::Write, path::Path};
use std::{convert::TryFrom, fmt, io::Read, io::Write, path::Path, str::FromStr};
use xz2::{read::XzDecoder, write::XzEncoder};

#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -80,6 +80,29 @@ impl TryFrom<&'_ str> for CompressionFormats {
}
}

impl FromStr for CompressionFormats {
type Err = Error;

fn from_str(value: &str) -> Result<Self, Self::Err> {
Self::try_from(value)
}
}

impl fmt::Display for CompressionFormats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, format) in self.iter().enumerate() {
if i != 0 {
write!(f, ",")?;
}
fmt::Display::fmt(match format {
CompressionFormat::Xz => "xz",
CompressionFormat::Gz => "gz",
}, f)?;
}
Ok(())
}
}

impl Default for CompressionFormats {
fn default() -> Self {
Self(vec![CompressionFormat::Gz, CompressionFormat::Xz])
Expand Down
14 changes: 13 additions & 1 deletion src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,52 @@ actor! {
#[derive(Debug)]
pub struct Generator {
/// The name of the product, for display
#[clap(value_name = "NAME")]
product_name: String = "Product",

/// The name of the component, distinct from other installed components
#[clap(value_name = "NAME")]
component_name: String = "component",

/// The name of the package, tarball
#[clap(value_name = "NAME")]
package_name: String = "package",

/// The directory under lib/ where the manifest lives
#[clap(value_name = "DIR")]
rel_manifest_dir: String = "packagelib",

/// The string to print after successful installation
#[clap(value_name = "MESSAGE")]
success_message: String = "Installed.",

/// Places to look for legacy manifests to uninstall
#[clap(value_name = "DIRS")]
legacy_manifest_dirs: String = "",

/// Directory containing files that should not be installed
#[clap(value_name = "DIR")]
non_installed_overlay: String = "",

/// Path prefixes of directories that should be installed/uninstalled in bulk
#[clap(value_name = "DIRS")]
bulk_dirs: String = "",

/// The directory containing the installation medium
#[clap(value_name = "DIR")]
image_dir: String = "./install_image",

/// The directory to do temporary work
#[clap(value_name = "DIR")]
work_dir: String = "./workdir",

/// The location to put the final image and tarball
#[clap(value_name = "DIR")]
output_dir: String = "./dist",

/// The formats used to compress the tarball
compression_formats: CompressionFormats = CompressionFormats::default(),
#[clap(value_name = "FORMAT", default_value_t)]
compression_formats: CompressionFormats,
}
}

Expand Down
106 changes: 19 additions & 87 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,96 +1,28 @@
use anyhow::{Context, Result};
use clap::{App, ArgMatches};
use clap::{self, Command, Parser};
use std::convert::TryInto;

fn main() -> Result<()> {
let yaml = clap::load_yaml!("main.yml");
let matches = App::from_yaml(yaml).get_matches();

match matches.subcommand() {
("combine", Some(matches)) => combine(matches),
("generate", Some(matches)) => generate(matches),
("script", Some(matches)) => script(matches),
("tarball", Some(matches)) => tarball(matches),
_ => unreachable!(),
}
}

/// Parse clap arguements into the type constructor.
macro_rules! parse(
($matches:expr => $type:ty { $( $option:tt => $setter:ident, )* }) => {
{
let mut command: $type = Default::default();
$(
if let Some(val) = $matches.value_of($option) {
command.$setter(val.try_into()?);
}
)*
command
}
}
);

fn combine(matches: &ArgMatches<'_>) -> Result<()> {
let combiner = parse!(matches => installer::Combiner {
"product-name" => product_name,
"package-name" => package_name,
"rel-manifest-dir" => rel_manifest_dir,
"success-message" => success_message,
"legacy-manifest-dirs" => legacy_manifest_dirs,
"input-tarballs" => input_tarballs,
"non-installed-overlay" => non_installed_overlay,
"work-dir" => work_dir,
"output-dir" => output_dir,
"compression-formats" => compression_formats,
});

combiner.run().context("failed to combine installers")?;
Ok(())
#[derive(Parser)]
struct CommandLine {
#[clap(subcommand)]
command: Subcommand,
}

fn generate(matches: &ArgMatches<'_>) -> Result<()> {
let generator = parse!(matches => installer::Generator {
"product-name" => product_name,
"component-name" => component_name,
"package-name" => package_name,
"rel-manifest-dir" => rel_manifest_dir,
"success-message" => success_message,
"legacy-manifest-dirs" => legacy_manifest_dirs,
"non-installed-overlay" => non_installed_overlay,
"bulk-dirs" => bulk_dirs,
"image-dir" => image_dir,
"work-dir" => work_dir,
"output-dir" => output_dir,
"compression-formats" => compression_formats,
});

generator.run().context("failed to generate installer")?;
Ok(())
#[derive(clap::Subcommand)]
enum Subcommand {
Generate(installer::Generator),
Combine(installer::Combiner),
Script(installer::Scripter),
Tarball(installer::Tarballer),
}

fn script(matches: &ArgMatches<'_>) -> Result<()> {
let scripter = parse!(matches => installer::Scripter {
"product-name" => product_name,
"rel-manifest-dir" => rel_manifest_dir,
"success-message" => success_message,
"legacy-manifest-dirs" => legacy_manifest_dirs,
"output-script" => output_script,
});

scripter
.run()
.context("failed to generate installation script")?;
Ok(())
}

fn tarball(matches: &ArgMatches<'_>) -> Result<()> {
let tarballer = parse!(matches => installer::Tarballer {
"input" => input,
"output" => output,
"work-dir" => work_dir,
"compression-formats" => compression_formats,
});

tarballer.run().context("failed to generate tarballs")?;
fn main() -> Result<()> {
let command_line = CommandLine::parse();
match command_line.command {
Subcommand::Combine(combiner) => combiner.run().context("failed to combine installers")?,
Subcommand::Generate(generator) => generator.run().context("failed to generate installer")?,
Subcommand::Script(scripter) => scripter.run().context("failed to generate installation script")?,
Subcommand::Tarball(tarballer) => tarballer.run().context("failed to generate tarballs")?,
}
Ok(())
}
Loading

0 comments on commit ae02ae4

Please sign in to comment.