@@ -688,6 +688,10 @@ static int merge_hunks(struct add_p_state *s, struct file_diff *file_diff,
688
688
< next -> new_offset + merged -> delta )
689
689
break ;
690
690
691
+ /*
692
+ * If the hunks were not edited, and overlap, we can simply
693
+ * extend the line range.
694
+ */
691
695
if (merged -> start < hunk -> start && merged -> end > hunk -> start ) {
692
696
merged -> end = hunk -> end ;
693
697
merged -> colored_end = hunk -> colored_end ;
@@ -699,16 +703,17 @@ static int merge_hunks(struct add_p_state *s, struct file_diff *file_diff,
699
703
- next -> new_offset ;
700
704
size_t overlap_end = hunk -> start ;
701
705
size_t overlap_start = overlap_end ;
702
- size_t overlap_next , len , i ;
706
+ size_t overlap_next , len , j ;
703
707
704
708
/*
705
- * One of the hunks was edited; let's ensure that at
706
- * least the last context line of the first hunk
707
- * overlaps with the corresponding line of the second
708
- * hunk, and then merge.
709
+ * One of the hunks was edited: the modified hunk was
710
+ * appended to the strbuf `s->plain`.
711
+ *
712
+ * Let's ensure that at least the last context line of
713
+ * the first hunk overlaps with the corresponding line
714
+ * of the second hunk, and then merge.
709
715
*/
710
-
711
- for (i = 0 ; i < overlapping_line_count ; i ++ ) {
716
+ for (j = 0 ; j < overlapping_line_count ; j ++ ) {
712
717
overlap_next = find_next_line (& s -> plain ,
713
718
overlap_end );
714
719
@@ -722,7 +727,7 @@ static int merge_hunks(struct add_p_state *s, struct file_diff *file_diff,
722
727
if (plain [overlap_end ] != ' ' )
723
728
return error (_ ("expected context line "
724
729
"#%d in\n%.*s" ),
725
- (int )(i + 1 ),
730
+ (int )(j + 1 ),
726
731
(int )(hunk -> end
727
732
- hunk -> start ),
728
733
plain + hunk -> start );
@@ -1004,21 +1009,13 @@ static void recolor_hunk(struct add_p_state *s, struct hunk *hunk)
1004
1009
1005
1010
static int edit_hunk_manually (struct add_p_state * s , struct hunk * hunk )
1006
1011
{
1007
- char * path = xstrdup (git_path ("addp-hunk-edit.diff" ));
1008
- int fd = xopen (path , O_WRONLY | O_CREAT | O_TRUNC , 0666 );
1009
- struct strbuf buf = STRBUF_INIT ;
1010
- size_t i , j ;
1011
- int res , copy ;
1012
-
1013
- if (fd < 0 ) {
1014
- res = error_errno (_ ("could not open '%s' for writing" ), path );
1015
- goto edit_hunk_manually_finish ;
1016
- }
1012
+ size_t i ;
1017
1013
1018
- strbuf_commented_addf (& buf , _ ("Manual hunk edit mode -- see bottom for "
1014
+ strbuf_reset (& s -> buf );
1015
+ strbuf_commented_addf (& s -> buf , _ ("Manual hunk edit mode -- see bottom for "
1019
1016
"a quick guide.\n" ));
1020
- render_hunk (s , hunk , 0 , 0 , & buf );
1021
- strbuf_commented_addf (& buf ,
1017
+ render_hunk (s , hunk , 0 , 0 , & s -> buf );
1018
+ strbuf_commented_addf (& s -> buf ,
1022
1019
_ ("---\n"
1023
1020
"To remove '%c' lines, make them ' ' lines "
1024
1021
"(context).\n"
@@ -1027,63 +1024,51 @@ static int edit_hunk_manually(struct add_p_state *s, struct hunk *hunk)
1027
1024
s -> mode -> is_reverse ? '+' : '-' ,
1028
1025
s -> mode -> is_reverse ? '-' : '+' ,
1029
1026
comment_line_char );
1030
- strbuf_commented_addf (& buf , "%s" , _ (s -> mode -> edit_hunk_hint ));
1027
+ strbuf_commented_addf (& s -> buf , "%s" , _ (s -> mode -> edit_hunk_hint ));
1031
1028
/*
1032
1029
* TRANSLATORS: 'it' refers to the patch mentioned in the previous
1033
1030
* messages.
1034
1031
*/
1035
- strbuf_commented_addf (& buf ,
1032
+ strbuf_commented_addf (& s -> buf ,
1036
1033
_ ("If it does not apply cleanly, you will be "
1037
1034
"given an opportunity to\n"
1038
1035
"edit again. If all lines of the hunk are "
1039
1036
"removed, then the edit is\n"
1040
1037
"aborted and the hunk is left unchanged.\n" ));
1041
- if (write_in_full (fd , buf .buf , buf .len ) < 0 ) {
1042
- res = error_errno (_ ("could not write to '%s'" ), path );
1043
- goto edit_hunk_manually_finish ;
1044
- }
1045
1038
1046
- res = close (fd );
1047
- fd = -1 ;
1048
- if (res < 0 )
1049
- goto edit_hunk_manually_finish ;
1050
-
1051
- hunk -> start = s -> plain .len ;
1052
- if (launch_editor (path , & s -> plain , NULL ) < 0 ) {
1053
- res = error_errno (_ ("could not edit '%s'" ), path );
1054
- goto edit_hunk_manually_finish ;
1055
- }
1056
- unlink (path );
1039
+ if (strbuf_edit_interactively (& s -> buf , "addp-hunk-edit.diff" , NULL ) < 0 )
1040
+ return -1 ;
1057
1041
1058
1042
/* strip out commented lines */
1059
- copy = s -> plain .buf [hunk -> start ] != comment_line_char ;
1060
- for (i = j = hunk -> start ; i < s -> plain .len ; ) {
1061
- if (copy )
1062
- s -> plain .buf [j ++ ] = s -> plain .buf [i ];
1063
- if (s -> plain .buf [i ++ ] == '\n' )
1064
- copy = s -> plain .buf [i ] != comment_line_char ;
1043
+ hunk -> start = s -> plain .len ;
1044
+ for (i = 0 ; i < s -> buf .len ; ) {
1045
+ const char * bol = s -> buf .buf + i ;
1046
+ size_t rest = s -> buf .len - i ;
1047
+ const char * eol = memchr (bol , '\n' , rest );
1048
+ size_t len = eol ? eol + 1 - bol : rest ;
1049
+
1050
+ if (* bol != comment_line_char )
1051
+ strbuf_add (& s -> plain , bol , len );
1052
+ i += len ;
1065
1053
}
1066
1054
1067
- if (j == hunk -> start )
1068
- /* User aborted by deleting everything */
1069
- goto edit_hunk_manually_finish ;
1055
+ hunk -> end = s -> plain .len ;
1056
+ if (hunk -> end == hunk -> start )
1057
+ /* The user aborted editing by deleting everything */
1058
+ return 0 ;
1070
1059
1071
- res = 1 ;
1072
- strbuf_setlen (& s -> plain , j );
1073
- hunk -> end = j ;
1074
1060
recolor_hunk (s , hunk );
1061
+
1062
+ /*
1063
+ * If the hunk header is intact, parse it, otherwise simply use the
1064
+ * hunk header prior to editing (which will adjust `hunk->start` to
1065
+ * skip the hunk header).
1066
+ */
1075
1067
if (s -> plain .buf [hunk -> start ] == '@' &&
1076
- /* If the hunk header was deleted, simply use the original one. */
1077
1068
parse_hunk_header (s , hunk ) < 0 )
1078
- res = -1 ;
1069
+ return error ( _ ( "could not parse hunk header" )) ;
1079
1070
1080
- edit_hunk_manually_finish :
1081
- if (fd >= 0 )
1082
- close (fd );
1083
- free (path );
1084
- strbuf_release (& buf );
1085
-
1086
- return res ;
1071
+ return 1 ;
1087
1072
}
1088
1073
1089
1074
static ssize_t recount_edited_hunk (struct add_p_state * s , struct hunk * hunk ,
@@ -1165,13 +1150,13 @@ static int edit_hunk_loop(struct add_p_state *s,
1165
1150
size_t plain_len = s -> plain .len , colored_len = s -> colored .len ;
1166
1151
struct hunk backup ;
1167
1152
1168
- memcpy ( & backup , hunk , sizeof ( backup )) ;
1153
+ backup = * hunk ;
1169
1154
1170
1155
for (;;) {
1171
1156
int res = edit_hunk_manually (s , hunk );
1172
1157
if (res == 0 ) {
1173
1158
/* abandonded */
1174
- memcpy ( hunk , & backup , sizeof ( backup )) ;
1159
+ * hunk = backup ;
1175
1160
return -1 ;
1176
1161
}
1177
1162
@@ -1187,7 +1172,7 @@ static int edit_hunk_loop(struct add_p_state *s,
1187
1172
/* Drop edits (they were appended to s->plain) */
1188
1173
strbuf_setlen (& s -> plain , plain_len );
1189
1174
strbuf_setlen (& s -> colored , colored_len );
1190
- memcpy ( hunk , & backup , sizeof ( backup )) ;
1175
+ * hunk = backup ;
1191
1176
1192
1177
/*
1193
1178
* TRANSLATORS: do not translate [y/n]
0 commit comments