77#include "parse-options.h"
88#include "setup.h"
99
10- static void flush_current_id (int patchlen , struct object_id * id , struct object_id * result )
10+ static void flush_current_id (struct object_id * id , struct object_id * result )
1111{
12- if (patchlen )
13- printf ("%s %s\n" , oid_to_hex (result ), oid_to_hex (id ));
12+ printf ("%s %s\n" , oid_to_hex (result ), oid_to_hex (id ));
1413}
1514
1615static int remove_space (char * line )
@@ -60,9 +59,27 @@ static int scan_hunk_header(const char *p, int *p_before, int *p_after)
6059 return 1 ;
6160}
6261
62+ /*
63+ * flag bits to control get_one_patchid()'s behaviour.
64+ *
65+ * STABLE/VERBATIM are given from the command line option as
66+ * --stable/--verbatim. FIND_HEADER conveys the internal state
67+ * maintained by the caller to allow the function to avoid mistaking
68+ * lines of log message before seeing the "diff" part as the beginning
69+ * of the next patch.
70+ */
71+ enum {
72+ GOPID_STABLE = (1 <<0 ), /* --stable */
73+ GOPID_VERBATIM = (1 <<1 ), /* --verbatim */
74+ GOPID_FIND_HEADER = (1 <<2 ), /* stop at the beginning of patch message */
75+ };
76+
6377static int get_one_patchid (struct object_id * next_oid , struct object_id * result ,
64- struct strbuf * line_buf , int stable , int verbatim )
78+ struct strbuf * line_buf , unsigned flags )
6579{
80+ int stable = flags & GOPID_STABLE ;
81+ int verbatim = flags & GOPID_VERBATIM ;
82+ int find_header = flags & GOPID_FIND_HEADER ;
6683 int patchlen = 0 , found_next = 0 ;
6784 int before = -1 , after = -1 ;
6885 int diff_is_binary = 0 ;
@@ -77,24 +94,40 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
7794 const char * p = line ;
7895 int len ;
7996
80- /* Possibly skip over the prefix added by "log" or "format-patch" */
81- if (!skip_prefix (line , "commit " , & p ) &&
82- !skip_prefix (line , "From " , & p ) &&
83- starts_with (line , "\\ " ) && 12 < strlen (line )) {
84- if (verbatim )
85- the_hash_algo -> update_fn (& ctx , line , strlen (line ));
86- continue ;
87- }
88-
89- if (!get_oid_hex (p , next_oid )) {
90- found_next = 1 ;
91- break ;
97+ /*
98+ * The caller hasn't seen us find a patch header and
99+ * return to it, or we have started processing patch
100+ * and may encounter the beginning of the next patch.
101+ */
102+ if (find_header ) {
103+ /*
104+ * If we see a line that begins with "<object name>",
105+ * "commit <object name>" or "From <object name>", it is
106+ * the beginning of a patch. Return to the caller, as
107+ * we are done with the one we have been processing.
108+ */
109+ if (skip_prefix (line , "commit " , & p ))
110+ ;
111+ else if (skip_prefix (line , "From " , & p ))
112+ ;
113+ if (!get_oid_hex (p , next_oid )) {
114+ if (verbatim )
115+ the_hash_algo -> update_fn (& ctx , line , strlen (line ));
116+ found_next = 1 ;
117+ break ;
118+ }
92119 }
93120
94121 /* Ignore commit comments */
95122 if (!patchlen && !starts_with (line , "diff " ))
96123 continue ;
97124
125+ /*
126+ * We are past the commit log message. Prepare to
127+ * stop at the beginning of the next patch header.
128+ */
129+ find_header = 1 ;
130+
98131 /* Parsing diff header? */
99132 if (before == -1 ) {
100133 if (starts_with (line , "GIT binary patch" ) ||
@@ -127,6 +160,16 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
127160 break ;
128161 }
129162
163+ /*
164+ * A hunk about an incomplete line may have this
165+ * marker at the end, which should just be ignored.
166+ */
167+ if (starts_with (line , "\\ " ) && 12 < strlen (line )) {
168+ if (verbatim )
169+ the_hash_algo -> update_fn (& ctx , line , strlen (line ));
170+ continue ;
171+ }
172+
130173 if (diff_is_binary ) {
131174 if (starts_with (line , "diff " )) {
132175 diff_is_binary = 0 ;
@@ -173,17 +216,20 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
173216 return patchlen ;
174217}
175218
176- static void generate_id_list (int stable , int verbatim )
219+ static void generate_id_list (unsigned flags )
177220{
178221 struct object_id oid , n , result ;
179222 int patchlen ;
180223 struct strbuf line_buf = STRBUF_INIT ;
181224
182225 oidclr (& oid , the_repository -> hash_algo );
226+ flags |= GOPID_FIND_HEADER ;
183227 while (!feof (stdin )) {
184- patchlen = get_one_patchid (& n , & result , & line_buf , stable , verbatim );
185- flush_current_id (patchlen , & oid , & result );
228+ patchlen = get_one_patchid (& n , & result , & line_buf , flags );
229+ if (patchlen )
230+ flush_current_id (& oid , & result );
186231 oidcpy (& oid , & n );
232+ flags &= ~GOPID_FIND_HEADER ;
187233 }
188234 strbuf_release (& line_buf );
189235}
@@ -219,6 +265,7 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)
219265 /* if nothing is set, default to unstable */
220266 struct patch_id_opts config = {0 , 0 };
221267 int opts = 0 ;
268+ unsigned flags = 0 ;
222269 struct option builtin_patch_id_options [] = {
223270 OPT_CMDMODE (0 , "unstable" , & opts ,
224271 N_ ("use the unstable patch-id algorithm" ), 1 ),
@@ -250,7 +297,11 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)
250297 if (!the_hash_algo )
251298 repo_set_hash_algo (the_repository , GIT_HASH_SHA1 );
252299
253- generate_id_list (opts ? opts > 1 : config .stable ,
254- opts ? opts == 3 : config .verbatim );
300+ if (opts ? opts > 1 : config .stable )
301+ flags |= GOPID_STABLE ;
302+ if (opts ? opts == 3 : config .verbatim )
303+ flags |= GOPID_VERBATIM ;
304+ generate_id_list (flags );
305+
255306 return 0 ;
256307}
0 commit comments