diff --git a/config.example.toml b/config.example.toml index fb8c5096..247d87d9 100644 --- a/config.example.toml +++ b/config.example.toml @@ -2,188 +2,239 @@ # [include] sections are processed in the order you write them # Files in $CONFIG_DIR/topgrade.d/ are automatically included before this file [include] -#paths = ["/etc/topgrade.toml"] +# paths = ["/etc/topgrade.toml"] + [misc] -# Don't ask for confirmations -#assume_yes = true - -# Disable specific steps - same options as the command line flag -#disable = ["system", "emacs"] - -# Ignore failures for these steps -#ignore_failures = ["powershell"] - -# Run specific steps - same options as the command line flag -#only = ["system", "emacs"] - -# Do not ask to retry failed steps (default: false) -#no_retry = true - -# Sudo command to be used -#sudo_command = "sudo" - # Run `sudo -v` to cache credentials at the start of the run # This avoids a blocking password prompt in the middle of an unattended run -#pre_sudo = false +# (default: false) +# pre_sudo = false -# Run inside tmux -#run_in_tmux = true +# Sudo command to be used +# sudo_command = "sudo" + +# Disable specific steps - same options as the command line flag +# disable = ["system", "emacs"] + +# Ignore failures for these steps +# ignore_failures = ["powershell"] # List of remote machines with Topgrade installed on them -#remote_topgrades = ["toothless", "pi", "parnas"] - -# Arguments to pass to SSH when upgrading remote systems -#ssh_arguments = "-o ConnectTimeout=2" +# remote_topgrades = ["toothless", "pi", "parnas"] # Path to Topgrade executable on remote machines -#remote_topgrade_path = ".cargo/bin/topgrade" +# remote_topgrade_path = ".cargo/bin/topgrade" + +# Arguments to pass to SSH when upgrading remote systems +# ssh_arguments = "-o ConnectTimeout=2" # Arguments to pass tmux when pulling Repositories -#tmux_arguments = "-S /var/tmux.sock" +# tmux_arguments = "-S /var/tmux.sock" -# Do not set the terminal title -#set_title = false +# Do not set the terminal title (dfault: true) +# set_title = true -# Display the time in step titles +# Display the time in step titles (default: true) # display_time = true -# Cleanup temporary or old files -#cleanup = true +# Don't ask for confirmations (no default value) +# assume_yes = true -# Skip sending a notification at the end of a run -#skip_notify = true +# Do not ask to retry failed steps (default: false) +# no_retry = true -# Whether to self update (this is ignored if the binary has been built without self update support, available also via setting the environment variable TOPGRADE_NO_SELF_UPGRADE) -#no_self_update = true +# Run inside tmux (default: false) +# run_in_tmux = true -# Extra Home Manager arguments -#home_manager_arguments = ["--flake", "file"] +# Cleanup temporary or old files (default: false) +# cleanup = true + +# Send a notification for every step (default: false) +# notify_each_step = false + +# Skip sending a notification at the end of a run (default: false) +# skip_notify = true + +# The Bash-it branch to update (default: "stable") +# bashit_branch = "stable" + +# Run specific steps - same options as the command line flag +# only = ["system", "emacs"] + +# Whether to self update +# +# this will be ignored if the binary is built without self update support +# +# available also via setting the environment variable TOPGRADE_NO_SELF_UPGRADE) +# no_self_update = true # Extra tracing filter directives # These are prepended to the `--log-filter` argument # See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives -#log_filters = ["topgrade::command=debug", "warn"] +# log_filters = ["topgrade::command=debug", "warn"] + # Commands to run before anything [pre_commands] -#"Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" +# "Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" + # Commands to run after anything [post_commands] -#"Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" +# "Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" + # Custom commands [commands] -#"Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter" -#"Custom command using interactive shell (unix)" = "-i vim_upgrade" +# "Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter" +# "Custom command using interactive shell (unix)" = "-i vim_upgrade" + [python] -#enable_pip_review = true ###disabled by default -#enable_pip_review_local = true ###disabled by default -#enable_pipupgrade = true ###disabled by default -#pipupgrade_arguments = "-y -u --pip-path pip" ###disabled by default +# enable_pip_review = true ###disabled by default +# enable_pip_review_local = true ###disabled by default +# enable_pipupgrade = true ###disabled by default +# pipupgrade_arguments = "-y -u --pip-path pip" ###disabled by default + [composer] -#self_update = true +# self_update = true + [brew] -#greedy_cask = true -#autoremove = true +# greedy_cask = true +# autoremove = true + [linux] -# Arch Package Manager to use. Allowed values: autodetect, aura, garuda_update, pacman, pamac, paru, pikaur, trizen, yay. -#arch_package_manager = "pacman" +# Arch Package Manager to use. +# Allowed values: +# autodetect, aura, garuda_update, pacman, pamac, paru, pikaur, trizen, yay +# arch_package_manager = "pacman" + # Arguments to pass yay (or paru) when updating packages -#yay_arguments = "--nodevel" +# yay_arguments = "--nodevel" + # Arguments to pass dnf when updating packages -#dnf_arguments = "--refresh" -#aura_aur_arguments = "-kx" -#aura_pacman_arguments = "" -#garuda_update_arguments = "" -#show_arch_news = true -#trizen_arguments = "--devel" -#pikaur_arguments = "" -#pamac_arguments = "--no-devel" -#enable_tlmgr = true -#emerge_sync_flags = "-q" -#emerge_update_flags = "-uDNa --with-bdeps=y world" -#redhat_distro_sync = false -#suse_dup = false -#rpm_ostree = false -#nix_arguments = "--flake" -#nix_env_arguments = "--prebuilt-only" +# dnf_arguments = "--refresh" + +# aura_aur_arguments = "-kx" + +# aura_pacman_arguments = "" +# garuda_update_arguments = "" + +# show_arch_news = true + +# trizen_arguments = "--devel" + +# pikaur_arguments = "" + +# pamac_arguments = "--no-devel" + +# enable_tlmgr = true + +# emerge_sync_flags = "-q" + +# emerge_update_flags = "-uDNa --with-bdeps=y world" + +# redhat_distro_sync = false + +# suse_dup = false + +# rpm_ostree = false + +# nix_arguments = "--flake" + +# nix_env_arguments = "--prebuilt-only" + +# Extra Home Manager arguments +# home_manager_arguments = ["--flake", "file"] + [git] -#max_concurrency = 5 +# max_concurrency = 5 + # Git repositories that you want to pull and push -#repos = [ -# "~/src/*/", -# "~/.config/something" -#] +# repos = [ +# "~/src/*/", +# "~/.config/something" +# ] # Repositories that you only want to pull -#pull_only_repos = [ -# "~/.config/something_else" -#] +# pull_only_repos = [ +# "~/.config/something_else" +# ] # Repositories that you only want to push -#push_only_repos = [ -# "~/src/*/", -# "~/.config/something_third" -#] +# push_only_repos = [ +# "~/src/*/", +# "~/.config/something_third" +# ] # Don't pull the predefined git repos -#pull_predefined = false +# pull_predefined = false # Arguments to pass Git when pulling repositories -#pull_arguments = "--rebase --autostash" +# pull_arguments = "--rebase --autostash" # Arguments to pass Git when pushing repositories -#push_arguments = "--all" +# push_arguments = "--all" + [windows] # Manually select Windows updates -#accept_all_updates = false -#open_remotes_in_new_terminal = true -#wsl_update_pre_release = true -#wsl_update_use_web_download = true +# accept_all_updates = false + +# open_remotes_in_new_terminal = true + +# wsl_update_pre_release = true + +# wsl_update_use_web_download = true # Causes Topgrade to rename itself during the run to allow package managers # to upgrade it. Use this only if you installed Topgrade by using a package # manager such as Scoop or Cargo -#self_rename = true +# self_rename = true + [npm] # Use sudo if the NPM directory isn't owned by the current user -#use_sudo = true +# use_sudo = true + [yarn] # Run `yarn global upgrade` with `sudo` -#use_sudo = true +# use_sudo = true + [vim] # For `vim-plug`, execute `PlugUpdate!` instead of `PlugUpdate` -#force_plug_update = true +# force_plug_update = true + [firmware] # Offer to update firmware; if false just check for and display available updates -#upgrade = true +# upgrade = true + [vagrant] # Vagrant directories -#directories = [] +# directories = [] # power on vagrant boxes if needed -#power_on = true +# power_on = true # Always suspend vagrant boxes instead of powering off -#always_suspend = true +# always_suspend = true + [flatpak] # Use sudo for updating the system-wide installation -#use_sudo = true +# use_sudo = true + [distrobox] -#use_root = false -#containers = ["archlinux-latest"] +# use_root = false + +# containers = ["archlinux-latest"] \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index cc176f7b..10ebbbb9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,57 +42,6 @@ macro_rules! str_value { }; } -macro_rules! check_deprecated { - ($config:expr, $old:ident, $section:ident, $new:ident) => { - if $config.$old.is_some() { - println!(concat!( - "'", - stringify!($old), - "' configuration option is deprecated. Rename it to '", - stringify!($new), - "' and put it under the section [", - stringify!($section), - "]", - )); - } - }; -} - -/// Get a deprecated option moved from a section to another -macro_rules! get_deprecated_moved_opt { - ($old_section:expr, $old:ident, $new_section:expr, $new:ident) => {{ - if let Some(old_section) = &$old_section { - if old_section.$old.is_some() { - return &old_section.$old; - } - } - - if let Some(new_section) = &$new_section { - return &new_section.$new; - } - - return &None; - }}; -} - -macro_rules! get_deprecated_moved_or_default_to { - ($old_section:expr, $old:ident, $new_section:expr, $new:ident, $default_ret:ident) => {{ - if let Some(old_section) = &$old_section { - if let Some(old) = old_section.$old { - return old; - } - } - - if let Some(new_section) = &$new_section { - if let Some(new) = new_section.$new { - return new; - } - } - - return $default_ret; - }}; -} - pub type Commands = BTreeMap; #[derive(ArgEnum, EnumString, EnumVariantNames, Debug, Clone, PartialEq, Eq, Deserialize, EnumIter, Copy)] @@ -390,11 +339,6 @@ pub struct Misc { sudo_command: Option, - #[merge(strategy = crate::utils::merge_strategies::vec_prepend_opt)] - git_repos: Option>, - - predefined_git_repos: Option, - #[merge(strategy = crate::utils::merge_strategies::vec_prepend_opt)] disable: Option>, @@ -409,9 +353,6 @@ pub struct Misc { #[merge(strategy = crate::utils::merge_strategies::string_append_opt)] ssh_arguments: Option, - #[merge(strategy = crate::utils::merge_strategies::string_append_opt)] - git_arguments: Option, - #[merge(strategy = crate::utils::merge_strategies::string_append_opt)] tmux_arguments: Option, @@ -421,15 +362,6 @@ pub struct Misc { assume_yes: Option, - #[merge(strategy = crate::utils::merge_strategies::string_append_opt)] - yay_arguments: Option, - - #[merge(strategy = crate::utils::merge_strategies::string_append_opt)] - aura_aur_arguments: Option, - - #[merge(strategy = crate::utils::merge_strategies::string_append_opt)] - aura_pacman_arguments: Option, - no_retry: Option, run_in_tmux: Option, @@ -438,8 +370,6 @@ pub struct Misc { notify_each_step: Option, - accept_all_windows_updates: Option, - skip_notify: Option, bashit_branch: Option, @@ -677,16 +607,6 @@ impl ConfigFile { } } - if let Some(misc) = &mut result.misc { - if let Some(ref mut paths) = &mut misc.git_repos { - for path in paths.iter_mut() { - let expanded = shellexpand::tilde::<&str>(&path.as_ref()).into_owned(); - debug!("Path {} expanded to {}", path, expanded); - *path = expanded; - } - } - } - if let Some(paths) = result.git.as_mut().and_then(|git| git.repos.as_mut()) { for path in paths.iter_mut() { let expanded = shellexpand::tilde::<&str>(&path.as_ref()).into_owned(); @@ -909,14 +829,6 @@ impl Config { ConfigFile::default() }; - if let Some(misc) = &config_file.misc { - check_deprecated!(misc, git_arguments, git, arguments); - check_deprecated!(misc, git_repos, git, repos); - check_deprecated!(misc, predefined_git_repos, git, pull_predefined); - check_deprecated!(misc, yay_arguments, linux, yay_arguments); - check_deprecated!(misc, accept_all_windows_updates, windows, accept_all_updates); - } - let allowed_steps = Self::allowed_steps(&opt, &config_file); Ok(Self { @@ -947,8 +859,8 @@ impl Config { } /// The list of git repositories to push and pull. - pub fn git_repos(&self) -> &Option> { - get_deprecated_moved_opt!(&self.config_file.misc, git_repos, &self.config_file.git, repos) + pub fn git_repos(&self) -> Option<&Vec> { + self.config_file.git.as_ref().and_then(|git| git.repos.as_ref()) } /// The list of additional git repositories to pull. pub fn git_pull_only_repos(&self) -> Option<&Vec> { @@ -1158,13 +1070,11 @@ impl Config { /// Whether to accept all Windows updates pub fn accept_all_windows_updates(&self) -> bool { - get_deprecated_moved_or_default_to!( - &self.config_file.misc, - accept_all_windows_updates, - &self.config_file.windows, - accept_all_updates, - true - ) + self.config_file + .windows + .as_ref() + .and_then(|windows| windows.accept_all_updates) + .unwrap_or(true) } /// Whether to self rename the Topgrade executable during the run @@ -1447,13 +1357,12 @@ impl Config { pub fn use_predefined_git_repos(&self) -> bool { !self.opt.disable_predefined_git_repos - && get_deprecated_moved_or_default_to!( - &self.config_file.misc, - predefined_git_repos, - &self.config_file.git, - pull_predefined, - true - ) + && self + .config_file + .git + .as_ref() + .and_then(|git| git.pull_predefined) + .unwrap_or(true) } pub fn verbose(&self) -> bool { diff --git a/src/steps/git.rs b/src/steps/git.rs index 1ac964db..d80a1c53 100644 --- a/src/steps/git.rs +++ b/src/steps/git.rs @@ -33,6 +33,7 @@ pub enum GitAction { Pull, } +#[derive(Debug)] pub struct Repositories<'a> { git: &'a Git, pull_repositories: HashSet, @@ -387,14 +388,27 @@ impl<'a> Repositories<'a> { } } + /// Return true if `pull_repos` and `push_repos` are both empty. pub fn is_empty(&self) -> bool { self.pull_repositories.is_empty() && self.push_repositories.is_empty() } + // The following 2 functions are `#[cfg(unix)]` because they are only used in + // the `oh-my-zsh` step, which is UNIX-only. + #[cfg(unix)] - pub fn remove(&mut self, path: &str) { + /// Return true if `pull_repos` is empty. + pub fn pull_is_empty(&self) -> bool { + self.pull_repositories.is_empty() + } + + #[cfg(unix)] + /// Remove `path` from `pull_repos` + /// + /// # Panic + /// Will panic if `path` is not in the `pull_repos` under a debug build. + pub fn remove_from_pull(&mut self, path: &str) { let _removed = self.pull_repositories.remove(path); - let _removed = self.push_repositories.remove(path); debug_assert!(_removed); } } diff --git a/src/steps/zsh.rs b/src/steps/zsh.rs index 8274bd72..8cba9ef6 100644 --- a/src/steps/zsh.rs +++ b/src/steps/zsh.rs @@ -230,8 +230,8 @@ pub fn run_oh_my_zsh(ctx: &ExecutionContext) -> Result<()> { custom_repos.insert_if_repo(entry.path(), crate::steps::git::GitAction::Pull); } - custom_repos.remove(&oh_my_zsh.to_string_lossy()); - if !custom_repos.is_empty() { + custom_repos.remove_from_pull(&oh_my_zsh.to_string_lossy()); + if !custom_repos.pull_is_empty() { println!("Pulling custom plugins and themes"); ctx.git().multi_pull(&custom_repos, ctx)?; }