]>
Commit | Line | Data |
---|---|---|
f522c9b5 SP |
1 | # git-gui index (add/remove) support |
2 | # Copyright (C) 2006, 2007 Shawn Pearce | |
3 | ||
d4e890e5 SP |
4 | proc _delete_indexlock {} { |
5 | if {[catch {file delete -- [gitdir index.lock]} err]} { | |
6 | error_popup [strcat [mc "Unable to unlock the index."] "\n\n$err"] | |
7 | } | |
8 | } | |
9 | ||
10 | proc _close_updateindex {fd after} { | |
c80d7be5 | 11 | global use_ttk NS |
d4e890e5 SP |
12 | fconfigure $fd -blocking 1 |
13 | if {[catch {close $fd} err]} { | |
14 | set w .indexfried | |
c80d7be5 PT |
15 | Dialog $w |
16 | wm withdraw $w | |
d4e890e5 SP |
17 | wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]] |
18 | wm geometry $w "+[winfo rootx .]+[winfo rooty .]" | |
ea888f84 PT |
19 | set s [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."] |
20 | text $w.msg -yscrollcommand [list $w.vs set] \ | |
21 | -width [string length $s] -relief flat \ | |
22 | -borderwidth 0 -highlightthickness 0 \ | |
c80d7be5 | 23 | -background [get_bg_color $w] |
ea888f84 | 24 | $w.msg tag configure bold -font font_uibold -justify center |
c80d7be5 | 25 | ${NS}::scrollbar $w.vs -command [list $w.msg yview] |
ea888f84 PT |
26 | $w.msg insert end $s bold \n\n$err {} |
27 | $w.msg configure -state disabled | |
28 | ||
c80d7be5 | 29 | ${NS}::button $w.continue \ |
d4e890e5 SP |
30 | -text [mc "Continue"] \ |
31 | -command [list destroy $w] | |
c80d7be5 | 32 | ${NS}::button $w.unlock \ |
d4e890e5 SP |
33 | -text [mc "Unlock Index"] \ |
34 | -command "destroy $w; _delete_indexlock" | |
ea888f84 PT |
35 | grid $w.msg - $w.vs -sticky news |
36 | grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2 | |
37 | grid columnconfigure $w 0 -weight 1 | |
38 | grid rowconfigure $w 0 -weight 1 | |
d4e890e5 SP |
39 | |
40 | wm protocol $w WM_DELETE_WINDOW update | |
ea888f84 | 41 | bind $w.continue <Visibility> " |
d4e890e5 | 42 | grab $w |
ea888f84 | 43 | focus %W |
d4e890e5 | 44 | " |
c80d7be5 | 45 | wm deiconify $w |
d4e890e5 SP |
46 | tkwait window $w |
47 | ||
48 | $::main_status stop | |
49 | unlock_index | |
50 | rescan $after 0 | |
51 | return | |
52 | } | |
53 | ||
f4e9996b | 54 | $::main_status stop |
d4e890e5 SP |
55 | unlock_index |
56 | uplevel #0 $after | |
57 | } | |
58 | ||
f522c9b5 | 59 | proc update_indexinfo {msg pathList after} { |
699d5601 | 60 | global update_index_cp |
f522c9b5 SP |
61 | |
62 | if {![lock_index update]} return | |
63 | ||
64 | set update_index_cp 0 | |
65 | set pathList [lsort $pathList] | |
66 | set totalCnt [llength $pathList] | |
67 | set batch [expr {int($totalCnt * .01) + 1}] | |
68 | if {$batch > 25} {set batch 25} | |
69 | ||
1cad232f | 70 | $::main_status start $msg [mc "files"] |
0b812616 | 71 | set fd [git_write update-index -z --index-info] |
f522c9b5 SP |
72 | fconfigure $fd \ |
73 | -blocking 0 \ | |
74 | -buffering full \ | |
75 | -buffersize 512 \ | |
76 | -encoding binary \ | |
77 | -translation binary | |
78 | fileevent $fd writable [list \ | |
79 | write_update_indexinfo \ | |
80 | $fd \ | |
81 | $pathList \ | |
82 | $totalCnt \ | |
83 | $batch \ | |
f522c9b5 SP |
84 | $after \ |
85 | ] | |
86 | } | |
87 | ||
1cad232f | 88 | proc write_update_indexinfo {fd pathList totalCnt batch after} { |
699d5601 | 89 | global update_index_cp |
f522c9b5 SP |
90 | global file_states current_diff_path |
91 | ||
92 | if {$update_index_cp >= $totalCnt} { | |
d4e890e5 | 93 | _close_updateindex $fd $after |
f522c9b5 SP |
94 | return |
95 | } | |
96 | ||
97 | for {set i $batch} \ | |
98 | {$update_index_cp < $totalCnt && $i > 0} \ | |
99 | {incr i -1} { | |
100 | set path [lindex $pathList $update_index_cp] | |
101 | incr update_index_cp | |
102 | ||
103 | set s $file_states($path) | |
104 | switch -glob -- [lindex $s 0] { | |
105 | A? {set new _O} | |
106 | M? {set new _M} | |
e681cb7d | 107 | T_ {set new _T} |
f522c9b5 SP |
108 | D_ {set new _D} |
109 | D? {set new _?} | |
110 | ?? {continue} | |
111 | } | |
112 | set info [lindex $s 2] | |
113 | if {$info eq {}} continue | |
114 | ||
115 | puts -nonewline $fd "$info\t[encoding convertto $path]\0" | |
116 | display_file $path $new | |
117 | } | |
118 | ||
1cad232f | 119 | $::main_status update $update_index_cp $totalCnt |
f522c9b5 SP |
120 | } |
121 | ||
122 | proc update_index {msg pathList after} { | |
699d5601 | 123 | global update_index_cp |
f522c9b5 SP |
124 | |
125 | if {![lock_index update]} return | |
126 | ||
127 | set update_index_cp 0 | |
128 | set pathList [lsort $pathList] | |
129 | set totalCnt [llength $pathList] | |
130 | set batch [expr {int($totalCnt * .01) + 1}] | |
131 | if {$batch > 25} {set batch 25} | |
132 | ||
1cad232f | 133 | $::main_status start $msg [mc "files"] |
0b812616 | 134 | set fd [git_write update-index --add --remove -z --stdin] |
f522c9b5 SP |
135 | fconfigure $fd \ |
136 | -blocking 0 \ | |
137 | -buffering full \ | |
138 | -buffersize 512 \ | |
139 | -encoding binary \ | |
140 | -translation binary | |
141 | fileevent $fd writable [list \ | |
142 | write_update_index \ | |
143 | $fd \ | |
144 | $pathList \ | |
145 | $totalCnt \ | |
146 | $batch \ | |
f522c9b5 SP |
147 | $after \ |
148 | ] | |
149 | } | |
150 | ||
1cad232f | 151 | proc write_update_index {fd pathList totalCnt batch after} { |
699d5601 | 152 | global update_index_cp |
f522c9b5 SP |
153 | global file_states current_diff_path |
154 | ||
155 | if {$update_index_cp >= $totalCnt} { | |
d4e890e5 | 156 | _close_updateindex $fd $after |
f522c9b5 SP |
157 | return |
158 | } | |
159 | ||
160 | for {set i $batch} \ | |
161 | {$update_index_cp < $totalCnt && $i > 0} \ | |
162 | {incr i -1} { | |
163 | set path [lindex $pathList $update_index_cp] | |
164 | incr update_index_cp | |
165 | ||
166 | switch -glob -- [lindex $file_states($path) 0] { | |
167 | AD {set new __} | |
168 | ?D {set new D_} | |
169 | _O - | |
170 | AM {set new A_} | |
e681cb7d | 171 | _T {set new T_} |
ff515d81 | 172 | _U - |
f522c9b5 SP |
173 | U? { |
174 | if {[file exists $path]} { | |
175 | set new M_ | |
176 | } else { | |
177 | set new D_ | |
178 | } | |
179 | } | |
180 | ?M {set new M_} | |
181 | ?? {continue} | |
182 | } | |
183 | puts -nonewline $fd "[encoding convertto $path]\0" | |
184 | display_file $path $new | |
185 | } | |
186 | ||
1cad232f | 187 | $::main_status update $update_index_cp $totalCnt |
f522c9b5 SP |
188 | } |
189 | ||
190 | proc checkout_index {msg pathList after} { | |
699d5601 | 191 | global update_index_cp |
f522c9b5 SP |
192 | |
193 | if {![lock_index update]} return | |
194 | ||
195 | set update_index_cp 0 | |
196 | set pathList [lsort $pathList] | |
197 | set totalCnt [llength $pathList] | |
198 | set batch [expr {int($totalCnt * .01) + 1}] | |
199 | if {$batch > 25} {set batch 25} | |
200 | ||
1cad232f | 201 | $::main_status start $msg [mc "files"] |
0b812616 SP |
202 | set fd [git_write checkout-index \ |
203 | --index \ | |
204 | --quiet \ | |
205 | --force \ | |
206 | -z \ | |
207 | --stdin \ | |
208 | ] | |
f522c9b5 SP |
209 | fconfigure $fd \ |
210 | -blocking 0 \ | |
211 | -buffering full \ | |
212 | -buffersize 512 \ | |
213 | -encoding binary \ | |
214 | -translation binary | |
215 | fileevent $fd writable [list \ | |
216 | write_checkout_index \ | |
217 | $fd \ | |
218 | $pathList \ | |
219 | $totalCnt \ | |
220 | $batch \ | |
f522c9b5 SP |
221 | $after \ |
222 | ] | |
223 | } | |
224 | ||
1cad232f | 225 | proc write_checkout_index {fd pathList totalCnt batch after} { |
699d5601 | 226 | global update_index_cp |
f522c9b5 SP |
227 | global file_states current_diff_path |
228 | ||
229 | if {$update_index_cp >= $totalCnt} { | |
d4e890e5 | 230 | _close_updateindex $fd $after |
f522c9b5 SP |
231 | return |
232 | } | |
233 | ||
234 | for {set i $batch} \ | |
235 | {$update_index_cp < $totalCnt && $i > 0} \ | |
236 | {incr i -1} { | |
237 | set path [lindex $pathList $update_index_cp] | |
238 | incr update_index_cp | |
239 | switch -glob -- [lindex $file_states($path) 0] { | |
240 | U? {continue} | |
241 | ?M - | |
e681cb7d | 242 | ?T - |
f522c9b5 SP |
243 | ?D { |
244 | puts -nonewline $fd "[encoding convertto $path]\0" | |
245 | display_file $path ?_ | |
246 | } | |
247 | } | |
248 | } | |
249 | ||
1cad232f | 250 | $::main_status update $update_index_cp $totalCnt |
f522c9b5 SP |
251 | } |
252 | ||
253 | proc unstage_helper {txt paths} { | |
254 | global file_states current_diff_path | |
255 | ||
256 | if {![lock_index begin-update]} return | |
257 | ||
258 | set pathList [list] | |
259 | set after {} | |
260 | foreach path $paths { | |
261 | switch -glob -- [lindex $file_states($path) 0] { | |
262 | A? - | |
263 | M? - | |
e681cb7d | 264 | T_ - |
f522c9b5 SP |
265 | D? { |
266 | lappend pathList $path | |
267 | if {$path eq $current_diff_path} { | |
268 | set after {reshow_diff;} | |
269 | } | |
270 | } | |
271 | } | |
272 | } | |
273 | if {$pathList eq {}} { | |
274 | unlock_index | |
275 | } else { | |
276 | update_indexinfo \ | |
277 | $txt \ | |
278 | $pathList \ | |
699d5601 | 279 | [concat $after [list ui_ready]] |
f522c9b5 SP |
280 | } |
281 | } | |
282 | ||
283 | proc do_unstage_selection {} { | |
284 | global current_diff_path selected_paths | |
285 | ||
286 | if {[array size selected_paths] > 0} { | |
287 | unstage_helper \ | |
288 | {Unstaging selected files from commit} \ | |
289 | [array names selected_paths] | |
290 | } elseif {$current_diff_path ne {}} { | |
291 | unstage_helper \ | |
c8c4854b | 292 | [mc "Unstaging %s from commit" [short_path $current_diff_path]] \ |
f522c9b5 SP |
293 | [list $current_diff_path] |
294 | } | |
295 | } | |
296 | ||
297 | proc add_helper {txt paths} { | |
298 | global file_states current_diff_path | |
299 | ||
300 | if {![lock_index begin-update]} return | |
301 | ||
302 | set pathList [list] | |
303 | set after {} | |
304 | foreach path $paths { | |
305 | switch -glob -- [lindex $file_states($path) 0] { | |
0aea2842 AG |
306 | _U - |
307 | U? { | |
308 | if {$path eq $current_diff_path} { | |
309 | unlock_index | |
310 | merge_stage_workdir $path | |
311 | return | |
312 | } | |
313 | } | |
f522c9b5 SP |
314 | _O - |
315 | ?M - | |
316 | ?D - | |
0aea2842 | 317 | ?T { |
f522c9b5 SP |
318 | lappend pathList $path |
319 | if {$path eq $current_diff_path} { | |
320 | set after {reshow_diff;} | |
321 | } | |
322 | } | |
323 | } | |
324 | } | |
325 | if {$pathList eq {}} { | |
326 | unlock_index | |
327 | } else { | |
328 | update_index \ | |
329 | $txt \ | |
330 | $pathList \ | |
5e6d7768 | 331 | [concat $after {ui_status [mc "Ready to commit."]}] |
f522c9b5 SP |
332 | } |
333 | } | |
334 | ||
335 | proc do_add_selection {} { | |
336 | global current_diff_path selected_paths | |
337 | ||
338 | if {[array size selected_paths] > 0} { | |
339 | add_helper \ | |
340 | {Adding selected files} \ | |
341 | [array names selected_paths] | |
342 | } elseif {$current_diff_path ne {}} { | |
343 | add_helper \ | |
c8c4854b | 344 | [mc "Adding %s" [short_path $current_diff_path]] \ |
f522c9b5 SP |
345 | [list $current_diff_path] |
346 | } | |
347 | } | |
348 | ||
349 | proc do_add_all {} { | |
350 | global file_states | |
351 | ||
352 | set paths [list] | |
353 | foreach path [array names file_states] { | |
354 | switch -glob -- [lindex $file_states($path) 0] { | |
355 | U? {continue} | |
356 | ?M - | |
e681cb7d | 357 | ?T - |
f522c9b5 SP |
358 | ?D {lappend paths $path} |
359 | } | |
360 | } | |
361 | add_helper {Adding all changed files} $paths | |
362 | } | |
363 | ||
364 | proc revert_helper {txt paths} { | |
365 | global file_states current_diff_path | |
366 | ||
367 | if {![lock_index begin-update]} return | |
368 | ||
369 | set pathList [list] | |
370 | set after {} | |
371 | foreach path $paths { | |
372 | switch -glob -- [lindex $file_states($path) 0] { | |
373 | U? {continue} | |
374 | ?M - | |
e681cb7d | 375 | ?T - |
f522c9b5 SP |
376 | ?D { |
377 | lappend pathList $path | |
378 | if {$path eq $current_diff_path} { | |
379 | set after {reshow_diff;} | |
380 | } | |
381 | } | |
382 | } | |
383 | } | |
384 | ||
1ac17950 CS |
385 | |
386 | # Split question between singular and plural cases, because | |
387 | # such distinction is needed in some languages. Previously, the | |
388 | # code used "Revert changes in" for both, but that can't work | |
389 | # in languages where 'in' must be combined with word from | |
390 | # rest of string (in diffrent way for both cases of course). | |
391 | # | |
392 | # FIXME: Unfortunately, even that isn't enough in some languages | |
393 | # as they have quite complex plural-form rules. Unfortunately, | |
394 | # msgcat doesn't seem to support that kind of string translation. | |
395 | # | |
f522c9b5 SP |
396 | set n [llength $pathList] |
397 | if {$n == 0} { | |
398 | unlock_index | |
399 | return | |
400 | } elseif {$n == 1} { | |
1ac17950 | 401 | set query [mc "Revert changes in file %s?" [short_path [lindex $pathList]]] |
f522c9b5 | 402 | } else { |
1ac17950 | 403 | set query [mc "Revert changes in these %i files?" $n] |
f522c9b5 SP |
404 | } |
405 | ||
406 | set reply [tk_dialog \ | |
407 | .confirm_revert \ | |
408 | "[appname] ([reponame])" \ | |
d4544601 CS |
409 | "$query |
410 | ||
411 | [mc "Any unstaged changes will be permanently lost by the revert."]" \ | |
f522c9b5 SP |
412 | question \ |
413 | 1 \ | |
1ac17950 CS |
414 | [mc "Do Nothing"] \ |
415 | [mc "Revert Changes"] \ | |
f522c9b5 SP |
416 | ] |
417 | if {$reply == 1} { | |
418 | checkout_index \ | |
419 | $txt \ | |
420 | $pathList \ | |
699d5601 | 421 | [concat $after [list ui_ready]] |
f522c9b5 SP |
422 | } else { |
423 | unlock_index | |
424 | } | |
425 | } | |
426 | ||
427 | proc do_revert_selection {} { | |
428 | global current_diff_path selected_paths | |
429 | ||
430 | if {[array size selected_paths] > 0} { | |
431 | revert_helper \ | |
700e5603 | 432 | [mc "Reverting selected files"] \ |
f522c9b5 SP |
433 | [array names selected_paths] |
434 | } elseif {$current_diff_path ne {}} { | |
435 | revert_helper \ | |
700e5603 | 436 | [mc "Reverting %s" [short_path $current_diff_path]] \ |
f522c9b5 SP |
437 | [list $current_diff_path] |
438 | } | |
439 | } | |
440 | ||
441 | proc do_select_commit_type {} { | |
442 | global commit_type selected_commit_type | |
443 | ||
444 | if {$selected_commit_type eq {new} | |
445 | && [string match amend* $commit_type]} { | |
446 | create_new_commit | |
447 | } elseif {$selected_commit_type eq {amend} | |
448 | && ![string match amend* $commit_type]} { | |
449 | load_last_commit | |
450 | ||
451 | # The amend request was rejected... | |
452 | # | |
453 | if {![string match amend* $commit_type]} { | |
454 | set selected_commit_type new | |
455 | } | |
456 | } | |
457 | } |