11use crate :: OutputFormat ;
2+ use gix:: repository:: IndexPersistedOrInMemory ;
23
34pub struct Options {
45 pub format : OutputFormat ,
@@ -8,17 +9,19 @@ pub struct Options {
89pub ( crate ) mod function {
910 use std:: { io, path:: Path } ;
1011
11- use anyhow:: bail;
12+ use anyhow:: { anyhow, bail} ;
13+ use gix:: bstr:: BStr ;
1214 use gix:: prelude:: FindExt ;
1315
16+ use crate :: repository:: PathsOrPatterns ;
1417 use crate :: {
1518 repository:: attributes:: query:: { attributes_cache, Options } ,
1619 OutputFormat ,
1720 } ;
1821
1922 pub fn query (
2023 repo : gix:: Repository ,
21- pathspecs : impl Iterator < Item = gix :: pathspec :: Pattern > ,
24+ input : PathsOrPatterns ,
2225 mut out : impl io:: Write ,
2326 mut err : impl io:: Write ,
2427 Options { format, statistics } : Options ,
@@ -27,32 +30,33 @@ pub(crate) mod function {
2730 bail ! ( "JSON output isn't implemented yet" ) ;
2831 }
2932
30- let mut cache = attributes_cache ( & repo) ?;
33+ let ( mut cache, index ) = attributes_cache ( & repo) ?;
3134 let mut matches = cache. attribute_matches ( ) ;
32- // TODO(pathspec): The search is just used as a shortcut to normalization, but one day should be used for an actual search.
33- let search = gix:: pathspec:: Search :: from_specs (
34- pathspecs,
35- repo. prefix ( ) ?. as_deref ( ) ,
36- repo. work_dir ( ) . unwrap_or_else ( || repo. git_dir ( ) ) ,
37- ) ?;
3835
39- for spec in search. into_patterns ( ) {
40- let is_dir = gix:: path:: from_bstr ( spec. path ( ) ) . metadata ( ) . ok ( ) . map ( |m| m. is_dir ( ) ) ;
41- let entry = cache. at_entry ( spec. path ( ) , is_dir, |oid, buf| repo. objects . find_blob ( oid, buf) ) ?;
36+ match input {
37+ PathsOrPatterns :: Paths ( paths) => {
38+ for path in paths {
39+ let is_dir = gix:: path:: from_bstr ( path. as_ref ( ) ) . metadata ( ) . ok ( ) . map ( |m| m. is_dir ( ) ) ;
4240
43- if !entry. matching_attributes ( & mut matches) {
44- continue ;
41+ let entry = cache. at_entry ( path. as_slice ( ) , is_dir, |oid, buf| repo. objects . find_blob ( oid, buf) ) ?;
42+ if !entry. matching_attributes ( & mut matches) {
43+ continue ;
44+ }
45+ print_match ( & matches, path. as_ref ( ) , & mut out) ?;
46+ }
4547 }
46- for m in matches. iter ( ) {
47- writeln ! (
48- out,
49- "{}:{}:{}\t {}\t {}" ,
50- m. location. source. map( Path :: to_string_lossy) . unwrap_or_default( ) ,
51- m. location. sequence_number,
52- m. pattern,
53- spec. path( ) ,
54- m. assignment
55- ) ?;
48+ PathsOrPatterns :: Patterns ( patterns) => {
49+ let mut pathspec = repo. pathspec ( patterns, true , & index) ?;
50+ for ( path, _entry) in pathspec
51+ . index_entries_with_paths ( & index)
52+ . ok_or_else ( || anyhow ! ( "Pathspec didn't match a single path in the index" ) ) ?
53+ {
54+ let entry = cache. at_entry ( path, Some ( false ) , |oid, buf| repo. objects . find_blob ( oid, buf) ) ?;
55+ if !entry. matching_attributes ( & mut matches) {
56+ continue ;
57+ }
58+ print_match ( & matches, path, & mut out) ?;
59+ }
5660 }
5761 }
5862
@@ -62,11 +66,32 @@ pub(crate) mod function {
6266 }
6367 Ok ( ( ) )
6468 }
69+
70+ fn print_match (
71+ matches : & gix:: attrs:: search:: Outcome ,
72+ path : & BStr ,
73+ mut out : impl std:: io:: Write ,
74+ ) -> std:: io:: Result < ( ) > {
75+ for m in matches. iter ( ) {
76+ writeln ! (
77+ out,
78+ "{}:{}:{}\t {}\t {}" ,
79+ m. location. source. map( Path :: to_string_lossy) . unwrap_or_default( ) ,
80+ m. location. sequence_number,
81+ m. pattern,
82+ path,
83+ m. assignment
84+ ) ?;
85+ }
86+ Ok ( ( ) )
87+ }
6588}
6689
67- pub ( crate ) fn attributes_cache ( repo : & gix:: Repository ) -> anyhow:: Result < gix:: worktree:: Cache > {
90+ pub ( crate ) fn attributes_cache (
91+ repo : & gix:: Repository ,
92+ ) -> anyhow:: Result < ( gix:: worktree:: Cache , IndexPersistedOrInMemory ) > {
6893 let index = repo. index_or_load_from_head ( ) ?;
69- Ok ( repo. attributes (
94+ let cache = repo. attributes (
7095 & index,
7196 if repo. is_bare ( ) {
7297 gix:: worktree:: cache:: state:: attributes:: Source :: IdMapping
@@ -75,5 +100,6 @@ pub(crate) fn attributes_cache(repo: &gix::Repository) -> anyhow::Result<gix::wo
75100 } ,
76101 gix:: worktree:: cache:: state:: ignore:: Source :: IdMapping ,
77102 None ,
78- ) ?)
103+ ) ?;
104+ Ok ( ( cache, index) )
79105}
0 commit comments