@@ -78,60 +78,69 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *
7878 return 1 ;
7979}
8080
81+ static int unique_in_pack (int len ,
82+ const unsigned char * match ,
83+ struct packed_git * p ,
84+ const unsigned char * * found_sha1 ,
85+ int seen_so_far )
86+ {
87+ uint32_t num , last , i , first = 0 ;
88+ const unsigned char * current = NULL ;
89+
90+ open_pack_index (p );
91+ num = p -> num_objects ;
92+ last = num ;
93+ while (first < last ) {
94+ uint32_t mid = (first + last ) / 2 ;
95+ const unsigned char * current ;
96+ int cmp ;
97+
98+ current = nth_packed_object_sha1 (p , mid );
99+ cmp = hashcmp (match , current );
100+ if (!cmp ) {
101+ first = mid ;
102+ break ;
103+ }
104+ if (cmp > 0 ) {
105+ first = mid + 1 ;
106+ continue ;
107+ }
108+ last = mid ;
109+ }
110+
111+ /*
112+ * At this point, "first" is the location of the lowest object
113+ * with an object name that could match "match". See if we have
114+ * 0, 1 or more objects that actually match(es).
115+ */
116+ for (i = first ; i < num ; i ++ ) {
117+ current = nth_packed_object_sha1 (p , first );
118+ if (!match_sha (len , match , current ))
119+ break ;
120+
121+ /* current matches */
122+ if (!seen_so_far ) {
123+ * found_sha1 = current ;
124+ seen_so_far ++ ;
125+ } else if (seen_so_far ) {
126+ /* is it the same as the one previously found elsewhere? */
127+ if (hashcmp (* found_sha1 , current ))
128+ return 2 ; /* definitely not unique */
129+ }
130+ }
131+ return seen_so_far ;
132+ }
133+
81134static int find_short_packed_object (int len , const unsigned char * match , unsigned char * sha1 )
82135{
83136 struct packed_git * p ;
84137 const unsigned char * found_sha1 = NULL ;
85138 int found = 0 ;
86139
87140 prepare_packed_git ();
88- for (p = packed_git ; p && found < 2 ; p = p -> next ) {
89- uint32_t num , last ;
90- uint32_t first = 0 ;
91- open_pack_index (p );
92- num = p -> num_objects ;
93- last = num ;
94- while (first < last ) {
95- uint32_t mid = (first + last ) / 2 ;
96- const unsigned char * current ;
97- int cmp ;
98-
99- current = nth_packed_object_sha1 (p , mid );
100- cmp = hashcmp (match , current );
101- if (!cmp ) {
102- first = mid ;
103- break ;
104- }
105- if (cmp > 0 ) {
106- first = mid + 1 ;
107- continue ;
108- }
109- last = mid ;
110- }
111- if (first < num ) {
112- const unsigned char * current , * next ;
113- current = nth_packed_object_sha1 (p , first );
114- if (match_sha (len , match , current )) {
115- next = nth_packed_object_sha1 (p , first + 1 );
116- if (!next || !match_sha (len , match , next )) {
117- /* unique within this pack */
118- if (!found ) {
119- found_sha1 = current ;
120- found ++ ;
121- }
122- else if (hashcmp (found_sha1 , current )) {
123- found = 2 ;
124- break ;
125- }
126- }
127- else {
128- /* not even unique within this pack */
129- found = 2 ;
130- break ;
131- }
132- }
133- }
134- }
141+ for (p = packed_git ; p && found < 2 ; p = p -> next )
142+ found = unique_in_pack (len , match , p , & found_sha1 , found );
143+
135144 if (found == 1 )
136145 hashcpy (sha1 , found_sha1 );
137146 return found ;
0 commit comments