@matheusbsbs / matheus-bagliano / commits / 3e34838caf
Fork 0

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 2fe5b2ee42897a3acc78e5ddaace3775eb2713ca (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>

Alexander Gavrilov committed Sep 20, 2008 at 12:19 UTC 3e34838caf796e67c057a136d1fdfe1d4286a003
3 files changed +70 -33
git-gui.sh
+8 -10
@@ -1059,6 +1059,7 @@ set current_branch {}
1059 set is_detached 0
1060 set current_diff_path {}
1061 set is_3way_diff 0
1062 +set is_conflict_diff 0
1063 set selected_commit_type new
1064
1065 set nullid "0000000000000000000000000000000000000000"
@@ -2078,19 +2079,21 @@ proc toggle_or_diff {w x y} {
2079 $ui_index tag remove in_sel 0.0 end
2080 $ui_workdir tag remove in_sel 0.0 end
2081
2081 - # Do not stage files with conflicts
2082 + # Determine the state of the file
2083 if {[info exists file_states($path)]} {
2084 set state [lindex $file_states($path) 0]
2085 } else {
2086 set state {__}
2087 }
2088
2088 - if {[string first {U} $state] >= 0} {
2089 - set col 1
2090 - }
2091 -
2089 # Restage the file, or simply show the diff
2090 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 +
2097 if {[string index $state 1] eq {O}} {
2098 set mmask {}
2099 } else {
@@ -3057,11 +3060,6 @@ $ctxmmg add command \
3060 -command {merge_resolve_one 1}
3061 lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
3062 $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
3063 create_common_diff_popup $ctxmmg
3064
3065 proc popup_diff_menu {ctxm ctxmmg x y X Y} {
lib/diff.tcl
+35 -17
@@ -69,9 +69,9 @@ A rescan will be automatically started to find other files which may have the sa
69 rescan ui_ready 0
70 }
71
72 -proc show_diff {path w {lno {}} {scroll_pos {}}} {
72 +proc show_diff {path w {lno {}} {scroll_pos {}} {callback {}}} {
73 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
75 global ui_diff ui_index ui_workdir
76 global current_diff_path current_diff_side current_diff_header
77 global current_diff_queue
@@ -92,36 +92,42 @@ proc show_diff {path w {lno {}} {scroll_pos {}}} {
92
93 set s $file_states($path)
94 set m [lindex $s 0]
95 + set is_conflict_diff 0
96 set current_diff_path $path
97 set current_diff_side $w
98 set current_diff_queue {}
99 ui_status [mc "Loading diff of %s..." [escape_path $path]]
100
101 + set cont_info [list $scroll_pos $callback]
102 +
103 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]
105 } elseif {$m eq {_O}} {
103 - show_other_diff $path $w $m $scroll_pos
106 + show_other_diff $path $w $m $cont_info
107 } else {
105 - start_show_diff $scroll_pos
108 + start_show_diff $cont_info
109 }
110 }
111
109 -proc show_unmerged_diff {scroll_pos} {
112 +proc show_unmerged_diff {cont_info} {
113 global current_diff_path current_diff_side
111 - global merge_stages ui_diff
114 + global merge_stages ui_diff is_conflict_diff
115 global current_diff_queue
116
117 if {$merge_stages(2) eq {}} {
118 + set is_conflict_diff 1
119 lappend current_diff_queue \
120 [list "LOCAL: deleted\nREMOTE:\n" d======= \
121 [list ":1:$current_diff_path" ":3:$current_diff_path"]]
122 } elseif {$merge_stages(3) eq {}} {
123 + set is_conflict_diff 1
124 lappend current_diff_queue \
125 [list "REMOTE: deleted\nLOCAL:\n" d======= \
126 [list ":1:$current_diff_path" ":2:$current_diff_path"]]
127 } elseif {[lindex $merge_stages(1) 0] eq {120000}
128 || [lindex $merge_stages(2) 0] eq {120000}
129 || [lindex $merge_stages(3) 0] eq {120000}} {
130 + set is_conflict_diff 1
131 lappend current_diff_queue \
132 [list "LOCAL:\n" d======= \
133 [list ":1:$current_diff_path" ":2:$current_diff_path"]]
@@ -129,14 +135,14 @@ proc show_unmerged_diff {scroll_pos} {
135 [list "REMOTE:\n" d======= \
136 [list ":1:$current_diff_path" ":3:$current_diff_path"]]
137 } else {
132 - start_show_diff $scroll_pos
138 + start_show_diff $cont_info
139 return
140 }
141
136 - advance_diff_queue $scroll_pos
142 + advance_diff_queue $cont_info
143 }
144
139 -proc advance_diff_queue {scroll_pos} {
145 +proc advance_diff_queue {cont_info} {
146 global current_diff_queue ui_diff
147
148 set item [lindex $current_diff_queue 0]
@@ -146,10 +152,10 @@ proc advance_diff_queue {scroll_pos} {
152 $ui_diff insert end [lindex $item 0] [lindex $item 1]
153 $ui_diff conf -state disabled
154
149 - start_show_diff $scroll_pos [lindex $item 2]
155 + start_show_diff $cont_info [lindex $item 2]
156 }
157
152 -proc show_other_diff {path w m scroll_pos} {
158 +proc show_other_diff {path w m cont_info} {
159 global file_states file_lists
160 global is_3way_diff diff_active repo_config
161 global ui_diff ui_index ui_workdir
@@ -228,16 +234,21 @@ proc show_other_diff {path w m scroll_pos} {
234 $ui_diff conf -state disabled
235 set diff_active 0
236 unlock_index
237 + set scroll_pos [lindex $cont_info 0]
238 if {$scroll_pos ne {}} {
239 update
240 $ui_diff yview moveto $scroll_pos
241 }
242 ui_ready
243 + set callback [lindex $cont_info 1]
244 + if {$callback ne {}} {
245 + eval $callback
246 + }
247 return
248 }
249 }
250
240 -proc start_show_diff {scroll_pos {add_opts {}}} {
251 +proc start_show_diff {cont_info {add_opts {}}} {
252 global file_states file_lists
253 global is_3way_diff diff_active repo_config
254 global ui_diff ui_index ui_workdir
@@ -292,12 +303,12 @@ proc start_show_diff {scroll_pos {add_opts {}}} {
303 -blocking 0 \
304 -encoding [get_path_encoding $path] \
305 -translation lf
295 - fileevent $fd readable [list read_diff $fd $scroll_pos]
306 + fileevent $fd readable [list read_diff $fd $cont_info]
307 }
308
298 -proc read_diff {fd scroll_pos} {
309 +proc read_diff {fd cont_info} {
310 global ui_diff diff_active
300 - global is_3way_diff current_diff_header
311 + global is_3way_diff is_conflict_diff current_diff_header
312 global current_diff_queue
313
314 $ui_diff conf -state normal
@@ -345,6 +356,7 @@ proc read_diff {fd scroll_pos} {
356 {--} {set tags d_--}
357 {++} {
358 if {[regexp {^\+\+([<>]{7} |={7})} $line _g op]} {
359 + set is_conflict_diff 1
360 set line [string replace $line 0 1 { }]
361 set tags d$op
362 } else {
@@ -364,6 +376,7 @@ proc read_diff {fd scroll_pos} {
376 {-} {set tags d_-}
377 {+} {
378 if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
379 + set is_conflict_diff 1
380 set line [string replace $line 0 0 { }]
381 set tags d$op
382 } else {
@@ -388,12 +401,13 @@ proc read_diff {fd scroll_pos} {
401 close $fd
402
403 if {$current_diff_queue ne {}} {
391 - advance_diff_queue $scroll_pos
404 + advance_diff_queue $cont_info
405 return
406 }
407
408 set diff_active 0
409 unlock_index
410 + set scroll_pos [lindex $cont_info 0]
411 if {$scroll_pos ne {}} {
412 update
413 $ui_diff yview moveto $scroll_pos
@@ -403,6 +417,10 @@ proc read_diff {fd scroll_pos} {
417 if {[$ui_diff index end] eq {2.0}} {
418 handle_empty_diff
419 }
420 + set callback [lindex $cont_info 1]
421 + if {$callback ne {}} {
422 + eval $callback
423 + }
424 }
425 }
426
lib/mergetool.tcl
+27 -6
@@ -5,12 +5,6 @@ proc merge_resolve_one {stage} {
5 global current_diff_path
6
7 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 -
8 1 { set targetquestion [mc "Force resolution to the base version?"] }
9 2 { set targetquestion [mc "Force resolution to this branch?"] }
10 3 { set targetquestion [mc "Force resolution to the other branch?"] }
@@ -29,6 +23,33 @@ This operation can be undone only by restarting the merge." \
23 }
24 }
25
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 +
53 proc merge_add_resolution {path} {
54 global current_diff_path ui_workdir
55