22
22
#include "commit-reach.h"
23
23
#include "worktree.h"
24
24
#include "hashmap.h"
25
+ #include "argv-array.h"
25
26
26
27
static struct ref_msg {
27
28
const char * gone ;
@@ -1863,21 +1864,62 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
1863
1864
return match_pattern (filter , refname );
1864
1865
}
1865
1866
1866
- /*
1867
- * Find the longest prefix of pattern we can pass to
1868
- * `for_each_fullref_in()`, namely the part of pattern preceding the
1869
- * first glob character. (Note that `for_each_fullref_in()` is
1870
- * perfectly happy working with a prefix that doesn't end at a
1871
- * pathname component boundary.)
1872
- */
1873
- static void find_longest_prefix (struct strbuf * out , const char * pattern )
1867
+ static int qsort_strcmp (const void * va , const void * vb )
1868
+ {
1869
+ const char * a = * (const char * * )va ;
1870
+ const char * b = * (const char * * )vb ;
1871
+
1872
+ return strcmp (a , b );
1873
+ }
1874
+
1875
+ static void find_longest_prefixes_1 (struct string_list * out ,
1876
+ struct strbuf * prefix ,
1877
+ const char * * patterns , size_t nr )
1874
1878
{
1875
- const char * p ;
1879
+ size_t i ;
1880
+
1881
+ for (i = 0 ; i < nr ; i ++ ) {
1882
+ char c = patterns [i ][prefix -> len ];
1883
+ if (!c || is_glob_special (c )) {
1884
+ string_list_append (out , prefix -> buf );
1885
+ return ;
1886
+ }
1887
+ }
1888
+
1889
+ i = 0 ;
1890
+ while (i < nr ) {
1891
+ size_t end ;
1892
+
1893
+ /*
1894
+ * Set "end" to the index of the element _after_ the last one
1895
+ * in our group.
1896
+ */
1897
+ for (end = i + 1 ; end < nr ; end ++ ) {
1898
+ if (patterns [i ][prefix -> len ] != patterns [end ][prefix -> len ])
1899
+ break ;
1900
+ }
1876
1901
1877
- for (p = pattern ; * p && !is_glob_special (* p ); p ++ )
1878
- ;
1902
+ strbuf_addch (prefix , patterns [i ][prefix -> len ]);
1903
+ find_longest_prefixes_1 (out , prefix , patterns + i , end - i );
1904
+ strbuf_setlen (prefix , prefix -> len - 1 );
1879
1905
1880
- strbuf_add (out , pattern , p - pattern );
1906
+ i = end ;
1907
+ }
1908
+ }
1909
+
1910
+ static void find_longest_prefixes (struct string_list * out ,
1911
+ const char * * patterns )
1912
+ {
1913
+ struct argv_array sorted = ARGV_ARRAY_INIT ;
1914
+ struct strbuf prefix = STRBUF_INIT ;
1915
+
1916
+ argv_array_pushv (& sorted , patterns );
1917
+ QSORT (sorted .argv , sorted .argc , qsort_strcmp );
1918
+
1919
+ find_longest_prefixes_1 (out , & prefix , sorted .argv , sorted .argc );
1920
+
1921
+ argv_array_clear (& sorted );
1922
+ strbuf_release (& prefix );
1881
1923
}
1882
1924
1883
1925
/*
@@ -1890,7 +1932,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
1890
1932
void * cb_data ,
1891
1933
int broken )
1892
1934
{
1893
- struct strbuf prefix = STRBUF_INIT ;
1935
+ struct string_list prefixes = STRING_LIST_INIT_DUP ;
1936
+ struct string_list_item * prefix ;
1894
1937
int ret ;
1895
1938
1896
1939
if (!filter -> match_as_path ) {
@@ -1916,21 +1959,15 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
1916
1959
return for_each_fullref_in ("" , cb , cb_data , broken );
1917
1960
}
1918
1961
1919
- if (filter -> name_patterns [1 ]) {
1920
- /*
1921
- * multiple patterns; in theory this could still work as long
1922
- * as the patterns are disjoint. We'd just make multiple calls
1923
- * to for_each_ref(). But if they're not disjoint, we'd end up
1924
- * reporting the same ref multiple times. So let's punt on that
1925
- * for now.
1926
- */
1927
- return for_each_fullref_in ("" , cb , cb_data , broken );
1928
- }
1962
+ find_longest_prefixes (& prefixes , filter -> name_patterns );
1929
1963
1930
- find_longest_prefix (& prefix , filter -> name_patterns [0 ]);
1964
+ for_each_string_list_item (prefix , & prefixes ) {
1965
+ ret = for_each_fullref_in (prefix -> string , cb , cb_data , broken );
1966
+ if (ret )
1967
+ break ;
1968
+ }
1931
1969
1932
- ret = for_each_fullref_in (prefix .buf , cb , cb_data , broken );
1933
- strbuf_release (& prefix );
1970
+ string_list_clear (& prefixes , 0 );
1934
1971
return ret ;
1935
1972
}
1936
1973
0 commit comments