diff --git a/src/execution_context.rs b/src/execution_context.rs index 0f039e56..73e0e1d9 100644 --- a/src/execution_context.rs +++ b/src/execution_context.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use crate::config::Config; use crate::executor::RunType; +use crate::git::Git; use directories::BaseDirs; #[cfg(unix)] use std::path::PathBuf; @@ -9,6 +10,7 @@ pub struct ExecutionContext<'a> { run_type: RunType, #[cfg(unix)] sudo: &'a Option, + git: &'a Git, config: &'a Config, base_dirs: &'a BaseDirs, } @@ -18,22 +20,25 @@ impl<'a> ExecutionContext<'a> { pub fn new( run_type: RunType, sudo: &'a Option, + git: &'a Git, config: &'a Config, base_dirs: &'a BaseDirs, ) -> ExecutionContext<'a> { ExecutionContext { run_type, sudo, + git, config, base_dirs, } } #[cfg(not(unix))] - pub fn new(run_type: RunType, config: &'a Config, base_dirs: &'a BaseDirs) -> ExecutionContext<'a> { + pub fn new(run_type: RunType, git: &'a Git, config: &'a Config, base_dirs: &'a BaseDirs) -> ExecutionContext<'a> { ExecutionContext { run_type, config, + git, base_dirs, } } @@ -42,6 +47,10 @@ impl<'a> ExecutionContext<'a> { self.run_type } + pub fn git(&self) -> &Git { + &self.git + } + #[cfg(unix)] pub fn sudo(&self) -> &Option { &self.sudo diff --git a/src/main.rs b/src/main.rs index db76ae7e..b5db47ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,10 +65,10 @@ fn run() -> Result<()> { let run_type = executor::RunType::new(config.dry_run()); #[cfg(unix)] - let ctx = execution_context::ExecutionContext::new(run_type, &sudo, &config, &base_dirs); + let ctx = execution_context::ExecutionContext::new(run_type, &sudo, &git, &config, &base_dirs); #[cfg(not(unix))] - let ctx = execution_context::ExecutionContext::new(run_type, &config, &base_dirs); + let ctx = execution_context::ExecutionContext::new(run_type, &git, &config, &base_dirs); let mut runner = runner::Runner::new(&ctx); @@ -212,9 +212,7 @@ fn run() -> Result<()> { git_repos.glob_insert(git_repo); } } - runner.execute("Git repositories", || { - git.multi_pull(&git_repos, run_type, config.git_arguments()) - })?; + runner.execute("Git repositories", || git.multi_pull_step(&git_repos, &ctx))?; } if should_run_powershell { @@ -229,7 +227,7 @@ fn run() -> Result<()> { runner.execute("antigen", || zsh::run_antigen(&base_dirs, run_type))?; runner.execute("zplug", || zsh::run_zplug(&base_dirs, run_type))?; runner.execute("zinit", || zsh::run_zinit(&base_dirs, run_type))?; - runner.execute("oh-my-zsh", || zsh::run_oh_my_zsh(&base_dirs, run_type))?; + runner.execute("oh-my-zsh", || zsh::run_oh_my_zsh(&ctx))?; runner.execute("fisher", || unix::run_fisher(&base_dirs, run_type))?; runner.execute("tmux", || tmux::run_tpm(&base_dirs, run_type))?; } diff --git a/src/steps/git.rs b/src/steps/git.rs index aae490e6..b52bc0d9 100644 --- a/src/steps/git.rs +++ b/src/steps/git.rs @@ -1,4 +1,5 @@ use crate::error::{SkipStep, TopgradeError}; +use crate::execution_context::ExecutionContext; use crate::executor::{CommandExt, RunType}; use crate::terminal::print_separator; use crate::utils::{which, PathExt}; @@ -95,22 +96,19 @@ impl Git { None } - - pub fn multi_pull( - &self, - repositories: &Repositories, - run_type: RunType, - extra_arguments: &Option, - ) -> Result<()> { + pub fn multi_pull_step(&self, repositories: &Repositories, ctx: &ExecutionContext) -> Result<()> { if repositories.repositories.is_empty() { return Err(SkipStep.into()); } + print_separator("Git repositories"); + self.multi_pull(repositories, ctx) + } + + pub fn multi_pull(&self, repositories: &Repositories, ctx: &ExecutionContext) -> Result<()> { let git = self.git.as_ref().unwrap(); - print_separator("Git repositories"); - - if let RunType::Dry = run_type { + if let RunType::Dry = ctx.run_type() { repositories .repositories .iter() @@ -133,7 +131,7 @@ impl Git { command.args(&["pull", "--ff-only"]).current_dir(&repo); - if let Some(extra_arguments) = extra_arguments { + if let Some(extra_arguments) = ctx.config().git_arguments() { command.args(extra_arguments.split_whitespace()); } @@ -259,4 +257,15 @@ impl<'a> Repositories<'a> { error!("Bad glob pattern: {}", pattern); } } + + #[cfg(unix)] + pub fn is_empty(&self) -> bool { + self.repositories.is_empty() + } + + #[cfg(unix)] + pub fn remove(&mut self, path: &str) { + let _removed = self.repositories.remove(path); + debug_assert!(_removed); + } } diff --git a/src/steps/zsh.rs b/src/steps/zsh.rs index 2291b3e0..ded07b98 100644 --- a/src/steps/zsh.rs +++ b/src/steps/zsh.rs @@ -1,10 +1,15 @@ -use crate::executor::RunType; +use crate::execution_context::ExecutionContext; +use crate::executor::{CommandExt, RunType}; +use crate::git::Repositories; use crate::terminal::print_separator; use crate::utils::{require, PathExt}; use anyhow::Result; use directories::BaseDirs; +use log::debug; use std::env; +use std::fs; use std::path::{Path, PathBuf}; +use std::process::Command; pub fn run_zr(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> { let zsh = require("zsh")?; @@ -78,13 +83,35 @@ pub fn run_zinit(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> { run_type.execute(zsh).args(&["-i", "-c", cmd.as_str()]).check_run() } -pub fn run_oh_my_zsh(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> { +pub fn run_oh_my_zsh(ctx: &ExecutionContext) -> Result<()> { require("zsh")?; - let oh_my_zsh = base_dirs.home_dir().join(".oh-my-zsh").require()?; + let oh_my_zsh = ctx.base_dirs().home_dir().join(".oh-my-zsh").require()?; print_separator("oh-my-zsh"); - run_type + let mut custom_dir = PathBuf::from( + Command::new("zsh") + .args(&["-i", "-c", "echo -n $ZSH_CUSTOM"]) + .check_output()?, + ); + custom_dir.push("plugins"); + + debug!("oh-my-zsh custom dir: {}", custom_dir.display()); + + let mut custom_plugins = Repositories::new(ctx.git()); + for entry in fs::read_dir(custom_dir)? { + let entry = entry?; + custom_plugins.insert_if_repo(entry.path()); + } + + custom_plugins.remove(&oh_my_zsh.to_string_lossy()); + + if !custom_plugins.is_empty() { + println!("Pulling custom plugins"); + ctx.git().multi_pull(&custom_plugins, ctx)?; + } + + ctx.run_type() .execute("sh") .env("ZSH", &oh_my_zsh) .arg(&oh_my_zsh.join("tools/upgrade.sh"))