Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26a2c3c266 | ||
|
|
ceafcba88f | ||
|
|
d7182b5a6e | ||
|
|
93ec1172fe | ||
|
|
609477a373 | ||
|
|
1d49af10a7 | ||
|
|
327ed837c2 | ||
|
|
d406e2aeab | ||
|
|
0991cc8a6f | ||
|
|
ac6330fac8 | ||
|
|
29f0d229d3 | ||
|
|
3dd11f7b52 | ||
|
|
ddb1a021bb | ||
|
|
565aa405be | ||
|
|
907465f891 | ||
|
|
250485c826 | ||
|
|
3a3f22b4e5 | ||
|
|
a3628d0d49 | ||
|
|
462016e51e | ||
|
|
199b81183b | ||
|
|
342d7f7209 | ||
|
|
9c2d121fc9 | ||
|
|
7728819133 | ||
|
|
a5d5d987d2 | ||
|
|
fae5d80f0a | ||
|
|
2369e371be | ||
|
|
e3b71b647f | ||
|
|
e224ea38b3 | ||
|
|
8ec37bcd44 | ||
|
|
6b7f6f4cc7 | ||
|
|
d767ef31a5 | ||
|
|
fcf776fe07 | ||
|
|
58060dda09 | ||
|
|
8cfc8d66be | ||
|
|
9dcc8fdd0d | ||
|
|
828477b255 | ||
|
|
4eae1fedf7 | ||
|
|
1051e4cf47 |
4
.github/workflows/check-and-lint.yaml
vendored
4
.github/workflows/check-and-lint.yaml
vendored
@@ -7,8 +7,8 @@ on:
|
||||
name: CI
|
||||
|
||||
env:
|
||||
RUST_VER: '1.60.0'
|
||||
CROSS_VER: '0.2.4'
|
||||
RUST_VER: '1.68.0'
|
||||
CROSS_VER: '0.2.5'
|
||||
CARGO_NET_RETRY: 3
|
||||
|
||||
jobs:
|
||||
|
||||
736
Cargo.lock
generated
736
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -4,9 +4,8 @@ description = "Upgrade all the things"
|
||||
categories = ["os"]
|
||||
keywords = ["upgrade", "update"]
|
||||
license = "GPL-3.0"
|
||||
# license-file = "LICENSE"
|
||||
repository = "https://github.com/topgrade-rs/topgrade"
|
||||
version = "10.2.5"
|
||||
version = "11.0.2"
|
||||
authors = ["Roey Darwish Dror <roey.ghost@gmail.com>", "Thomas Schönauer <t.schoenauer@hgs-wt.at>"]
|
||||
exclude = ["doc/screenshot.gif"]
|
||||
edition = "2021"
|
||||
@@ -22,7 +21,8 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
home = "~0.5"
|
||||
directories = "~4.0"
|
||||
etcetera = "~0.8"
|
||||
once_cell = "~1.17"
|
||||
serde = { version = "~1.0", features = ["derive"] }
|
||||
toml = "0.5"
|
||||
which_crate = { version = "~4.1", package = "which" }
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Workaround for: https://github.com/cross-rs/cross/issues/1100
|
||||
# TODO: Remove this file altogether once a new version of cross (after v0.2.4) is released.
|
||||
[target.x86_64-unknown-freebsd.env]
|
||||
passthrough = ["AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-ar"]
|
||||
20
README.md
20
README.md
@@ -10,7 +10,12 @@
|
||||
|
||||
<img alt="Demo" src="doc/screenshot.gif" width="550px">
|
||||
</div>
|
||||
|
||||
|
||||
## Maintainers Wanted
|
||||
|
||||
I currently have not enough time to maintain this project on the level required and which the project deserves. For this reason I'm asking the community to help supporting the project, to help and work on resolving issues and create new features. Thanks for all your help.
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
> **Note**
|
||||
@@ -28,6 +33,7 @@ To remedy this, **Topgrade** detects which tools you use and runs the appropriat
|
||||
- NixOS: [Nixpkgs](https://search.nixos.org/packages?show=topgrade)
|
||||
- Void Linux: [XBPS](https://voidlinux.org/packages/?arch=x86_64&q=topgrade)
|
||||
- macOS: [Homebrew](https://formulae.brew.sh/formula/topgrade) or [MacPorts](https://ports.macports.org/port/topgrade/)
|
||||
- Windows: [Scoop](https://github.com/ScoopInstaller/Main/blob/master/bucket/topgrade.json)
|
||||
|
||||
Other systems users can either use `cargo install` or the compiled binaries from the release page.
|
||||
The compiled binaries contain a self-upgrading feature.
|
||||
@@ -43,7 +49,7 @@ Visit the documentation at [topgrade-rs.github.io](https://topgrade-rs.github.io
|
||||
> **Warning**
|
||||
> Work in Progress
|
||||
|
||||
## Customization
|
||||
## Configuration
|
||||
|
||||
See `config.example.toml` for an example configuration file.
|
||||
|
||||
@@ -54,6 +60,14 @@ The configuration should be placed in the following paths depending on the opera
|
||||
- **Windows** - `%APPDATA%/topgrade.toml`
|
||||
- **macOS** and **other Unix systems** - `${XDG_CONFIG_HOME:-~/.config}/topgrade.toml`
|
||||
|
||||
### Custom Commands
|
||||
|
||||
Custom commands can be defined in the config file which can be run before, during, or after the inbuilt commands, as required.
|
||||
By default, the custom commands are run using a new shell according to the `$SHELL` environment variable on unix (falls back to `sh`) or `pwsh` on windows (falls back to `powershell`).
|
||||
|
||||
On unix, if you want to run your command using an interactive shell, for example to source your shell's rc files, you can add `-i` at the start of your custom command.
|
||||
But note that this requires the command to exit the shell correctly or else the shell will hang indefinitely.
|
||||
|
||||
## Remote Execution
|
||||
|
||||
You can specify a key called `remote_topgrades` in the configuration file.
|
||||
@@ -80,8 +94,6 @@ Just fork the repository and start coding.
|
||||
|
||||
- Check if your code passes `cargo fmt` and `cargo clippy`.
|
||||
- Check if your code is self explanatory, if not it should be documented by comments.
|
||||
- Make a pull request to the `dev` branch for new features or to the `bug-fixes` branch for bug fixes.
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] Add a proper testing framework to the code base.
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
# 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 a possibly-unattended run.
|
||||
#pre_sudo = false
|
||||
@@ -47,6 +50,9 @@
|
||||
# Skip the preamble displayed when topgrade is run
|
||||
#display_preamble = false
|
||||
|
||||
# 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
|
||||
|
||||
[git]
|
||||
#max_concurrency = 5
|
||||
# Additional git repositories to pull
|
||||
@@ -71,6 +77,7 @@
|
||||
# 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"
|
||||
|
||||
[brew]
|
||||
#greedy_cask = true
|
||||
|
||||
@@ -10,7 +10,7 @@ use clap_complete::Shell;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use etcetera::base_strategy::BaseStrategy;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use strum::{EnumIter, EnumString, EnumVariantNames, IntoEnumIterator};
|
||||
@@ -18,6 +18,7 @@ use tracing::debug;
|
||||
use which_crate::which;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::sudo::SudoKind;
|
||||
|
||||
use super::utils::{editor, hostname};
|
||||
|
||||
@@ -115,6 +116,7 @@ pub enum Step {
|
||||
Helix,
|
||||
Krew,
|
||||
Macports,
|
||||
Mamba,
|
||||
Mas,
|
||||
Micro,
|
||||
Myrepos,
|
||||
@@ -293,6 +295,7 @@ pub struct Vim {
|
||||
#[serde(deny_unknown_fields)]
|
||||
/// Configuration file
|
||||
pub struct ConfigFile {
|
||||
sudo_command: Option<SudoKind>,
|
||||
pre_sudo: Option<bool>,
|
||||
pre_commands: Option<Commands>,
|
||||
post_commands: Option<Commands>,
|
||||
@@ -334,19 +337,20 @@ pub struct ConfigFile {
|
||||
vagrant: Option<Vagrant>,
|
||||
flatpak: Option<Flatpak>,
|
||||
distrobox: Option<Distrobox>,
|
||||
no_self_update: Option<bool>,
|
||||
}
|
||||
|
||||
fn config_directory(base_dirs: &BaseDirs) -> PathBuf {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
return base_dirs.config_dir().to_owned();
|
||||
fn config_directory() -> PathBuf {
|
||||
#[cfg(unix)]
|
||||
return crate::XDG_DIRS.config_dir();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
return base_dirs.home_dir().join(".config");
|
||||
#[cfg(windows)]
|
||||
return crate::WINDOWS_DIRS.config_dir();
|
||||
}
|
||||
|
||||
impl ConfigFile {
|
||||
fn ensure(base_dirs: &BaseDirs) -> Result<PathBuf> {
|
||||
let config_directory = config_directory(base_dirs);
|
||||
fn ensure() -> Result<PathBuf> {
|
||||
let config_directory = config_directory();
|
||||
|
||||
let config_path = config_directory.join("topgrade.toml");
|
||||
|
||||
@@ -370,11 +374,11 @@ impl ConfigFile {
|
||||
/// Read the configuration file.
|
||||
///
|
||||
/// If the configuration file does not exist the function returns the default ConfigFile.
|
||||
fn read(base_dirs: &BaseDirs, config_path: Option<PathBuf>) -> Result<ConfigFile> {
|
||||
fn read(config_path: Option<PathBuf>) -> Result<ConfigFile> {
|
||||
let config_path = if let Some(path) = config_path {
|
||||
path
|
||||
} else {
|
||||
Self::ensure(base_dirs)?
|
||||
Self::ensure()?
|
||||
};
|
||||
|
||||
let contents = fs::read_to_string(&config_path).map_err(|e| {
|
||||
@@ -408,8 +412,8 @@ impl ConfigFile {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn edit(base_dirs: &BaseDirs) -> Result<()> {
|
||||
let config_path = Self::ensure(base_dirs)?;
|
||||
fn edit() -> Result<()> {
|
||||
let config_path = Self::ensure()?;
|
||||
let editor = editor();
|
||||
debug!("Editor: {:?}", editor);
|
||||
|
||||
@@ -520,6 +524,10 @@ pub struct CommandLineArgs {
|
||||
/// Print roff manpage and exit
|
||||
#[clap(long, hide = true)]
|
||||
pub gen_manpage: bool,
|
||||
|
||||
/// Don't update Topgrade
|
||||
#[clap(long = "no-self-update")]
|
||||
pub no_self_update: bool,
|
||||
}
|
||||
|
||||
impl CommandLineArgs {
|
||||
@@ -559,10 +567,10 @@ impl Config {
|
||||
/// Load the configuration.
|
||||
///
|
||||
/// The function parses the command line arguments and reading the configuration file.
|
||||
pub fn load(base_dirs: &BaseDirs, opt: CommandLineArgs) -> Result<Self> {
|
||||
let config_directory = config_directory(base_dirs);
|
||||
pub fn load(opt: CommandLineArgs) -> Result<Self> {
|
||||
let config_directory = config_directory();
|
||||
let config_file = if config_directory.is_dir() {
|
||||
ConfigFile::read(base_dirs, opt.config.clone()).unwrap_or_else(|e| {
|
||||
ConfigFile::read(opt.config.clone()).unwrap_or_else(|e| {
|
||||
// Inform the user about errors when loading the configuration,
|
||||
// but fallback to the default config to at least attempt to do something
|
||||
tracing::error!("failed to load configuration: {}", e);
|
||||
@@ -589,8 +597,8 @@ impl Config {
|
||||
}
|
||||
|
||||
/// Launch an editor to edit the configuration
|
||||
pub fn edit(base_dirs: &BaseDirs) -> Result<()> {
|
||||
ConfigFile::edit(base_dirs)
|
||||
pub fn edit() -> Result<()> {
|
||||
ConfigFile::edit()
|
||||
}
|
||||
|
||||
/// The list of commands to run before performing any step.
|
||||
@@ -643,6 +651,11 @@ impl Config {
|
||||
enabled_steps
|
||||
}
|
||||
|
||||
/// Tell whether we should run a self update.
|
||||
pub fn no_self_update(&self) -> bool {
|
||||
self.opt.no_self_update || self.config_file.no_self_update.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Tell whether we should run in tmux.
|
||||
pub fn run_in_tmux(&self) -> bool {
|
||||
self.opt.run_in_tmux || self.config_file.run_in_tmux.unwrap_or(false)
|
||||
@@ -984,7 +997,7 @@ impl Config {
|
||||
.linux
|
||||
.as_ref()
|
||||
.and_then(|linux| linux.rpm_ostree)
|
||||
.unwrap_or(true)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Should we ignore failures for this step
|
||||
@@ -1017,6 +1030,10 @@ impl Config {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn sudo_command(&self) -> Option<SudoKind> {
|
||||
self.config_file.sudo_command
|
||||
}
|
||||
|
||||
/// If `true`, `sudo` should be called after `pre_commands` in order to elevate at the
|
||||
/// start of the session (and not in the middle).
|
||||
pub fn pre_sudo(&self) -> bool {
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::sudo::Sudo;
|
||||
use crate::utils::require_option;
|
||||
use crate::{config::Config, executor::Executor};
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
|
||||
@@ -14,7 +13,6 @@ pub struct ExecutionContext<'a> {
|
||||
sudo: Option<Sudo>,
|
||||
git: &'a Git,
|
||||
config: &'a Config,
|
||||
base_dirs: &'a BaseDirs,
|
||||
/// Name of a tmux session to execute commands in, if any.
|
||||
/// This is used in `./steps/remote/ssh.rs`, where we want to run `topgrade` in a new
|
||||
/// tmux window for each remote.
|
||||
@@ -22,19 +20,12 @@ pub struct ExecutionContext<'a> {
|
||||
}
|
||||
|
||||
impl<'a> ExecutionContext<'a> {
|
||||
pub fn new(
|
||||
run_type: RunType,
|
||||
sudo: Option<Sudo>,
|
||||
git: &'a Git,
|
||||
config: &'a Config,
|
||||
base_dirs: &'a BaseDirs,
|
||||
) -> Self {
|
||||
pub fn new(run_type: RunType, sudo: Option<Sudo>, git: &'a Git, config: &'a Config) -> Self {
|
||||
Self {
|
||||
run_type,
|
||||
sudo,
|
||||
git,
|
||||
config,
|
||||
base_dirs,
|
||||
tmux_session: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
@@ -60,10 +51,6 @@ impl<'a> ExecutionContext<'a> {
|
||||
self.config
|
||||
}
|
||||
|
||||
pub fn base_dirs(&self) -> &BaseDirs {
|
||||
self.base_dirs
|
||||
}
|
||||
|
||||
pub fn set_tmux_session(&self, session_name: String) {
|
||||
self.tmux_session.lock().unwrap().replace(session_name);
|
||||
}
|
||||
|
||||
109
src/main.rs
109
src/main.rs
@@ -2,14 +2,19 @@
|
||||
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
use std::time::Duration;
|
||||
|
||||
use clap::CommandFactory;
|
||||
use clap::{crate_version, Parser};
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use color_eyre::eyre::Result;
|
||||
use console::Key;
|
||||
#[cfg(windows)]
|
||||
use etcetera::base_strategy::Windows;
|
||||
use etcetera::base_strategy::{BaseStrategy, Xdg};
|
||||
use once_cell::sync::Lazy;
|
||||
use tracing::debug;
|
||||
|
||||
use self::config::{CommandLineArgs, Config, Step};
|
||||
@@ -36,12 +41,15 @@ mod sudo;
|
||||
mod terminal;
|
||||
mod utils;
|
||||
|
||||
pub static HOME_DIR: Lazy<PathBuf> = Lazy::new(|| home::home_dir().expect("No home directory"));
|
||||
pub static XDG_DIRS: Lazy<Xdg> = Lazy::new(|| Xdg::new().expect("No home directory"));
|
||||
#[cfg(windows)]
|
||||
pub static WINDOWS_DIRS: Lazy<Windows> = Lazy::new(|| Windows::new().expect("No home directory"));
|
||||
|
||||
fn run() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
ctrlc::set_handler();
|
||||
|
||||
let base_dirs = directories::BaseDirs::new().ok_or_else(|| eyre!("No base directories"))?;
|
||||
|
||||
let opt = CommandLineArgs::parse();
|
||||
|
||||
if let Some(shell) = opt.gen_completion {
|
||||
@@ -66,7 +74,7 @@ fn run() -> Result<()> {
|
||||
}
|
||||
|
||||
if opt.edit_config() {
|
||||
Config::edit(&base_dirs)?;
|
||||
Config::edit()?;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
@@ -75,7 +83,7 @@ fn run() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let config = Config::load(&base_dirs, opt)?;
|
||||
let config = Config::load(opt)?;
|
||||
terminal::set_title(config.set_title());
|
||||
terminal::display_time(config.display_time());
|
||||
terminal::set_desktop_notifications(config.notify_each_step());
|
||||
@@ -86,11 +94,14 @@ fn run() -> Result<()> {
|
||||
debug!("Binary path: {:?}", std::env::current_exe());
|
||||
debug!("Self Update: {:?}", cfg!(feature = "self-update"));
|
||||
|
||||
if config.display_preamble() || !config.skip_notify() {
|
||||
print_warning("Due to a design issue with notify-send it could be that topgrade hangs when it's finished.
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if config.display_preamble() && terminal::supports_notify_send() && !config.skip_notify() {
|
||||
print_warning("Due to a design issue with notify-send it could be that topgrade hangs when it's finished.
|
||||
If this is the case on your system add the --skip-notify flag to the topgrade command or set skip_notify = true in the config file.
|
||||
If you don't want this message to appear any longer set display_preamble = false in the config file.
|
||||
For more information about this issue see https://askubuntu.com/questions/110969/notify-send-ignores-timeout and https://github.com/topgrade-rs/topgrade/issues/288.");
|
||||
}
|
||||
}
|
||||
|
||||
if config.run_in_tmux() && env::var("TOPGRADE_INSIDE_TMUX").is_err() {
|
||||
@@ -104,16 +115,18 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
let git = git::Git::new();
|
||||
let mut git_repos = git::Repositories::new(&git);
|
||||
|
||||
let sudo = sudo::Sudo::detect();
|
||||
let sudo = config.sudo_command().map_or_else(sudo::Sudo::detect, sudo::Sudo::new);
|
||||
let run_type = executor::RunType::new(config.dry_run());
|
||||
|
||||
let ctx = execution_context::ExecutionContext::new(run_type, sudo, &git, &config, &base_dirs);
|
||||
let ctx = execution_context::ExecutionContext::new(run_type, sudo, &git, &config);
|
||||
|
||||
let mut runner = runner::Runner::new(&ctx);
|
||||
|
||||
#[cfg(feature = "self-update")]
|
||||
{
|
||||
if !run_type.dry() && env::var("TOPGRADE_NO_SELF_UPGRADE").is_err() {
|
||||
let config_self_upgrade = env::var("TOPGRADE_NO_SELF_UPGRADE").is_err() && !config.no_self_update();
|
||||
|
||||
if !run_type.dry() && config_self_upgrade {
|
||||
let result = self_update::self_update();
|
||||
|
||||
if let Err(e) = &result {
|
||||
@@ -244,7 +257,7 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
#[cfg(target_os = "android")]
|
||||
runner.execute(Step::Pkg, "Termux Packages", || android::upgrade_packages(&ctx))?;
|
||||
|
||||
let emacs = emacs::Emacs::new(&base_dirs);
|
||||
let emacs = emacs::Emacs::new();
|
||||
if config.use_predefined_git_repos() {
|
||||
if config.should_run(Step::Emacs) {
|
||||
if !emacs.is_doom() {
|
||||
@@ -252,43 +265,43 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
git_repos.insert_if_repo(directory);
|
||||
}
|
||||
}
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".doom.d"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".doom.d"));
|
||||
}
|
||||
|
||||
if config.should_run(Step::Vim) {
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".vim"));
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".config/nvim"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".vim"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".config/nvim"));
|
||||
}
|
||||
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".ideavimrc"));
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".intellimacs"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".ideavimrc"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".intellimacs"));
|
||||
|
||||
if config.should_run(Step::Rcm) {
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".dotfiles"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".dotfiles"));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
git_repos.insert_if_repo(zsh::zshrc(&base_dirs));
|
||||
git_repos.insert_if_repo(zsh::zshrc());
|
||||
if config.should_run(Step::Tmux) {
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".tmux"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".tmux"));
|
||||
}
|
||||
git_repos.insert_if_repo(base_dirs.home_dir().join(".config/fish"));
|
||||
git_repos.insert_if_repo(base_dirs.config_dir().join("openbox"));
|
||||
git_repos.insert_if_repo(base_dirs.config_dir().join("bspwm"));
|
||||
git_repos.insert_if_repo(base_dirs.config_dir().join("i3"));
|
||||
git_repos.insert_if_repo(base_dirs.config_dir().join("sway"));
|
||||
git_repos.insert_if_repo(HOME_DIR.join(".config/fish"));
|
||||
git_repos.insert_if_repo(XDG_DIRS.config_dir().join("openbox"));
|
||||
git_repos.insert_if_repo(XDG_DIRS.config_dir().join("bspwm"));
|
||||
git_repos.insert_if_repo(XDG_DIRS.config_dir().join("i3"));
|
||||
git_repos.insert_if_repo(XDG_DIRS.config_dir().join("sway"));
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
git_repos.insert_if_repo(
|
||||
base_dirs
|
||||
.data_local_dir()
|
||||
WINDOWS_DIRS
|
||||
.cache_dir()
|
||||
.join("Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState"),
|
||||
);
|
||||
|
||||
#[cfg(windows)]
|
||||
windows::insert_startup_scripts(&ctx, &mut git_repos).ok();
|
||||
windows::insert_startup_scripts(&mut git_repos).ok();
|
||||
|
||||
if let Some(profile) = powershell.profile() {
|
||||
git_repos.insert_if_repo(profile);
|
||||
@@ -314,30 +327,29 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
runner.execute(Step::Shell, "zr", || zsh::run_zr(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "zr", || zsh::run_zr(run_type))?;
|
||||
runner.execute(Step::Shell, "antibody", || zsh::run_antibody(run_type))?;
|
||||
runner.execute(Step::Shell, "antigen", || zsh::run_antigen(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "zgenom", || zsh::run_zgenom(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "zplug", || zsh::run_zplug(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "zinit", || zsh::run_zinit(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "zi", || zsh::run_zi(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "zim", || zsh::run_zim(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Shell, "antidote", || zsh::run_antidote(&ctx))?;
|
||||
runner.execute(Step::Shell, "antigen", || zsh::run_antigen(run_type))?;
|
||||
runner.execute(Step::Shell, "zgenom", || zsh::run_zgenom(run_type))?;
|
||||
runner.execute(Step::Shell, "zplug", || zsh::run_zplug(run_type))?;
|
||||
runner.execute(Step::Shell, "zinit", || zsh::run_zinit(run_type))?;
|
||||
runner.execute(Step::Shell, "zi", || zsh::run_zi(run_type))?;
|
||||
runner.execute(Step::Shell, "zim", || zsh::run_zim(run_type))?;
|
||||
runner.execute(Step::Shell, "oh-my-zsh", || zsh::run_oh_my_zsh(&ctx))?;
|
||||
runner.execute(Step::Shell, "fisher", || unix::run_fisher(run_type))?;
|
||||
runner.execute(Step::Shell, "bash-it", || unix::run_bashit(&ctx))?;
|
||||
runner.execute(Step::Shell, "oh-my-fish", || unix::run_oh_my_fish(&ctx))?;
|
||||
runner.execute(Step::Shell, "fish-plug", || unix::run_fish_plug(&ctx))?;
|
||||
runner.execute(Step::Shell, "fundle", || unix::run_fundle(&ctx))?;
|
||||
runner.execute(Step::Tmux, "tmux", || tmux::run_tpm(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Tmux, "tmux", || tmux::run_tpm(run_type))?;
|
||||
runner.execute(Step::Tldr, "TLDR", || unix::run_tldr(run_type))?;
|
||||
runner.execute(Step::Pearl, "pearl", || unix::run_pearl(run_type))?;
|
||||
#[cfg(not(any(target_os = "macos", target_os = "android")))]
|
||||
runner.execute(Step::GnomeShellExtensions, "Gnome Shell Extensions", || {
|
||||
unix::upgrade_gnome_extensions(&ctx)
|
||||
})?;
|
||||
runner.execute(Step::Sdkman, "SDKMAN!", || {
|
||||
unix::run_sdkman(&base_dirs, config.cleanup(), run_type)
|
||||
})?;
|
||||
runner.execute(Step::Sdkman, "SDKMAN!", || unix::run_sdkman(config.cleanup(), run_type))?;
|
||||
runner.execute(Step::Rcm, "rcm", || unix::run_rcm(&ctx))?;
|
||||
}
|
||||
|
||||
@@ -349,8 +361,8 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
)))]
|
||||
runner.execute(Step::Atom, "apm", || generic::run_apm(run_type))?;
|
||||
runner.execute(Step::Fossil, "fossil", || generic::run_fossil(run_type))?;
|
||||
runner.execute(Step::Rustup, "rustup", || generic::run_rustup(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Juliaup, "juliaup", || generic::run_juliaup(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Rustup, "rustup", || generic::run_rustup(&ctx))?;
|
||||
runner.execute(Step::Juliaup, "juliaup", || generic::run_juliaup(run_type))?;
|
||||
runner.execute(Step::Dotnet, ".NET", || generic::run_dotnet_upgrade(&ctx))?;
|
||||
runner.execute(Step::Choosenim, "choosenim", || generic::run_choosenim(&ctx))?;
|
||||
runner.execute(Step::Cargo, "cargo", || generic::run_cargo_update(&ctx))?;
|
||||
@@ -362,23 +374,20 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
runner.execute(Step::Vcpkg, "vcpkg", || generic::run_vcpkg_update(&ctx))?;
|
||||
runner.execute(Step::Pipx, "pipx", || generic::run_pipx_update(run_type))?;
|
||||
runner.execute(Step::Conda, "conda", || generic::run_conda_update(&ctx))?;
|
||||
runner.execute(Step::Mamba, "mamba", || generic::run_mamba_update(&ctx))?;
|
||||
runner.execute(Step::Pip3, "pip3", || generic::run_pip3_update(run_type))?;
|
||||
runner.execute(Step::PipReview, "pip-review", || generic::run_pip_review_update(&ctx))?;
|
||||
runner.execute(Step::Pipupgrade, "pipupgrade", || generic::run_pipupgrade_update(&ctx))?;
|
||||
runner.execute(Step::Ghcup, "ghcup", || generic::run_ghcup_update(run_type))?;
|
||||
runner.execute(Step::Stack, "stack", || generic::run_stack_update(run_type))?;
|
||||
runner.execute(Step::Tlmgr, "tlmgr", || generic::run_tlmgr_update(&ctx))?;
|
||||
runner.execute(Step::Myrepos, "myrepos", || {
|
||||
generic::run_myrepos_update(&base_dirs, run_type)
|
||||
})?;
|
||||
runner.execute(Step::Chezmoi, "chezmoi", || {
|
||||
generic::run_chezmoi_update(&base_dirs, run_type)
|
||||
})?;
|
||||
runner.execute(Step::Myrepos, "myrepos", || generic::run_myrepos_update(run_type))?;
|
||||
runner.execute(Step::Chezmoi, "chezmoi", || generic::run_chezmoi_update(run_type))?;
|
||||
runner.execute(Step::Jetpack, "jetpack", || generic::run_jetpack(run_type))?;
|
||||
runner.execute(Step::Vim, "vim", || vim::upgrade_vim(&base_dirs, &ctx))?;
|
||||
runner.execute(Step::Vim, "Neovim", || vim::upgrade_neovim(&base_dirs, &ctx))?;
|
||||
runner.execute(Step::Vim, "vim", || vim::upgrade_vim(&ctx))?;
|
||||
runner.execute(Step::Vim, "Neovim", || vim::upgrade_neovim(&ctx))?;
|
||||
runner.execute(Step::Vim, "The Ultimate vimrc", || vim::upgrade_ultimate_vimrc(&ctx))?;
|
||||
runner.execute(Step::Vim, "voom", || vim::run_voom(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Vim, "voom", || vim::run_voom(run_type))?;
|
||||
runner.execute(Step::Kakoune, "Kakoune", || kakoune::upgrade_kak_plug(&ctx))?;
|
||||
runner.execute(Step::Helix, "helix", || generic::run_helix_grammars(&ctx))?;
|
||||
runner.execute(Step::Node, "npm", || node::run_npm_upgrade(&ctx))?;
|
||||
@@ -389,7 +398,7 @@ For more information about this issue see https://askubuntu.com/questions/110969
|
||||
runner.execute(Step::Composer, "composer", || generic::run_composer_update(&ctx))?;
|
||||
runner.execute(Step::Krew, "krew", || generic::run_krew_upgrade(run_type))?;
|
||||
runner.execute(Step::Helm, "helm", || generic::run_helm_repo_update(run_type))?;
|
||||
runner.execute(Step::Gem, "gem", || generic::run_gem(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Gem, "gem", || generic::run_gem(run_type))?;
|
||||
runner.execute(Step::RubyGems, "rubygems", || generic::run_rubygems(&ctx))?;
|
||||
runner.execute(Step::Julia, "julia", || generic::update_julia_packages(&ctx))?;
|
||||
runner.execute(Step::Haxelib, "haxelib", || generic::run_haxelib_update(&ctx))?;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#[cfg(any(windows, target_os = "macos"))]
|
||||
#[cfg(any(windows))]
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use etcetera::base_strategy::BaseStrategy;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::execution_context::ExecutionContext;
|
||||
@@ -23,20 +23,12 @@ pub struct Emacs {
|
||||
}
|
||||
|
||||
impl Emacs {
|
||||
fn directory_path(base_dirs: &BaseDirs) -> Option<PathBuf> {
|
||||
fn directory_path() -> Option<PathBuf> {
|
||||
#[cfg(unix)]
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "macos")] {
|
||||
let emacs_xdg_dir = env::var("XDG_CONFIG_HOME")
|
||||
.ok()
|
||||
.and_then(|config| PathBuf::from(config).join("emacs").if_exists())
|
||||
.or_else(|| base_dirs.home_dir().join(".config/emacs").if_exists());
|
||||
} else {
|
||||
let emacs_xdg_dir = base_dirs.config_dir().join("emacs").if_exists();
|
||||
}
|
||||
}
|
||||
#[cfg(unix)]
|
||||
return base_dirs.home_dir().join(".emacs.d").if_exists().or(emacs_xdg_dir);
|
||||
return {
|
||||
let emacs_xdg_dir = crate::XDG_DIRS.config_dir().join("emacs").if_exists();
|
||||
crate::HOME_DIR.join(".emacs.d").if_exists().or(emacs_xdg_dir)
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
return env::var("HOME")
|
||||
@@ -47,11 +39,11 @@ impl Emacs {
|
||||
.if_exists()
|
||||
.or_else(|| PathBuf::from(&home).join(".config\\emacs").if_exists())
|
||||
})
|
||||
.or_else(|| base_dirs.data_dir().join(".emacs.d").if_exists());
|
||||
.or_else(|| crate::WINDOWS_DIRS.data_dir().join(".emacs.d").if_exists());
|
||||
}
|
||||
|
||||
pub fn new(base_dirs: &BaseDirs) -> Self {
|
||||
let directory = Emacs::directory_path(base_dirs);
|
||||
pub fn new() -> Self {
|
||||
let directory = Emacs::directory_path();
|
||||
let doom = directory.as_ref().and_then(|d| d.join(DOOM_PATH).if_exists());
|
||||
Self { directory, doom }
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use std::{fs, io::Write};
|
||||
use color_eyre::eyre::eyre;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use tempfile::tempfile_in;
|
||||
use tracing::{debug, error};
|
||||
|
||||
@@ -17,6 +16,8 @@ use crate::execution_context::ExecutionContext;
|
||||
use crate::executor::{ExecutorOutput, RunType};
|
||||
use crate::terminal::{print_separator, shell};
|
||||
use crate::utils::{self, require, require_option, which, PathExt};
|
||||
use crate::Step;
|
||||
use crate::HOME_DIR;
|
||||
use crate::{
|
||||
error::{SkipStep, StepFailed, TopgradeError},
|
||||
terminal::print_warning,
|
||||
@@ -25,7 +26,7 @@ use crate::{
|
||||
pub fn run_cargo_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let cargo_dir = env::var_os("CARGO_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| ctx.base_dirs().home_dir().join(".cargo"))
|
||||
.unwrap_or_else(|| HOME_DIR.join(".cargo"))
|
||||
.require()?;
|
||||
utils::require("cargo").or_else(|_| {
|
||||
require_option(
|
||||
@@ -56,7 +57,24 @@ pub fn run_cargo_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
ctx.run_type()
|
||||
.execute(cargo_update)
|
||||
.args(["install-update", "--git", "--all"])
|
||||
.status_checked()
|
||||
.status_checked()?;
|
||||
|
||||
if ctx.config().cleanup() {
|
||||
let cargo_cache = utils::require("cargo-cache")
|
||||
.ok()
|
||||
.or_else(|| cargo_dir.join("bin/cargo-cache").if_exists());
|
||||
match cargo_cache {
|
||||
Some(e) => {
|
||||
ctx.run_type().execute(e).args(["-a"]).status_checked()?;
|
||||
}
|
||||
None => {
|
||||
let message = String::from("cargo-cache isn't installed so Topgrade can't cleanup cargo packages.\nInstall cargo-cache by running `cargo install cargo-cache`");
|
||||
print_warning(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_flutter_upgrade(run_type: RunType) -> Result<()> {
|
||||
@@ -66,9 +84,9 @@ pub fn run_flutter_upgrade(run_type: RunType) -> Result<()> {
|
||||
run_type.execute(flutter).arg("upgrade").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_gem(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_gem(run_type: RunType) -> Result<()> {
|
||||
let gem = utils::require("gem")?;
|
||||
base_dirs.home_dir().join(".gem").require()?;
|
||||
HOME_DIR.join(".gem").require()?;
|
||||
|
||||
print_separator("Gems");
|
||||
|
||||
@@ -84,22 +102,28 @@ pub fn run_gem(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_rubygems(ctx: &ExecutionContext) -> Result<()> {
|
||||
ctx.base_dirs().home_dir().join(".gem").require()?;
|
||||
HOME_DIR.join(".gem").require()?;
|
||||
let gem = require("gem")?;
|
||||
|
||||
print_separator("RubyGems");
|
||||
if let Some(sudo) = &ctx.sudo() {
|
||||
let gem_path_str = gem.as_os_str();
|
||||
if gem_path_str.to_str().unwrap().contains("asdf") {
|
||||
ctx.run_type()
|
||||
.execute(gem)
|
||||
.args(["update", "--system"])
|
||||
.status_checked()?;
|
||||
} else if let Some(sudo) = &ctx.sudo() {
|
||||
if !std::path::Path::new("/usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb").exists() {
|
||||
ctx.run_type()
|
||||
.execute(sudo)
|
||||
.arg("-EH")
|
||||
.arg(require("gem")?)
|
||||
.arg(gem)
|
||||
.args(["update", "--system"])
|
||||
.status_checked()?;
|
||||
}
|
||||
} else {
|
||||
print_warning("No sudo detected. Skipping system upgrade");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -183,24 +207,19 @@ pub fn run_apm(run_type: RunType) -> Result<()> {
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_rustup(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_rustup(ctx: &ExecutionContext) -> Result<()> {
|
||||
let rustup = utils::require("rustup")?;
|
||||
|
||||
print_separator("rustup");
|
||||
|
||||
if rustup.canonicalize()?.is_descendant_of(base_dirs.home_dir()) {
|
||||
run_type.execute(&rustup).args(["self", "update"]).status_checked()?;
|
||||
}
|
||||
|
||||
run_type.execute(&rustup).arg("update").status_checked()
|
||||
ctx.run_type().execute(rustup).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_juliaup(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_juliaup(run_type: RunType) -> Result<()> {
|
||||
let juliaup = utils::require("juliaup")?;
|
||||
|
||||
print_separator("juliaup");
|
||||
|
||||
if juliaup.canonicalize()?.is_descendant_of(base_dirs.home_dir()) {
|
||||
if juliaup.canonicalize()?.is_descendant_of(&HOME_DIR) {
|
||||
run_type.execute(&juliaup).args(["self", "update"]).status_checked()?;
|
||||
}
|
||||
|
||||
@@ -314,10 +333,33 @@ pub fn run_conda_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
print_separator("Conda");
|
||||
|
||||
ctx.run_type()
|
||||
.execute(conda)
|
||||
.args(["update", "--all", "-y"])
|
||||
.status_checked()
|
||||
let mut command = ctx.run_type().execute(conda);
|
||||
command.args(["update", "--all"]);
|
||||
if ctx.config().yes(Step::Conda) {
|
||||
command.arg("--yes");
|
||||
}
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_mamba_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let mamba = utils::require("mamba")?;
|
||||
|
||||
let output = Command::new("mamba")
|
||||
.args(["config", "--show", "auto_activate_base"])
|
||||
.output_checked_utf8()?;
|
||||
debug!("Mamba output: {}", output.stdout);
|
||||
if output.stdout.contains("False") {
|
||||
return Err(SkipStep("auto_activate_base is set to False".to_string()).into());
|
||||
}
|
||||
|
||||
print_separator("Mamba");
|
||||
|
||||
let mut command = ctx.run_type().execute(mamba);
|
||||
command.args(["update", "--all"]);
|
||||
if ctx.config().yes(Step::Mamba) {
|
||||
command.arg("--yes");
|
||||
}
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_pip3_update(run_type: RunType) -> Result<()> {
|
||||
@@ -327,6 +369,21 @@ pub fn run_pip3_update(run_type: RunType) -> Result<()> {
|
||||
.output_checked_utf8()
|
||||
.map_err(|_| SkipStep("pip does not exists".to_string()))?;
|
||||
|
||||
let check_externally_managed = "import sysconfig; from os import path; print('Y') if path.isfile(path.join(sysconfig.get_path('stdlib'), 'EXTERNALLY-MANAGED')) else print('N')";
|
||||
Command::new(&python3)
|
||||
.args(["-c", check_externally_managed])
|
||||
.output_checked_utf8()
|
||||
.map_err(|_| SkipStep("pip may be externally managed".to_string()))
|
||||
.and_then(|output| match output.stdout.trim() {
|
||||
"N" => Ok(()),
|
||||
"Y" => Err(SkipStep("pip is externally managed".to_string())),
|
||||
_ => {
|
||||
print_warning("Unexpected output when checking EXTERNALLY-MANAGED");
|
||||
print_warning(output.stdout.trim());
|
||||
Err(SkipStep("pip may be externally managed".to_string()))
|
||||
}
|
||||
})?;
|
||||
|
||||
print_separator("pip3");
|
||||
if std::env::var("VIRTUAL_ENV").is_ok() {
|
||||
print_warning("This step is will be skipped when running inside a virtual environment");
|
||||
@@ -436,38 +493,46 @@ pub fn run_tlmgr_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_chezmoi_update(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_chezmoi_update(run_type: RunType) -> Result<()> {
|
||||
let chezmoi = utils::require("chezmoi")?;
|
||||
base_dirs.home_dir().join(".local/share/chezmoi").require()?;
|
||||
HOME_DIR.join(".local/share/chezmoi").require()?;
|
||||
|
||||
print_separator("chezmoi");
|
||||
|
||||
run_type.execute(chezmoi).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_myrepos_update(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_myrepos_update(run_type: RunType) -> Result<()> {
|
||||
let myrepos = utils::require("mr")?;
|
||||
base_dirs.home_dir().join(".mrconfig").require()?;
|
||||
HOME_DIR.join(".mrconfig").require()?;
|
||||
|
||||
print_separator("myrepos");
|
||||
|
||||
run_type
|
||||
.execute(&myrepos)
|
||||
.arg("--directory")
|
||||
.arg(base_dirs.home_dir())
|
||||
.arg(&*HOME_DIR)
|
||||
.arg("checkout")
|
||||
.status_checked()?;
|
||||
run_type
|
||||
.execute(&myrepos)
|
||||
.arg("--directory")
|
||||
.arg(base_dirs.home_dir())
|
||||
.arg(&*HOME_DIR)
|
||||
.arg("update")
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_custom_command(name: &str, command: &str, ctx: &ExecutionContext) -> Result<()> {
|
||||
print_separator(name);
|
||||
ctx.run_type().execute(shell()).arg("-c").arg(command).status_checked()
|
||||
let mut exec = ctx.run_type().execute(shell());
|
||||
#[cfg(unix)]
|
||||
let command = if let Some(command) = command.strip_prefix("-i ") {
|
||||
exec.arg("-i");
|
||||
command
|
||||
} else {
|
||||
command
|
||||
};
|
||||
exec.arg("-c").arg(command).status_checked()
|
||||
}
|
||||
|
||||
pub fn run_composer_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
@@ -479,7 +544,7 @@ pub fn run_composer_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
.map(|s| PathBuf::from(s.stdout.trim()))?
|
||||
.require()?;
|
||||
|
||||
if !composer_home.is_descendant_of(ctx.base_dirs().home_dir()) {
|
||||
if !composer_home.is_descendant_of(&HOME_DIR) {
|
||||
return Err(SkipStep(format!(
|
||||
"Composer directory {} isn't a decandent of the user's home directory",
|
||||
composer_home.display()
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::utils::require_option;
|
||||
use crate::HOME_DIR;
|
||||
use color_eyre::eyre::Result;
|
||||
#[cfg(target_os = "linux")]
|
||||
use nix::unistd::Uid;
|
||||
@@ -265,7 +266,7 @@ pub fn run_yarn_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
pub fn deno_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
let deno = require("deno")?;
|
||||
let deno_dir = ctx.base_dirs().home_dir().join(".deno");
|
||||
let deno_dir = HOME_DIR.join(".deno");
|
||||
|
||||
if !deno.canonicalize()?.is_descendant_of(&deno_dir) {
|
||||
let skip_reason = SkipStep("Deno installed outside of .deno directory".to_string());
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn upgrade_packages(ctx: &ExecutionContext) -> Result<()> {
|
||||
ctx.run_type().execute(&pkg).arg("clean").status_checked()?;
|
||||
|
||||
let apt = require("apt")?;
|
||||
let mut command = ctx.run_type().execute(&apt);
|
||||
let mut command = ctx.run_type().execute(apt);
|
||||
command.arg("autoremove");
|
||||
if ctx.config().yes(Step::System) {
|
||||
command.arg("-y");
|
||||
|
||||
@@ -26,6 +26,7 @@ pub enum Distribution {
|
||||
CentOS,
|
||||
ClearLinux,
|
||||
Fedora,
|
||||
FedoraSilverblue,
|
||||
Debian,
|
||||
Gentoo,
|
||||
OpenMandriva,
|
||||
@@ -43,13 +44,25 @@ impl Distribution {
|
||||
fn parse_os_release(os_release: &ini::Ini) -> Result<Self> {
|
||||
let section = os_release.general_section();
|
||||
let id = section.get("ID");
|
||||
let variant: Option<Vec<&str>> = section.get("VARIANT").map(|s| s.split_whitespace().collect());
|
||||
let id_like: Option<Vec<&str>> = section.get("ID_LIKE").map(|s| s.split_whitespace().collect());
|
||||
|
||||
Ok(match id {
|
||||
Some("alpine") => Distribution::Alpine,
|
||||
Some("centos") | Some("rhel") | Some("ol") => Distribution::CentOS,
|
||||
Some("clear-linux-os") => Distribution::ClearLinux,
|
||||
Some("fedora") | Some("nobara") => Distribution::Fedora,
|
||||
Some("fedora") | Some("nobara") => {
|
||||
if let Some(variant) = variant {
|
||||
if variant.contains(&"Silverblue") {
|
||||
return Ok(Distribution::FedoraSilverblue);
|
||||
} else {
|
||||
return Ok(Distribution::Fedora);
|
||||
};
|
||||
} else {
|
||||
return Ok(Distribution::Fedora);
|
||||
}
|
||||
}
|
||||
|
||||
Some("void") => Distribution::Void,
|
||||
Some("debian") | Some("pureos") => Distribution::Debian,
|
||||
Some("arch") | Some("anarchy") | Some("manjaro-arm") | Some("garuda") | Some("artix") => Distribution::Arch,
|
||||
@@ -103,6 +116,7 @@ impl Distribution {
|
||||
Distribution::Alpine => upgrade_alpine_linux(ctx),
|
||||
Distribution::Arch => archlinux::upgrade_arch_linux(ctx),
|
||||
Distribution::CentOS | Distribution::Fedora => upgrade_redhat(ctx),
|
||||
Distribution::FedoraSilverblue => upgrade_fedora_silverblue(ctx),
|
||||
Distribution::ClearLinux => upgrade_clearlinux(ctx),
|
||||
Distribution::Debian => upgrade_debian(ctx),
|
||||
Distribution::Gentoo => upgrade_gentoo(ctx),
|
||||
@@ -202,6 +216,14 @@ fn upgrade_redhat(ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn upgrade_fedora_silverblue(ctx: &ExecutionContext) -> Result<()> {
|
||||
let ostree = require("rpm-ostree")?;
|
||||
let mut command = ctx.run_type().execute(ostree);
|
||||
command.arg("upgrade");
|
||||
command.status_checked()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn upgrade_bedrock_strata(ctx: &ExecutionContext) -> Result<()> {
|
||||
if let Some(sudo) = ctx.sudo() {
|
||||
ctx.run_type().execute(sudo).args(["brl", "update"]).status_checked()?;
|
||||
@@ -361,6 +383,13 @@ fn upgrade_gentoo(ctx: &ExecutionContext) -> Result<()> {
|
||||
fn upgrade_debian(ctx: &ExecutionContext) -> Result<()> {
|
||||
if let Some(sudo) = &ctx.sudo() {
|
||||
let apt = which("apt-fast")
|
||||
.or_else(|| {
|
||||
if which("mist").is_some() {
|
||||
Some(PathBuf::from("mist"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.or_else(|| {
|
||||
if Path::new("/usr/bin/nala").exists() {
|
||||
Some(Path::new("/usr/bin/nala").to_path_buf())
|
||||
@@ -436,8 +465,9 @@ fn upgrade_solus(ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn update_am(ctx: &ExecutionContext) -> Result<()> {
|
||||
let am = require("am")?;
|
||||
if let Some(sudo) = ctx.sudo() {
|
||||
ctx.run_type().execute(sudo).args(["am", "-u"]).status_checked()?;
|
||||
ctx.run_type().execute(sudo).arg(am).arg("-u").status_checked()?;
|
||||
} else {
|
||||
print_warning("No sudo detected. Skipping AM Step");
|
||||
}
|
||||
@@ -450,10 +480,28 @@ pub fn run_pacdef(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
print_separator("pacdef");
|
||||
|
||||
ctx.run_type().execute(&pacdef).arg("sync").status_checked()?;
|
||||
let output = ctx.run_type().execute(&pacdef).arg("version").output_checked()?;
|
||||
let string = String::from_utf8(output.stdout)?;
|
||||
let new_version = string.contains("version: 1");
|
||||
|
||||
println!();
|
||||
ctx.run_type().execute(&pacdef).arg("review").status_checked()
|
||||
if new_version {
|
||||
ctx.run_type()
|
||||
.execute(&pacdef)
|
||||
.args(["package", "sync"])
|
||||
.status_checked()?;
|
||||
|
||||
println!();
|
||||
ctx.run_type()
|
||||
.execute(&pacdef)
|
||||
.args(["package", "review"])
|
||||
.status_checked()?;
|
||||
} else {
|
||||
ctx.run_type().execute(&pacdef).arg("sync").status_checked()?;
|
||||
|
||||
println!();
|
||||
ctx.run_type().execute(&pacdef).arg("review").status_checked()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_pacstall(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
@@ -5,9 +5,8 @@ use std::process::Command;
|
||||
use std::{env, path::Path};
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::Step;
|
||||
use crate::{Step, HOME_DIR};
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use home;
|
||||
use ini::Ini;
|
||||
use tracing::debug;
|
||||
@@ -127,7 +126,7 @@ pub fn run_fisher(run_type: RunType) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn run_bashit(ctx: &ExecutionContext) -> Result<()> {
|
||||
ctx.base_dirs().home_dir().join(".bash_it").require()?;
|
||||
HOME_DIR.join(".bash_it").require()?;
|
||||
|
||||
print_separator("Bash-it");
|
||||
|
||||
@@ -139,10 +138,7 @@ pub fn run_bashit(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
pub fn run_oh_my_fish(ctx: &ExecutionContext) -> Result<()> {
|
||||
let fish = require("fish")?;
|
||||
ctx.base_dirs()
|
||||
.home_dir()
|
||||
.join(".local/share/omf/pkg/omf/functions/omf.fish")
|
||||
.require()?;
|
||||
HOME_DIR.join(".local/share/omf/pkg/omf/functions/omf.fish").require()?;
|
||||
|
||||
print_separator("oh-my-fish");
|
||||
|
||||
@@ -171,8 +167,7 @@ pub fn run_pkgin(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
pub fn run_fish_plug(ctx: &ExecutionContext) -> Result<()> {
|
||||
let fish = require("fish")?;
|
||||
ctx.base_dirs()
|
||||
.home_dir()
|
||||
HOME_DIR
|
||||
.join(".local/share/fish/plug/kidonng/fish-plug/functions/plug.fish")
|
||||
.require()?;
|
||||
|
||||
@@ -191,7 +186,7 @@ pub fn run_fish_plug(ctx: &ExecutionContext) -> Result<()> {
|
||||
/// See: <https://github.com/danhper/fundle>
|
||||
pub fn run_fundle(ctx: &ExecutionContext) -> Result<()> {
|
||||
let fish = require("fish")?;
|
||||
ctx.base_dirs().home_dir().join(".config/fish/fundle").require()?;
|
||||
HOME_DIR.join(".config/fish/fundle").require()?;
|
||||
|
||||
print_separator("fundle");
|
||||
|
||||
@@ -335,6 +330,7 @@ pub fn run_nix(ctx: &ExecutionContext) -> Result<()> {
|
||||
let nix = require("nix")?;
|
||||
let nix_channel = require("nix-channel")?;
|
||||
let nix_env = require("nix-env")?;
|
||||
// TODO: Is None possible here?
|
||||
let profile_path = match home::home_dir() {
|
||||
Some(home) => Path::new(&home).join(".nix-profile"),
|
||||
None => Path::new("/nix/var/nix/profiles/per-user/default").into(),
|
||||
@@ -435,12 +431,12 @@ pub fn run_pearl(run_type: RunType) -> Result<()> {
|
||||
run_type.execute(pearl).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_sdkman(base_dirs: &BaseDirs, cleanup: bool, run_type: RunType) -> Result<()> {
|
||||
pub fn run_sdkman(cleanup: bool, run_type: RunType) -> Result<()> {
|
||||
let bash = require("bash")?;
|
||||
|
||||
let sdkman_init_path = env::var("SDKMAN_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".sdkman"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join(".sdkman"))
|
||||
.join("bin")
|
||||
.join("sdkman-init.sh")
|
||||
.require()
|
||||
@@ -450,7 +446,7 @@ pub fn run_sdkman(base_dirs: &BaseDirs, cleanup: bool, run_type: RunType) -> Res
|
||||
|
||||
let sdkman_config_path = env::var("SDKMAN_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".sdkman"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join(".sdkman"))
|
||||
.join("etc")
|
||||
.join("config")
|
||||
.require()?;
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::path::Path;
|
||||
use std::{ffi::OsStr, process::Command};
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use etcetera::base_strategy::BaseStrategy;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
@@ -164,9 +165,8 @@ pub fn reboot() -> Result<()> {
|
||||
Command::new("shutdown").args(["/R", "/T", "0"]).status_checked()
|
||||
}
|
||||
|
||||
pub fn insert_startup_scripts(ctx: &ExecutionContext, git_repos: &mut Repositories) -> Result<()> {
|
||||
let startup_dir = ctx
|
||||
.base_dirs()
|
||||
pub fn insert_startup_scripts(git_repos: &mut Repositories) -> Result<()> {
|
||||
let startup_dir = crate::WINDOWS_DIRS
|
||||
.data_dir()
|
||||
.join("Microsoft\\Windows\\Start Menu\\Programs\\Startup");
|
||||
for entry in std::fs::read_dir(&startup_dir)?.flatten() {
|
||||
|
||||
@@ -5,11 +5,11 @@ use std::process::Command;
|
||||
use color_eyre::eyre::eyre;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::executor::RunType;
|
||||
use crate::terminal::print_separator;
|
||||
use crate::HOME_DIR;
|
||||
use crate::{
|
||||
execution_context::ExecutionContext,
|
||||
utils::{which, PathExt},
|
||||
@@ -18,11 +18,8 @@ use crate::{
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::process::CommandExt as _;
|
||||
|
||||
pub fn run_tpm(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
let tpm = base_dirs
|
||||
.home_dir()
|
||||
.join(".tmux/plugins/tpm/bin/update_plugins")
|
||||
.require()?;
|
||||
pub fn run_tpm(run_type: RunType) -> Result<()> {
|
||||
let tpm = HOME_DIR.join(".tmux/plugins/tpm/bin/update_plugins").require()?;
|
||||
|
||||
print_separator("tmux plugins");
|
||||
|
||||
|
||||
@@ -35,27 +35,18 @@ endif
|
||||
|
||||
if exists(":Lazy")
|
||||
echo "Lazy Update"
|
||||
+Lazy! sync
|
||||
Lazy! sync | qa
|
||||
endif
|
||||
|
||||
function! UpdateCoCAndTS()
|
||||
if exists(":CocUpdateSync")
|
||||
echo "CocUpdateSync"
|
||||
CocUpdateSync
|
||||
endif
|
||||
|
||||
if exists(":TSUpdateSync")
|
||||
echo "TreeSitter Update"
|
||||
TSUpdate
|
||||
endif
|
||||
|
||||
quitall
|
||||
endfunction
|
||||
if exists(":AstroUpdate")
|
||||
echo "AstroUpdate"
|
||||
AstroUpdate
|
||||
endif
|
||||
|
||||
if exists(':PackerSync')
|
||||
echo "Packer"
|
||||
autocmd User PackerComplete * call UpdateCoCAndTS()
|
||||
autocmd User PackerComplete quitall
|
||||
PackerSync
|
||||
else
|
||||
call UpdateCoCAndTS()
|
||||
quitall
|
||||
endif
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use crate::command::CommandExt;
|
||||
use crate::error::{SkipStep, TopgradeError};
|
||||
use crate::HOME_DIR;
|
||||
use color_eyre::eyre::Result;
|
||||
use etcetera::base_strategy::BaseStrategy;
|
||||
|
||||
use crate::executor::{Executor, ExecutorOutput, RunType};
|
||||
use crate::terminal::print_separator;
|
||||
@@ -8,7 +10,6 @@ use crate::{
|
||||
execution_context::ExecutionContext,
|
||||
utils::{require, PathExt},
|
||||
};
|
||||
use directories::BaseDirs;
|
||||
use std::path::PathBuf;
|
||||
use std::{
|
||||
io::{self, Write},
|
||||
@@ -18,22 +19,19 @@ use tracing::debug;
|
||||
|
||||
const UPGRADE_VIM: &str = include_str!("upgrade.vim");
|
||||
|
||||
pub fn vimrc(base_dirs: &BaseDirs) -> Result<PathBuf> {
|
||||
base_dirs
|
||||
.home_dir()
|
||||
pub fn vimrc() -> Result<PathBuf> {
|
||||
HOME_DIR
|
||||
.join(".vimrc")
|
||||
.require()
|
||||
.or_else(|_| base_dirs.home_dir().join(".vim/vimrc").require())
|
||||
.or_else(|_| HOME_DIR.join(".vim/vimrc").require())
|
||||
}
|
||||
|
||||
fn nvimrc(base_dirs: &BaseDirs) -> Result<PathBuf> {
|
||||
fn nvimrc() -> Result<PathBuf> {
|
||||
#[cfg(unix)]
|
||||
let base_dir =
|
||||
// Bypass directories crate as nvim doesn't use the macOS-specific directories.
|
||||
std::env::var_os("XDG_CONFIG_HOME").map_or_else(|| base_dirs.home_dir().join(".config"), PathBuf::from);
|
||||
let base_dir = crate::XDG_DIRS.config_dir();
|
||||
|
||||
#[cfg(windows)]
|
||||
let base_dir = base_dirs.cache_dir();
|
||||
let base_dir = crate::WINDOWS_DIRS.cache_dir();
|
||||
|
||||
base_dir
|
||||
.join("nvim/init.vim")
|
||||
@@ -74,7 +72,7 @@ fn upgrade(command: &mut Executor, ctx: &ExecutionContext) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn upgrade_ultimate_vimrc(ctx: &ExecutionContext) -> Result<()> {
|
||||
let config_dir = ctx.base_dirs().home_dir().join(".vim_runtime").require()?;
|
||||
let config_dir = HOME_DIR.join(".vim_runtime").require()?;
|
||||
let git = require("git")?;
|
||||
let python = require("python3")?;
|
||||
let update_plugins = config_dir.join("update_plugins.py").require()?;
|
||||
@@ -105,7 +103,7 @@ pub fn upgrade_ultimate_vimrc(ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn upgrade_vim(base_dirs: &BaseDirs, ctx: &ExecutionContext) -> Result<()> {
|
||||
pub fn upgrade_vim(ctx: &ExecutionContext) -> Result<()> {
|
||||
let vim = require("vim")?;
|
||||
|
||||
let output = Command::new(&vim).arg("--version").output_checked_utf8()?;
|
||||
@@ -113,7 +111,7 @@ pub fn upgrade_vim(base_dirs: &BaseDirs, ctx: &ExecutionContext) -> Result<()> {
|
||||
return Err(SkipStep(String::from("vim binary might be actually nvim")).into());
|
||||
}
|
||||
|
||||
let vimrc = vimrc(base_dirs)?;
|
||||
let vimrc = vimrc()?;
|
||||
|
||||
print_separator("Vim");
|
||||
upgrade(
|
||||
@@ -127,9 +125,9 @@ pub fn upgrade_vim(base_dirs: &BaseDirs, ctx: &ExecutionContext) -> Result<()> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn upgrade_neovim(base_dirs: &BaseDirs, ctx: &ExecutionContext) -> Result<()> {
|
||||
pub fn upgrade_neovim(ctx: &ExecutionContext) -> Result<()> {
|
||||
let nvim = require("nvim")?;
|
||||
let nvimrc = nvimrc(base_dirs)?;
|
||||
let nvimrc = nvimrc()?;
|
||||
|
||||
print_separator("Neovim");
|
||||
upgrade(
|
||||
@@ -143,7 +141,7 @@ pub fn upgrade_neovim(base_dirs: &BaseDirs, ctx: &ExecutionContext) -> Result<()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn run_voom(_base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_voom(run_type: RunType) -> Result<()> {
|
||||
let voom = require("voom")?;
|
||||
|
||||
print_separator("voom");
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use tracing::debug;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
@@ -13,22 +12,41 @@ use crate::executor::RunType;
|
||||
use crate::git::Repositories;
|
||||
use crate::terminal::print_separator;
|
||||
use crate::utils::{require, PathExt};
|
||||
use crate::HOME_DIR;
|
||||
|
||||
pub fn run_zr(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_zr(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
|
||||
require("zr")?;
|
||||
|
||||
print_separator("zr");
|
||||
|
||||
let cmd = format!("source {} && zr --update", zshrc(base_dirs).display());
|
||||
let cmd = format!("source {} && zr --update", zshrc().display());
|
||||
run_type.execute(zsh).args(["-l", "-c", cmd.as_str()]).status_checked()
|
||||
}
|
||||
|
||||
pub fn zshrc(base_dirs: &BaseDirs) -> PathBuf {
|
||||
fn zdotdir() -> PathBuf {
|
||||
env::var("ZDOTDIR")
|
||||
.map(|p| Path::new(&p).join(".zshrc"))
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".zshrc"))
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| HOME_DIR.clone())
|
||||
}
|
||||
|
||||
pub fn zshrc() -> PathBuf {
|
||||
zdotdir().join(".zshrc")
|
||||
}
|
||||
|
||||
pub fn run_antidote(ctx: &ExecutionContext) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
let mut antidote = zdotdir().join(".antidote").require()?;
|
||||
antidote.push("antidote.zsh");
|
||||
|
||||
print_separator("antidote");
|
||||
|
||||
ctx.run_type()
|
||||
.execute(zsh)
|
||||
.arg("-c")
|
||||
.arg(format!("source {} && antidote update", antidote.display()))
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_antibody(run_type: RunType) -> Result<()> {
|
||||
@@ -40,12 +58,12 @@ pub fn run_antibody(run_type: RunType) -> Result<()> {
|
||||
run_type.execute(antibody).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_antigen(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_antigen(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
let zshrc = zshrc(base_dirs).require()?;
|
||||
let zshrc = zshrc().require()?;
|
||||
env::var("ADOTDIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join("antigen.zsh"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join("antigen.zsh"))
|
||||
.require()?;
|
||||
|
||||
print_separator("antigen");
|
||||
@@ -54,12 +72,12 @@ pub fn run_antigen(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
run_type.execute(zsh).args(["-l", "-c", cmd.as_str()]).status_checked()
|
||||
}
|
||||
|
||||
pub fn run_zgenom(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_zgenom(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
let zshrc = zshrc(base_dirs).require()?;
|
||||
let zshrc = zshrc().require()?;
|
||||
env::var("ZGEN_SOURCE")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".zgenom"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join(".zgenom"))
|
||||
.require()?;
|
||||
|
||||
print_separator("zgenom");
|
||||
@@ -68,13 +86,13 @@ pub fn run_zgenom(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
run_type.execute(zsh).args(["-l", "-c", cmd.as_str()]).status_checked()
|
||||
}
|
||||
|
||||
pub fn run_zplug(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_zplug(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
zshrc(base_dirs).require()?;
|
||||
zshrc().require()?;
|
||||
|
||||
env::var("ZPLUG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".zplug"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join(".zplug"))
|
||||
.require()?;
|
||||
|
||||
print_separator("zplug");
|
||||
@@ -85,13 +103,13 @@ pub fn run_zplug(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_zinit(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_zinit(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
let zshrc = zshrc(base_dirs).require()?;
|
||||
let zshrc = zshrc().require()?;
|
||||
|
||||
env::var("ZINIT_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".zinit"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join(".zinit"))
|
||||
.require()?;
|
||||
|
||||
print_separator("zinit");
|
||||
@@ -100,11 +118,11 @@ pub fn run_zinit(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
run_type.execute(zsh).args(["-i", "-c", cmd.as_str()]).status_checked()
|
||||
}
|
||||
|
||||
pub fn run_zi(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_zi(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
let zshrc = zshrc(base_dirs).require()?;
|
||||
let zshrc = zshrc().require()?;
|
||||
|
||||
base_dirs.home_dir().join(".zi").require()?;
|
||||
HOME_DIR.join(".zi").require()?;
|
||||
|
||||
print_separator("zi");
|
||||
|
||||
@@ -112,7 +130,7 @@ pub fn run_zi(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
run_type.execute(zsh).args(["-i", "-c", &cmd]).status_checked()
|
||||
}
|
||||
|
||||
pub fn run_zim(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
pub fn run_zim(run_type: RunType) -> Result<()> {
|
||||
let zsh = require("zsh")?;
|
||||
env::var("ZIM_HOME")
|
||||
.or_else(|_| {
|
||||
@@ -123,7 +141,7 @@ pub fn run_zim(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
.map(|o| o.stdout)
|
||||
})
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| base_dirs.home_dir().join(".zim"))
|
||||
.unwrap_or_else(|_| HOME_DIR.join(".zim"))
|
||||
.require()?;
|
||||
|
||||
print_separator("zim");
|
||||
@@ -136,7 +154,7 @@ pub fn run_zim(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
|
||||
pub fn run_oh_my_zsh(ctx: &ExecutionContext) -> Result<()> {
|
||||
require("zsh")?;
|
||||
let oh_my_zsh = ctx.base_dirs().home_dir().join(".oh-my-zsh").require()?;
|
||||
let oh_my_zsh = HOME_DIR.join(".oh-my-zsh").require()?;
|
||||
|
||||
print_separator("oh-my-zsh");
|
||||
|
||||
|
||||
21
src/sudo.rs
21
src/sudo.rs
@@ -4,6 +4,8 @@ use std::path::PathBuf;
|
||||
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
use serde::Deserialize;
|
||||
use strum::AsRefStr;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::execution_context::ExecutionContext;
|
||||
@@ -24,12 +26,18 @@ impl Sudo {
|
||||
pub fn detect() -> Option<Self> {
|
||||
which("doas")
|
||||
.map(|p| (p, SudoKind::Doas))
|
||||
.or_else(|| which("please").map(|p| (p, SudoKind::Please)))
|
||||
.or_else(|| which("sudo").map(|p| (p, SudoKind::Sudo)))
|
||||
.or_else(|| which("gsudo").map(|p| (p, SudoKind::Gsudo)))
|
||||
.or_else(|| which("pkexec").map(|p| (p, SudoKind::Pkexec)))
|
||||
.map(|(path, kind)| Self { path, kind })
|
||||
}
|
||||
|
||||
/// Create Sudo from SudoKind, if found in the system
|
||||
pub fn new(kind: SudoKind) -> Option<Self> {
|
||||
which(kind.as_ref()).map(|path| Self { path, kind })
|
||||
}
|
||||
|
||||
/// Elevate permissions with `sudo`.
|
||||
///
|
||||
/// This helps prevent blocking `sudo` prompts from stopping the run in the middle of a
|
||||
@@ -47,6 +55,12 @@ impl Sudo {
|
||||
// See: https://man.openbsd.org/doas
|
||||
cmd.arg("echo");
|
||||
}
|
||||
SudoKind::Please => {
|
||||
// From `man please`
|
||||
// -w, --warm
|
||||
// Warm the access token and exit.
|
||||
cmd.arg("-w");
|
||||
}
|
||||
SudoKind::Sudo => {
|
||||
// From `man sudo` on macOS:
|
||||
// -v, --validate
|
||||
@@ -93,9 +107,12 @@ impl Sudo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum SudoKind {
|
||||
#[derive(Clone, Copy, Debug, Deserialize, AsRefStr)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum SudoKind {
|
||||
Doas,
|
||||
Please,
|
||||
Sudo,
|
||||
Gsudo,
|
||||
Pkexec,
|
||||
|
||||
@@ -345,3 +345,8 @@ pub fn notify_desktop<P: AsRef<str>>(message: P, timeout: Option<Duration>) {
|
||||
pub fn display_time(display_time: bool) {
|
||||
TERMINAL.lock().unwrap().display_time(display_time);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn supports_notify_send() -> bool {
|
||||
TERMINAL.lock().unwrap().notify_send.is_some()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user