You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
3.3 KiB
97 lines
3.3 KiB
/*! Gitig is a small cli program to handle gitignore files
|
|
|
|
It helps adding new entries to ignore and start a new project with templates from [Github](https://github.com/github/gitignore).
|
|
|
|
This project used [rust-cli-boilerplate](https://github.com/ssokolow/rust-cli-boilerplate)
|
|
*/
|
|
// Copyright 2017-2019, Stephan Sokolow
|
|
|
|
// `error_chain` recursion adjustment
|
|
#![recursion_limit = "1024"]
|
|
// Make rustc's built-in lints more strict and set clippy into a whitelist-based configuration so
|
|
// we see new lints as they get written (We'll opt back out selectively)
|
|
#![warn(
|
|
warnings,
|
|
rust_2018_idioms,
|
|
clippy::all,
|
|
clippy::complexity,
|
|
clippy::correctness,
|
|
clippy::pedantic,
|
|
clippy::perf,
|
|
clippy::style,
|
|
clippy::restriction
|
|
)]
|
|
// Opt out of the lints I've seen and don't want
|
|
#![allow(
|
|
clippy::float_arithmetic,
|
|
clippy::implicit_return,
|
|
clippy::filter_map,
|
|
clippy::wildcard_imports,
|
|
clippy::integer_arithmetic
|
|
)]
|
|
|
|
#[macro_use]
|
|
extern crate error_chain;
|
|
|
|
// stdlib imports
|
|
use std::convert::TryInto;
|
|
|
|
// 3rd-party imports
|
|
mod errors;
|
|
use log::trace;
|
|
use structopt::StructOpt;
|
|
|
|
// Local imports
|
|
mod app;
|
|
mod cache;
|
|
mod gitignore;
|
|
mod helpers;
|
|
mod template;
|
|
|
|
/// Boilerplate to parse command-line arguments, set up logging, and handle bubbled-up `Error`s.
|
|
///
|
|
/// Based on the `StructOpt` example from stderrlog and the suggested error-chain harness from
|
|
/// [quickstart.rs](https://github.com/brson/error-chain/blob/master/examples/quickstart.rs).
|
|
///
|
|
/// See `app::main` for the application-specific logic.
|
|
///
|
|
/// **TODO:** Consider switching to Failure and look into `impl Termination` as a way to avoid
|
|
/// having to put the error message pretty-printing inside main()
|
|
#[allow(clippy::result_expect_used, clippy::exit, clippy::use_debug)]
|
|
fn main() {
|
|
// Parse command-line arguments (exiting on parse error, --version, or --help)
|
|
let opts = app::CliOpts::from_args();
|
|
|
|
// Configure logging output so that -q is "decrease verbosity" rather than instant silence
|
|
let verbosity = opts
|
|
.boilerplate
|
|
.verbose
|
|
.saturating_add(app::DEFAULT_VERBOSITY)
|
|
.saturating_sub(opts.boilerplate.quiet);
|
|
stderrlog::new()
|
|
.module(module_path!())
|
|
.quiet(verbosity == 0)
|
|
.verbosity(verbosity.saturating_sub(1).try_into().expect("should never even come close"))
|
|
.timestamp(opts.boilerplate.timestamp.unwrap_or(stderrlog::Timestamp::Off))
|
|
.init()
|
|
.expect("initializing logging output");
|
|
trace!("Initialized logging, {} v{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
|
|
|
trace!("Starting with application");
|
|
if let Err(ref e) = app::main(opts) {
|
|
use std::io::prelude::*;
|
|
let stderr = std::io::stderr();
|
|
let mut lock = stderr.lock();
|
|
// Write the top-level error message, then chained errors, then backtrace if available
|
|
writeln!(lock, "error: {}", e).expect("error while writing error");
|
|
for e in e.iter().skip(1) {
|
|
writeln!(lock, "caused by: {}", e).expect("error while writing error");
|
|
}
|
|
if let Some(backtrace) = e.backtrace() {
|
|
writeln!(lock, "backtrace: {:?}", backtrace).expect("error while writing error");
|
|
}
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
// vim: set sw=4 sts=4 expandtab :
|