Skip to content

Commit

Permalink
refactor: migrate git2 to gix (#121)
Browse files Browse the repository at this point in the history
Signed-off-by: tison <wander4096@gmail.com>
  • Loading branch information
tisonkun committed Mar 24, 2024
1 parent badc166 commit 6db9b1c
Show file tree
Hide file tree
Showing 8 changed files with 1,013 additions and 123 deletions.
1,012 changes: 929 additions & 83 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ ENV RUSTFLAGS="-C target-feature=-crt-static"
WORKDIR /build
COPY . .
RUN apk fix && \
apk --no-cache --update add libssh2-dev musl-dev pkgconfig && \
apk --no-cache --update add musl-dev && \
cargo build --release --bin hawkeye

FROM public.ecr.aws/docker/library/alpine:3.19.0
RUN apk fix && apk --no-cache --update add gcompat libgcc && mkdir -p /github/workspace
RUN apk fix && apk --no-cache --update add libgcc && mkdir -p /github/workspace
COPY --from=build /build/target/release/hawkeye /bin/
WORKDIR /github/workspace/
ENTRYPOINT ["/bin/hawkeye"]
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ inceptionYear = 2023
[git]
# If enabled, do not process files that are ignored by Git; possible value: ['auto', 'enable', 'disable']
# 'auto' means this feature tries to be enabled with:
# * libgit2 - if `basedir` is in a Git repository.
# * gix - if `basedir` is in a Git repository.
# * ignore crate's gitignore rules - if `basedir` is not in a Git repository.
# 'enabled' means always enabled with libgit2; failed if it is impossible.
# 'enabled' means always enabled with gix; failed if it is impossible.
# default: 'auto'
ignore = 'auto'
```
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ inputs:

runs:
using: docker
image: docker://ghcr.io/korandoru/hawkeye:edge
image: Dockerfile
args:
- ${{ inputs.mode }}
- --config
Expand Down
3 changes: 2 additions & 1 deletion fmt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ license.workspace = true
repository.workspace = true

[dependencies]
git2 = "0.18.3"
gix = { version = "0.61", default-features = false, features = ["excludes"] }
ignore = "0.4.22"
pathdiff = "0.2.1"
regex = "1.10.3"
serde = { version = "1.0.197", features = ["derive"] }
snafu.workspace = true
Expand Down
29 changes: 26 additions & 3 deletions fmt/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,33 @@ pub enum Error {
loc: snafu::Location,
},

#[snafu(display("Git operation failed: {}", source))]
GitOp {
#[snafu(display("cannot discover git repository with gix: {}", source))]
GixDiscoverOp {
#[snafu(source)]
source: git2::Error,
source: Box<gix::discover::Error>,
#[snafu(implicit)]
loc: snafu::Location,
},

#[snafu(display("cannot create gix exclude stack: {}", source))]
GixExcludeOp {
#[snafu(source)]
source: Box<gix::worktree::excludes::Error>,
#[snafu(implicit)]
loc: snafu::Location,
},

#[snafu(display("cannot check gix exclude: {}", source))]
GixCheckExcludeOp {
#[snafu(source)]
source: std::io::Error,
#[snafu(implicit)]
loc: snafu::Location,
},

#[snafu(display("path not found {}", path))]
GixPathNotFount {
path: String,
#[snafu(implicit)]
loc: snafu::Location,
},
Expand Down
59 changes: 41 additions & 18 deletions fmt/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@

use std::path::Path;

use git2::Repository;
use snafu::ResultExt;
use gix::Repository;
use snafu::{IntoError, OptionExt, ResultExt};
use tracing::info;

use crate::{
config,
error::{GitOpSnafu, InvalidConfigSnafu, ResolveAbsolutePathSnafu},
error::{
GixCheckExcludeOpSnafu, GixDiscoverOpSnafu, GixExcludeOpSnafu, GixPathNotFountSnafu,
InvalidConfigSnafu, ResolveAbsolutePathSnafu,
},
Result,
};

Expand All @@ -34,38 +37,58 @@ impl GitHelper {
return Ok(None);
}

match Repository::discover(basedir) {
Ok(repo) => {
if repo.workdir().is_none() {
if config.ignore.is_auto() {
info!("git.ignore=auto is resolved to disabled; bare repository detected");
let is_auto = config.ignore.is_auto();
match gix::discover(basedir) {
Ok(repo) => match repo.worktree() {
None => {
let message = "bare repository detected";
if is_auto {
info!("git.ignore=auto is resolved to fallback; {message}");
Ok(None)
} else {
InvalidConfigSnafu {
message: "Git repository is bare".to_string(),
}
.fail()
InvalidConfigSnafu { message }.fail()
}
} else {
}
Some(_) => {
info!("git.ignore=auto is resolved to enabled");
Ok(Some(GitHelper { repo }))
}
}
},
Err(err) => {
if config.ignore.is_auto() {
if is_auto {
info!(?err, "git.ignore=auto is resolved to disabled");
Ok(None)
} else {
Err(err).context(GitOpSnafu)
Err(GixDiscoverOpSnafu {}.into_error(Box::new(err)))
}
}
}
}

pub fn ignored(&self, path: &Path) -> Result<bool> {
pub fn ignored(&self, path: &Path, is_dir: bool) -> Result<bool> {
let path = path.canonicalize().context(ResolveAbsolutePathSnafu {
path: path.display().to_string(),
})?;
self.repo.is_path_ignored(path).context(GitOpSnafu)
let workdir = self
.repo
.work_dir()
.context(GixPathNotFountSnafu { path: "workdir" })?;
let workdir = workdir.canonicalize().context(ResolveAbsolutePathSnafu {
path: workdir.display().to_string(),
})?;
let at_path = pathdiff::diff_paths(path, workdir)
.context(GixPathNotFountSnafu { path: "<relative>" })?;
let worktree = self
.repo
.worktree()
.context(GixPathNotFountSnafu { path: "worktree" })?;
let mut attrs = worktree
.excludes(None)
.map_err(Box::new)
.context(GixExcludeOpSnafu)?;
let platform = attrs
.at_path(at_path, Some(is_dir))
.context(GixCheckExcludeOpSnafu)?;
Ok(platform.is_excluded())
}
}
23 changes: 10 additions & 13 deletions fmt/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::path::PathBuf;

use ignore::overrides::OverrideBuilder;
use snafu::{ensure, ResultExt};
use tracing::{debug, info};
use tracing::debug;
use walkdir::WalkDir;

use crate::{
Expand Down Expand Up @@ -92,16 +92,13 @@ impl Selection {
);

let result = match GitHelper::create(&self.basedir, self.git)? {
None => {
select_files_with_ignore(&self.basedir, &includes, &excludes, &reverse_excludes, {
if self.git.ignore.is_auto() {
info!("git.ignore=auto is resolved to enable ignore crate's gitignore");
true
} else {
false
}
})?
}
None => select_files_with_ignore(
&self.basedir,
&includes,
&excludes,
&reverse_excludes,
self.git.ignore.is_auto(),
)?,
Some(git_helper) => select_files_with_git(
&self.basedir,
&includes,
Expand Down Expand Up @@ -193,7 +190,7 @@ fn select_files_with_git(
if file_type.is_symlink() {
debug!("skip symlink: {:?}", path);
} else if file_type.is_dir() {
if git_helper.ignored(path)? {
if git_helper.ignored(path, true)? {
debug!("skip git ignored directory: {:?}", path);
it.skip_current_dir();
continue;
Expand All @@ -204,7 +201,7 @@ fn select_files_with_git(
continue;
}
} else if file_type.is_file() {
if git_helper.ignored(path)? {
if git_helper.ignored(path, false)? {
debug!("skip git ignored file: {:?}", path);
continue;
}
Expand Down

0 comments on commit 6db9b1c

Please sign in to comment.