Skip to content

Commit 3e34838

Browse files
angavrilovspearce
authored andcommitted
git-gui: Reenable staging unmerged files by clicking the icon.
This restores functionality of the file icon for unmerged files. Safety is enforced by loading the diff and checking for lines that look like conflict markers. If such lines are found, or the conflict involves deletion and/or symlinks, a confirmation dialog is presented. Otherwise, the icon immediately stages the working copy version of the file. Includes a revert of 2fe5b2e (Restore ability to Stage Working Copy for conflicts) Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Tested-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
1 parent 6fc835a commit 3e34838

File tree

3 files changed

+70
-33
lines changed

3 files changed

+70
-33
lines changed

git-gui.sh

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,7 @@ set current_branch {}
10591059
set is_detached 0
10601060
set current_diff_path {}
10611061
set is_3way_diff 0
1062+
set is_conflict_diff 0
10621063
set selected_commit_type new
10631064
10641065
set nullid "0000000000000000000000000000000000000000"
@@ -2078,19 +2079,21 @@ proc toggle_or_diff {w x y} {
20782079
$ui_index tag remove in_sel 0.0 end
20792080
$ui_workdir tag remove in_sel 0.0 end
20802081
2081-
# Do not stage files with conflicts
2082+
# Determine the state of the file
20822083
if {[info exists file_states($path)]} {
20832084
set state [lindex $file_states($path) 0]
20842085
} else {
20852086
set state {__}
20862087
}
20872088
2088-
if {[string first {U} $state] >= 0} {
2089-
set col 1
2090-
}
2091-
20922089
# Restage the file, or simply show the diff
20932090
if {$col == 0 && $y > 1} {
2091+
# Conflicts need special handling
2092+
if {[string first {U} $state] >= 0} {
2093+
merge_stage_workdir $path $w $lno
2094+
return
2095+
}
2096+
20942097
if {[string index $state 1] eq {O}} {
20952098
set mmask {}
20962099
} else {
@@ -3057,11 +3060,6 @@ $ctxmmg add command \
30573060
-command {merge_resolve_one 1}
30583061
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
30593062
$ctxmmg add separator
3060-
$ctxmmg add command \
3061-
-label [mc "Stage Working Copy"] \
3062-
-command {merge_resolve_one 0}
3063-
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
3064-
$ctxmmg add separator
30653063
create_common_diff_popup $ctxmmg
30663064
30673065
proc popup_diff_menu {ctxm ctxmmg x y X Y} {

lib/diff.tcl

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ A rescan will be automatically started to find other files which may have the sa
6969
rescan ui_ready 0
7070
}
7171

72-
proc show_diff {path w {lno {}} {scroll_pos {}}} {
72+
proc show_diff {path w {lno {}} {scroll_pos {}} {callback {}}} {
7373
global file_states file_lists
74-
global is_3way_diff diff_active repo_config
74+
global is_3way_diff is_conflict_diff diff_active repo_config
7575
global ui_diff ui_index ui_workdir
7676
global current_diff_path current_diff_side current_diff_header
7777
global current_diff_queue
@@ -92,51 +92,57 @@ proc show_diff {path w {lno {}} {scroll_pos {}}} {
9292

9393
set s $file_states($path)
9494
set m [lindex $s 0]
95+
set is_conflict_diff 0
9596
set current_diff_path $path
9697
set current_diff_side $w
9798
set current_diff_queue {}
9899
ui_status [mc "Loading diff of %s..." [escape_path $path]]
99100

101+
set cont_info [list $scroll_pos $callback]
102+
100103
if {[string first {U} $m] >= 0} {
101-
merge_load_stages $path [list show_unmerged_diff $scroll_pos]
104+
merge_load_stages $path [list show_unmerged_diff $cont_info]
102105
} elseif {$m eq {_O}} {
103-
show_other_diff $path $w $m $scroll_pos
106+
show_other_diff $path $w $m $cont_info
104107
} else {
105-
start_show_diff $scroll_pos
108+
start_show_diff $cont_info
106109
}
107110
}
108111

109-
proc show_unmerged_diff {scroll_pos} {
112+
proc show_unmerged_diff {cont_info} {
110113
global current_diff_path current_diff_side
111-
global merge_stages ui_diff
114+
global merge_stages ui_diff is_conflict_diff
112115
global current_diff_queue
113116

114117
if {$merge_stages(2) eq {}} {
118+
set is_conflict_diff 1
115119
lappend current_diff_queue \
116120
[list "LOCAL: deleted\nREMOTE:\n" d======= \
117121
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
118122
} elseif {$merge_stages(3) eq {}} {
123+
set is_conflict_diff 1
119124
lappend current_diff_queue \
120125
[list "REMOTE: deleted\nLOCAL:\n" d======= \
121126
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
122127
} elseif {[lindex $merge_stages(1) 0] eq {120000}
123128
|| [lindex $merge_stages(2) 0] eq {120000}
124129
|| [lindex $merge_stages(3) 0] eq {120000}} {
130+
set is_conflict_diff 1
125131
lappend current_diff_queue \
126132
[list "LOCAL:\n" d======= \
127133
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
128134
lappend current_diff_queue \
129135
[list "REMOTE:\n" d======= \
130136
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
131137
} else {
132-
start_show_diff $scroll_pos
138+
start_show_diff $cont_info
133139
return
134140
}
135141

136-
advance_diff_queue $scroll_pos
142+
advance_diff_queue $cont_info
137143
}
138144

139-
proc advance_diff_queue {scroll_pos} {
145+
proc advance_diff_queue {cont_info} {
140146
global current_diff_queue ui_diff
141147

142148
set item [lindex $current_diff_queue 0]
@@ -146,10 +152,10 @@ proc advance_diff_queue {scroll_pos} {
146152
$ui_diff insert end [lindex $item 0] [lindex $item 1]
147153
$ui_diff conf -state disabled
148154

149-
start_show_diff $scroll_pos [lindex $item 2]
155+
start_show_diff $cont_info [lindex $item 2]
150156
}
151157

152-
proc show_other_diff {path w m scroll_pos} {
158+
proc show_other_diff {path w m cont_info} {
153159
global file_states file_lists
154160
global is_3way_diff diff_active repo_config
155161
global ui_diff ui_index ui_workdir
@@ -228,16 +234,21 @@ proc show_other_diff {path w m scroll_pos} {
228234
$ui_diff conf -state disabled
229235
set diff_active 0
230236
unlock_index
237+
set scroll_pos [lindex $cont_info 0]
231238
if {$scroll_pos ne {}} {
232239
update
233240
$ui_diff yview moveto $scroll_pos
234241
}
235242
ui_ready
243+
set callback [lindex $cont_info 1]
244+
if {$callback ne {}} {
245+
eval $callback
246+
}
236247
return
237248
}
238249
}
239250

240-
proc start_show_diff {scroll_pos {add_opts {}}} {
251+
proc start_show_diff {cont_info {add_opts {}}} {
241252
global file_states file_lists
242253
global is_3way_diff diff_active repo_config
243254
global ui_diff ui_index ui_workdir
@@ -292,12 +303,12 @@ proc start_show_diff {scroll_pos {add_opts {}}} {
292303
-blocking 0 \
293304
-encoding [get_path_encoding $path] \
294305
-translation lf
295-
fileevent $fd readable [list read_diff $fd $scroll_pos]
306+
fileevent $fd readable [list read_diff $fd $cont_info]
296307
}
297308

298-
proc read_diff {fd scroll_pos} {
309+
proc read_diff {fd cont_info} {
299310
global ui_diff diff_active
300-
global is_3way_diff current_diff_header
311+
global is_3way_diff is_conflict_diff current_diff_header
301312
global current_diff_queue
302313

303314
$ui_diff conf -state normal
@@ -345,6 +356,7 @@ proc read_diff {fd scroll_pos} {
345356
{--} {set tags d_--}
346357
{++} {
347358
if {[regexp {^\+\+([<>]{7} |={7})} $line _g op]} {
359+
set is_conflict_diff 1
348360
set line [string replace $line 0 1 { }]
349361
set tags d$op
350362
} else {
@@ -364,6 +376,7 @@ proc read_diff {fd scroll_pos} {
364376
{-} {set tags d_-}
365377
{+} {
366378
if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
379+
set is_conflict_diff 1
367380
set line [string replace $line 0 0 { }]
368381
set tags d$op
369382
} else {
@@ -388,12 +401,13 @@ proc read_diff {fd scroll_pos} {
388401
close $fd
389402

390403
if {$current_diff_queue ne {}} {
391-
advance_diff_queue $scroll_pos
404+
advance_diff_queue $cont_info
392405
return
393406
}
394407

395408
set diff_active 0
396409
unlock_index
410+
set scroll_pos [lindex $cont_info 0]
397411
if {$scroll_pos ne {}} {
398412
update
399413
$ui_diff yview moveto $scroll_pos
@@ -403,6 +417,10 @@ proc read_diff {fd scroll_pos} {
403417
if {[$ui_diff index end] eq {2.0}} {
404418
handle_empty_diff
405419
}
420+
set callback [lindex $cont_info 1]
421+
if {$callback ne {}} {
422+
eval $callback
423+
}
406424
}
407425
}
408426

lib/mergetool.tcl

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@ proc merge_resolve_one {stage} {
55
global current_diff_path
66

77
switch -- $stage {
8-
0 { # Stage without confirmation, to minimize
9-
# disruption of the rerere workflow
10-
merge_add_resolution $current_diff_path
11-
return
12-
}
13-
148
1 { set targetquestion [mc "Force resolution to the base version?"] }
159
2 { set targetquestion [mc "Force resolution to this branch?"] }
1610
3 { set targetquestion [mc "Force resolution to the other branch?"] }
@@ -29,6 +23,33 @@ This operation can be undone only by restarting the merge." \
2923
}
3024
}
3125

26+
proc merge_stage_workdir {path w lno} {
27+
global current_diff_path diff_active
28+
29+
if {$diff_active} return
30+
31+
if {$path ne $current_diff_path} {
32+
show_diff $path $w $lno {} [list do_merge_stage_workdir $path]
33+
} else {
34+
do_merge_stage_workdir $path
35+
}
36+
}
37+
38+
proc do_merge_stage_workdir {path} {
39+
global current_diff_path is_conflict_diff
40+
41+
if {$path ne $current_diff_path} return;
42+
43+
if {$is_conflict_diff} {
44+
if {[ask_popup [mc "File %s seems to have unresolved conflicts, still stage?" \
45+
[short_path $path]]] ne {yes}} {
46+
return
47+
}
48+
}
49+
50+
merge_add_resolution $path
51+
}
52+
3253
proc merge_add_resolution {path} {
3354
global current_diff_path ui_workdir
3455

0 commit comments

Comments
 (0)