From e734817db0af028f2aea356b44c74b7ac51023cd Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 23 Nov 2006 21:40:45 -0500 Subject: [PATCH] git-gui: Added revert changes command. Users sometimes need to be able to throw away locally modified files in order to go back to the last committed version of that file. To perform a revert the user must first uninclude each file from the new commit as the working file must at least partially match the index, and we use git-checkout-index to update the working directory. Signed-off-by: Shawn O. Pearce --- git-gui | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 177 insertions(+), 7 deletions(-) diff --git a/git-gui b/git-gui index 8246037fa..34a1daa44 100755 --- a/git-gui +++ b/git-gui @@ -1277,9 +1277,26 @@ proc display_file {path state} { set old_w [mapcol $old_m $path] set new_icon [mapicon $new_m $path] + if {$new_m eq {__}} { + set lno [lsearch -sorted $file_lists($old_w) $path] + if {$lno >= 0} { + set file_lists($old_w) \ + [lreplace $file_lists($old_w) $lno $lno] + incr lno + $old_w conf -state normal + $old_w delete $lno.0 [expr {$lno + 1}].0 + $old_w conf -state disabled + } + unset file_states($path) + catch {unset selected_paths($path)} + return + } + if {$new_w ne $old_w} { set lno [lsearch -sorted $file_lists($old_w) $path] if {$lno >= 0} { + set file_lists($old_w) \ + [lreplace $file_lists($old_w) $lno $lno] incr lno $old_w conf -state normal $old_w delete $lno.0 [expr {$lno + 1}].0 @@ -1500,6 +1517,84 @@ proc write_update_index {fd pathList totalCnt batch msg after} { [expr {100.0 * $update_index_cp / $totalCnt}]] } +proc checkout_index {msg pathList after} { + global update_index_cp ui_status_value + + if {![lock_index update]} return + + set update_index_cp 0 + set pathList [lsort $pathList] + set totalCnt [llength $pathList] + set batch [expr {int($totalCnt * .01) + 1}] + if {$batch > 25} {set batch 25} + + set ui_status_value [format \ + "$msg... %i/%i files (%.2f%%)" \ + $update_index_cp \ + $totalCnt \ + 0.0] + set cmd [list git checkout-index] + lappend cmd --index + lappend cmd --quiet + lappend cmd --force + lappend cmd -z + lappend cmd --stdin + set fd [open "| $cmd " w] + fconfigure $fd \ + -blocking 0 \ + -buffering full \ + -buffersize 512 \ + -translation binary + fileevent $fd writable [list \ + write_checkout_index \ + $fd \ + $pathList \ + $totalCnt \ + $batch \ + $msg \ + $after \ + ] +} + +proc write_checkout_index {fd pathList totalCnt batch msg after} { + global update_index_cp ui_status_value + global file_states current_diff + + if {$update_index_cp >= $totalCnt} { + close $fd + unlock_index + uplevel #0 $after + return + } + + for {set i $batch} \ + {$update_index_cp < $totalCnt && $i > 0} \ + {incr i -1} { + set path [lindex $pathList $update_index_cp] + incr update_index_cp + + switch -glob -- [lindex $file_states($path) 0] { + AM - + AD {set new A_} + MM - + MD {set new M_} + _M - + _D {set new __} + ?? {continue} + } + + puts -nonewline $fd $path + puts -nonewline $fd "\0" + display_file $path $new + } + + set ui_status_value [format \ + "$msg... %i/%i files (%.2f%%)" \ + $update_index_cp \ + $totalCnt \ + [expr {100.0 * $update_index_cp / $totalCnt}]] +} + ###################################################################### ## ## remote management @@ -1708,11 +1803,12 @@ foreach i { {_M i mod "Modified"} {M_ i fulltick "Included in commit"} {MM i parttick "Partially included"} + {MD i question "Included (but gone)"} {_O o plain "Untracked"} {A_ o fulltick "Added by commit"} {AM o parttick "Partially added"} - {AD o question "Added (but now gone)"} + {AD o question "Added (but gone)"} {_D i question "Missing"} {DD i removed "Removed by commit"} @@ -2159,6 +2255,74 @@ proc do_include_all {} { $paths } +proc revert_helper {txt paths} { + global file_states current_diff + + if {![lock_index begin-update]} return + + set pathList [list] + set after {} + foreach path $paths { + switch -glob -- [lindex $file_states($path) 0] { + AM - + AD - + MM - + MD - + _M - + _D { + lappend pathList $path + if {$path eq $current_diff} { + set after {reshow_diff;} + } + } + } + } + + set n [llength $pathList] + if {$n == 0} { + unlock_index + return + } elseif {$n == 1} { + set s "[short_path [lindex $pathList]]" + } else { + set s "these $n files" + } + + set reply [tk_dialog \ + .confirm_revert \ + "title" \ + "Revert unincluded changes in $s? + +Any unincluded changes will be permanently lost by the revert." \ + questhead \ + 1 \ + {Do Nothing} \ + {Revert Changes} \ + ] + if {$reply == 1} { + checkout_index \ + $txt \ + $pathList \ + [concat $after {set ui_status_value {Ready.}}] + } else { + unlock_index + } +} + +proc do_revert_selection {} { + global current_diff selected_paths + + if {[array size selected_paths] > 0} { + revert_helper \ + {Reverting selected files} \ + [array names selected_paths] + } elseif {$current_diff ne {}} { + revert_helper \ + "Reverting [short_path $current_diff]" \ + [list $current_diff] + } +} + proc do_signoff {} { global ui_comm @@ -2818,12 +2982,6 @@ lappend disable_on_lock \ lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] -.mbar.commit add command -label {Remove From Commit} \ - -command do_remove_selection \ - -font font_ui -lappend disable_on_lock \ - [list .mbar.commit entryconf [.mbar.commit index last] -state] - .mbar.commit add command -label {Include In Commit} \ -command do_include_selection \ -font font_ui @@ -2837,6 +2995,18 @@ lappend disable_on_lock \ lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] +.mbar.commit add command -label {Remove From Commit} \ + -command do_remove_selection \ + -font font_ui +lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + +.mbar.commit add command -label {Revert Changes} \ + -command do_revert_selection \ + -font font_ui +lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + .mbar.commit add separator .mbar.commit add command -label {Sign Off} \ -- 2.30.2