A cli program to easily handle .gitignore files
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

4 years ago
4 years ago
4 years ago
4 years ago
  1. /*! Gitig is a small cli program to handle gitignore files
  2. It helps adding new entries to ignore and start a new project with templates from [Github](https://github.com/github/gitignore).
  3. This project used [rust-cli-boilerplate](https://github.com/ssokolow/rust-cli-boilerplate)
  4. */
  5. // Copyright 2017-2019, Stephan Sokolow
  6. // `error_chain` recursion adjustment
  7. #![recursion_limit = "1024"]
  8. // Make rustc's built-in lints more strict and set clippy into a whitelist-based configuration so
  9. // we see new lints as they get written (We'll opt back out selectively)
  10. #![warn(
  11. warnings,
  12. rust_2018_idioms,
  13. clippy::all,
  14. clippy::complexity,
  15. clippy::correctness,
  16. clippy::pedantic,
  17. clippy::perf,
  18. clippy::style,
  19. clippy::restriction
  20. )]
  21. // Opt out of the lints I've seen and don't want
  22. #![allow(
  23. clippy::float_arithmetic,
  24. clippy::implicit_return,
  25. clippy::filter_map,
  26. clippy::wildcard_imports,
  27. clippy::integer_arithmetic
  28. )]
  29. #![feature(seek_stream_len)]
  30. #[macro_use]
  31. extern crate error_chain;
  32. // stdlib imports
  33. use std::convert::TryInto;
  34. // 3rd-party imports
  35. mod errors;
  36. use log::trace;
  37. use structopt::StructOpt;
  38. // Local imports
  39. mod app;
  40. mod cache;
  41. mod gitignore;
  42. mod helpers;
  43. mod template;
  44. /// Boilerplate to parse command-line arguments, set up logging, and handle bubbled-up `Error`s.
  45. ///
  46. /// Based on the `StructOpt` example from stderrlog and the suggested error-chain harness from
  47. /// [quickstart.rs](https://github.com/brson/error-chain/blob/master/examples/quickstart.rs).
  48. ///
  49. /// See `app::main` for the application-specific logic.
  50. ///
  51. /// **TODO:** Consider switching to Failure and look into `impl Termination` as a way to avoid
  52. /// having to put the error message pretty-printing inside main()
  53. #[allow(clippy::result_expect_used, clippy::exit, clippy::use_debug)]
  54. fn main() {
  55. // Parse command-line arguments (exiting on parse error, --version, or --help)
  56. let opts = app::CliOpts::from_args();
  57. // Configure logging output so that -q is "decrease verbosity" rather than instant silence
  58. let verbosity = opts
  59. .boilerplate
  60. .verbose
  61. .saturating_add(app::DEFAULT_VERBOSITY)
  62. .saturating_sub(opts.boilerplate.quiet);
  63. stderrlog::new()
  64. .module(module_path!())
  65. .quiet(verbosity == 0)
  66. .verbosity(verbosity.saturating_sub(1).try_into().expect("should never even come close"))
  67. .timestamp(opts.boilerplate.timestamp.unwrap_or(stderrlog::Timestamp::Off))
  68. .init()
  69. .expect("initializing logging output");
  70. trace!("Initialized logging, {} v{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
  71. trace!("Starting with application");
  72. if let Err(ref e) = app::main(opts) {
  73. use std::io::prelude::*;
  74. let stderr = std::io::stderr();
  75. let mut lock = stderr.lock();
  76. // Write the top-level error message, then chained errors, then backtrace if available
  77. writeln!(lock, "error: {}", e).expect("error while writing error");
  78. for e in e.iter().skip(1) {
  79. writeln!(lock, "caused by: {}", e).expect("error while writing error");
  80. }
  81. if let Some(backtrace) = e.backtrace() {
  82. writeln!(lock, "backtrace: {:?}", backtrace).expect("error while writing error");
  83. }
  84. std::process::exit(1);
  85. }
  86. }
  87. // vim: set sw=4 sts=4 expandtab :