@@ -45,6 +45,8 @@ static const char *me;
4545
4646#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
4747
48+ static char * get_encoding (const char * message );
49+
4850static void parse_args (int argc , const char * * argv )
4951{
5052 const char * const * usage_str =
@@ -73,33 +75,64 @@ static void parse_args(int argc, const char **argv)
7375 exit (1 );
7476}
7577
76- static char * get_oneline (const char * message )
78+ struct commit_message {
79+ char * parent_label ;
80+ const char * label ;
81+ const char * subject ;
82+ char * reencoded_message ;
83+ const char * message ;
84+ };
85+
86+ static int get_message (const char * raw_message , struct commit_message * out )
7787{
78- char * result ;
79- const char * p = message , * abbrev , * eol ;
88+ const char * encoding ;
89+ const char * p , * abbrev , * eol ;
90+ char * q ;
8091 int abbrev_len , oneline_len ;
8192
82- if (!p )
83- die ("Could not read commit message of %s" ,
84- sha1_to_hex (commit -> object .sha1 ));
93+ if (!raw_message )
94+ return -1 ;
95+ encoding = get_encoding (raw_message );
96+ if (!encoding )
97+ encoding = "UTF-8" ;
98+ if (!git_commit_encoding )
99+ git_commit_encoding = "UTF-8" ;
100+ if ((out -> reencoded_message = reencode_string (raw_message ,
101+ git_commit_encoding , encoding )))
102+ out -> message = out -> reencoded_message ;
103+
104+ abbrev = find_unique_abbrev (commit -> object .sha1 , DEFAULT_ABBREV );
105+ abbrev_len = strlen (abbrev );
106+
107+ /* Find beginning and end of commit subject. */
108+ p = out -> message ;
85109 while (* p && (* p != '\n' || p [1 ] != '\n' ))
86110 p ++ ;
87-
88111 if (* p ) {
89112 p += 2 ;
90113 for (eol = p + 1 ; * eol && * eol != '\n' ; eol ++ )
91114 ; /* do nothing */
92115 } else
93116 eol = p ;
94- abbrev = find_unique_abbrev (commit -> object .sha1 , DEFAULT_ABBREV );
95- abbrev_len = strlen (abbrev );
96117 oneline_len = eol - p ;
97- result = xmalloc (abbrev_len + 5 + oneline_len );
98- memcpy (result , abbrev , abbrev_len );
99- memcpy (result + abbrev_len , "... " , 4 );
100- memcpy (result + abbrev_len + 4 , p , oneline_len );
101- result [abbrev_len + 4 + oneline_len ] = '\0' ;
102- return result ;
118+
119+ out -> parent_label = xmalloc (strlen ("parent of " ) + abbrev_len +
120+ strlen ("... " ) + oneline_len + 1 );
121+ q = out -> parent_label ;
122+ q = mempcpy (q , "parent of " , strlen ("parent of " ));
123+ out -> label = q ;
124+ q = mempcpy (q , abbrev , abbrev_len );
125+ q = mempcpy (q , "... " , strlen ("... " ));
126+ out -> subject = q ;
127+ q = mempcpy (q , p , oneline_len );
128+ * q = '\0' ;
129+ return 0 ;
130+ }
131+
132+ static void free_message (struct commit_message * msg )
133+ {
134+ free (msg -> parent_label );
135+ free (msg -> reencoded_message );
103136}
104137
105138static char * get_encoding (const char * message )
@@ -248,9 +281,10 @@ static int revert_or_cherry_pick(int argc, const char **argv)
248281{
249282 unsigned char head [20 ];
250283 struct commit * base , * next , * parent ;
284+ const char * next_label ;
251285 int i , index_fd , clean ;
252- char * oneline , * reencoded_message = NULL ;
253- const char * message , * encoding ;
286+ struct commit_message msg = { NULL , NULL , NULL , NULL , NULL } ;
287+
254288 char * defmsg = git_pathdup ("MERGE_MSG" );
255289 struct merge_options o ;
256290 struct tree * result , * next_tree , * base_tree , * head_tree ;
@@ -314,14 +348,14 @@ static int revert_or_cherry_pick(int argc, const char **argv)
314348 else
315349 parent = commit -> parents -> item ;
316350
317- if (!(message = commit -> buffer ))
318- die ("Cannot get commit message for %s" ,
319- sha1_to_hex (commit -> object .sha1 ));
320-
321351 if (parent && parse_commit (parent ) < 0 )
322352 die ("%s: cannot parse parent commit %s" ,
323353 me , sha1_to_hex (parent -> object .sha1 ));
324354
355+ if (get_message (commit -> buffer , & msg ) != 0 )
356+ die ("Cannot get commit message for %s" ,
357+ sha1_to_hex (commit -> object .sha1 ));
358+
325359 /*
326360 * "commit" is an existing commit. We would want to apply
327361 * the difference it introduces since its first parent "prev"
@@ -332,24 +366,12 @@ static int revert_or_cherry_pick(int argc, const char **argv)
332366 msg_fd = hold_lock_file_for_update (& msg_file , defmsg ,
333367 LOCK_DIE_ON_ERROR );
334368
335- encoding = get_encoding (message );
336- if (!encoding )
337- encoding = "UTF-8" ;
338- if (!git_commit_encoding )
339- git_commit_encoding = "UTF-8" ;
340- if ((reencoded_message = reencode_string (message ,
341- git_commit_encoding , encoding )))
342- message = reencoded_message ;
343-
344- oneline = get_oneline (message );
345-
346369 if (action == REVERT ) {
347- char * oneline_body = strchr (oneline , ' ' );
348-
349370 base = commit ;
350371 next = parent ;
372+ next_label = msg .parent_label ;
351373 add_to_msg ("Revert \"" );
352- add_to_msg (oneline_body + 1 );
374+ add_to_msg (msg . subject );
353375 add_to_msg ("\"\n\nThis reverts commit " );
354376 add_to_msg (sha1_to_hex (commit -> object .sha1 ));
355377
@@ -361,8 +383,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
361383 } else {
362384 base = parent ;
363385 next = commit ;
364- set_author_ident_env (message );
365- add_message_to_msg (message );
386+ next_label = msg .label ;
387+ set_author_ident_env (msg .message );
388+ add_message_to_msg (msg .message );
366389 if (no_replay ) {
367390 add_to_msg ("(cherry picked from commit " );
368391 add_to_msg (sha1_to_hex (commit -> object .sha1 ));
@@ -373,7 +396,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
373396 read_cache ();
374397 init_merge_options (& o );
375398 o .branch1 = "HEAD" ;
376- o .branch2 = oneline ;
399+ o .branch2 = next ? next_label : "(empty tree)" ;
377400
378401 head_tree = parse_tree_indirect (head );
379402 next_tree = next ? next -> tree : empty_tree ();
@@ -437,7 +460,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
437460 args [i ] = NULL ;
438461 return execv_git_cmd (args );
439462 }
440- free ( reencoded_message );
463+ free_message ( & msg );
441464 free (defmsg );
442465
443466 return 0 ;
0 commit comments