1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::path::PathBuf;
use clap::{Parser, Subcommand};
use clap_complete::Shell;
/// A small dotfile manager.
#[derive(Debug, Parser, Default, Clone)]
#[clap(author, version, about, long_about = None)]
pub struct Options {
/// Location of the global configuration
#[clap(
short,
long,
value_parser,
default_value = ".dotter/global.toml",
global = true
)]
pub global_config: PathBuf,
/// Location of the local configuration
#[clap(
short,
long,
value_parser,
default_value = ".dotter/local.toml",
global = true
)]
pub local_config: PathBuf,
/// Location of cache file
#[clap(long, value_parser, default_value = ".dotter/cache.toml")]
pub cache_file: PathBuf,
/// Directory to cache into.
#[clap(long, value_parser, default_value = ".dotter/cache")]
pub cache_directory: PathBuf,
/// Location of optional pre-deploy hook
#[clap(long, value_parser, default_value = ".dotter/pre_deploy.sh")]
pub pre_deploy: PathBuf,
/// Location of optional post-deploy hook
#[clap(long, value_parser, default_value = ".dotter/post_deploy.sh")]
pub post_deploy: PathBuf,
/// Location of optional pre-undeploy hook
#[clap(long, value_parser, default_value = ".dotter/pre_undeploy.sh")]
pub pre_undeploy: PathBuf,
/// Location of optional post-undeploy hook
#[clap(long, value_parser, default_value = ".dotter/post_undeploy.sh")]
pub post_undeploy: PathBuf,
/// Dry run - don't do anything, only print information.
/// Implies -v at least once
#[clap(short = 'd', long = "dry-run", global = true)]
pub dry_run: bool,
/// Verbosity level - specify up to 3 times to get more detailed output.
/// Specifying at least once prints the differences between what was before and after Dotter's run
#[clap(short = 'v', long = "verbose", action = clap::ArgAction::Count, global = true)]
pub verbosity: u8,
/// Quiet - only print errors
#[clap(short, long, value_parser, global = true)]
pub quiet: bool,
/// Force - instead of skipping, overwrite target files if their content is unexpected.
/// Overrides --dry-run.
#[clap(short, long, value_parser, global = true)]
pub force: bool,
/// Assume "yes" instead of prompting when removing empty directories
#[clap(short = 'y', long = "noconfirm", global = true)]
pub noconfirm: bool,
/// Take standard input as an additional files/variables patch, added after evaluating
/// `local.toml`. Assumes --noconfirm flag because all of stdin is taken as the patch.
#[clap(short, long, value_parser, global = true)]
pub patch: bool,
/// Amount of lines that are printed before and after a diff hunk.
#[clap(long, value_parser, default_value = "3")]
pub diff_context_lines: usize,
#[clap(subcommand)]
pub action: Option<Action>,
}
#[derive(Debug, Clone, Subcommand, Default)]
pub enum Action {
/// Deploy the files to their respective targets. This is the default subcommand.
#[default]
Deploy,
/// Delete all deployed files from their target locations.
/// Note that this operates on all files that are currently in cache.
Undeploy,
/// Initialize global.toml with a single package containing all the files in the current
/// directory pointing to a dummy value and a local.toml that selects that package.
Init,
/// Run continuously, watching the repository for changes and deploying as soon as they
/// happen. Can be ran with `--dry-run`
#[cfg(feature = "watch")]
Watch,
/// Generate shell completions
GenCompletions {
/// Set the shell for generating completions [values: bash, elvish, fish, powerShell, zsh]
#[clap(long, short)]
shell: Shell,
/// Set the out directory for writing completions file
#[clap(long)]
to: Option<PathBuf>,
},
}
pub fn get_options() -> Options {
let mut opt = Options::parse();
if opt.dry_run {
opt.verbosity = std::cmp::max(opt.verbosity, 1);
}
opt.verbosity = std::cmp::min(3, opt.verbosity);
if opt.patch {
opt.noconfirm = true;
}
opt
}