From 369ea6a140438fdbaf29ff31f3fea8195603b5e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 07:23:23 +0100 Subject: [PATCH 01/39] Bump struct-patch from 0.8.7 to 0.9.0 (#2583) Bumps [struct-patch](https://github.com/yanganto/struct-patch) from 0.8.7 to 0.9.0. - [Release notes](https://github.com/yanganto/struct-patch/releases) - [Commits](https://github.com/yanganto/struct-patch/compare/v0.8.7...v0.9.0) --- updated-dependencies: - dependency-name: struct-patch dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f15e14f983..f02a5a1817 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3320,18 +3320,18 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "struct-patch" -version = "0.8.7" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde1b55ce4b9efe4b5c302dea2d0f1297a522963024e160a587a2670c24f3f04" +checksum = "198180af96bd27ff18f84da0d689ff51e24dde06e9d95badb0d2c01bb915ffd0" dependencies = [ "struct-patch-derive", ] [[package]] name = "struct-patch-derive" -version = "0.8.7" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac94fea04bf721f57ed7f421e64d3a04858e15708d00e8aa814cad7507427503" +checksum = "81c0fa19d1fb0c92c763f74904b40b10b4d0740b80e3b0c6bfe52fcbcab2f24c" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 75bb1cd9c6..67424121c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ scopetime = { path = "./scopetime", version = "0.1" } serde = "1.0" shellexpand = "3.1" simplelog = { version = "0.12", default-features = false } -struct-patch = "0.8" +struct-patch = "0.9" syntect = { version = "5.2", default-features = false, features = [ "parsing", "default-syntaxes", From 156381155e12d89b39e657f07c8dac557271d24f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 13:22:09 +0800 Subject: [PATCH 02/39] Bump clap from 4.5.32 to 4.5.34 (#2585) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.32 to 4.5.34. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.32...clap_complete-v4.5.34) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f02a5a1817..68ef85cd0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,18 +432,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" dependencies = [ "anstream", "anstyle", From 89f73d2ec2efceae4ae18d996b12c350cb909af9 Mon Sep 17 00:00:00 2001 From: Johannes Agricola Date: Fri, 4 Apr 2025 15:27:50 +0200 Subject: [PATCH 03/39] Disable dotted range commit yanking (#2577) The algorithm for computing marked_consecutive assumes that commits are consecutive in the commit graph if they are consecutive in the linearized log used in` commitlist.rs`. That is not universally correct, as siblings may also be displayed consecutively in this list. For now, this just removes generating commit lists in dotted range notation. Co-authored-by: Naseschwarz --- CHANGELOG.md | 3 + asyncgit/src/sync/commits_info.rs | 14 ++- src/components/commitlist.rs | 186 ++++++++++++++++++++++++++---- src/queue.rs | 2 +- 4 files changed, 182 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 012b60e5ff..423aea3ee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * set the terminal title to `gitui ({repo_path})` [[@acuteenvy](https://github.com/acuteenvy)] ([#2462](https://github.com/gitui-org/gitui/issues/2462)) * respect `.mailmap` [[@acuteenvy](https://github.com/acuteenvy)] ([#2406](https://github.com/gitui-org/gitui/issues/2406)) +### Fixes +* yanking commit ranges no longer generates incorrect dotted range notations, but lists each individual commit [[@naseschwarz](https://github.com/naseschwarz)] (https://github.com/gitui-org/gitui/issues/2576) + ## [0.27.0] - 2024-01-14 **new: manage remotes** diff --git a/asyncgit/src/sync/commits_info.rs b/asyncgit/src/sync/commits_info.rs index df426249e7..111a2b9bce 100644 --- a/asyncgit/src/sync/commits_info.rs +++ b/asyncgit/src/sync/commits_info.rs @@ -49,6 +49,18 @@ impl CommitId { let commit_obj = repo.revparse_single(revision)?; Ok(commit_obj.id().into()) } + + /// Tries to convert a &str representation of a commit id into + /// a `CommitId` + pub fn from_str_unchecked(commit_id_str: &str) -> Result { + match Oid::from_str(commit_id_str) { + Err(e) => Err(crate::Error::Generic(format!( + "Could not convert {}", + e.message() + ))), + Ok(v) => Ok(Self::new(v)), + } + } } impl Display for CommitId { @@ -73,7 +85,7 @@ impl From for CommitId { } /// -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CommitInfo { /// pub message: String, diff --git a/src/components/commitlist.rs b/src/components/commitlist.rs index 52e4e7be9d..f2c8a448a6 100644 --- a/src/components/commitlist.rs +++ b/src/components/commitlist.rs @@ -132,10 +132,9 @@ impl CommitList { commits } - /// - pub fn copy_commit_hash(&self) -> Result<()> { - let marked = self.marked.as_slice(); - let yank: Option = match marked { + /// Build string of marked or selected (if none are marked) commit ids + fn concat_selected_commit_ids(&self) -> Option { + match self.marked.as_slice() { [] => self .items .iter() @@ -144,24 +143,19 @@ impl CommitList { .saturating_sub(self.items.index_offset()), ) .map(|e| e.id.to_string()), - [(_idx, commit)] => Some(commit.to_string()), - [first, .., last] => { - let marked_consecutive = - marked.windows(2).all(|w| w[0].0 + 1 == w[1].0); - - let yank = if marked_consecutive { - format!("{}^..{}", first.1, last.1) - } else { - marked - .iter() - .map(|(_idx, commit)| commit.to_string()) - .join(" ") - }; - Some(yank) - } - }; + marked => Some( + marked + .iter() + .map(|(_idx, commit)| commit.to_string()) + .join(" "), + ), + } + } - if let Some(yank) = yank { + /// Copy currently marked or selected (if none are marked) commit ids + /// to clipboard + pub fn copy_commit_hash(&self) -> Result<()> { + if let Some(yank) = self.concat_selected_commit_ids() { crate::clipboard::copy_string(&yank)?; self.queue.push(InternalEvent::ShowInfoMsg( strings::copy_success(&yank), @@ -893,8 +887,36 @@ impl Component for CommitList { #[cfg(test)] mod tests { + use asyncgit::sync::CommitInfo; + use super::*; + impl Default for CommitList { + fn default() -> Self { + Self { + title: String::from("").into_boxed_str(), + selection: 0, + highlighted_selection: Option::None, + highlights: Option::None, + tags: Option::None, + items: ItemBatch::default(), + commits: IndexSet::default(), + marked: Vec::default(), + scroll_top: Cell::default(), + local_branches: BTreeMap::default(), + remote_branches: BTreeMap::default(), + theme: SharedTheme::default(), + key_config: SharedKeyConfig::default(), + scroll_state: (Instant::now(), 0.0), + current_size: Cell::default(), + repo: RepoPathRef::new(sync::RepoPath::Path( + std::path::PathBuf::default(), + )), + queue: Queue::default(), + } + } + } + #[test] fn test_string_width_align() { assert_eq!(string_width_align("123", 3), "123"); @@ -916,4 +938,126 @@ mod tests { "Jon Grythe Stødle " ); } + + /// Build a commit list with a few commits loaded + fn build_commit_list_with_some_commits() -> CommitList { + let mut items = ItemBatch::default(); + let basic_commit_info = CommitInfo { + message: String::default(), + time: 0, + author: String::default(), + id: CommitId::default(), + }; + // This just creates a sequence of fake ordered ids + // 0000000000000000000000000000000000000000 + // 0000000000000000000000000000000000000001 + // 0000000000000000000000000000000000000002 + // ... + items.set_items( + 2, /* randomly choose an offset */ + (0..20) + .map(|idx| CommitInfo { + id: CommitId::from_str_unchecked(&format!( + "{idx:040}", + )) + .unwrap(), + ..basic_commit_info.clone() + }) + .collect(), + None, + ); + CommitList { + items, + selection: 4, // Randomly select one commit + ..Default::default() + } + } + + /// Build a value for cl.marked based on indices into cl.items + fn build_marked_from_indices( + cl: &CommitList, + marked_indices: &[usize], + ) -> Vec<(usize, CommitId)> { + let offset = cl.items.index_offset(); + marked_indices + .iter() + .map(|idx| { + (*idx, cl.items.iter().nth(*idx - offset).unwrap().id) + }) + .collect() + } + + #[test] + fn test_copy_commit_list_empty() { + assert_eq!( + CommitList::default().concat_selected_commit_ids(), + None + ); + } + + #[test] + fn test_copy_commit_none_marked() { + let cl = CommitList { + selection: 4, + ..build_commit_list_with_some_commits() + }; + // ids from build_commit_list_with_some_commits() are + // offset by two, so we expect commit id 2 for + // selection = 4 + assert_eq!( + cl.concat_selected_commit_ids(), + Some(String::from( + "0000000000000000000000000000000000000002" + )) + ); + } + + #[test] + fn test_copy_commit_one_marked() { + let cl = build_commit_list_with_some_commits(); + let cl = CommitList { + marked: build_marked_from_indices(&cl, &[3]), + ..cl + }; + assert_eq!( + cl.concat_selected_commit_ids(), + Some(String::from( + "0000000000000000000000000000000000000001", + )) + ); + } + + #[test] + fn test_copy_commit_range_marked() { + let cl = build_commit_list_with_some_commits(); + let cl = CommitList { + marked: build_marked_from_indices(&cl, &[4, 5, 6, 7]), + ..cl + }; + assert_eq!( + cl.concat_selected_commit_ids(), + Some(String::from(concat!( + "0000000000000000000000000000000000000002 ", + "0000000000000000000000000000000000000003 ", + "0000000000000000000000000000000000000004 ", + "0000000000000000000000000000000000000005" + ))) + ); + } + + #[test] + fn test_copy_commit_random_marked() { + let cl = build_commit_list_with_some_commits(); + let cl = CommitList { + marked: build_marked_from_indices(&cl, &[4, 7]), + ..cl + }; + assert_eq!( + cl.concat_selected_commit_ids(), + Some(String::from(concat!( + "0000000000000000000000000000000000000002 ", + "0000000000000000000000000000000000000005" + ))) + ); + } } diff --git a/src/queue.rs b/src/queue.rs index 44268a851d..635fbc9e71 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -160,7 +160,7 @@ pub enum InternalEvent { } /// single threaded simple queue for components to communicate with each other -#[derive(Clone)] +#[derive(Clone, Default)] pub struct Queue { data: Rc>>, } From 7f75307f6e29d2a12bb5994a25e300c312d7c930 Mon Sep 17 00:00:00 2001 From: Johannes Agricola Date: Fri, 4 Apr 2025 15:28:44 +0200 Subject: [PATCH 04/39] Resolve core.hooksPath relative to GIT_WORK_TREE (#2571) * Resolve core.hooksPath relative to GIT_WORK_TREE git supports relative values in core.hooksPath. `man git-config`: > A relative path is taken as relative to the directory where the hooks are > run (see the "DESCRIPTION" section of githooks[5]). `man githooks`: > Before Git invokes a hook, it changes its working directory to either > $GIT_DIR in a bare repository or the root of the working tree in a > > non-bare repository. I.e. relative paths in core.hooksPath in non-bare repositories are always relative to GIT_WORK_TREE. There is a further exception; I believe this is not considered for path resolution: > An exception are hooks triggered during a push (pre-receive, update, > post-receive, post-update, push-to-checkout) which are always executed > in $GIT_DIR. * Favor Repository::workdir() over path().parent() This more clearly errors in case of bare repositories instead of using the parent directory of the bare repository. --------- Co-authored-by: Naseschwarz Co-authored-by: extrawurst <776816+extrawurst@users.noreply.github.com> --- CHANGELOG.md | 1 + asyncgit/src/sync/hooks.rs | 56 ++++++++++++++++++++++++-- git2-hooks/src/hookspath.rs | 79 ++++++++++++++++++++++++++++++++----- 3 files changed, 123 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 423aea3ee8..c7caec869d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * respect `.mailmap` [[@acuteenvy](https://github.com/acuteenvy)] ([#2406](https://github.com/gitui-org/gitui/issues/2406)) ### Fixes +* resolve `core.hooksPath` relative to `GIT_WORK_TREE` [[@naseschwarz](https://github.com/naseschwarz)] ([#2571](https://github.com/gitui-org/gitui/issues/2571)) * yanking commit ranges no longer generates incorrect dotted range notations, but lists each individual commit [[@naseschwarz](https://github.com/naseschwarz)] (https://github.com/gitui-org/gitui/issues/2576) ## [0.27.0] - 2024-01-14 diff --git a/asyncgit/src/sync/hooks.rs b/asyncgit/src/sync/hooks.rs index 3e82cf6f8d..6fc672134f 100644 --- a/asyncgit/src/sync/hooks.rs +++ b/asyncgit/src/sync/hooks.rs @@ -76,11 +76,28 @@ pub fn hooks_prepare_commit_msg( mod tests { use super::*; use crate::sync::tests::repo_init; + use std::fs::File; + use std::io::Write; + use std::path::Path; + + fn create_hook_in_path(path: &Path, hook_script: &[u8]) { + File::create(path).unwrap().write_all(hook_script).unwrap(); + + #[cfg(unix)] + { + std::process::Command::new("chmod") + .arg("+x") + .arg(path) + // .current_dir(path) + .output() + .unwrap(); + } + } #[test] fn test_post_commit_hook_reject_in_subfolder() { let (_td, repo) = repo_init().unwrap(); - let root = repo.path().parent().unwrap(); + let root = repo.workdir().unwrap(); let hook = b"#!/bin/sh echo 'rejected' @@ -113,7 +130,7 @@ mod tests { #[cfg(unix)] fn test_pre_commit_workdir() { let (_td, repo) = repo_init().unwrap(); - let root = repo.path().parent().unwrap(); + let root = repo.workdir().unwrap(); let repo_path: &RepoPath = &root.as_os_str().to_str().unwrap().into(); let workdir = @@ -143,7 +160,7 @@ mod tests { #[test] fn test_hooks_commit_msg_reject_in_subfolder() { let (_td, repo) = repo_init().unwrap(); - let root = repo.path().parent().unwrap(); + let root = repo.workdir().unwrap(); let hook = b"#!/bin/sh echo 'msg' > $1 @@ -174,4 +191,37 @@ mod tests { assert_eq!(msg, String::from("msg\n")); } + + #[test] + fn test_hooks_commit_msg_reject_in_hooks_folder_githooks_moved_absolute( + ) { + let (_td, repo) = repo_init().unwrap(); + let root = repo.workdir().unwrap(); + let mut config = repo.config().unwrap(); + + const HOOKS_DIR: &'static str = "my_hooks"; + config.set_str("core.hooksPath", HOOKS_DIR).unwrap(); + + let hook = b"#!/bin/sh + echo 'msg' > \"$1\" + echo 'rejected' + exit 1 + "; + let hooks_folder = root.join(HOOKS_DIR); + std::fs::create_dir_all(&hooks_folder).unwrap(); + create_hook_in_path(&hooks_folder.join("commit-msg"), hook); + + let mut msg = String::from("test"); + let res = hooks_commit_msg( + &hooks_folder.to_str().unwrap().into(), + &mut msg, + ) + .unwrap(); + assert_eq!( + res, + HookResult::NotOk(String::from("rejected\n")) + ); + + assert_eq!(msg, String::from("msg\n")); + } } diff --git a/git2-hooks/src/hookspath.rs b/git2-hooks/src/hookspath.rs index 3648676ee2..af4f8af0a7 100644 --- a/git2-hooks/src/hookspath.rs +++ b/git2-hooks/src/hookspath.rs @@ -41,16 +41,8 @@ impl HookPaths { if let Some(config_path) = Self::config_hook_path(repo)? { let hooks_path = PathBuf::from(config_path); - let hook = hooks_path.join(hook); - - let hook = shellexpand::full( - hook.as_os_str() - .to_str() - .ok_or(HooksError::PathToString)?, - )?; - - let hook = PathBuf::from_str(hook.as_ref()) - .map_err(|_| HooksError::PathToString)?; + let hook = + Self::expand_path(&hooks_path.join(hook), &pwd)?; return Ok(Self { git: git_dir, @@ -66,6 +58,41 @@ impl HookPaths { }) } + /// Expand path according to the rule of githooks and config + /// core.hooksPath + fn expand_path(path: &Path, pwd: &Path) -> Result { + let hook_expanded = shellexpand::full( + path.as_os_str() + .to_str() + .ok_or(HooksError::PathToString)?, + )?; + let hook_expanded = PathBuf::from_str(hook_expanded.as_ref()) + .map_err(|_| HooksError::PathToString)?; + + // `man git-config`: + // + // > A relative path is taken as relative to the + // > directory where the hooks are run (see the + // > "DESCRIPTION" section of githooks[5]). + // + // `man githooks`: + // + // > Before Git invokes a hook, it changes its + // > working directory to either $GIT_DIR in a bare + // > repository or the root of the working tree in a + // > non-bare repository. + // + // I.e. relative paths in core.hooksPath in non-bare + // repositories are always relative to GIT_WORK_TREE. + Ok({ + if hook_expanded.is_absolute() { + hook_expanded + } else { + pwd.join(hook_expanded) + } + }) + } + fn config_hook_path(repo: &Repository) -> Result> { Ok(repo.config()?.get_string(CONFIG_HOOKS_PATH).ok()) } @@ -232,3 +259,35 @@ impl CommandExt for Command { self } } + +#[cfg(test)] +mod test { + use super::HookPaths; + use std::path::Path; + + #[test] + fn test_hookspath_relative() { + assert_eq!( + HookPaths::expand_path( + &Path::new("pre-commit"), + &Path::new("example_git_root"), + ) + .unwrap(), + Path::new("example_git_root").join("pre-commit") + ); + } + + #[test] + fn test_hookspath_absolute() { + let absolute_hook = + std::env::current_dir().unwrap().join("pre-commit"); + assert_eq!( + HookPaths::expand_path( + &absolute_hook, + &Path::new("example_git_root"), + ) + .unwrap(), + absolute_hook + ); + } +} From cc907996f4ee291b59fd7740378fb247d6074ba2 Mon Sep 17 00:00:00 2001 From: extrawurst <776816+extrawurst@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:06:00 +0200 Subject: [PATCH 05/39] fix latest clippy (#2597) --- asyncgit/src/sync/branch/mod.rs | 2 +- asyncgit/src/sync/commit.rs | 1 - asyncgit/src/sync/remotes/push.rs | 3 ++- filetreelist/src/item.rs | 2 +- filetreelist/src/treeitems_iter.rs | 2 +- src/app.rs | 8 ++++---- src/components/changes.rs | 2 +- src/components/commitlist.rs | 4 ++++ src/components/textinput.rs | 2 +- src/components/utils/filetree.rs | 2 +- src/keys/key_config.rs | 8 ++++++++ src/popups/blame_file.rs | 4 ++++ src/popups/commit.rs | 6 +++--- src/popups/create_remote.rs | 2 +- src/popups/file_revlog.rs | 2 +- src/popups/options.rs | 4 ++-- src/tabs/stashing.rs | 2 +- src/tabs/stashlist.rs | 2 +- src/tabs/status.rs | 2 +- src/ui/scrollbar.rs | 4 ++-- src/ui/syntax_text.rs | 4 ++++ 21 files changed, 44 insertions(+), 24 deletions(-) diff --git a/asyncgit/src/sync/branch/mod.rs b/asyncgit/src/sync/branch/mod.rs index 93185d6f45..66e47aa65b 100644 --- a/asyncgit/src/sync/branch/mod.rs +++ b/asyncgit/src/sync/branch/mod.rs @@ -271,7 +271,7 @@ pub fn config_is_pull_rebase(repo_path: &RepoPath) -> Result { let value = rebase.value().map(String::from).unwrap_or_default(); return Ok(value == "true"); - }; + } Ok(false) } diff --git a/asyncgit/src/sync/commit.rs b/asyncgit/src/sync/commit.rs index bb7e6384c5..f4e0b194ea 100644 --- a/asyncgit/src/sync/commit.rs +++ b/asyncgit/src/sync/commit.rs @@ -55,7 +55,6 @@ pub fn amend( /// Wrap `Repository::signature` to allow unknown user.name. /// /// See . -#[allow(clippy::redundant_pub_crate)] pub(crate) fn signature_allow_undefined_name( repo: &Repository, ) -> std::result::Result, git2::Error> { diff --git a/asyncgit/src/sync/remotes/push.rs b/asyncgit/src/sync/remotes/push.rs index b28b8a22d3..707f7572ad 100644 --- a/asyncgit/src/sync/remotes/push.rs +++ b/asyncgit/src/sync/remotes/push.rs @@ -17,6 +17,7 @@ use crate::{ use crossbeam_channel::Sender; use git2::{PackBuilderStage, PushOptions}; use scopetime::scope_time; +use std::fmt::Write as _; /// pub trait AsyncProgress: Clone + Send + Sync { @@ -182,7 +183,7 @@ pub fn push_raw( if let Ok(Some(branch_upstream_merge)) = get_branch_upstream_merge(repo_path, branch) { - push_ref.push_str(&format!(":{branch_upstream_merge}")); + let _ = write!(push_ref, ":{branch_upstream_merge}"); } } diff --git a/filetreelist/src/item.rs b/filetreelist/src/item.rs index f664031b14..b06c275df2 100644 --- a/filetreelist/src/item.rs +++ b/filetreelist/src/item.rs @@ -55,7 +55,7 @@ impl TreeItemInfo { Path::new( self.full_path .components() - .last() + .next_back() .and_then(|c| c.as_os_str().to_str()) .unwrap_or_default(), ) diff --git a/filetreelist/src/treeitems_iter.rs b/filetreelist/src/treeitems_iter.rs index 4feeb3e8ca..fddf35a1e9 100644 --- a/filetreelist/src/treeitems_iter.rs +++ b/filetreelist/src/treeitems_iter.rs @@ -35,7 +35,7 @@ impl<'a> Iterator for TreeItemsIterator<'a> { *i += 1; } else { self.increments = Some(0); - }; + } loop { if !init { diff --git a/src/app.rs b/src/app.rs index 45037f048f..68d2987c6f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -275,7 +275,7 @@ impl App { 3 => self.stashing_tab.draw(f, chunks_main[1])?, 4 => self.stashlist_tab.draw(f, chunks_main[1])?, _ => bail!("unknown tab"), - }; + } } self.draw_popups(f)?; @@ -905,7 +905,7 @@ impl App { InternalEvent::CommitSearch(options) => { self.revlog.search(options); } - }; + } Ok(flags) } @@ -997,7 +997,7 @@ impl App { undo_last_commit(&self.repo.borrow()) ); } - }; + } flags.insert(NeedsUpdate::ALL); @@ -1019,7 +1019,7 @@ impl App { )); self.tags_popup.update_tags()?; - }; + } Ok(()) } diff --git a/src/components/changes.rs b/src/components/changes.rs index 7b0bc4270b..48883d20e8 100644 --- a/src/components/changes.rs +++ b/src/components/changes.rs @@ -92,7 +92,7 @@ impl ChangesComponent { &self.repo.borrow(), path, )?, - }; + } } else { let config = self.options.borrow().status_show_untracked(); diff --git a/src/components/commitlist.rs b/src/components/commitlist.rs index f2c8a448a6..d45bec1739 100644 --- a/src/components/commitlist.rs +++ b/src/components/commitlist.rs @@ -115,6 +115,10 @@ impl CommitList { } /// + #[expect( + clippy::missing_const_for_fn, + reason = "as of 1.86.0 clippy wants this to be const even though that breaks" + )] pub fn marked(&self) -> &[(usize, CommitId)] { &self.marked } diff --git a/src/components/textinput.rs b/src/components/textinput.rs index e6586b8355..e67d19eac9 100644 --- a/src/components/textinput.rs +++ b/src/components/textinput.rs @@ -176,7 +176,7 @@ impl TextInputComponent { ) .title(self.title.clone()), ); - }; + } text_area }); } diff --git a/src/components/utils/filetree.rs b/src/components/utils/filetree.rs index 8b298dbb93..a0b507fa82 100644 --- a/src/components/utils/filetree.rs +++ b/src/components/utils/filetree.rs @@ -90,7 +90,7 @@ impl FileTreeItem { match path .components() - .last() + .next_back() .map(std::path::Component::as_os_str) .map(OsStr::to_string_lossy) .map(String::from) diff --git a/src/keys/key_config.rs b/src/keys/key_config.rs index 9cd4eb73f2..fe6a987765 100644 --- a/src/keys/key_config.rs +++ b/src/keys/key_config.rs @@ -40,6 +40,10 @@ impl KeyConfig { Ok(Self { keys, symbols }) } + #[expect( + clippy::missing_const_for_fn, + reason = "as of 1.86.0 clippy wants this to be const even though that breaks" + )] fn get_key_symbol(&self, k: KeyCode) -> &str { match k { KeyCode::Enter => &self.symbols.enter, @@ -106,6 +110,10 @@ impl KeyConfig { } } + #[expect( + clippy::missing_const_for_fn, + reason = "as of 1.86.0 clippy wants this to be const even though that breaks" + )] fn get_modifier_hint(&self, modifier: KeyModifiers) -> &str { match modifier { KeyModifiers::CONTROL => &self.symbols.control, diff --git a/src/popups/blame_file.rs b/src/popups/blame_file.rs index 273ca5ace3..9672965bcb 100644 --- a/src/popups/blame_file.rs +++ b/src/popups/blame_file.rs @@ -41,6 +41,10 @@ struct SyntaxFileBlame { } impl SyntaxFileBlame { + #[expect( + clippy::missing_const_for_fn, + reason = "as of 1.86.0 clippy wants this to be const even though that breaks" + )] fn path(&self) -> &str { &self.file_blame.path } diff --git a/src/popups/commit.rs b/src/popups/commit.rs index 4dcfc3241c..008fc6f8a7 100644 --- a/src/popups/commit.rs +++ b/src/popups/commit.rs @@ -27,7 +27,9 @@ use ratatui::{ widgets::Paragraph, Frame, }; + use std::{ + fmt::Write as _, fs::{read_to_string, File}, io::{Read, Write}, path::PathBuf, @@ -470,9 +472,7 @@ impl CommitPopup { let mut msg = msg.to_owned(); if let (Some(user), Some(mail)) = (user, mail) { - msg.push_str(&format!( - "\n\nSigned-off-by: {user} <{mail}>" - )); + let _ = write!(msg, "\n\nSigned-off-by: {user} <{mail}>"); } Ok(msg) diff --git a/src/popups/create_remote.rs b/src/popups/create_remote.rs index ac64934da5..8e464931e8 100644 --- a/src/popups/create_remote.rs +++ b/src/popups/create_remote.rs @@ -209,6 +209,6 @@ impl CreateRemotePopup { self.hide(); } - }; + } } } diff --git a/src/popups/file_revlog.rs b/src/popups/file_revlog.rs index c946323b5d..6bbbffbe8a 100644 --- a/src/popups/file_revlog.rs +++ b/src/popups/file_revlog.rs @@ -521,7 +521,7 @@ impl Component for FileRevlogPopup { InspectCommitOpen::new(commit_id), ), )); - }; + } } else if key_match(key, self.key_config.keys.blame) { if let Some(open_request) = self.open_request.clone() diff --git a/src/popups/options.rs b/src/popups/options.rs index 0b06131b48..e74e8bdc0b 100644 --- a/src/popups/options.rs +++ b/src/popups/options.rs @@ -207,7 +207,7 @@ impl OptionsPopup { .borrow_mut() .diff_hunk_lines_change(true); } - }; + } } else { match self.selection { AppOption::StatusShowUntracked => { @@ -246,7 +246,7 @@ impl OptionsPopup { .borrow_mut() .diff_hunk_lines_change(false); } - }; + } } self.queue diff --git a/src/tabs/stashing.rs b/src/tabs/stashing.rs index e5564563aa..5b2fe4b496 100644 --- a/src/tabs/stashing.rs +++ b/src/tabs/stashing.rs @@ -245,7 +245,7 @@ impl Component for Stashing { } else { Ok(EventState::NotConsumed) }; - }; + } } Ok(EventState::NotConsumed) diff --git a/src/tabs/stashlist.rs b/src/tabs/stashlist.rs index c8dceb2f63..1a97a0ac38 100644 --- a/src/tabs/stashlist.rs +++ b/src/tabs/stashlist.rs @@ -102,7 +102,7 @@ impl StashList { Action::StashDrop(ids) => self.drop(repo, ids)?, Action::StashPop(id) => self.pop(repo, *id)?, _ => (), - }; + } Ok(()) } diff --git a/src/tabs/status.rs b/src/tabs/status.rs index 034ffe39e6..40cf210786 100644 --- a/src/tabs/status.rs +++ b/src/tabs/status.rs @@ -348,7 +348,7 @@ impl Status { self.diff.focus(true); } - }; + } self.update_diff()?; diff --git a/src/ui/scrollbar.rs b/src/ui/scrollbar.rs index 6ae7ca3ee2..a0a9b3df80 100644 --- a/src/ui/scrollbar.rs +++ b/src/ui/scrollbar.rs @@ -49,7 +49,7 @@ impl Scrollbar { let right = area.right().saturating_sub(1); if right <= area.left() { return; - }; + } let (bar_top, bar_height) = { let scrollbar_area = area.inner(Margin { @@ -86,7 +86,7 @@ impl Scrollbar { let bottom = area.bottom().saturating_sub(1); if bottom <= area.top() { return; - }; + } let (bar_left, bar_width) = { let scrollbar_area = area.inner(Margin { diff --git a/src/ui/syntax_text.rs b/src/ui/syntax_text.rs index 8d758f20cc..057f9e3588 100644 --- a/src/ui/syntax_text.rs +++ b/src/ui/syntax_text.rs @@ -168,6 +168,10 @@ impl SyntaxText { } /// + #[expect( + clippy::missing_const_for_fn, + reason = "as of 1.86.0 clippy wants this to be const even though that breaks" + )] pub fn path(&self) -> &Path { &self.path } From eeebb0a647cd41141f2047e32937d4e46e81c5ac Mon Sep 17 00:00:00 2001 From: extrawurst <776816+extrawurst@users.noreply.github.com> Date: Mon, 7 Apr 2025 18:02:34 +0200 Subject: [PATCH 06/39] fix cargo deny advisory warning (#2598) --- Cargo.lock | 215 +++++++++++++++++++++++--------------------- asyncgit/Cargo.toml | 2 +- 2 files changed, 113 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68ef85cd0d..22d53743a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -924,9 +924,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.35" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "libz-ng-sys", @@ -1206,9 +1206,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.70.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736f14636705f3a56ea52b553e67282519418d9a35bb1e90b3a9637a00296b68" +checksum = "a61e71ec6817fc3c9f12f812682cfe51ee6ea0d2e27e02fc3849c35524617435" dependencies = [ "gix-actor", "gix-commitgraph", @@ -1247,9 +1247,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.33.2" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20018a1a6332e065f1fcc8305c1c932c6b8c9985edea2284b3c79dc6fa3ee4b2" +checksum = "f438c87d4028aca4b82f82ba8d8ab1569823cfb3e5bc5fa8456a71678b2a20e7" dependencies = [ "bstr", "gix-date", @@ -1279,25 +1279,25 @@ dependencies = [ [[package]] name = "gix-command" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb410b84d6575db45e62025a9118bdbf4d4b099ce7575a76161e898d9ca98df1" +checksum = "c0378995847773a697f8e157fe2963ecf3462fe64be05b7b3da000b3b472def8" dependencies = [ "bstr", "gix-path", + "gix-quote", "gix-trace", "shell-words", ] [[package]] name = "gix-commitgraph" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e23a8ec2d8a16026a10dafdb6ed51bcfd08f5d97f20fa52e200bc50cb72e4877" +checksum = "043cbe49b7a7505150db975f3cb7c15833335ac1e26781f615454d9d640a28fe" dependencies = [ "bstr", "gix-chunk", - "gix-features", "gix-hash", "memmap2", "thiserror 2.0.12", @@ -1305,9 +1305,9 @@ dependencies = [ [[package]] name = "gix-config" -version = "0.43.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "377c1efd2014d5d469e0b3cd2952c8097bce9828f634e04d5665383249f1d9e9" +checksum = "9c6f830bf746604940261b49abf7f655d2c19cadc9f4142ae9379e3a316e8cfa" dependencies = [ "bstr", "gix-config-value", @@ -1326,9 +1326,9 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.14.11" +version = "0.14.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11365144ef93082f3403471dbaa94cfe4b5e72743bdb9560719a251d439f4cee" +checksum = "8dc2c844c4cf141884678cabef736fd91dd73068b9146e6f004ba1a0457944b6" dependencies = [ "bitflags 2.9.0", "bstr", @@ -1339,9 +1339,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f" +checksum = "daa30058ec7d3511fbc229e4f9e696a35abd07ec5b82e635eff864a2726217e4" dependencies = [ "bstr", "itoa", @@ -1351,9 +1351,9 @@ dependencies = [ [[package]] name = "gix-diff" -version = "0.50.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62afb7f4ca0acdf4e9dad92065b2eb1bf2993bcc5014b57bc796e3a365b17c4d" +checksum = "a2c975dad2afc85e4e233f444d1efbe436c3cdcf3a07173984509c436d00a3f8" dependencies = [ "bstr", "gix-hash", @@ -1363,9 +1363,9 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.38.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c2414bdf04064e0f5a5aa029dfda1e663cf9a6c4bfc8759f2d369299bb65d8" +checksum = "f7fb8a4349b854506a3915de18d3341e5f1daa6b489c8affc9ca0d69efe86781" dependencies = [ "bstr", "dunce", @@ -1379,42 +1379,43 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.40.0" +version = "0.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bfdd4838a8d42bd482c9f0cb526411d003ee94cc7c7b08afe5007329c71d554" +checksum = "016d6050219458d14520fe22bdfdeb9cb71631dec9bc2724767c983f60109634" dependencies = [ "crc32fast", "crossbeam-channel", "flate2", - "gix-hash", + "gix-path", "gix-trace", "gix-utils", "libc", "once_cell", "parking_lot", "prodash", - "sha1", - "sha1_smol", "thiserror 2.0.12", "walkdir", ] [[package]] name = "gix-fs" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "182e7fa7bfdf44ffb7cfe7451b373cdf1e00870ac9a488a49587a110c562063d" +checksum = "951e886120dc5fa8cac053e5e5c89443f12368ca36811b2e43d1539081f9c111" dependencies = [ + "bstr", "fastrand", "gix-features", + "gix-path", "gix-utils", + "thiserror 2.0.12", ] [[package]] name = "gix-glob" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9c7249fa0a78f9b363aa58323db71e0a6161fd69860ed6f48dedf0ef3a314e" +checksum = "20972499c03473e773a2099e5fd0c695b9b72465837797a51a43391a1635a030" dependencies = [ "bitflags 2.9.0", "bstr", @@ -1424,19 +1425,21 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e81c5ec48649b1821b3ed066a44efb95f1a268b35c1d91295e61252539fbe9f8" +checksum = "834e79722063958b03342edaa1e17595cd2939bb2b3306b3225d0815566dcb49" dependencies = [ "faster-hex", + "gix-features", + "sha1-checked", "thiserror 2.0.12", ] [[package]] name = "gix-hashtable" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189130bc372accd02e0520dc5ab1cef318dcc2bc829b76ab8d84bbe90ac212d1" +checksum = "f06066d8702a9186dc1fdc1ed751ff2d7e924ceca21cb5d51b8f990c9c2e014a" dependencies = [ "gix-hash", "hashbrown 0.14.5", @@ -1445,9 +1448,9 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.38.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd12e3626879369310fffe2ac61acc828613ef656b50c4ea984dd59d7dc85d8" +checksum = "855bece2d4153453aa5d0a80d51deea1ce8cd6a3b4cf213da85ac344ccb908a7" dependencies = [ "bitflags 2.9.0", "bstr", @@ -1473,9 +1476,9 @@ dependencies = [ [[package]] name = "gix-lock" -version = "16.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9739815270ff6940968441824d162df9433db19211ca9ba8c3fc1b50b849c642" +checksum = "df47b8f11c34520db5541bc5fc9fbc8e4b0bdfcec3736af89ccb1a5728a0126f" dependencies = [ "gix-tempfile", "gix-utils", @@ -1484,9 +1487,9 @@ dependencies = [ [[package]] name = "gix-object" -version = "0.47.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc4b3a0044244f0fe22347fb7a79cca165e37829d668b41b85ff46a43e5fd68" +checksum = "4943fcdae6ffc135920c9ea71e0362ed539182924ab7a85dd9dac8d89b0dd69a" dependencies = [ "bstr", "gix-actor", @@ -1505,9 +1508,9 @@ dependencies = [ [[package]] name = "gix-odb" -version = "0.67.0" +version = "0.68.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e93457df69cd09573608ce9fa4f443fbd84bc8d15d8d83adecd471058459c1b" +checksum = "50306d40dcc982eb6b7593103f066ea6289c7b094cb9db14f3cd2be0b9f5e610" dependencies = [ "arc-swap", "gix-date", @@ -1526,9 +1529,9 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.57.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc13a475b3db735617017fb35f816079bf503765312d4b1913b18cf96f3fa515" +checksum = "9b65fffb09393c26624ca408d32cfe8776fb94cd0a5cdf984905e1d2f39779cb" dependencies = [ "clru", "gix-chunk", @@ -1545,9 +1548,9 @@ dependencies = [ [[package]] name = "gix-packetline" -version = "0.18.3" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e5ae6bc3ac160a6bf44a55f5537813ca3ddb08549c0fd3e7ef699c73c439cd" +checksum = "123844a70cf4d5352441dc06bab0da8aef61be94ec239cb631e0ba01dc6d3a04" dependencies = [ "bstr", "faster-hex", @@ -1557,9 +1560,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.14" +version = "0.10.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c40f12bb65a8299be0cfb90fe718e3be236b7a94b434877012980863a883a99f" +checksum = "f910668e2f6b2a55ff35a1f04df88a1a049f7b868507f4cbeeaa220eaba7be87" dependencies = [ "bstr", "gix-trace", @@ -1570,9 +1573,9 @@ dependencies = [ [[package]] name = "gix-protocol" -version = "0.48.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c61bd61afc6b67d213241e2100394c164be421e3f7228d3521b04f48ca5ba90" +checksum = "5678ddae1d62880bc30e2200be1b9387af3372e0e88e21f81b4e7f8367355b5a" dependencies = [ "bstr", "gix-date", @@ -1589,9 +1592,9 @@ dependencies = [ [[package]] name = "gix-quote" -version = "0.4.15" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49357fccdb0c85c0d3a3292a9f6db32d9b3535959b5471bb9624908f4a066c6" +checksum = "1b005c550bf84de3b24aa5e540a23e6146a1c01c7d30470e35d75a12f827f969" dependencies = [ "bstr", "gix-utils", @@ -1600,9 +1603,9 @@ dependencies = [ [[package]] name = "gix-ref" -version = "0.50.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47adf4c5f933429f8554e95d0d92eee583cfe4b95d2bf665cd6fd4a1531ee20c" +checksum = "b2e1f7eb6b7ce82d2d19961f74bd637bab3ea79b1bc7bfb23dbefc67b0415d8b" dependencies = [ "gix-actor", "gix-features", @@ -1621,9 +1624,9 @@ dependencies = [ [[package]] name = "gix-refspec" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59650228d8f612f68e7f7a25f517fcf386c5d0d39826085492e94766858b0a90" +checksum = "1d8587b21e2264a6e8938d940c5c99662779c13a10741a5737b15fc85c252ffc" dependencies = [ "bstr", "gix-hash", @@ -1635,9 +1638,9 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe28bbccca55da6d66e6c6efc6bb4003c29d407afd8178380293729733e6b53" +checksum = "342caa4e158df3020cadf62f656307c3948fe4eacfdf67171d7212811860c3e9" dependencies = [ "bitflags 2.9.0", "bstr", @@ -1653,9 +1656,9 @@ dependencies = [ [[package]] name = "gix-revwalk" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ecb80c235b1e9ef2b99b23a81ea50dd569a88a9eb767179793269e0e616247" +checksum = "2dc7c3d7e5cdc1ab8d35130106e4af0a4f9f9eca0c81f4312b690780e92bde0d" dependencies = [ "gix-commitgraph", "gix-date", @@ -1668,9 +1671,9 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.11" +version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84dae13271f4313f8d60a166bf27e54c968c7c33e2ffd31c48cafe5da649875" +checksum = "47aeb0f13de9ef2f3033f5ff218de30f44db827ac9f1286f9ef050aacddd5888" dependencies = [ "bitflags 2.9.0", "gix-path", @@ -1680,9 +1683,9 @@ dependencies = [ [[package]] name = "gix-shallow" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab72543011e303e52733c85bef784603ef39632ddf47f69723def52825e35066" +checksum = "cc0598aacfe1d52575a21c9492fee086edbb21e228ec36c819c42ab923f434c3" dependencies = [ "bstr", "gix-hash", @@ -1692,9 +1695,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "16.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2558f423945ef24a8328c55d1fd6db06b8376b0e7013b1bb476cc4ffdf678501" +checksum = "3d6de439bbb9a5d3550c9c7fab0e16d2d637d120fcbe0dfbc538772a187f099b" dependencies = [ "gix-fs", "libc", @@ -1711,9 +1714,9 @@ checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7" [[package]] name = "gix-transport" -version = "0.45.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11187418489477b1b5b862ae1aedbbac77e582f2c4b0ef54280f20cfe5b964d9" +checksum = "b3f68c2870bfca8278389d2484a7f2215b67d0b0cc5277d3c72ad72acf41787e" dependencies = [ "bstr", "gix-command", @@ -1727,9 +1730,9 @@ dependencies = [ [[package]] name = "gix-traverse" -version = "0.44.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bec70e53896586ef32a3efa7e4427b67308531ed186bb6120fb3eca0f0d61b4" +checksum = "36c0b049f8bdb61b20016694102f7b507f2e1727e83e9c5e6dad4f7d84ff7384" dependencies = [ "bitflags 2.9.0", "gix-commitgraph", @@ -1744,9 +1747,9 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29218c768b53dd8f116045d87fec05b294c731a4b2bdd257eeca2084cc150b13" +checksum = "48dfe23f93f1ddb84977d80bb0dd7aa09d1bf5d5afc0c9b6820cccacc25ae860" dependencies = [ "bstr", "gix-features", @@ -1758,9 +1761,9 @@ dependencies = [ [[package]] name = "gix-utils" -version = "0.1.14" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08f24e03ac8916c478c8419d7d3c33393da9bb41fa4c24455d5406aeefd35f" +checksum = "189f8724cf903e7fd57cfe0b7bc209db255cacdcb22c781a022f52c3a774f8d0" dependencies = [ "fastrand", "unicode-normalization", @@ -1768,9 +1771,9 @@ dependencies = [ [[package]] name = "gix-validate" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eaa01c3337d885617c0a42e92823922a2aea71f4caeace6fe87002bdcadbd90" +checksum = "34b5f1253109da6c79ed7cf6e1e38437080bb6d704c76af14c93e2f255234084" dependencies = [ "bstr", "thiserror 2.0.12", @@ -2101,10 +2104,11 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jiff" -version = "0.1.21" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0ce60560149333a8e41ca7dc78799c47c5fd435e2bc18faf6a054382eec037" +checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" dependencies = [ + "jiff-static", "jiff-tzdb-platform", "log", "portable-atomic", @@ -2113,17 +2117,28 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "jiff-static" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "jiff-tzdb" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" +checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" [[package]] name = "jiff-tzdb-platform" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" dependencies = [ "jiff-tzdb", ] @@ -2314,9 +2329,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" dependencies = [ "adler2", ] @@ -2744,18 +2759,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "prodash" -version = "29.0.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a266d8d6020c61a437be704c5e618037588e1985c7dbb7bf8d265db84cffe325" +checksum = "9ee7ce24c980b976607e2d6ae4aae92827994d23fed71659c3ede3f92528b58b" dependencies = [ "log", "parking_lot", @@ -3106,24 +3121,18 @@ dependencies = [ "cfg-if", "cpufeatures", "digest", - "sha1-asm", ] [[package]] -name = "sha1-asm" -version = "0.5.3" +name = "sha1-checked" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286acebaf8b67c1130aedffad26f594eff0c1292389158135327d2e23aed582b" +checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" dependencies = [ - "cc", + "digest", + "sha1", ] -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - [[package]] name = "sha2" version = "0.10.8" @@ -3368,9 +3377,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.96" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -4024,9 +4033,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.22" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" dependencies = [ "memchr", ] diff --git a/asyncgit/Cargo.toml b/asyncgit/Cargo.toml index 51971123b3..d1a8d76b1e 100644 --- a/asyncgit/Cargo.toml +++ b/asyncgit/Cargo.toml @@ -19,7 +19,7 @@ easy-cast = "0.5" fuzzy-matcher = "0.3" git2 = "0.20" git2-hooks = { path = "../git2-hooks", version = ">=0.4" } -gix = { version = "0.70.0", default-features = false, features = [ +gix = { version = "0.71.0", default-features = false, features = [ "max-performance", "revision", ] } From e299017e7995d600859c8eca2c5efbbfa5ad0da4 Mon Sep 17 00:00:00 2001 From: extrawurst Date: Fri, 11 Apr 2025 06:08:26 +0300 Subject: [PATCH 07/39] crossbeam-channel upgrade --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22d53743a2..68058043f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -525,9 +525,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] From 313220ae9463ba12830b04d0e9ac770c79e55790 Mon Sep 17 00:00:00 2001 From: Peer Sommerlund Date: Fri, 11 Apr 2025 07:44:49 +0200 Subject: [PATCH 08/39] Fix #315 run brew test in CI (#2596) Co-authored-by: extrawurst <776816+extrawurst@users.noreply.github.com> --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b15568ab49..4349fa3e90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -275,3 +275,31 @@ jobs: with: name: release-notes.txt path: ./release-notes.txt + + test-homebrew: + name: Test Homebrew Formula (macOS) + runs-on: macos-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install stable Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Install Homebrew + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + - name: Set up Homebrew in PATH + run: | + echo "$HOMEBREW_PREFIX/bin:$HOMEBREW_PREFIX/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" >> $GITHUB_PATH + + - name: Update Homebrew + run: brew update + + - name: Let Homebrew build gitui from source + run: brew install --head --build-from-source gitui + + - name: Run Homebrew test + run: brew test gitui From 7804ce70044e717eb37baccc3fb97878a6609f0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:04:55 +0200 Subject: [PATCH 09/39] Bump anyhow from 1.0.97 to 1.0.98 (#2606) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.97 to 1.0.98. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.97...1.0.98) --- updated-dependencies: - dependency-name: anyhow dependency-version: 1.0.98 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68058043f9..1d7d4416d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arc-swap" From 741de5fad531deca8ccd48010023908020676192 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:07:37 +0200 Subject: [PATCH 10/39] Bump openssl-sys from 0.9.106 to 0.9.107 (#2605) Bumps [openssl-sys](https://github.com/sfackler/rust-openssl) from 0.9.106 to 0.9.107. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.106...openssl-sys-v0.9.107) --- updated-dependencies: - dependency-name: openssl-sys dependency-version: 0.9.107 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d7d4416d6..f10481452f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2507,9 +2507,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", From 670b22eacfe136a185da0ac5f1de802da010f62f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:07:49 +0200 Subject: [PATCH 11/39] Bump struct-patch from 0.9.0 to 0.9.2 (#2604) Bumps [struct-patch](https://github.com/yanganto/struct-patch) from 0.9.0 to 0.9.2. - [Release notes](https://github.com/yanganto/struct-patch/releases) - [Commits](https://github.com/yanganto/struct-patch/compare/v0.9.0...v0.9.2) --- updated-dependencies: - dependency-name: struct-patch dependency-version: 0.9.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f10481452f..f1a81261f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3329,18 +3329,18 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "struct-patch" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198180af96bd27ff18f84da0d689ff51e24dde06e9d95badb0d2c01bb915ffd0" +checksum = "38a8aef6d40b8eda588b2036cf3519526894fdd49305063ee43233c2942136b6" dependencies = [ "struct-patch-derive", ] [[package]] name = "struct-patch-derive" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c0fa19d1fb0c92c763f74904b40b10b4d0740b80e3b0c6bfe52fcbcab2f24c" +checksum = "8b3e885afd59c2097c651763bf9cc2cd09703f2cff1d7ad6bf6dbcc19e1d0317" dependencies = [ "proc-macro2", "quote", From f67eed9c9d20654c4d893f781c2dbd92e1bc81f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:08:00 +0200 Subject: [PATCH 12/39] Bump indexmap from 2.8.0 to 2.9.0 (#2602) Bumps [indexmap](https://github.com/indexmap-rs/indexmap) from 2.8.0 to 2.9.0. - [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md) - [Commits](https://github.com/indexmap-rs/indexmap/compare/2.8.0...2.9.0) --- updated-dependencies: - dependency-name: indexmap dependency-version: 2.9.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f1a81261f2..662002aaf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2011,9 +2011,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", From aa513b40e191da181174836aac27545bd952a613 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:08:12 +0200 Subject: [PATCH 13/39] Bump ron from 0.9.0 to 0.10.1 (#2601) Bumps [ron](https://github.com/ron-rs/ron) from 0.9.0 to 0.10.1. - [Release notes](https://github.com/ron-rs/ron/releases) - [Changelog](https://github.com/ron-rs/ron/blob/master/CHANGELOG.md) - [Commits](https://github.com/ron-rs/ron/compare/v0.9.0...v0.10.1) --- updated-dependencies: - dependency-name: ron dependency-version: 0.10.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 662002aaf0..6e73ae1029 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2926,9 +2926,9 @@ dependencies = [ [[package]] name = "ron" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f3aa105dea217ef30d89581b65a4d527a19afc95ef5750be3890e8d3c5b837" +checksum = "beceb6f7bf81c73e73aeef6dd1356d9a1b2b4909e1f0fc3e59b034f9572d7b7f" dependencies = [ "base64", "bitflags 2.9.0", diff --git a/Cargo.toml b/Cargo.toml index 67424121c3..916ce17019 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ ratatui = { version = "0.29", default-features = false, features = [ 'serde', ] } rayon-core = "1.12" -ron = "0.9" +ron = "0.10" scopeguard = "1.2" scopetime = { path = "./scopetime", version = "0.1" } serde = "1.0" From 44d4a8deb1acf9c4d434efe0b77ccf472dfb65a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:08:25 +0200 Subject: [PATCH 14/39] Bump clap from 4.5.34 to 4.5.35 (#2592) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.34 to 4.5.35. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.34...clap_complete-v4.5.35) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: extrawurst <776816+extrawurst@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e73ae1029..d4cb273974 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,18 +432,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.34" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.34" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", From 7c41e99f98bf872fd8cfd9a20484166b34a5c868 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 08:54:08 +0200 Subject: [PATCH 15/39] Bump shellexpand from 3.1.0 to 3.1.1 (#2607) Bumps [shellexpand](https://gitlab.com/ijackson/rust-shellexpand) from 3.1.0 to 3.1.1. - [Commits](https://gitlab.com/ijackson/rust-shellexpand/compare/shellexpand-3.1.0...shellexpand-3.1.1) --- updated-dependencies: - dependency-name: shellexpand dependency-version: 3.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4cb273974..e596730f5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3158,9 +3158,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shellexpand" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" dependencies = [ "dirs", ] From 9781608584151ae4932515b8d356f77110e24a0a Mon Sep 17 00:00:00 2001 From: extrawurst <776816+extrawurst@users.noreply.github.com> Date: Tue, 15 Apr 2025 09:22:50 +0200 Subject: [PATCH 16/39] upgrade dirs (#2569) --- Cargo.lock | 122 ++++++++++---------------------------------- Cargo.toml | 2 +- asyncgit/Cargo.toml | 2 +- 3 files changed, 30 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e596730f5e..6b2a3bedd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -208,7 +208,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -714,23 +714,23 @@ dependencies = [ [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -858,7 +858,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2114,7 +2114,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2582,7 +2582,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2876,13 +2876,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.69", + "thiserror 2.0.12", ] [[package]] @@ -2983,7 +2983,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3444,7 +3444,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3806,7 +3806,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3822,7 +3822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ "windows-core 0.57.0", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3831,7 +3831,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3843,7 +3843,7 @@ dependencies = [ "windows-implement", "windows-interface", "windows-result", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3880,16 +3880,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -3898,7 +3889,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3907,22 +3898,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -3931,46 +3907,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3983,48 +3941,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 916ce17019..8d5b5e2fad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ chrono = { version = "0.4", default-features = false, features = ["clock"] } clap = { version = "4.5", features = ["env", "cargo"] } crossbeam-channel = "0.5" crossterm = { version = "0.28", features = ["serde"] } -dirs = "5.0" +dirs = "6.0" easy-cast = "0.5" filetreelist = { path = "./filetreelist", version = "0.5" } fuzzy-matcher = "0.3" diff --git a/asyncgit/Cargo.toml b/asyncgit/Cargo.toml index d1a8d76b1e..7966e82e5c 100644 --- a/asyncgit/Cargo.toml +++ b/asyncgit/Cargo.toml @@ -14,7 +14,7 @@ keywords = ["git"] [dependencies] bitflags = "2" crossbeam-channel = "0.5" -dirs = "5.0" +dirs = "6.0" easy-cast = "0.5" fuzzy-matcher = "0.3" git2 = "0.20" From 711210b97bcb069e9c37406cebba9ab34b11f0dd Mon Sep 17 00:00:00 2001 From: Joshix-1 <57299889+Joshix-1@users.noreply.github.com> Date: Tue, 15 Apr 2025 13:01:39 +0000 Subject: [PATCH 17/39] Run git-hooks more correctly (#2483) --- CHANGELOG.md | 1 + asyncgit/src/sync/hooks.rs | 72 +++++++++------ asyncgit/src/sync/mod.rs | 12 ++- asyncgit/src/sync/repository.rs | 6 ++ git2-hooks/src/hookspath.rs | 158 ++++++++++++++++++++++---------- git2-hooks/src/lib.rs | 67 +++++++++++--- 6 files changed, 224 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7caec869d..47231d74b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +* execute git-hooks directly if possible (on *nix) else use sh instead of bash (without reading SHELL variable) [[@Joshix](https://github.com/Joshix-1)] ([#2483](https://github.com/extrawurst/gitui/pull/2483)) ### Added * support loading custom syntax highlighting themes from a file [[@acuteenvy](https://github.com/acuteenvy)] ([#2565](https://github.com/gitui-org/gitui/pull/2565)) diff --git a/asyncgit/src/sync/hooks.rs b/asyncgit/src/sync/hooks.rs index 6fc672134f..b78f25d9e9 100644 --- a/asyncgit/src/sync/hooks.rs +++ b/asyncgit/src/sync/hooks.rs @@ -74,14 +74,40 @@ pub fn hooks_prepare_commit_msg( #[cfg(test)] mod tests { + use std::{ffi::OsString, io::Write as _, path::Path}; + + use git2::Repository; + use tempfile::TempDir; + use super::*; - use crate::sync::tests::repo_init; - use std::fs::File; - use std::io::Write; - use std::path::Path; + use crate::sync::tests::repo_init_with_prefix; + + fn repo_init() -> Result<(TempDir, Repository)> { + let mut os_string: OsString = OsString::new(); + + os_string.push("gitui $# ' "); + + #[cfg(target_os = "linux")] + { + use std::os::unix::ffi::OsStrExt; + + const INVALID_UTF8: &[u8] = b"\xED\xA0\x80"; + + os_string.push(std::ffi::OsStr::from_bytes(INVALID_UTF8)); + + assert!(os_string.to_str().is_none()); + } + + os_string.push(" "); + + repo_init_with_prefix(os_string) + } fn create_hook_in_path(path: &Path, hook_script: &[u8]) { - File::create(path).unwrap().write_all(hook_script).unwrap(); + std::fs::File::create(path) + .unwrap() + .write_all(hook_script) + .unwrap(); #[cfg(unix)] { @@ -102,7 +128,7 @@ mod tests { let hook = b"#!/bin/sh echo 'rejected' exit 1 - "; + "; git2_hooks::create_hook( &repo, @@ -113,9 +139,7 @@ mod tests { let subfolder = root.join("foo/"); std::fs::create_dir_all(&subfolder).unwrap(); - let res = - hooks_post_commit(&subfolder.to_str().unwrap().into()) - .unwrap(); + let res = hooks_post_commit(&subfolder.into()).unwrap(); assert_eq!( res, @@ -131,16 +155,12 @@ mod tests { fn test_pre_commit_workdir() { let (_td, repo) = repo_init().unwrap(); let root = repo.workdir().unwrap(); - let repo_path: &RepoPath = - &root.as_os_str().to_str().unwrap().into(); - let workdir = - crate::sync::utils::repo_work_dir(repo_path).unwrap(); + let repo_path: &RepoPath = &root.to_path_buf().into(); let hook = b"#!/bin/sh - echo $(pwd) + echo \"$(pwd)\" exit 1 - "; - + "; git2_hooks::create_hook( &repo, git2_hooks::HOOK_PRE_COMMIT, @@ -149,8 +169,9 @@ mod tests { let res = hooks_pre_commit(repo_path).unwrap(); if let HookResult::NotOk(res) = res { assert_eq!( - std::path::Path::new(res.trim_end()), - std::path::Path::new(&workdir) + res.trim_end().trim_end_matches('/'), + // TODO: fix if output isn't utf8. + root.to_string_lossy().trim_end_matches('/'), ); } else { assert!(false); @@ -163,10 +184,10 @@ mod tests { let root = repo.workdir().unwrap(); let hook = b"#!/bin/sh - echo 'msg' > $1 + echo 'msg' > \"$1\" echo 'rejected' exit 1 - "; + "; git2_hooks::create_hook( &repo, @@ -178,11 +199,8 @@ mod tests { std::fs::create_dir_all(&subfolder).unwrap(); let mut msg = String::from("test"); - let res = hooks_commit_msg( - &subfolder.to_str().unwrap().into(), - &mut msg, - ) - .unwrap(); + let res = + hooks_commit_msg(&subfolder.into(), &mut msg).unwrap(); assert_eq!( res, @@ -199,7 +217,7 @@ mod tests { let root = repo.workdir().unwrap(); let mut config = repo.config().unwrap(); - const HOOKS_DIR: &'static str = "my_hooks"; + const HOOKS_DIR: &str = "my_hooks"; config.set_str("core.hooksPath", HOOKS_DIR).unwrap(); let hook = b"#!/bin/sh @@ -213,7 +231,7 @@ mod tests { let mut msg = String::from("test"); let res = hooks_commit_msg( - &hooks_folder.to_str().unwrap().into(), + &hooks_folder.to_path_buf().into(), &mut msg, ) .unwrap(); diff --git a/asyncgit/src/sync/mod.rs b/asyncgit/src/sync/mod.rs index c52a556aad..09d4e6ef53 100644 --- a/asyncgit/src/sync/mod.rs +++ b/asyncgit/src/sync/mod.rs @@ -123,7 +123,7 @@ pub mod tests { }; use crate::error::Result; use git2::Repository; - use std::{path::Path, process::Command}; + use std::{ffi::OsStr, path::Path, process::Command}; use tempfile::TempDir; /// @@ -144,11 +144,19 @@ pub mod tests { /// pub fn repo_init() -> Result<(TempDir, Repository)> { + repo_init_with_prefix("gitui") + } + + /// + #[inline] + pub fn repo_init_with_prefix( + prefix: impl AsRef, + ) -> Result<(TempDir, Repository)> { init_log(); sandbox_config_files(); - let td = TempDir::new()?; + let td = TempDir::with_prefix(prefix)?; let repo = Repository::init(td.path())?; { let mut config = repo.config()?; diff --git a/asyncgit/src/sync/repository.rs b/asyncgit/src/sync/repository.rs index 2a0af47dbd..ea251c5e46 100644 --- a/asyncgit/src/sync/repository.rs +++ b/asyncgit/src/sync/repository.rs @@ -42,6 +42,12 @@ impl RepoPath { } } +impl From for RepoPath { + fn from(value: PathBuf) -> Self { + Self::Path(value) + } +} + impl From<&str> for RepoPath { fn from(p: &str) -> Self { Self::Path(PathBuf::from(p)) diff --git a/git2-hooks/src/hookspath.rs b/git2-hooks/src/hookspath.rs index af4f8af0a7..1518bfd76f 100644 --- a/git2-hooks/src/hookspath.rs +++ b/git2-hooks/src/hookspath.rs @@ -3,7 +3,7 @@ use git2::Repository; use crate::{error::Result, HookResult, HooksError}; use std::{ - env, + ffi::{OsStr, OsString}, path::{Path, PathBuf}, process::Command, str::FromStr, @@ -17,6 +17,7 @@ pub struct HookPaths { const CONFIG_HOOKS_PATH: &str = "core.hooksPath"; const DEFAULT_HOOKS_PATH: &str = "hooks"; +const ENOEXEC: i32 = 8; impl HookPaths { /// `core.hooksPath` always takes precedence. @@ -134,30 +135,76 @@ impl HookPaths { /// this function calls hook scripts based on conventions documented here /// see pub fn run_hook(&self, args: &[&str]) -> Result { - let hook = self.hook.clone(); - - let arg_str = format!("{:?} {}", hook, args.join(" ")); - // Use -l to avoid "command not found" on Windows. - let bash_args = - vec!["-l".to_string(), "-c".to_string(), arg_str]; + self.run_hook_os_str(args) + } + /// this function calls hook scripts based on conventions documented here + /// see + pub fn run_hook_os_str(&self, args: I) -> Result + where + I: IntoIterator + Copy, + S: AsRef, + { + let hook = self.hook.clone(); log::trace!("run hook '{:?}' in '{:?}'", hook, self.pwd); - let git_shell = find_bash_executable() - .or_else(find_default_unix_shell) - .unwrap_or_else(|| "bash".into()); - let output = Command::new(git_shell) - .args(bash_args) - .with_no_window() - .current_dir(&self.pwd) - // This call forces Command to handle the Path environment correctly on windows, - // the specific env set here does not matter - // see https://github.com/rust-lang/rust/issues/37519 - .env( - "DUMMY_ENV_TO_FIX_WINDOWS_CMD_RUNS", - "FixPathHandlingOnWindows", + let run_command = |command: &mut Command| { + command + .args(args) + .current_dir(&self.pwd) + .with_no_window() + .output() + }; + + let output = if cfg!(windows) { + // execute hook in shell + let command = { + // SEE: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_02 + // Enclosing characters in single-quotes ( '' ) shall preserve the literal value of each character within the single-quotes. + // A single-quote cannot occur within single-quotes. + const REPLACEMENT: &str = concat!( + "'", // closing single-quote + "\\'", // one escaped single-quote (outside of single-quotes) + "'", // new single-quote + ); + + let mut os_str = OsString::new(); + os_str.push("'"); + if let Some(hook) = hook.to_str() { + os_str.push(hook.replace('\'', REPLACEMENT)); + } else { + #[cfg(windows)] + { + use std::os::windows::ffi::OsStrExt; + if hook + .as_os_str() + .encode_wide() + .any(|x| x == u16::from(b'\'')) + { + // TODO: escape single quotes instead of failing + return Err(HooksError::PathToString); + } + } + + os_str.push(hook.as_os_str()); + } + os_str.push("'"); + os_str.push(" \"$@\""); + + os_str + }; + run_command( + sh_command().arg("-c").arg(command).arg(&hook), ) - .output()?; + } else { + // execute hook directly + match run_command(&mut Command::new(&hook)) { + Err(err) if err.raw_os_error() == Some(ENOEXEC) => { + run_command(sh_command().arg(&hook)) + } + result => result, + } + }?; if output.status.success() { Ok(HookResult::Ok { hook }) @@ -177,33 +224,28 @@ impl HookPaths { } } -#[cfg(unix)] -fn is_executable(path: &Path) -> bool { - use std::os::unix::fs::PermissionsExt; +fn sh_command() -> Command { + let mut command = Command::new(sh_path()); - let metadata = match path.metadata() { - Ok(metadata) => metadata, - Err(e) => { - log::error!("metadata error: {}", e); - return false; - } - }; - - let permissions = metadata.permissions(); + if cfg!(windows) { + // This call forces Command to handle the Path environment correctly on windows, + // the specific env set here does not matter + // see https://github.com/rust-lang/rust/issues/37519 + command.env( + "DUMMY_ENV_TO_FIX_WINDOWS_CMD_RUNS", + "FixPathHandlingOnWindows", + ); - permissions.mode() & 0o111 != 0 -} + // Use -l to avoid "command not found" + command.arg("-l"); + } -#[cfg(windows)] -/// windows does not consider bash scripts to be executable so we consider everything -/// to be executable (which is not far from the truth for windows platform.) -const fn is_executable(_: &Path) -> bool { - true + command } -// Find bash.exe, and avoid finding wsl's bash.exe on Windows. -// None for non-Windows. -fn find_bash_executable() -> Option { +/// Get the path to the sh executable. +/// On Windows get the sh.exe bundled with Git for Windows +pub fn sh_path() -> PathBuf { if cfg!(windows) { Command::new("where.exe") .arg("git") @@ -217,16 +259,36 @@ fn find_bash_executable() -> Option { .as_deref() .and_then(Path::parent) .and_then(Path::parent) - .map(|p| p.join("usr/bin/bash.exe")) + .map(|p| p.join("usr/bin/sh.exe")) .filter(|p| p.exists()) + .unwrap_or_else(|| "sh".into()) } else { - None + "sh".into() } } -// Find default shell on Unix-like OS. -fn find_default_unix_shell() -> Option { - env::var_os("SHELL").map(PathBuf::from) +#[cfg(unix)] +fn is_executable(path: &Path) -> bool { + use std::os::unix::fs::PermissionsExt; + + let metadata = match path.metadata() { + Ok(metadata) => metadata, + Err(e) => { + log::error!("metadata error: {}", e); + return false; + } + }; + + let permissions = metadata.permissions(); + + permissions.mode() & 0o111 != 0 +} + +#[cfg(windows)] +/// windows does not consider shell scripts to be executable so we consider everything +/// to be executable (which is not far from the truth for windows platform.) +const fn is_executable(_: &Path) -> bool { + true } trait CommandExt { diff --git a/git2-hooks/src/lib.rs b/git2-hooks/src/lib.rs index 2a458856d7..4c949a1e46 100644 --- a/git2-hooks/src/lib.rs +++ b/git2-hooks/src/lib.rs @@ -132,10 +132,7 @@ pub fn hooks_commit_msg( let temp_file = hook.git.join(HOOK_COMMIT_MSG_TEMP_FILE); File::create(&temp_file)?.write_all(msg.as_bytes())?; - let res = hook.run_hook(&[temp_file - .as_os_str() - .to_string_lossy() - .as_ref()])?; + let res = hook.run_hook_os_str([&temp_file])?; // load possibly altered msg msg.clear(); @@ -282,7 +279,7 @@ exit 0 let hook = br#"#!/bin/sh COMMIT_MSG="$(cat "$1")" -printf "$COMMIT_MSG" | sed 's/sth/shell_command/g' >"$1" +printf "$COMMIT_MSG" | sed 's/sth/shell_command/g' > "$1" exit 0 "#; @@ -309,6 +306,41 @@ exit 0 assert!(res.is_ok()); } + #[test] + fn test_hook_with_missing_shebang() { + const TEXT: &str = "Hello, world!"; + + let (_td, repo) = repo_init(); + + let hook = b"echo \"$@\"\nexit 42"; + + create_hook(&repo, HOOK_PRE_COMMIT, hook); + + let hook = + HookPaths::new(&repo, None, HOOK_PRE_COMMIT).unwrap(); + + assert!(hook.found()); + + let result = hook.run_hook(&[TEXT]).unwrap(); + + let HookResult::RunNotSuccessful { + code, + stdout, + stderr, + hook: h, + } = result + else { + unreachable!("run_hook should've failed"); + }; + + let stdout = stdout.as_str().trim_ascii_end(); + + assert_eq!(code, Some(42)); + assert_eq!(h, hook.hook); + assert_eq!(stdout, TEXT, "{:?} != {TEXT:?}", stdout); + assert!(stderr.is_empty()); + } + #[test] fn test_no_hook_found() { let (_td, repo) = repo_init(); @@ -388,6 +420,8 @@ exit 1 #[test] fn test_env_containing_path() { + const PATH_EXPORT: &str = "export PATH"; + let (_td, repo) = repo_init(); let hook = b"#!/bin/sh @@ -402,9 +436,12 @@ exit 1 unreachable!() }; - assert!(stdout - .lines() - .any(|line| line.starts_with("export PATH"))); + assert!( + stdout + .lines() + .any(|line| line.starts_with(PATH_EXPORT)), + "Could not find line starting with {PATH_EXPORT:?} in: {stdout:?}" + ); } #[test] @@ -470,7 +507,7 @@ sys.exit(0) create_hook(&repo, HOOK_PRE_COMMIT, hook); let res = hooks_pre_commit(&repo, None).unwrap(); - assert!(res.is_ok()); + assert!(res.is_ok(), "{res:?}"); } #[test] @@ -499,9 +536,9 @@ sys.exit(1) let (_td, repo) = repo_init(); let hook = b"#!/bin/sh -echo 'msg' > $1 -echo 'rejected' -exit 1 + echo 'msg' > \"$1\" + echo 'rejected' + exit 1 "; create_hook(&repo, HOOK_COMMIT_MSG, hook); @@ -525,7 +562,7 @@ exit 1 let (_td, repo) = repo_init(); let hook = b"#!/bin/sh -echo 'msg' > $1 +echo 'msg' > \"$1\" exit 0 "; @@ -565,7 +602,7 @@ exit 0 let (_td, repo) = repo_init(); let hook = b"#!/bin/sh -echo msg:$2 > $1 +echo \"msg:$2\" > \"$1\" exit 0 "; @@ -589,7 +626,7 @@ exit 0 let (_td, repo) = repo_init(); let hook = b"#!/bin/sh -echo $2,$3 > $1 +echo \"$2,$3\" > \"$1\" echo 'rejected' exit 2 "; From 29c8f48bc8c08d556a81b7f9be2cba35d0b527dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 09:18:32 +0200 Subject: [PATCH 18/39] Bump clap from 4.5.35 to 4.5.36 (#2608) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.35 to 4.5.36. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.35...clap_complete-v4.5.36) --- updated-dependencies: - dependency-name: clap dependency-version: 4.5.36 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b2a3bedd1..d44efdd51e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,18 +432,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.35" +version = "4.5.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" +checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.35" +version = "4.5.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" +checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" dependencies = [ "anstream", "anstyle", @@ -858,7 +858,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2114,7 +2114,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2983,7 +2983,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3444,7 +3444,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3806,7 +3806,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] From 489918eb514dee6df0d0a14f48b9147a57538ce7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 09:18:43 +0200 Subject: [PATCH 19/39] Bump env_logger from 0.11.6 to 0.11.8 (#2610) Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.6 to 0.11.8. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.6...v0.11.8) --- updated-dependencies: - dependency-name: env_logger dependency-version: 0.11.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d44efdd51e..42bf83d873 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -834,14 +834,14 @@ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -1835,12 +1835,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "iana-time-zone" version = "0.1.61" From 7f88934d05ac760b964d45d74dae5075b007160f Mon Sep 17 00:00:00 2001 From: Johannes Agricola Date: Wed, 16 Apr 2025 09:21:06 +0200 Subject: [PATCH 20/39] Bump msrv to 1.81 (#2613) Co-authored-by: Naseschwarz --- .clippy.toml | 2 +- .github/workflows/ci.yml | 31 ++++++++++++++++--- CHANGELOG.md | 1 + Cargo.toml | 2 +- README.md | 2 +- asyncgit/src/sync/branch/mod.rs | 6 ++-- asyncgit/src/sync/hooks.rs | 7 ++--- asyncgit/src/sync/remotes/push.rs | 4 +-- asyncgit/src/sync/stash.rs | 2 +- asyncgit/src/sync/utils.rs | 4 +-- git2-hooks/src/hookspath.rs | 6 ++-- src/args.rs | 2 +- src/components/commitlist.rs | 50 +++++++++++++++++++------------ 13 files changed, 76 insertions(+), 43 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 7c7c792b85..3d894c832e 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1,2 +1,2 @@ -msrv = "1.70.0" +msrv = "1.81.0" cognitive-complexity-threshold = 18 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4349fa3e90..57a9e664cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - rust: [nightly, stable, '1.70'] + rust: [nightly, stable, '1.81'] runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.rust == 'nightly' }} @@ -41,6 +41,9 @@ jobs: toolchain: ${{ matrix.rust }} components: clippy + - name: Override rust toolchain + run: rustup override set ${{ matrix.rust }} + - name: Rustup Show run: rustup show @@ -89,7 +92,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [nightly, stable, '1.70'] + rust: [nightly, stable, '1.81'] continue-on-error: ${{ matrix.rust == 'nightly' }} steps: - uses: actions/checkout@v4 @@ -112,6 +115,12 @@ jobs: - name: Manually install target run: rustup target add x86_64-unknown-linux-musl + - name: Override rust toolchain + run: rustup override set ${{ matrix.rust }} + + - name: Rustup Show + run: rustup show + - name: Setup MUSL run: | sudo apt-get -qq install musl-tools @@ -135,7 +144,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [nightly, stable, '1.70'] + rust: [nightly, stable, '1.81'] continue-on-error: ${{ matrix.rust == 'nightly' }} steps: - uses: actions/checkout@v4 @@ -151,6 +160,10 @@ jobs: uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} + + - name: Override rust toolchain + run: rustup override set ${{ matrix.rust }} + - name: Setup ARM toolchain run: | rustup target add aarch64-unknown-linux-gnu @@ -166,6 +179,9 @@ jobs: echo "$GITHUB_WORKSPACE/gcc-arm-8.2-2018.08-x86_64-aarch64-linux-gnu/bin" >> $GITHUB_PATH echo "$GITHUB_WORKSPACE/gcc-arm-8.2-2018.08-x86_64-arm-linux-gnueabihf/bin" >> $GITHUB_PATH + - name: Rustup Show + run: rustup show + - name: Build Debug run: | make build-linux-arm-debug @@ -179,7 +195,7 @@ jobs: strategy: fail-fast: false matrix: - rust: [nightly, stable, '1.70'] + rust: [nightly, stable, '1.81'] continue-on-error: ${{ matrix.rust == 'nightly' }} steps: - uses: actions/checkout@v4 @@ -195,9 +211,16 @@ jobs: uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} + + - name: Override rust toolchain + run: rustup override set ${{ matrix.rust }} + - name: Setup target run: rustup target add x86_64-apple-darwin + - name: Rustup Show + run: rustup show + - name: Build Debug run: | make build-apple-x86-debug diff --git a/CHANGELOG.md b/CHANGELOG.md index 47231d74b1..a8fe41fdd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * add `use_selection_fg` to theme file to allow customizing selection foreground color [[@Upsylonbare](https://github.com/Upsylonbare)] ([#2515](https://github.com/gitui-org/gitui/pull/2515)) ### Changed +* increase MSRV from 1.70 to 1.81 [[@naseschwarz](https://github.com/naseschwarz)] ([#2094](https://github.com/gitui-org/gitui/issues/2094)) * improve syntax highlighting file detection [[@acuteenvy](https://github.com/acuteenvy)] ([#2524](https://github.com/extrawurst/gitui/pull/2524)) * Updated project links to point to `gitui-org` instead of `extrawurst` [[@vasleymus](https://github.com/vasleymus)] ([#2538](https://github.com/gitui-org/gitui/pull/2538)) * After commit: jump back to unstaged area [[@tommady](https://github.com/tommady)] ([#2476](https://github.com/extrawurst/gitui/issues/2476)) diff --git a/Cargo.toml b/Cargo.toml index 8d5b5e2fad..ae7b777f08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.27.0" authors = ["extrawurst "] description = "blazing fast terminal-ui for git" edition = "2021" -rust-version = "1.70" +rust-version = "1.81" exclude = [".github/*", ".vscode/*", "assets/*"] homepage = "https://github.com/gitui-org/gitui" repository = "https://github.com/gitui-org/gitui" diff --git a/README.md b/README.md index 4b8b90e7d6..dd4270d6ed 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ see [NIGHTLIES.md](./NIGHTLIES.md) ### Requirements -- Minimum supported `rust`/`cargo` version: `1.70` +- Minimum supported `rust`/`cargo` version: `1.81` - See [Install Rust](https://www.rust-lang.org/tools/install) - To build openssl dependency (see https://docs.rs/openssl/latest/openssl/) diff --git a/asyncgit/src/sync/branch/mod.rs b/asyncgit/src/sync/branch/mod.rs index 66e47aa65b..81ec2ec586 100644 --- a/asyncgit/src/sync/branch/mod.rs +++ b/asyncgit/src/sync/branch/mod.rs @@ -701,7 +701,7 @@ mod tests_branches { &root.as_os_str().to_str().unwrap().into(); let upstream_merge_res = - get_branch_upstream_merge(&repo_path, "master"); + get_branch_upstream_merge(repo_path, "master"); assert!( upstream_merge_res.is_ok_and(|v| v.as_ref().is_none()) ); @@ -721,12 +721,12 @@ mod tests_branches { config .set_str( &format!("branch.{branch_name}.merge"), - &upstrem_merge, + upstrem_merge, ) .expect("fail set branch merge config"); let upstream_merge_res = - get_branch_upstream_merge(&repo_path, &branch_name); + get_branch_upstream_merge(repo_path, branch_name); assert!(upstream_merge_res .as_ref() .is_ok_and(|v| v.as_ref().is_some())); diff --git a/asyncgit/src/sync/hooks.rs b/asyncgit/src/sync/hooks.rs index b78f25d9e9..111b426259 100644 --- a/asyncgit/src/sync/hooks.rs +++ b/asyncgit/src/sync/hooks.rs @@ -230,11 +230,8 @@ mod tests { create_hook_in_path(&hooks_folder.join("commit-msg"), hook); let mut msg = String::from("test"); - let res = hooks_commit_msg( - &hooks_folder.to_path_buf().into(), - &mut msg, - ) - .unwrap(); + let res = + hooks_commit_msg(&hooks_folder.into(), &mut msg).unwrap(); assert_eq!( res, HookResult::NotOk(String::from("rejected\n")) diff --git a/asyncgit/src/sync/remotes/push.rs b/asyncgit/src/sync/remotes/push.rs index 707f7572ad..0916bfdc91 100644 --- a/asyncgit/src/sync/remotes/push.rs +++ b/asyncgit/src/sync/remotes/push.rs @@ -290,7 +290,7 @@ mod tests { // Attempt force push, // should work as it forces the push through - assert!(!push_branch( + assert!(push_branch( &tmp_other_repo_dir.path().to_str().unwrap().into(), "origin", "master", @@ -299,7 +299,7 @@ mod tests { None, None, ) - .is_err()); + .is_ok()); } #[test] diff --git a/asyncgit/src/sync/stash.rs b/asyncgit/src/sync/stash.rs index c496168116..8a65f92feb 100644 --- a/asyncgit/src/sync/stash.rs +++ b/asyncgit/src/sync/stash.rs @@ -144,7 +144,7 @@ mod tests { let repo_path: &RepoPath = &root.as_os_str().to_str().unwrap().into(); - assert!(!stash_save(repo_path, None, true, false).is_ok()); + assert!(stash_save(repo_path, None, true, false).is_err()); assert!(get_stashes(repo_path).unwrap().is_empty()); } diff --git a/asyncgit/src/sync/utils.rs b/asyncgit/src/sync/utils.rs index 8e767bbfd4..ebae31beb0 100644 --- a/asyncgit/src/sync/utils.rs +++ b/asyncgit/src/sync/utils.rs @@ -242,7 +242,7 @@ mod tests { let root = repo.path().parent().unwrap(); let repo_path = root.as_os_str().to_str().unwrap(); - assert!(!stage_add_file(&repo_path.into(), file_path).is_ok()); + assert!(stage_add_file(&repo_path.into(), file_path).is_err()); } #[test] @@ -440,7 +440,7 @@ mod tests { let repo_path: &RepoPath = &root.as_os_str().to_str().unwrap().into(); - assert!(!get_head(repo_path).is_ok()); + assert!(get_head(repo_path).is_err()); Ok(()) } diff --git a/git2-hooks/src/hookspath.rs b/git2-hooks/src/hookspath.rs index 1518bfd76f..a601b159c2 100644 --- a/git2-hooks/src/hookspath.rs +++ b/git2-hooks/src/hookspath.rs @@ -331,8 +331,8 @@ mod test { fn test_hookspath_relative() { assert_eq!( HookPaths::expand_path( - &Path::new("pre-commit"), - &Path::new("example_git_root"), + Path::new("pre-commit"), + Path::new("example_git_root"), ) .unwrap(), Path::new("example_git_root").join("pre-commit") @@ -346,7 +346,7 @@ mod test { assert_eq!( HookPaths::expand_path( &absolute_hook, - &Path::new("example_git_root"), + Path::new("example_git_root"), ) .unwrap(), absolute_hook diff --git a/src/args.rs b/src/args.rs index 8ef3aeb42f..6c09317314 100644 --- a/src/args.rs +++ b/src/args.rs @@ -139,7 +139,7 @@ fn setup_logging(path_override: Option) -> Result<()> { path }; - println!("Logging enabled. Log written to: {path:?}"); + println!("Logging enabled. Log written to: {}", path.display()); WriteLogger::init( LevelFilter::Trace, diff --git a/src/components/commitlist.rs b/src/components/commitlist.rs index d45bec1739..dde38ba06e 100644 --- a/src/components/commitlist.rs +++ b/src/components/commitlist.rs @@ -488,24 +488,36 @@ impl CommitList { txt.push(splitter.clone()); } - let style_hash = normal - .then(|| theme.commit_hash(selected)) - .unwrap_or_else(|| theme.commit_unhighlighted()); - let style_time = normal - .then(|| theme.commit_time(selected)) - .unwrap_or_else(|| theme.commit_unhighlighted()); - let style_author = normal - .then(|| theme.commit_author(selected)) - .unwrap_or_else(|| theme.commit_unhighlighted()); - let style_tags = normal - .then(|| theme.tags(selected)) - .unwrap_or_else(|| theme.commit_unhighlighted()); - let style_branches = normal - .then(|| theme.branch(selected, true)) - .unwrap_or_else(|| theme.commit_unhighlighted()); - let style_msg = normal - .then(|| theme.text(true, selected)) - .unwrap_or_else(|| theme.commit_unhighlighted()); + let style_hash = if normal { + theme.commit_hash(selected) + } else { + theme.commit_unhighlighted() + }; + let style_time = if normal { + theme.commit_time(selected) + } else { + theme.commit_unhighlighted() + }; + let style_author = if normal { + theme.commit_author(selected) + } else { + theme.commit_unhighlighted() + }; + let style_tags = if normal { + theme.tags(selected) + } else { + theme.commit_unhighlighted() + }; + let style_branches = if normal { + theme.branch(selected, true) + } else { + theme.commit_unhighlighted() + }; + let style_msg = if normal { + theme.text(true, selected) + } else { + theme.commit_unhighlighted() + }; // commit hash txt.push(Span::styled(Cow::from(&*e.hash_short), style_hash)); @@ -898,7 +910,7 @@ mod tests { impl Default for CommitList { fn default() -> Self { Self { - title: String::from("").into_boxed_str(), + title: String::new().into_boxed_str(), selection: 0, highlighted_selection: Option::None, highlights: Option::None, From 0e3767102a6bb5c14a319f7280bb289b55ca573b Mon Sep 17 00:00:00 2001 From: Joshix-1 <57299889+Joshix-1@users.noreply.github.com> Date: Wed, 16 Apr 2025 08:41:14 +0000 Subject: [PATCH 21/39] use gix_path::env::shell() to get the shell in git2-hooks (#2612) Co-authored-by: Johannes Agricola --- Cargo.lock | 1 + git2-hooks/Cargo.toml | 1 + git2-hooks/src/hookspath.rs | 26 +------------------------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42bf83d873..2abe61b64a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1138,6 +1138,7 @@ version = "0.4.0" dependencies = [ "git2", "git2-testing", + "gix-path", "log", "pretty_assertions", "shellexpand", diff --git a/git2-hooks/Cargo.toml b/git2-hooks/Cargo.toml index 3fab403cd2..6bdd0497a9 100644 --- a/git2-hooks/Cargo.toml +++ b/git2-hooks/Cargo.toml @@ -14,6 +14,7 @@ keywords = ["git"] [dependencies] git2 = ">=0.17" +gix-path = "0.10" log = "0.4" shellexpand = "3.1" thiserror = "2.0" diff --git a/git2-hooks/src/hookspath.rs b/git2-hooks/src/hookspath.rs index a601b159c2..fc4db5c87a 100644 --- a/git2-hooks/src/hookspath.rs +++ b/git2-hooks/src/hookspath.rs @@ -225,7 +225,7 @@ impl HookPaths { } fn sh_command() -> Command { - let mut command = Command::new(sh_path()); + let mut command = Command::new(gix_path::env::shell()); if cfg!(windows) { // This call forces Command to handle the Path environment correctly on windows, @@ -243,30 +243,6 @@ fn sh_command() -> Command { command } -/// Get the path to the sh executable. -/// On Windows get the sh.exe bundled with Git for Windows -pub fn sh_path() -> PathBuf { - if cfg!(windows) { - Command::new("where.exe") - .arg("git") - .output() - .ok() - .map(|out| { - PathBuf::from(Into::::into( - String::from_utf8_lossy(&out.stdout), - )) - }) - .as_deref() - .and_then(Path::parent) - .and_then(Path::parent) - .map(|p| p.join("usr/bin/sh.exe")) - .filter(|p| p.exists()) - .unwrap_or_else(|| "sh".into()) - } else { - "sh".into() - } -} - #[cfg(unix)] fn is_executable(path: &Path) -> bool { use std::os::unix::fs::PermissionsExt; From e08d954573f2da5d66ace2822f439ee0b97ade34 Mon Sep 17 00:00:00 2001 From: Johannes Agricola Date: Wed, 16 Apr 2025 10:45:08 +0200 Subject: [PATCH 22/39] Clean up a few `#[allow]`s (#2614) --- asyncgit/src/error.rs | 2 -- asyncgit/src/sync/config.rs | 3 --- asyncgit/src/sync/logwalker.rs | 1 - asyncgit/src/sync/patches.rs | 6 ++---- asyncgit/src/sync/staging/mod.rs | 6 +++--- filetreelist/src/error.rs | 2 -- filetreelist/src/filetreeitems.rs | 2 -- src/components/utils/emoji.rs | 9 +++++---- src/components/utils/logitems.rs | 9 +++------ src/options.rs | 2 -- 10 files changed, 13 insertions(+), 29 deletions(-) diff --git a/asyncgit/src/error.rs b/asyncgit/src/error.rs index 8bd730096e..2113e93d6e 100644 --- a/asyncgit/src/error.rs +++ b/asyncgit/src/error.rs @@ -1,5 +1,3 @@ -#![allow(renamed_and_removed_lints, clippy::unknown_clippy_lints)] - use std::{ num::TryFromIntError, path::StripPrefixError, string::FromUtf8Error, diff --git a/asyncgit/src/sync/config.rs b/asyncgit/src/sync/config.rs index 17a62b6736..9b5d85d823 100644 --- a/asyncgit/src/sync/config.rs +++ b/asyncgit/src/sync/config.rs @@ -1,6 +1,3 @@ -//TODO: hopefully released in next rust (see https://github.com/rust-lang/rust-clippy/issues/9440) -#![allow(clippy::use_self)] - use crate::error::Result; use git2::Repository; use scopetime::scope_time; diff --git a/asyncgit/src/sync/logwalker.rs b/asyncgit/src/sync/logwalker.rs index 743376d34f..b42447642c 100644 --- a/asyncgit/src/sync/logwalker.rs +++ b/asyncgit/src/sync/logwalker.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use super::{CommitId, SharedCommitFilterFn}; use crate::error::Result; use git2::{Commit, Oid, Repository}; diff --git a/asyncgit/src/sync/patches.rs b/asyncgit/src/sync/patches.rs index e87a3c9777..4107dae4b5 100644 --- a/asyncgit/src/sync/patches.rs +++ b/asyncgit/src/sync/patches.rs @@ -2,14 +2,12 @@ use super::diff::{get_diff_raw, DiffOptions, HunkHeader}; use crate::error::{Error, Result}; use git2::{Diff, DiffLine, Patch, Repository}; -#[allow(clippy::redundant_pub_crate)] -pub(crate) struct HunkLines<'a> { +pub struct HunkLines<'a> { pub hunk: HunkHeader, pub lines: Vec>, } -#[allow(clippy::redundant_pub_crate)] -pub(crate) fn get_file_diff_patch<'a>( +pub fn get_file_diff_patch<'a>( repo: &'a Repository, file: &str, is_staged: bool, diff --git a/asyncgit/src/sync/staging/mod.rs b/asyncgit/src/sync/staging/mod.rs index d037499a07..06e09fe66b 100644 --- a/asyncgit/src/sync/staging/mod.rs +++ b/asyncgit/src/sync/staging/mod.rs @@ -68,9 +68,9 @@ impl NewFromOldContent { } } -// this is the heart of the per line discard,stage,unstage. heavily inspired by the great work in nodegit: https://github.com/nodegit/nodegit -#[allow(clippy::redundant_pub_crate)] -pub(crate) fn apply_selection( +// this is the heart of the per line discard,stage,unstage. heavily inspired by the great work in +// nodegit: https://github.com/nodegit/nodegit +pub fn apply_selection( lines: &[DiffLinePosition], hunks: &[HunkLines], old_lines: &[&str], diff --git a/filetreelist/src/error.rs b/filetreelist/src/error.rs index 068db8b4c8..7c929e37e0 100644 --- a/filetreelist/src/error.rs +++ b/filetreelist/src/error.rs @@ -1,5 +1,3 @@ -#![allow(renamed_and_removed_lints, clippy::unknown_clippy_lints)] - use std::{num::TryFromIntError, path::PathBuf}; use thiserror::Error; diff --git a/filetreelist/src/filetreeitems.rs b/filetreelist/src/filetreeitems.rs index 8547d37032..637bfb3781 100644 --- a/filetreelist/src/filetreeitems.rs +++ b/filetreelist/src/filetreeitems.rs @@ -144,8 +144,6 @@ impl FileTreeItems { let item_path = Path::new(item.info().full_path_str()); - //TODO: fix once FP in clippy is fixed - #[allow(clippy::needless_borrow)] if item_path.starts_with(&path) { item.hide(); } else { diff --git a/src/components/utils/emoji.rs b/src/components/utils/emoji.rs index 75fe84dc5d..3980cd30b3 100644 --- a/src/components/utils/emoji.rs +++ b/src/components/utils/emoji.rs @@ -7,9 +7,10 @@ static EMOJI_REPLACER: Lazy = // Replace markdown emojis with Unicode equivalent // :hammer: --> 🔨 #[inline] -pub fn emojifi_string(s: &mut String) { - let resulting_cow = EMOJI_REPLACER.replace_all(s); - if let Cow::Owned(altered_s) = resulting_cow { - *s = altered_s; +pub fn emojifi_string(s: String) -> String { + if let Cow::Owned(altered_s) = EMOJI_REPLACER.replace_all(&s) { + altered_s + } else { + s } } diff --git a/src/components/utils/logitems.rs b/src/components/utils/logitems.rs index 4c980b65fa..9e0706226e 100644 --- a/src/components/utils/logitems.rs +++ b/src/components/utils/logitems.rs @@ -41,12 +41,11 @@ impl From for LogEntry { }; let author = c.author; - #[allow(unused_mut)] - let mut msg = c.message; + let msg = c.message; // Replace markdown emojis with Unicode equivalent #[cfg(feature = "ghemoji")] - emojifi_string(&mut msg); + let msg = emojifi_string(msg); Self { author: author.into(), @@ -175,9 +174,7 @@ mod tests { use super::*; fn test_conversion(s: &str) -> String { - let mut s = s.to_string(); - emojifi_string(&mut s); - s + emojifi_string(s.into()) } #[test] diff --git a/src/options.rs b/src/options.rs index db04802092..0fafe64151 100644 --- a/src/options.rs +++ b/src/options.rs @@ -152,8 +152,6 @@ impl Options { Ok(from_bytes(&buffer)?) } - //TODO: fix once FP in clippy is fixed - #[allow(clippy::needless_borrow)] fn save_failable(&self) -> Result<()> { let dir = Self::options_file(&self.repo)?; From baa1822180beabf136797d7c1003e4f712512c58 Mon Sep 17 00:00:00 2001 From: Johannes Agricola Date: Fri, 18 Apr 2025 09:29:06 +0200 Subject: [PATCH 23/39] Remove some `#[allow]`s II (#2616) Co-authored-by: Naseschwarz --- src/args.rs | 1 - src/components/commit_details/compare_details.rs | 1 - src/components/commit_details/details.rs | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/args.rs b/src/args.rs index 6c09317314..4c1a64ec92 100644 --- a/src/args.rs +++ b/src/args.rs @@ -38,7 +38,6 @@ pub fn process_cmdline() -> Result { .get_one::("directory") .map_or_else(|| PathBuf::from("."), PathBuf::from); - #[allow(clippy::option_if_let_else)] let repo_path = if let Some(w) = workdir { RepoPath::Workdir { gitdir, workdir: w } } else { diff --git a/src/components/commit_details/compare_details.rs b/src/components/commit_details/compare_details.rs index e10974f337..3438447c61 100644 --- a/src/components/commit_details/compare_details.rs +++ b/src/components/commit_details/compare_details.rs @@ -58,7 +58,6 @@ impl CompareDetailsComponent { }); } - #[allow(unstable_name_collisions)] fn get_commit_text(&self, data: &CommitDetails) -> Vec { let mut res = vec![ Line::from(vec![ diff --git a/src/components/commit_details/details.rs b/src/components/commit_details/details.rs index 0609982548..95aa018ac5 100644 --- a/src/components/commit_details/details.rs +++ b/src/components/commit_details/details.rs @@ -155,7 +155,7 @@ impl DetailsComponent { .collect() } - #[allow(unstable_name_collisions, clippy::too_many_lines)] + #[allow(clippy::too_many_lines)] fn get_text_info(&self) -> Vec { self.data.as_ref().map_or_else(Vec::new, |data| { let mut res = vec![ From 782ec070b4596ba0955f7b2cfa3284ba04560e06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Apr 2025 09:32:27 +0200 Subject: [PATCH 24/39] Bump once_cell from 1.21.1 to 1.21.3 (#2588) Bumps [once_cell](https://github.com/matklad/once_cell) from 1.21.1 to 1.21.3. - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.21.1...v1.21.3) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: extrawurst <776816+extrawurst@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2abe61b64a..8a80ca5ef7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2453,9 +2453,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "onig" From 9056e5e75cca02c8605c3fc318e460ea061c8bb0 Mon Sep 17 00:00:00 2001 From: Johannes Agricola Date: Fri, 18 Apr 2025 09:53:25 +0200 Subject: [PATCH 25/39] Show cursor on panic (#2620) ratatui::Terminal starts by hiding the cursor. If we panic and abort, that Terminal instance is not dropped, which leaves restoring the cursor state to us. Co-authored-by: Naseschwarz --- src/main.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index feea894491..524261d0b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -288,8 +288,10 @@ fn setup_terminal() -> Result<()> { } fn shutdown_terminal() { + let mut stdout = io::stdout(); + let leave_screen = - io::stdout().execute(LeaveAlternateScreen).map(|_f| ()); + stdout.execute(LeaveAlternateScreen).map(|_f| ()); if let Err(e) = leave_screen { eprintln!("leave_screen failed:\n{e}"); @@ -300,6 +302,10 @@ fn shutdown_terminal() { if let Err(e) = leave_raw_mode { eprintln!("leave_raw_mode failed:\n{e}"); } + + if let Err(e) = stdout.execute(crossterm::cursor::Show) { + eprintln!("Showing cursor failed:\n{e}"); + } } fn draw(terminal: &mut Terminal, app: &App) -> io::Result<()> { From 9271b4116eb31dbc03f14f68e84eda0c264570e9 Mon Sep 17 00:00:00 2001 From: extrawurst Date: Fri, 18 Apr 2025 10:05:23 +0200 Subject: [PATCH 26/39] remove duplicate panic handler --- src/main.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 524261d0b1..83742ca455 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,7 +73,6 @@ use std::{ io::{self, Stdout}, panic, path::Path, - process, time::{Duration, Instant}, }; use ui::style::Theme; @@ -413,12 +412,6 @@ fn set_panic_handlers() -> Result<()> { // global threadpool rayon_core::ThreadPoolBuilder::new() - .panic_handler(|e| { - let backtrace = Backtrace::new(); - shutdown_terminal(); - log_eprintln!("\nGitUI was close due to an unexpected panic.\nPlease file an issue on https://github.com/gitui-org/gitui/issues with the following info:\n\n{:?}\ntrace:\n{:?}", e, backtrace); - process::abort(); - }) .num_threads(4) .build_global()?; From 1205cd620b202ae08626b444e12f6a3534e32d70 Mon Sep 17 00:00:00 2001 From: extrawurst Date: Fri, 18 Apr 2025 10:08:02 +0200 Subject: [PATCH 27/39] Revert "Show cursor on panic (#2620)" This reverts commit 9056e5e75cca02c8605c3fc318e460ea061c8bb0. --- src/main.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 83742ca455..73accbae16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -287,10 +287,8 @@ fn setup_terminal() -> Result<()> { } fn shutdown_terminal() { - let mut stdout = io::stdout(); - let leave_screen = - stdout.execute(LeaveAlternateScreen).map(|_f| ()); + io::stdout().execute(LeaveAlternateScreen).map(|_f| ()); if let Err(e) = leave_screen { eprintln!("leave_screen failed:\n{e}"); @@ -301,10 +299,6 @@ fn shutdown_terminal() { if let Err(e) = leave_raw_mode { eprintln!("leave_raw_mode failed:\n{e}"); } - - if let Err(e) = stdout.execute(crossterm::cursor::Show) { - eprintln!("Showing cursor failed:\n{e}"); - } } fn draw(terminal: &mut Terminal, app: &App) -> io::Result<()> { From ae7b7b0c21a1056359179427b1fc025df34347e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 20:20:40 +0200 Subject: [PATCH 28/39] Bump clap from 4.5.36 to 4.5.37 (#2621) Bumps [clap](https://github.com/clap-rs/clap) from 4.5.36 to 4.5.37. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.36...clap_complete-v4.5.37) --- updated-dependencies: - dependency-name: clap dependency-version: 4.5.37 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a80ca5ef7..52e26fd1b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,18 +432,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", From ee5c243cbf63a920e9e378f1ef61def578c20f10 Mon Sep 17 00:00:00 2001 From: Lena <126529524+acuteenvy@users.noreply.github.com> Date: Mon, 21 Apr 2025 18:22:25 +0000 Subject: [PATCH 29/39] Improve error messages (#2617) --- CHANGELOG.md | 1 + src/main.rs | 47 ++++++++++++++++++++++------------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8fe41fdd9..edba904edd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * add `use_selection_fg` to theme file to allow customizing selection foreground color [[@Upsylonbare](https://github.com/Upsylonbare)] ([#2515](https://github.com/gitui-org/gitui/pull/2515)) ### Changed +* improve error messages [[@acuteenvy](https://github.com/acuteenvy)] ([#2617](https://github.com/gitui-org/gitui/pull/2617)) * increase MSRV from 1.70 to 1.81 [[@naseschwarz](https://github.com/naseschwarz)] ([#2094](https://github.com/gitui-org/gitui/issues/2094)) * improve syntax highlighting file detection [[@acuteenvy](https://github.com/acuteenvy)] ([#2524](https://github.com/extrawurst/gitui/pull/2524)) * Updated project links to point to `gitui-org` instead of `extrawurst` [[@vasleymus](https://github.com/vasleymus)] ([#2538](https://github.com/gitui-org/gitui/pull/2538)) diff --git a/src/main.rs b/src/main.rs index 73accbae16..2e8e9b8575 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,20 +119,24 @@ enum Updater { NotifyWatcher, } +/// Do `log::error!` and `eprintln!` in one line. +macro_rules! log_eprintln { + ( $($arg:tt)* ) => {{ + log::error!($($arg)*); + eprintln!($($arg)*); + }}; +} + fn main() -> Result<()> { let app_start = Instant::now(); let cliargs = process_cmdline()?; asyncgit::register_tracing_logging(); - - if !valid_path(&cliargs.repo_path) { - eprintln!("invalid path\nplease run gitui inside of a non-bare git repository"); - return Ok(()); - } + ensure_valid_path(&cliargs.repo_path)?; let key_config = KeyConfig::init() - .map_err(|e| eprintln!("KeyConfig loading error: {e}")) + .map_err(|e| log_eprintln!("KeyConfig loading error: {e}")) .unwrap_or_default(); let theme = Theme::init(&cliargs.theme); @@ -141,7 +145,7 @@ fn main() -> Result<()> { shutdown_terminal(); } - set_panic_handlers()?; + set_panic_handler()?; let mut repo_path = cliargs.repo_path; let mut terminal = start_terminal(io::stdout(), &repo_path)?; @@ -291,13 +295,13 @@ fn shutdown_terminal() { io::stdout().execute(LeaveAlternateScreen).map(|_f| ()); if let Err(e) = leave_screen { - eprintln!("leave_screen failed:\n{e}"); + log::error!("leave_screen failed:\n{e}"); } let leave_raw_mode = disable_raw_mode(); if let Err(e) = leave_raw_mode { - eprintln!("leave_raw_mode failed:\n{e}"); + log::error!("leave_raw_mode failed:\n{e}"); } } @@ -315,12 +319,14 @@ fn draw(terminal: &mut Terminal, app: &App) -> io::Result<()> { Ok(()) } -fn valid_path(repo_path: &RepoPath) -> bool { - let error = asyncgit::sync::repo_open_error(repo_path); - if let Some(error) = &error { - log::error!("repo open error: {error}"); +fn ensure_valid_path(repo_path: &RepoPath) -> Result<()> { + match asyncgit::sync::repo_open_error(repo_path) { + Some(e) => { + log::error!("{e}"); + bail!(e) + } + None => Ok(()), } - error.is_none() } fn select_event( @@ -388,20 +394,11 @@ fn start_terminal( Ok(terminal) } -// do log::error! and eprintln! in one line, pass string, error and backtrace -macro_rules! log_eprintln { - ($string:expr, $e:expr, $bt:expr) => { - log::error!($string, $e, $bt); - eprintln!($string, $e, $bt); - }; -} - -fn set_panic_handlers() -> Result<()> { - // regular panic handler +fn set_panic_handler() -> Result<()> { panic::set_hook(Box::new(|e| { let backtrace = Backtrace::new(); shutdown_terminal(); - log_eprintln!("\nGitUI was close due to an unexpected panic.\nPlease file an issue on https://github.com/gitui-org/gitui/issues with the following info:\n\n{:?}\ntrace:\n{:?}", e, backtrace); + log_eprintln!("\nGitUI was closed due to an unexpected panic.\nPlease file an issue on https://github.com/gitui-org/gitui/issues with the following info:\n\n{e}\n\ntrace:\n{backtrace:?}"); })); // global threadpool From 706cdf9243b3c069d9fbb7ac8e9904b0f8d38389 Mon Sep 17 00:00:00 2001 From: Fatpandac Date: Tue, 22 Apr 2025 02:23:05 +0800 Subject: [PATCH 30/39] feat: file and status tab support pageup and pagedown (#2496) --- CHANGELOG.md | 1 + filetreelist/src/filetree.rs | 56 ++++++++++++++++++++++++++++-- src/components/revision_files.rs | 2 ++ src/components/status_tree.rs | 10 ++++++ src/components/utils/statustree.rs | 34 +++++++++++++++++- 5 files changed, 99 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edba904edd..e60180cdc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * execute git-hooks directly if possible (on *nix) else use sh instead of bash (without reading SHELL variable) [[@Joshix](https://github.com/Joshix-1)] ([#2483](https://github.com/extrawurst/gitui/pull/2483)) ### Added +* Files and status tab support pageUp and pageDown [[@fatpandac](https://github.com/fatpandac)] ([#1951](https://github.com/extrawurst/gitui/issues/1951)) * support loading custom syntax highlighting themes from a file [[@acuteenvy](https://github.com/acuteenvy)] ([#2565](https://github.com/gitui-org/gitui/pull/2565)) * Select syntax highlighting theme out of the defaults from syntect [[@vasilismanol](https://github.com/vasilismanol)] ([#1931](https://github.com/extrawurst/gitui/issues/1931)) * new command-line option to override the default log file path (`--logfile`) [[@acuteenvy](https://github.com/acuteenvy)] ([#2539](https://github.com/gitui-org/gitui/pull/2539)) diff --git a/filetreelist/src/filetree.rs b/filetreelist/src/filetree.rs index 023da8caf9..7ffd5c01b9 100644 --- a/filetreelist/src/filetree.rs +++ b/filetreelist/src/filetree.rs @@ -2,7 +2,7 @@ use crate::{ error::Result, filetreeitems::FileTreeItems, tree_iter::TreeIterator, TreeItemInfo, }; -use std::{collections::BTreeSet, path::Path}; +use std::{cell::Cell, collections::BTreeSet, path::Path}; /// #[derive(Copy, Clone, Debug)] @@ -30,6 +30,7 @@ pub struct FileTree { selection: Option, // caches the absolute selection translated to visual index visual_selection: Option, + pub window_height: Cell>, } impl FileTree { @@ -42,6 +43,7 @@ impl FileTree { items: FileTreeItems::new(list, collapsed)?, selection: if list.is_empty() { None } else { Some(0) }, visual_selection: None, + window_height: None.into(), }; new_self.visual_selection = new_self.calc_visual_selection(); @@ -112,6 +114,18 @@ impl FileTree { } } + fn selection_page_updown( + &self, + range: impl Iterator, + ) -> Option { + let page_size = self.window_height.get().unwrap_or(0); + + range + .filter(|index| self.is_visible_index(*index)) + .take(page_size) + .last() + } + /// pub fn move_selection(&mut self, dir: MoveSelection) -> bool { self.selection.is_some_and(|selection| { @@ -130,9 +144,13 @@ impl FileTree { Self::selection_start(selection) } MoveSelection::End => self.selection_end(selection), - MoveSelection::PageDown | MoveSelection::PageUp => { - None + MoveSelection::PageUp => { + self.selection_page_updown((0..=selection).rev()) } + MoveSelection::PageDown => self + .selection_page_updown( + selection..(self.items.len()), + ), }; let changed_index = @@ -514,4 +532,36 @@ mod test { assert_eq!(s.count, 3); assert_eq!(s.index, 2); } + + #[test] + fn test_selection_page_updown() { + let items = vec![ + Path::new("a/b/c"), // + Path::new("a/b/c2"), // + Path::new("a/d"), // + Path::new("a/e"), // + ]; + + //0 a/ + //1 b/ + //2 c + //3 c2 + //4 d + //5 e + + let mut tree = + FileTree::new(&items, &BTreeSet::new()).unwrap(); + + tree.window_height.set(Some(3)); + + tree.selection = Some(0); + assert!(tree.move_selection(MoveSelection::PageDown)); + assert_eq!(tree.selection, Some(2)); + assert!(tree.move_selection(MoveSelection::PageDown)); + assert_eq!(tree.selection, Some(4)); + assert!(tree.move_selection(MoveSelection::PageUp)); + assert_eq!(tree.selection, Some(2)); + assert!(tree.move_selection(MoveSelection::PageUp)); + assert_eq!(tree.selection, Some(0)); + } } diff --git a/src/components/revision_files.rs b/src/components/revision_files.rs index 8a56071684..f3fec043d0 100644 --- a/src/components/revision_files.rs +++ b/src/components/revision_files.rs @@ -275,6 +275,8 @@ impl RevisionFilesComponent { let tree_height = usize::from(area.height.saturating_sub(2)); let tree_width = usize::from(area.width); + self.tree.window_height.set(Some(tree_height)); + self.tree.visual_selection().map_or_else( || { self.scroll.reset(); diff --git a/src/components/status_tree.rs b/src/components/status_tree.rs index 4fb762c1af..1d5f39cb6f 100644 --- a/src/components/status_tree.rs +++ b/src/components/status_tree.rs @@ -351,6 +351,7 @@ impl DrawableComponent for StatusTreeComponent { .map(|idx| idx.saturating_sub(selection_offset)) .unwrap_or_default(); let tree_height = r.height.saturating_sub(2) as usize; + self.tree.window_height.set(Some(tree_height)); self.scroll_top.set(ui::calc_scroll_top( self.scroll_top.get(), @@ -504,6 +505,15 @@ impl Component for StatusTreeComponent { || key_match(e, self.key_config.keys.shift_down) { Ok(self.move_selection(MoveSelection::End).into()) + } else if key_match(e, self.key_config.keys.page_up) { + Ok(self + .move_selection(MoveSelection::PageUp) + .into()) + } else if key_match(e, self.key_config.keys.page_down) + { + Ok(self + .move_selection(MoveSelection::PageDown) + .into()) } else if key_match(e, self.key_config.keys.move_left) { Ok(self diff --git a/src/components/utils/statustree.rs b/src/components/utils/statustree.rs index 2118ab0ed8..32e6c22025 100644 --- a/src/components/utils/statustree.rs +++ b/src/components/utils/statustree.rs @@ -3,7 +3,7 @@ use super::filetree::{ }; use anyhow::Result; use asyncgit::StatusItem; -use std::{cmp, collections::BTreeSet}; +use std::{cell::Cell, cmp, collections::BTreeSet}; //TODO: use new `filetreelist` crate @@ -16,6 +16,8 @@ pub struct StatusTree { // some folders may be folded up, this allows jumping // over folders which are folded into their parent pub available_selections: Vec, + + pub window_height: Cell>, } /// @@ -27,6 +29,8 @@ pub enum MoveSelection { Right, Home, End, + PageDown, + PageUp, } #[derive(Copy, Clone, Debug)] @@ -143,6 +147,15 @@ impl StatusTree { } MoveSelection::Home => SelectionChange::new(0, false), MoveSelection::End => self.selection_end(), + MoveSelection::PageUp => self.selection_page_updown( + selection, + (0..=selection).rev(), + ), + MoveSelection::PageDown => self + .selection_page_updown( + selection, + selection..(self.tree.len()), + ), }; let changed_index = @@ -283,6 +296,25 @@ impl StatusTree { SelectionChange::new(new_index, false) } + fn selection_page_updown( + &self, + current_index: usize, + range: impl Iterator, + ) -> SelectionChange { + let page_size = self.window_height.get().unwrap_or(0); + + let new_index = range + .filter(|index| { + self.available_selections.contains(index) + && self.is_visible_index(*index) + }) + .take(page_size) + .last() + .unwrap_or(current_index); + + SelectionChange::new(new_index, false) + } + fn is_visible_index(&self, idx: usize) -> bool { self.tree[idx].info.visible } From beb71fb69b0918d13984ff5af771579ff055ff86 Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Sun, 27 Apr 2025 15:44:18 -0400 Subject: [PATCH 31/39] Initial Implementation: Create a set of potential config locations to search for --- src/args.rs | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/args.rs b/src/args.rs index 4c1a64ec92..3c0e56ac4a 100644 --- a/src/args.rs +++ b/src/args.rs @@ -159,15 +159,42 @@ fn get_app_cache_path() -> Result { } pub fn get_app_config_path() -> Result { - let mut path = if cfg!(target_os = "macos") { - dirs::home_dir().map(|h| h.join(".config")) - } else { - dirs::config_dir() + // List of potential config directories in order of priority + let potential_config_dirs = [ + env::var_os("XDG_CONFIG_HOME").map(PathBuf::from), + // This is in the list since it was the hardcoded behavior on macos before + // I expect this to be what most people have XDG_CONFIG_HOME set to already + // But explicitly including this will avoid breaking anyone's existing config + dirs::home_dir().map(|p| p.join(".config")), + dirs::config_dir(), + ] + .into_iter() + // Remove any that resulted in None from unset env vars + .flatten() + // Remove any paths that aren't found on the system + .filter(|path| path.is_dir()); + + let mut target_config_dir = None; + + for potential_dir in potential_config_dirs { + let search_path = potential_dir.join("gitui"); + + // Prefer any preexisting gitui config dir + if search_path.is_dir() { + target_config_dir = Some(search_path); + break; + } + + // Set fallback to first existing directory + if target_config_dir.is_none() { + target_config_dir = Some(search_path); + } } - .ok_or_else(|| anyhow!("failed to find os config dir."))?; - path.push("gitui"); - Ok(path) + let config_dir = target_config_dir + .ok_or_else(|| anyhow!("failed to find os cache dir."))?; + + Ok(config_dir) } #[test] From 8e307d30ec9622be121de5d616370b19064cb99a Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 02:16:51 -0400 Subject: [PATCH 32/39] Apply the same logic to get_app_cache_path --- src/args.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/args.rs b/src/args.rs index 3c0e56ac4a..4d579a6df9 100644 --- a/src/args.rs +++ b/src/args.rs @@ -150,12 +150,36 @@ fn setup_logging(path_override: Option) -> Result<()> { } fn get_app_cache_path() -> Result { - let mut path = dirs::cache_dir() + let potential_cache_dirs = [ + env::var_os("XDG_CACHE_HOME").map(PathBuf::from), + dirs::cache_dir(), + ] + .into_iter() + .flatten() + .filter(|path| path.is_dir()); + + let mut target_cache_dir = None; + + for potential_dir in potential_cache_dirs { + let search_path = potential_dir.join("gitui"); + + // Prefer any preexisting gitui cache dir + if search_path.is_dir() { + target_cache_dir = Some(search_path); + break; + } + + // Set fallback to first existing directory + if target_cache_dir.is_none() { + target_cache_dir = Some(search_path); + } + } + + let cache_dir = target_cache_dir .ok_or_else(|| anyhow!("failed to find os cache dir."))?; - path.push("gitui"); - fs::create_dir_all(&path)?; - Ok(path) + fs::create_dir_all(&cache_dir)?; + Ok(cache_dir) } pub fn get_app_config_path() -> Result { From fb935b71fa33ae2b7a4b74163d4529fbacf1f3ef Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 05:09:03 -0400 Subject: [PATCH 33/39] Refactor to make logic more reusable and testable --- src/args.rs | 82 ++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/src/args.rs b/src/args.rs index 4d579a6df9..008f808b23 100644 --- a/src/args.rs +++ b/src/args.rs @@ -149,76 +149,62 @@ fn setup_logging(path_override: Option) -> Result<()> { Ok(()) } -fn get_app_cache_path() -> Result { - let potential_cache_dirs = [ - env::var_os("XDG_CACHE_HOME").map(PathBuf::from), - dirs::cache_dir(), - ] - .into_iter() - .flatten() - .filter(|path| path.is_dir()); +fn get_path_from_canidates( + canidates: Vec>, +) -> Result { + let valid_canidates = + canidates.into_iter().flatten().filter(|path| path.is_dir()); - let mut target_cache_dir = None; + let mut target_dir = None; - for potential_dir in potential_cache_dirs { + for potential_dir in valid_canidates { let search_path = potential_dir.join("gitui"); - // Prefer any preexisting gitui cache dir + // Prefer preexisting gitui directory if search_path.is_dir() { - target_cache_dir = Some(search_path); + target_dir = Some(search_path); break; } - // Set fallback to first existing directory - if target_cache_dir.is_none() { - target_cache_dir = Some(search_path); - } + // Fallback to first existing directory + target_dir.get_or_insert(search_path); } - let cache_dir = target_cache_dir - .ok_or_else(|| anyhow!("failed to find os cache dir."))?; + let dir = target_dir.ok_or_else(|| { + anyhow!("failed to find valid path within canidates") + })?; + + Ok(dir) +} + +fn get_app_cache_path() -> Result { + let cache_dir_canidates = vec![ + env::var_os("XDG_CACHE_HOME").map(PathBuf::from), + dirs::cache_dir(), + ]; - fs::create_dir_all(&cache_dir)?; - Ok(cache_dir) + match get_path_from_canidates(cache_dir_canidates) { + Ok(cache_dir) => { + fs::create_dir_all(&cache_dir)?; + Ok(cache_dir) + } + Err(_) => Err(anyhow!("failed to find os cache dir.")), + } } pub fn get_app_config_path() -> Result { // List of potential config directories in order of priority - let potential_config_dirs = [ + let config_dir_canidates = vec![ env::var_os("XDG_CONFIG_HOME").map(PathBuf::from), // This is in the list since it was the hardcoded behavior on macos before // I expect this to be what most people have XDG_CONFIG_HOME set to already // But explicitly including this will avoid breaking anyone's existing config dirs::home_dir().map(|p| p.join(".config")), dirs::config_dir(), - ] - .into_iter() - // Remove any that resulted in None from unset env vars - .flatten() - // Remove any paths that aren't found on the system - .filter(|path| path.is_dir()); - - let mut target_config_dir = None; - - for potential_dir in potential_config_dirs { - let search_path = potential_dir.join("gitui"); - - // Prefer any preexisting gitui config dir - if search_path.is_dir() { - target_config_dir = Some(search_path); - break; - } - - // Set fallback to first existing directory - if target_config_dir.is_none() { - target_config_dir = Some(search_path); - } - } - - let config_dir = target_config_dir - .ok_or_else(|| anyhow!("failed to find os cache dir."))?; + ]; - Ok(config_dir) + get_path_from_canidates(config_dir_canidates) + .map_err(|_| anyhow!("failed to find os config dir.")) } #[test] From 819b4ca5bbf701db5565bfc0309e776b448de28f Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 13:35:03 -0400 Subject: [PATCH 34/39] Realize I don't know how to spell candidates --- src/args.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/args.rs b/src/args.rs index 008f808b23..f5f56366c2 100644 --- a/src/args.rs +++ b/src/args.rs @@ -149,15 +149,17 @@ fn setup_logging(path_override: Option) -> Result<()> { Ok(()) } -fn get_path_from_canidates( - canidates: Vec>, +fn get_path_from_candidates( + candidates: Vec>, ) -> Result { - let valid_canidates = - canidates.into_iter().flatten().filter(|path| path.is_dir()); + let valid_candidates = candidates + .into_iter() + .flatten() + .filter(|path| path.is_dir()); let mut target_dir = None; - for potential_dir in valid_canidates { + for potential_dir in valid_candidates { let search_path = potential_dir.join("gitui"); // Prefer preexisting gitui directory @@ -171,19 +173,19 @@ fn get_path_from_canidates( } let dir = target_dir.ok_or_else(|| { - anyhow!("failed to find valid path within canidates") + anyhow!("failed to find valid path within candidates") })?; Ok(dir) } fn get_app_cache_path() -> Result { - let cache_dir_canidates = vec![ + let cache_dir_candidates = vec![ env::var_os("XDG_CACHE_HOME").map(PathBuf::from), dirs::cache_dir(), ]; - match get_path_from_canidates(cache_dir_canidates) { + match get_path_from_candidates(cache_dir_candidates) { Ok(cache_dir) => { fs::create_dir_all(&cache_dir)?; Ok(cache_dir) @@ -194,7 +196,7 @@ fn get_app_cache_path() -> Result { pub fn get_app_config_path() -> Result { // List of potential config directories in order of priority - let config_dir_canidates = vec![ + let config_dir_candidates = vec![ env::var_os("XDG_CONFIG_HOME").map(PathBuf::from), // This is in the list since it was the hardcoded behavior on macos before // I expect this to be what most people have XDG_CONFIG_HOME set to already @@ -203,7 +205,7 @@ pub fn get_app_config_path() -> Result { dirs::config_dir(), ]; - get_path_from_canidates(config_dir_canidates) + get_path_from_candidates(config_dir_candidates) .map_err(|_| anyhow!("failed to find os config dir.")) } From cbc388d78b5812e42838dda4b1c87e3cecbdc65b Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 13:50:21 -0400 Subject: [PATCH 35/39] refactor to be a little cleaner --- src/args.rs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/args.rs b/src/args.rs index f5f56366c2..c2a870ffff 100644 --- a/src/args.rs +++ b/src/args.rs @@ -150,16 +150,14 @@ fn setup_logging(path_override: Option) -> Result<()> { } fn get_path_from_candidates( - candidates: Vec>, + candidates: impl IntoIterator>, ) -> Result { - let valid_candidates = candidates - .into_iter() - .flatten() - .filter(|path| path.is_dir()); - let mut target_dir = None; - for potential_dir in valid_candidates { + // Filter into existing directories + for potential_dir in + candidates.into_iter().flatten().filter(|p| p.is_dir()) + { let search_path = potential_dir.join("gitui"); // Prefer preexisting gitui directory @@ -172,31 +170,27 @@ fn get_path_from_candidates( target_dir.get_or_insert(search_path); } - let dir = target_dir.ok_or_else(|| { + target_dir.ok_or_else(|| { anyhow!("failed to find valid path within candidates") - })?; - - Ok(dir) + }) } fn get_app_cache_path() -> Result { - let cache_dir_candidates = vec![ + let cache_dir_candidates = [ env::var_os("XDG_CACHE_HOME").map(PathBuf::from), dirs::cache_dir(), ]; - match get_path_from_candidates(cache_dir_candidates) { - Ok(cache_dir) => { - fs::create_dir_all(&cache_dir)?; - Ok(cache_dir) - } - Err(_) => Err(anyhow!("failed to find os cache dir.")), - } + let cache_dir = get_path_from_candidates(cache_dir_candidates) + .map_err(|_| anyhow!("failed to find os cache dir."))?; + + fs::create_dir_all(&cache_dir)?; + Ok(cache_dir) } pub fn get_app_config_path() -> Result { // List of potential config directories in order of priority - let config_dir_candidates = vec![ + let config_dir_candidates = [ env::var_os("XDG_CONFIG_HOME").map(PathBuf::from), // This is in the list since it was the hardcoded behavior on macos before // I expect this to be what most people have XDG_CONFIG_HOME set to already From 299015a3b3d6b062b925218c8c04a56c0acaf0c5 Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 16:03:38 -0400 Subject: [PATCH 36/39] don't create an empty config folder I am a bit hesitant about this change since I am unsure if any logic depends on a config folder needing to exist. But as far as I can tell nothing does and creating a empty config folder in someones dotfiles when they don't want any configuration for gitui seems like terrible UX. --- src/args.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/args.rs b/src/args.rs index c2a870ffff..3c85513a35 100644 --- a/src/args.rs +++ b/src/args.rs @@ -49,7 +49,6 @@ pub fn process_cmdline() -> Result { .map_or_else(|| PathBuf::from("theme.ron"), PathBuf::from); let confpath = get_app_config_path()?; - fs::create_dir_all(&confpath)?; let theme = confpath.join(arg_theme); let notify_watcher: bool = From 9ea0d0db24f464f11d3ccc13a761017f01cab56f Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 13:25:21 -0400 Subject: [PATCH 37/39] Add unit tests --- src/args.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/args.rs b/src/args.rs index 3c85513a35..c39afad331 100644 --- a/src/args.rs +++ b/src/args.rs @@ -202,7 +202,50 @@ pub fn get_app_config_path() -> Result { .map_err(|_| anyhow!("failed to find os config dir.")) } -#[test] -fn verify_app() { - app().debug_assert(); +#[cfg(test)] +mod tests { + use std::fs; + + use super::{app, get_path_from_candidates}; + use tempfile::tempdir; + + #[test] + fn verify_app() { + app().debug_assert(); + } + + #[test] + fn test_config_dir_candidates_from_preexisting() { + let temp_dummy_1 = tempdir().expect("should create temp dir"); + let temp_dummy_2 = tempdir().expect("should create temp dir"); + let temp_target = tempdir().expect("should create temp dir"); + let temp_goal = temp_target.path().join("gitui"); + + fs::create_dir_all(&temp_goal) + .expect("should create temp target directory"); + + let candidates = [ + Some(temp_dummy_1.path().to_path_buf()), + Some(temp_target.path().to_path_buf()), + Some(temp_dummy_2.path().to_path_buf()), + ]; + let result = get_path_from_candidates(candidates) + .expect("should find the included target"); + assert_eq!(result, temp_goal); + } + + #[test] + fn test_config_dir_candidates_no_preexisting() { + let temp_dummy_1 = tempdir().expect("should create temp dir"); + let temp_dummy_2 = tempdir().expect("should create temp dir"); + + let candidates = [ + Some(temp_dummy_1.path().to_path_buf()), + Some(temp_dummy_2.path().to_path_buf()), + ]; + + let result = get_path_from_candidates(candidates) + .expect("should return first candidate"); + assert_eq!(result, temp_dummy_1.path().join("gitui")); + } } From cde05b15fbb7615f486eb575be68c66b4d6bb641 Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Mon, 28 Apr 2025 15:12:18 -0400 Subject: [PATCH 38/39] Update docs to reflect new behavior --- KEY_CONFIG.md | 15 ++++++++++----- README.md | 4 ++-- THEMES.md | 21 +++++++++++++-------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/KEY_CONFIG.md b/KEY_CONFIG.md index 658aad11b6..d43351e023 100644 --- a/KEY_CONFIG.md +++ b/KEY_CONFIG.md @@ -19,12 +19,17 @@ Create a `key_bindings.ron` file like this: ) ``` -The config file format based on the [Ron file format](https://github.com/ron-rs/ron). +The keybinding config file uses the [Ron file format](https://github.com/ron-rs/ron). The location of the file depends on your OS: -* `$HOME/.config/gitui/key_bindings.ron` (mac) -* `$XDG_CONFIG_HOME/gitui/key_bindings.ron` (linux using XDG) -* `$HOME/.config/gitui/key_bindings.ron` (linux) -* `%APPDATA%/gitui/key_bindings.ron` (Windows) +`gitui` will look for an existing `/gitui` in the following order: +* `$XDG_CONFIG_HOME/gitui/` (with `XDG_CONFIG_HOME` set) +* `$HOME/.config/gitui/` +* Default OS Location: + * `$HOME/Library/Application Support/` (mac) + * `$HOME/.config/gitui/` (linux) + * `%APPDATA%/gitui/` (Windows) + +Key bindings are configured in `key_bindings.ron` within your first found `gitui` config folder. See all possible keys to overwrite in gitui: [here](https://github.com/gitui-org/gitui/blob/master/src/keys/key_list.rs#L83) diff --git a/README.md b/README.md index dd4270d6ed..3067111396 100644 --- a/README.md +++ b/README.md @@ -250,9 +250,9 @@ see [FAQs page](./FAQ.md) To run with logging enabled run `gitui -l`. This will log to: - +- With `XDG_CACHE_HOME` set: `$XDG_CACHE_HOME/gitui/gitui.log` +or default to - macOS: `$HOME/Library/Caches/gitui/gitui.log` -- Linux using `XDG`: `$XDG_CACHE_HOME/gitui/gitui.log` - Linux: `$HOME/.cache/gitui/gitui.log` - Windows: `%LOCALAPPDATA%/gitui/gitui.log` diff --git a/THEMES.md b/THEMES.md index 52c235b496..376334d349 100644 --- a/THEMES.md +++ b/THEMES.md @@ -7,14 +7,19 @@ default on light terminal: To change the colors of the default theme you need to add a `theme.ron` file that contains the colors you want to override. Note that you don’t have to specify the full theme anymore (as of 0.23). Instead, it is sufficient to override just the values that you want to differ from their default values. -The file uses the [Ron format](https://github.com/ron-rs/ron) and is located at one of the following paths, depending on your operating system: - -* `$HOME/.config/gitui/theme.ron` (mac) -* `$XDG_CONFIG_HOME/gitui/theme.ron` (linux using XDG) -* `$HOME/.config/gitui/theme.ron` (linux) -* `%APPDATA%/gitui/theme.ron` (Windows) - -Alternatively, you can create a theme in the same directory mentioned above and use it with the `-t` flag followed by the name of the file in the directory. E.g. If you are on linux calling `gitui -t arc.ron`, this will load the theme in `$XDG_CONFIG_HOME/gitui/arc.ron` or `$HOME/.config/gitui/arc.ron`. +The theme file uses the [Ron file format](https://github.com/ron-rs/ron). +The location of the file depends on your OS: +`gitui` will look for an existing `/gitui` in the following order: +* `$XDG_CONFIG_HOME/gitui/` (with `XDG_CONFIG_HOME` set) +* `$HOME/.config/gitui/` +* Default OS Location: + * `$HOME/Library/Application Support/` (mac) + * `$HOME/.config/gitui/` (linux) + * `%APPDATA%/gitui/` (Windows) + +The theme is configured in `theme.ron` within your first found `gitui` config folder. + +Alternatively, you can create a theme in the same directory mentioned above and use it with the `-t` flag followed by the name of the file in the directory. E.g. Calling `gitui -t arc.ron` will load the `arc.ron` theme from your first found `/gitui` config folder using the logic above. Example theme override: From e8440c289ff0b876040b7443a919b6165fe535df Mon Sep 17 00:00:00 2001 From: KlassyKat Date: Tue, 29 Apr 2025 05:47:18 -0400 Subject: [PATCH 39/39] Add changelog item --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e60180cdc5..53799e3457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * add `use_selection_fg` to theme file to allow customizing selection foreground color [[@Upsylonbare](https://github.com/Upsylonbare)] ([#2515](https://github.com/gitui-org/gitui/pull/2515)) ### Changed +* Respect `XDG_CONFIG_HOME` and `XDG_CACHE_HOME` irrespective of OS [[@KlassyKat](https://github.com/KlassyKat)] ([#1498](https://github.com/gitui-org/gitui/issues/1498)) * improve error messages [[@acuteenvy](https://github.com/acuteenvy)] ([#2617](https://github.com/gitui-org/gitui/pull/2617)) * increase MSRV from 1.70 to 1.81 [[@naseschwarz](https://github.com/naseschwarz)] ([#2094](https://github.com/gitui-org/gitui/issues/2094)) * improve syntax highlighting file detection [[@acuteenvy](https://github.com/acuteenvy)] ([#2524](https://github.com/extrawurst/gitui/pull/2524))