@@ -45,6 +45,8 @@ static const char *me;
45
45
46
46
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
47
47
48
+ static char * get_encoding (const char * message );
49
+
48
50
static void parse_args (int argc , const char * * argv )
49
51
{
50
52
const char * const * usage_str =
@@ -73,33 +75,64 @@ static void parse_args(int argc, const char **argv)
73
75
exit (1 );
74
76
}
75
77
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 )
77
87
{
78
- char * result ;
79
- const char * p = message , * abbrev , * eol ;
88
+ const char * encoding ;
89
+ const char * p , * abbrev , * eol ;
90
+ char * q ;
80
91
int abbrev_len , oneline_len ;
81
92
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 ;
85
109
while (* p && (* p != '\n' || p [1 ] != '\n' ))
86
110
p ++ ;
87
-
88
111
if (* p ) {
89
112
p += 2 ;
90
113
for (eol = p + 1 ; * eol && * eol != '\n' ; eol ++ )
91
114
; /* do nothing */
92
115
} else
93
116
eol = p ;
94
- abbrev = find_unique_abbrev (commit -> object .sha1 , DEFAULT_ABBREV );
95
- abbrev_len = strlen (abbrev );
96
117
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 );
103
136
}
104
137
105
138
static char * get_encoding (const char * message )
@@ -248,9 +281,10 @@ static int revert_or_cherry_pick(int argc, const char **argv)
248
281
{
249
282
unsigned char head [20 ];
250
283
struct commit * base , * next , * parent ;
284
+ const char * next_label ;
251
285
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
+
254
288
char * defmsg = git_pathdup ("MERGE_MSG" );
255
289
struct merge_options o ;
256
290
struct tree * result , * next_tree , * base_tree , * head_tree ;
@@ -314,14 +348,14 @@ static int revert_or_cherry_pick(int argc, const char **argv)
314
348
else
315
349
parent = commit -> parents -> item ;
316
350
317
- if (!(message = commit -> buffer ))
318
- die ("Cannot get commit message for %s" ,
319
- sha1_to_hex (commit -> object .sha1 ));
320
-
321
351
if (parent && parse_commit (parent ) < 0 )
322
352
die ("%s: cannot parse parent commit %s" ,
323
353
me , sha1_to_hex (parent -> object .sha1 ));
324
354
355
+ if (get_message (commit -> buffer , & msg ) != 0 )
356
+ die ("Cannot get commit message for %s" ,
357
+ sha1_to_hex (commit -> object .sha1 ));
358
+
325
359
/*
326
360
* "commit" is an existing commit. We would want to apply
327
361
* the difference it introduces since its first parent "prev"
@@ -332,24 +366,12 @@ static int revert_or_cherry_pick(int argc, const char **argv)
332
366
msg_fd = hold_lock_file_for_update (& msg_file , defmsg ,
333
367
LOCK_DIE_ON_ERROR );
334
368
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
-
346
369
if (action == REVERT ) {
347
- char * oneline_body = strchr (oneline , ' ' );
348
-
349
370
base = commit ;
350
371
next = parent ;
372
+ next_label = msg .parent_label ;
351
373
add_to_msg ("Revert \"" );
352
- add_to_msg (oneline_body + 1 );
374
+ add_to_msg (msg . subject );
353
375
add_to_msg ("\"\n\nThis reverts commit " );
354
376
add_to_msg (sha1_to_hex (commit -> object .sha1 ));
355
377
@@ -361,8 +383,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
361
383
} else {
362
384
base = parent ;
363
385
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 );
366
389
if (no_replay ) {
367
390
add_to_msg ("(cherry picked from commit " );
368
391
add_to_msg (sha1_to_hex (commit -> object .sha1 ));
@@ -373,7 +396,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
373
396
read_cache ();
374
397
init_merge_options (& o );
375
398
o .branch1 = "HEAD" ;
376
- o .branch2 = oneline ;
399
+ o .branch2 = next ? next_label : "(empty tree)" ;
377
400
378
401
head_tree = parse_tree_indirect (head );
379
402
next_tree = next ? next -> tree : empty_tree ();
@@ -437,7 +460,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
437
460
args [i ] = NULL ;
438
461
return execv_git_cmd (args );
439
462
}
440
- free ( reencoded_message );
463
+ free_message ( & msg );
441
464
free (defmsg );
442
465
443
466
return 0 ;
0 commit comments