Skip to content

Commit

Permalink
Merge branch 'submodule-active'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 17, 2023
2 parents 169228b + af1cab3 commit a3afaa4
Show file tree
Hide file tree
Showing 55 changed files with 1,200 additions and 311 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ jobs:
- name: Install Rust
run: rustup update stable && rustup default stable && rustup target add ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- run: set +x; for name in gix-actor gix-attributes gix-bitmap gix-chunk gix-command gix-commitgraph gix-date gix-glob gix-hash gix-hashtable gix-mailmap gix-object gix-packetline gix-path gix-pathspec gix-quote gix-refspec gix-revision gix-traverse gix-validate; do (cd $name && cargo build --target ${{ matrix.target }}); done
- run: set +x; for name in gix-actor gix-attributes gix-bitmap gix-chunk gix-command gix-commitgraph gix-date gix-glob gix-hash gix-hashtable gix-mailmap gix-object gix-packetline gix-path gix-quote gix-refspec gix-revision gix-traverse gix-validate; do (cd $name && cargo build --target ${{ matrix.target }}); done
name: crates without feature toggles
- run: set +x; for feature in progress fs-walkdir-parallel parallel io-pipe crc32 zlib zlib-rust-backend fast-sha1 rustsha1 cache-efficiency-debug; do (cd gix-features && cargo build --features $feature --target ${{ matrix.target }}); done
name: features of gix-features
Expand Down
34 changes: 34 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ tracing = { version = "0.1.37", optional = true }
owo-colors = "3.5.0"
tabled = { version = "0.10.0", default-features = false }

once_cell = "1.18.0"
document-features = { version = "0.2.0", optional = true }

[profile.dev.package]
Expand Down
22 changes: 15 additions & 7 deletions gitoxide-core/src/query/engine/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@ impl query::Engine {
mut progress: impl gix::Progress,
) -> anyhow::Result<()> {
match cmd {
Command::TracePath { mut spec } => {
Command::TracePath { spec } => {
let is_excluded = spec.is_excluded();
let relpath = spec
.normalize(
self.repo.prefix()?.unwrap_or_default().as_ref(),
self.repo.work_dir().unwrap_or_else(|| self.repo.git_dir()),
// Just to get the normalized version of the path with everything auto-configured.
let relpath = self
.repo
.pathspec(
Some(spec.to_bstring()),
false,
&gix::index::State::new(self.repo.object_hash()),
)?
.path();
.search()
.patterns()
.next()
.expect("exactly one")
.path()
.to_owned();
if relpath.is_empty() || is_excluded {
bail!("Invalid pathspec {spec} - path must not be empty, not be excluded, and wildcards are taken literally")
}
Expand All @@ -36,7 +44,7 @@ impl query::Engine {
|r| r.get(0),
)
.optional()?
.context("Path not found anywhere in recorded history")?;
.with_context(|| format!("Path '{relpath}' not found anywhere in recorded history"))?;

let mut by_file_id = self
.con
Expand Down
1 change: 1 addition & 0 deletions gitoxide-core/src/query/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub enum Command {
}

pub(crate) mod update;

pub use update::update;

mod command;
80 changes: 53 additions & 27 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::repository::IndexPersistedOrInMemory;

pub struct Options {
pub format: OutputFormat,
Expand All @@ -8,17 +9,19 @@ pub struct Options {
pub(crate) mod function {
use std::{io, path::Path};

use anyhow::bail;
use anyhow::{anyhow, bail};
use gix::bstr::BStr;
use gix::prelude::FindExt;

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

pub fn query(
repo: gix::Repository,
pathspecs: impl Iterator<Item = gix::pathspec::Pattern>,
input: PathsOrPatterns,
mut out: impl io::Write,
mut err: impl io::Write,
Options { format, statistics }: Options,
Expand All @@ -27,32 +30,33 @@ pub(crate) mod function {
bail!("JSON output isn't implemented yet");
}

let mut cache = attributes_cache(&repo)?;
let (mut cache, index) = attributes_cache(&repo)?;
let mut matches = cache.attribute_matches();
// TODO(pathspec): The search is just used as a shortcut to normalization, but one day should be used for an actual search.
let search = gix::pathspec::Search::from_specs(
pathspecs,
repo.prefix()?.as_deref(),
repo.work_dir().unwrap_or_else(|| repo.git_dir()),
)?;

for spec in search.into_patterns() {
let is_dir = gix::path::from_bstr(spec.path()).metadata().ok().map(|m| m.is_dir());
let entry = cache.at_entry(spec.path(), is_dir, |oid, buf| repo.objects.find_blob(oid, buf))?;
match input {
PathsOrPatterns::Paths(paths) => {
for path in paths {
let is_dir = gix::path::from_bstr(path.as_ref()).metadata().ok().map(|m| m.is_dir());

if !entry.matching_attributes(&mut matches) {
continue;
let entry = cache.at_entry(path.as_slice(), is_dir, |oid, buf| repo.objects.find_blob(oid, buf))?;
if !entry.matching_attributes(&mut matches) {
continue;
}
print_match(&matches, path.as_ref(), &mut out)?;
}
}
for m in matches.iter() {
writeln!(
out,
"{}:{}:{}\t{}\t{}",
m.location.source.map(Path::to_string_lossy).unwrap_or_default(),
m.location.sequence_number,
m.pattern,
spec.path(),
m.assignment
)?;
PathsOrPatterns::Patterns(patterns) => {
let mut pathspec = repo.pathspec(patterns, true, &index)?;
for (path, _entry) in pathspec
.index_entries_with_paths(&index)
.ok_or_else(|| anyhow!("Pathspec didn't match a single path in the index"))?
{
let entry = cache.at_entry(path, Some(false), |oid, buf| repo.objects.find_blob(oid, buf))?;
if !entry.matching_attributes(&mut matches) {
continue;
}
print_match(&matches, path, &mut out)?;
}
}
}

Expand All @@ -62,11 +66,32 @@ pub(crate) mod function {
}
Ok(())
}

fn print_match(
matches: &gix::attrs::search::Outcome,
path: &BStr,
mut out: impl std::io::Write,
) -> std::io::Result<()> {
for m in matches.iter() {
writeln!(
out,
"{}:{}:{}\t{}\t{}",
m.location.source.map(Path::to_string_lossy).unwrap_or_default(),
m.location.sequence_number,
m.pattern,
path,
m.assignment
)?;
}
Ok(())
}
}

pub(crate) fn attributes_cache(repo: &gix::Repository) -> anyhow::Result<gix::worktree::Cache> {
pub(crate) fn attributes_cache(
repo: &gix::Repository,
) -> anyhow::Result<(gix::worktree::Cache, IndexPersistedOrInMemory)> {
let index = repo.index_or_load_from_head()?;
Ok(repo.attributes(
let cache = repo.attributes(
&index,
if repo.is_bare() {
gix::worktree::cache::state::attributes::Source::IdMapping
Expand All @@ -75,5 +100,6 @@ pub(crate) fn attributes_cache(repo: &gix::Repository) -> anyhow::Result<gix::wo
},
gix::worktree::cache::state::ignore::Source::IdMapping,
None,
)?)
)?;
Ok((cache, index))
}
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub(crate) mod function {
}
});

let mut cache = attributes_cache(&repo)?;
let (mut cache, _index) = attributes_cache(&repo)?;
let mut matches = cache.attribute_matches();
let mut progress = progress.add_child("validate");
let mut mismatches = Vec::new();
Expand Down
71 changes: 45 additions & 26 deletions gitoxide-core/src/repository/exclude.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::io;

use anyhow::bail;
use anyhow::{anyhow, bail};
use gix::bstr::BStr;
use gix::prelude::FindExt;

use crate::repository::PathsOrPatterns;
use crate::OutputFormat;

pub mod query {
Expand All @@ -20,7 +22,7 @@ pub mod query {

pub fn query(
repo: gix::Repository,
pathspecs: impl Iterator<Item = gix::pathspec::Pattern>,
input: PathsOrPatterns,
mut out: impl io::Write,
mut err: impl io::Write,
query::Options {
Expand All @@ -41,30 +43,29 @@ pub fn query(
Default::default(),
)?;

// TODO(pathspec): actually use the search to find items. This looks like `gix` capabilities to put it all together.
let search = gix::pathspec::Search::from_specs(
pathspecs,
repo.prefix()?.as_deref(),
repo.work_dir().unwrap_or_else(|| repo.git_dir()),
)?;

for spec in search.into_patterns() {
let path = spec.path();
let is_dir = gix::path::from_bstr(path).metadata().ok().map(|m| m.is_dir());
let entry = cache.at_entry(path, is_dir, |oid, buf| repo.objects.find_blob(oid, buf))?;
let match_ = entry
.matching_exclude_pattern()
.and_then(|m| (show_ignore_patterns || !m.pattern.is_negative()).then_some(m));
match match_ {
Some(m) => writeln!(
out,
"{}:{}:{}\t{}",
m.source.map(std::path::Path::to_string_lossy).unwrap_or_default(),
m.sequence_number,
m.pattern,
path
)?,
None => writeln!(out, "::\t{path}")?,
match input {
PathsOrPatterns::Paths(paths) => {
for path in paths {
let is_dir = gix::path::from_bstr(path.as_ref()).metadata().ok().map(|m| m.is_dir());
let entry = cache.at_entry(path.as_slice(), is_dir, |oid, buf| repo.objects.find_blob(oid, buf))?;
let match_ = entry
.matching_exclude_pattern()
.and_then(|m| (show_ignore_patterns || !m.pattern.is_negative()).then_some(m));
print_match(match_, path.as_ref(), &mut out)?;
}
}
PathsOrPatterns::Patterns(patterns) => {
for (path, _entry) in repo
.pathspec(patterns.into_iter(), repo.work_dir().is_some(), &index)?
.index_entries_with_paths(&index)
.ok_or_else(|| anyhow!("Pathspec didn't yield any entry"))?
{
let entry = cache.at_entry(path, Some(false), |oid, buf| repo.objects.find_blob(oid, buf))?;
let match_ = entry
.matching_exclude_pattern()
.and_then(|m| (show_ignore_patterns || !m.pattern.is_negative()).then_some(m));
print_match(match_, path, &mut out)?;
}
}
}

Expand All @@ -74,3 +75,21 @@ pub fn query(
}
Ok(())
}

fn print_match(
m: Option<gix::ignore::search::Match<'_>>,
path: &BStr,
mut out: impl std::io::Write,
) -> std::io::Result<()> {
match m {
Some(m) => writeln!(
out,
"{}:{}:{}\t{}",
m.source.map(std::path::Path::to_string_lossy).unwrap_or_default(),
m.sequence_number,
m.pattern,
path
),
None => writeln!(out, "::\t{path}"),
}
}
Loading

0 comments on commit a3afaa4

Please sign in to comment.