Skip to content

Commit 711210b

Browse files
authored
Run git-hooks more correctly (#2483)
1 parent 9781608 commit 711210b

File tree

6 files changed

+224
-92
lines changed

6 files changed

+224
-92
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## Unreleased
9+
* 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))
910

1011
### Added
1112
* support loading custom syntax highlighting themes from a file [[@acuteenvy](https://github.com/acuteenvy)] ([#2565](https://github.com/gitui-org/gitui/pull/2565))

asyncgit/src/sync/hooks.rs

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,40 @@ pub fn hooks_prepare_commit_msg(
7474

7575
#[cfg(test)]
7676
mod tests {
77+
use std::{ffi::OsString, io::Write as _, path::Path};
78+
79+
use git2::Repository;
80+
use tempfile::TempDir;
81+
7782
use super::*;
78-
use crate::sync::tests::repo_init;
79-
use std::fs::File;
80-
use std::io::Write;
81-
use std::path::Path;
83+
use crate::sync::tests::repo_init_with_prefix;
84+
85+
fn repo_init() -> Result<(TempDir, Repository)> {
86+
let mut os_string: OsString = OsString::new();
87+
88+
os_string.push("gitui $# ' ");
89+
90+
#[cfg(target_os = "linux")]
91+
{
92+
use std::os::unix::ffi::OsStrExt;
93+
94+
const INVALID_UTF8: &[u8] = b"\xED\xA0\x80";
95+
96+
os_string.push(std::ffi::OsStr::from_bytes(INVALID_UTF8));
97+
98+
assert!(os_string.to_str().is_none());
99+
}
100+
101+
os_string.push(" ");
102+
103+
repo_init_with_prefix(os_string)
104+
}
82105

83106
fn create_hook_in_path(path: &Path, hook_script: &[u8]) {
84-
File::create(path).unwrap().write_all(hook_script).unwrap();
107+
std::fs::File::create(path)
108+
.unwrap()
109+
.write_all(hook_script)
110+
.unwrap();
85111

86112
#[cfg(unix)]
87113
{
@@ -102,7 +128,7 @@ mod tests {
102128
let hook = b"#!/bin/sh
103129
echo 'rejected'
104130
exit 1
105-
";
131+
";
106132

107133
git2_hooks::create_hook(
108134
&repo,
@@ -113,9 +139,7 @@ mod tests {
113139
let subfolder = root.join("foo/");
114140
std::fs::create_dir_all(&subfolder).unwrap();
115141

116-
let res =
117-
hooks_post_commit(&subfolder.to_str().unwrap().into())
118-
.unwrap();
142+
let res = hooks_post_commit(&subfolder.into()).unwrap();
119143

120144
assert_eq!(
121145
res,
@@ -131,16 +155,12 @@ mod tests {
131155
fn test_pre_commit_workdir() {
132156
let (_td, repo) = repo_init().unwrap();
133157
let root = repo.workdir().unwrap();
134-
let repo_path: &RepoPath =
135-
&root.as_os_str().to_str().unwrap().into();
136-
let workdir =
137-
crate::sync::utils::repo_work_dir(repo_path).unwrap();
158+
let repo_path: &RepoPath = &root.to_path_buf().into();
138159

139160
let hook = b"#!/bin/sh
140-
echo $(pwd)
161+
echo \"$(pwd)\"
141162
exit 1
142-
";
143-
163+
";
144164
git2_hooks::create_hook(
145165
&repo,
146166
git2_hooks::HOOK_PRE_COMMIT,
@@ -149,8 +169,9 @@ mod tests {
149169
let res = hooks_pre_commit(repo_path).unwrap();
150170
if let HookResult::NotOk(res) = res {
151171
assert_eq!(
152-
std::path::Path::new(res.trim_end()),
153-
std::path::Path::new(&workdir)
172+
res.trim_end().trim_end_matches('/'),
173+
// TODO: fix if output isn't utf8.
174+
root.to_string_lossy().trim_end_matches('/'),
154175
);
155176
} else {
156177
assert!(false);
@@ -163,10 +184,10 @@ mod tests {
163184
let root = repo.workdir().unwrap();
164185

165186
let hook = b"#!/bin/sh
166-
echo 'msg' > $1
187+
echo 'msg' > \"$1\"
167188
echo 'rejected'
168189
exit 1
169-
";
190+
";
170191

171192
git2_hooks::create_hook(
172193
&repo,
@@ -178,11 +199,8 @@ mod tests {
178199
std::fs::create_dir_all(&subfolder).unwrap();
179200

180201
let mut msg = String::from("test");
181-
let res = hooks_commit_msg(
182-
&subfolder.to_str().unwrap().into(),
183-
&mut msg,
184-
)
185-
.unwrap();
202+
let res =
203+
hooks_commit_msg(&subfolder.into(), &mut msg).unwrap();
186204

187205
assert_eq!(
188206
res,
@@ -199,7 +217,7 @@ mod tests {
199217
let root = repo.workdir().unwrap();
200218
let mut config = repo.config().unwrap();
201219

202-
const HOOKS_DIR: &'static str = "my_hooks";
220+
const HOOKS_DIR: &str = "my_hooks";
203221
config.set_str("core.hooksPath", HOOKS_DIR).unwrap();
204222

205223
let hook = b"#!/bin/sh
@@ -213,7 +231,7 @@ mod tests {
213231

214232
let mut msg = String::from("test");
215233
let res = hooks_commit_msg(
216-
&hooks_folder.to_str().unwrap().into(),
234+
&hooks_folder.to_path_buf().into(),
217235
&mut msg,
218236
)
219237
.unwrap();

asyncgit/src/sync/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub mod tests {
123123
};
124124
use crate::error::Result;
125125
use git2::Repository;
126-
use std::{path::Path, process::Command};
126+
use std::{ffi::OsStr, path::Path, process::Command};
127127
use tempfile::TempDir;
128128

129129
///
@@ -144,11 +144,19 @@ pub mod tests {
144144

145145
///
146146
pub fn repo_init() -> Result<(TempDir, Repository)> {
147+
repo_init_with_prefix("gitui")
148+
}
149+
150+
///
151+
#[inline]
152+
pub fn repo_init_with_prefix(
153+
prefix: impl AsRef<OsStr>,
154+
) -> Result<(TempDir, Repository)> {
147155
init_log();
148156

149157
sandbox_config_files();
150158

151-
let td = TempDir::new()?;
159+
let td = TempDir::with_prefix(prefix)?;
152160
let repo = Repository::init(td.path())?;
153161
{
154162
let mut config = repo.config()?;

asyncgit/src/sync/repository.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ impl RepoPath {
4242
}
4343
}
4444

45+
impl From<PathBuf> for RepoPath {
46+
fn from(value: PathBuf) -> Self {
47+
Self::Path(value)
48+
}
49+
}
50+
4551
impl From<&str> for RepoPath {
4652
fn from(p: &str) -> Self {
4753
Self::Path(PathBuf::from(p))

0 commit comments

Comments
 (0)