Skip to content

Commit

Permalink
feat: gix attributes validate-baseline works in bare repostiories.
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed May 24, 2023
1 parent 39b0ba5 commit 596ff7a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 12 deletions.
48 changes: 46 additions & 2 deletions gitoxide-core/src/repository/attributes/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::OutputFormat;
use gix::odb::FindExt;

pub struct Options {
pub format: OutputFormat,
Expand Down Expand Up @@ -58,11 +59,54 @@ pub(crate) mod function {
}
}

pub(crate) enum Index {
Shared(gix::worktree::Index),
Owned(gix::index::File),
}

impl std::ops::Deref for Index {
type Target = gix::index::File;

fn deref(&self) -> &Self::Target {
match self {
Index::Shared(i) => i,
Index::Owned(i) => i,
}
}
}

impl Index {
pub fn into_owned(self) -> gix::index::File {
match self {
Index::Shared(i) => gix::index::File::clone(&i),
Index::Owned(i) => i,
}
}
}

pub(crate) fn index_on_demand(repo: &gix::Repository) -> anyhow::Result<Index> {
Ok(match repo.index() {
Ok(index) => Index::Shared(index),
Err(gix::worktree::open_index::Error::IndexFile(_)) => {
let tree = repo.head_commit()?.tree_id()?;
Index::Owned(gix::index::File::from_state(
gix::index::State::from_tree(&tree, |oid, buf| repo.objects.find_tree_iter(oid, buf).ok())?,
repo.git_dir().join("index"),
))
}
Err(err) => return Err(err.into()),
})
}

pub(crate) fn attributes_cache(repo: &gix::Repository) -> anyhow::Result<gix::worktree::Cache> {
let index = repo.index()?;
let index = index_on_demand(repo)?;
Ok(repo.attributes(
&index,
gix::worktree::cache::state::attributes::Source::WorktreeThenIdMapping,
if repo.is_bare() {
gix::worktree::cache::state::attributes::Source::IdMapping
} else {
gix::worktree::cache::state::attributes::Source::WorktreeThenIdMapping
},
gix::worktree::cache::state::ignore::Source::IdMapping,
None,
)?)
Expand Down
32 changes: 22 additions & 10 deletions gitoxide-core/src/repository/attributes/validate_baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub(crate) mod function {
use gix::odb::FindExt;
use gix::Progress;

use crate::repository::attributes::query::attributes_cache;
use crate::repository::attributes::query::{attributes_cache, index_on_demand};
use crate::repository::attributes::validate_baseline::Options;
use crate::OutputFormat;

Expand All @@ -32,21 +32,30 @@ pub(crate) mod function {
Options {
format,
statistics,
ignore,
mut ignore,
}: Options,
) -> anyhow::Result<()> {
if format != OutputFormat::Human {
bail!("JSON output isn't implemented yet");
}

if repo.is_bare() {
writeln!(
err,
"Repo {:?} is bare - disabling git-ignore baseline as `git check-ignore` needs a worktree",
repo.path()
)
.ok();
ignore = false;
}
let mut num_entries = None;
let pathspecs = pathspecs
.map(|i| anyhow::Result::Ok(Box::new(i) as Box<dyn Iterator<Item = gix::path::Spec> + Send + 'static>))
.unwrap_or_else({
let repo = repo.clone();
let num_entries = &mut num_entries;
move || -> anyhow::Result<_> {
let index = repo.open_index()?;
let index = index_on_demand(&repo)?.into_owned();
let (entries, path_backing) = index.into_parts().0.into_entries();
*num_entries = Some(entries.len());
Ok(Box::new(entries.into_iter().map(move |e| {
Expand All @@ -55,15 +64,11 @@ pub(crate) mod function {
}
})?;

let work_dir = repo
.work_dir()
.map(ToOwned::to_owned)
.ok_or_else(|| anyhow!("repository at {:?} must have a worktree checkout", repo.path()))?;
let (tx_base, rx_base) = std::sync::mpsc::channel::<(String, Baseline)>();
let feed_attrs = {
let (tx, rx) = std::sync::mpsc::sync_channel::<gix::path::Spec>(1);
std::thread::spawn({
let path = work_dir.clone();
let path = repo.path().to_owned();
let tx_base = tx_base.clone();
let mut progress = progress.add_child("attributes");
move || -> anyhow::Result<()> {
Expand Down Expand Up @@ -106,10 +111,17 @@ pub(crate) mod function {
});
tx
};
let work_dir = ignore
.then(|| {
repo.work_dir()
.map(ToOwned::to_owned)
.ok_or_else(|| anyhow!("repository at {:?} must have a worktree checkout", repo.path()))
})
.transpose()?;
let feed_excludes = ignore.then(|| {
let (tx, rx) = std::sync::mpsc::sync_channel::<gix::path::Spec>(1);
std::thread::spawn({
let path = work_dir.clone();
let path = work_dir.expect("present if we are here");
let tx_base = tx_base.clone();
let mut progress = progress.add_child("excludes");
move || -> anyhow::Result<()> {
Expand Down Expand Up @@ -239,7 +251,7 @@ pub(crate) mod function {
}
bail!(
"{}: Validation failed with {} mismatches out of {}",
gix::path::realpath(&work_dir).unwrap_or(work_dir).display(),
gix::path::realpath(repo.work_dir().unwrap_or(repo.git_dir()))?.display(),
mismatches.len(),
progress
.counter()
Expand Down

0 comments on commit 596ff7a

Please sign in to comment.