2222#include "commit-reach.h"
2323#include "worktree.h"
2424#include "hashmap.h"
25+ #include "argv-array.h"
2526
2627static struct ref_msg {
2728 const char * gone ;
@@ -1863,21 +1864,62 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
18631864 return match_pattern (filter , refname );
18641865}
18651866
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 )
18741878{
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+ }
18761901
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 );
18791905
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 );
18811923}
18821924
18831925/*
@@ -1890,7 +1932,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
18901932 void * cb_data ,
18911933 int broken )
18921934{
1893- struct strbuf prefix = STRBUF_INIT ;
1935+ struct string_list prefixes = STRING_LIST_INIT_DUP ;
1936+ struct string_list_item * prefix ;
18941937 int ret ;
18951938
18961939 if (!filter -> match_as_path ) {
@@ -1916,21 +1959,15 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
19161959 return for_each_fullref_in ("" , cb , cb_data , broken );
19171960 }
19181961
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 );
19291963
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+ }
19311969
1932- ret = for_each_fullref_in (prefix .buf , cb , cb_data , broken );
1933- strbuf_release (& prefix );
1970+ string_list_clear (& prefixes , 0 );
19341971 return ret ;
19351972}
19361973
0 commit comments