1pub mod cli;
2pub mod commands;
3pub mod configs;
4pub mod defaults;
5pub mod error;
6pub mod handlers;
7pub mod macros;
8
9use ansi_term::Colour::Green;
10use std::path::PathBuf;
11
12use std::fs;
13
14use configs::{ConfigFile, DotsyConfig, Link};
15use error::DotsyError;
16extern crate shellexpand;
17
18pub type DotsyResult<T, E = DotsyError> = ::std::result::Result<T, E>;
19
20fn get_absolute_link(link: Link, global_config: &DotsyConfig) -> Link {
23 let from = absolute(
24 global_config
25 .dotfiles
26 .join(&global_config.configs_dir)
27 .join(link.from),
28 );
29 let to = absolute(link.to);
30
31 Link {
32 from,
33 to,
34 glob: link.glob,
35 }
36}
37
38fn link_exists(path: &PathBuf) -> bool {
39 let metadata = fs::symlink_metadata(path);
40 if metadata.is_err() {
41 return false;
42 }
43 true
44}
45
46fn is_symlink(path: &PathBuf) -> bool {
47 let metadata = fs::symlink_metadata(path);
48 if metadata.is_err() {
49 return false;
50 }
51 metadata.unwrap().file_type().is_symlink()
52}
53
54fn absolute(base: PathBuf) -> PathBuf {
55 match shellexpand::tilde(&base.into_os_string().to_str().unwrap()) {
56 std::borrow::Cow::Borrowed(s) => PathBuf::from(s),
57 std::borrow::Cow::Owned(s) => PathBuf::from(s),
58 }
59}
60
61pub fn install_configs(configs: Vec<String>, global_config: &DotsyConfig) {
62 for config in configs {
63 install_config(config, global_config)
64 }
65}
66
67pub fn uninstall_configs(configs: Vec<String>, global_config: &DotsyConfig) {
68 for config in configs {
69 uninstall_config(config, global_config);
70 }
71}
72
73fn uninstall_config(config: String, global_config: &DotsyConfig) {
74 println!(
75 "{message}: {arg}",
76 message = Green.paint("Attempting to uninstall config"),
77 arg = config
78 );
79
80 let config = {
81 let this = configs::ConfigConfig::load_by_name(&config, global_config);
82 match this {
83 Ok(t) => t,
84 Err(e) => return dotsy_log_error!("{}", e),
85 }
86 };
87
88 for link in config.links.unwrap_or_default() {
90 handlers::link::unlink_file(link, global_config)
91 .unwrap_or_else(|e| dotsy_log_error!("{}", e));
92 }
93
94 for script in config.revert_shell.unwrap_or_default() {
96 handlers::script::run_script(&script).unwrap_or_else(|e| dotsy_log_error!("{}", e));
97 }
98}
99
100fn install_config(config: String, global_config: &DotsyConfig) {
101 println!(
102 "{message}: {arg}",
103 message = Green.paint("Attempting to install config"),
104 arg = config
105 );
106
107 let config = {
108 let this = configs::ConfigConfig::load_by_name(&config, global_config);
109 match this {
110 Ok(t) => t,
111 Err(e) => return dotsy_log_error!("{}", e),
112 }
113 };
114
115 for link in config.links.unwrap_or_default() {
119 handlers::link::link_file(link, global_config)
120 .unwrap_or_else(|e| dotsy_log_error!("{}", e));
121 }
122
123 for script in config.shell.unwrap_or_default() {
125 handlers::script::run_script(&script).unwrap_or_else(|e| dotsy_log_error!("{}", e));
126 }
127
128 for dir in config.directories.unwrap_or_default() {
130 handlers::files::create_dir(absolute(dir)).unwrap_or_else(|e| dotsy_log_error!("{}", e));
131 }
132}
133
134fn uninstall_profile(_profile: String, global_config: &DotsyConfig) {
135 println!(
136 "{message}: {arg}",
137 message = Green.paint("Attempting to uninstall profile"),
138 arg = _profile
139 );
140 let profile = configs::ProfileConfig::load_by_name(&_profile, global_config).unwrap();
141
142 for link in profile.links.unwrap_or_default() {
144 handlers::link::unlink_file(link, global_config)
145 .unwrap_or_else(|e| dotsy_log_error!("{}", e));
146 }
147
148 for script in profile.revert_shell.unwrap_or_default() {
150 handlers::script::run_script(&script).unwrap_or_else(|e| dotsy_log_error!("{}", e));
151 }
152
153 for config in profile.configs.unwrap_or_default() {
155 uninstall_config(config, global_config);
156 }
157 println!(
158 "{message}: {arg}",
159 message = Green.paint("Finished uninstalling profile"),
160 arg = _profile
161 );
162}
163
164fn install_profile(_profile: String, global_config: &DotsyConfig) {
165 println!(
166 "{message}: {arg}",
167 message = Green.paint("Attempting to install profile"),
168 arg = _profile
169 );
170 let profile = configs::ProfileConfig::load_by_name(&_profile, global_config).unwrap();
171
172 for link in profile.links.unwrap_or_default() {
175 handlers::link::link_file(link, global_config)
176 .unwrap_or_else(|e| dotsy_log_error!("{}", e));
177 }
178
179 for dir in profile.directories.unwrap_or_default() {
181 handlers::files::create_dir(absolute(dir)).unwrap_or_else(|e| dotsy_log_error!("{}", e));
182 }
183
184 for script in profile.shell.unwrap_or_default() {
186 handlers::script::run_script(&script).unwrap_or_else(|e| dotsy_log_error!("{}", e));
187 }
188
189 install_configs(profile.configs.unwrap_or_default(), global_config);
191
192 println!(
193 "{message}: {arg}",
194 message = Green.paint("Finished installing profile"),
195 arg = _profile
196 );
197}
198
199pub fn load_rcfile() -> DotsyResult<DotsyConfig> {
200 let rcfile_path = defaults::fallback_path().unwrap();
201
202 let mut config = configs::DotsyConfig::load(rcfile_path).unwrap();
203 config.dotfiles = absolute(config.dotfiles);
204
205 Ok(config)
206}