diff options
-rw-r--r-- | lib/checkout_op.tcl | 51 | ||||
-rw-r--r-- | lib/status_bar.tcl | 22 |
2 files changed, 55 insertions, 18 deletions
diff --git a/lib/checkout_op.tcl b/lib/checkout_op.tcl index 844d8e551c..5d02daac6f 100644 --- a/lib/checkout_op.tcl +++ b/lib/checkout_op.tcl @@ -19,6 +19,7 @@ field create 0; # create the branch if it doesn't exist? field reset_ok 0; # did the user agree to reset? field fetch_ok 0; # did the fetch succeed? +field readtree_d {}; # buffered output from read-tree field update_old {}; # was the update-ref call deferred? field reflog_msg {}; # log message for the update-ref call @@ -309,51 +310,69 @@ method _name {} { method _readtree {} { global HEAD - ui_status "Updating working directory to '[_name $this]'..." + set readtree_d {} + $::main_status start \ + "Updating working directory to '[_name $this]'..." \ + {files checked out} + set cmd [list git read-tree] lappend cmd -m lappend cmd -u + lappend cmd -v lappend cmd --exclude-per-directory=.gitignore lappend cmd $HEAD lappend cmd $new_hash - set fd [open "| $cmd" r] + + if {[catch { + set fd [open "| $cmd 2>@1" r] + } err]} { + # Older versions of Tcl 8.4 don't have this 2>@1 IO + # redirect operator. Fallback to |& cat for those. + # + set fd [open "| $cmd |& cat" r] + } + fconfigure $fd -blocking 0 -translation binary fileevent $fd readable [cb _readtree_wait $fd] } method _readtree_wait {fd} { - global selected_commit_type commit_type HEAD MERGE_HEAD PARENT - global current_branch is_detached - global ui_comm + global current_branch + + set buf [read $fd] + $::main_status update_meter $buf + append readtree_d $buf - # -- We never get interesting output on stdout; only stderr. - # - read $fd fconfigure $fd -blocking 1 if {![eof $fd]} { fconfigure $fd -blocking 0 return } - set name [_name $this] - - # -- The working directory wasn't in sync with the index and - # we'd have to overwrite something to make the switch. A - # merge is required. - # - if {[catch {close $fd} err]} { + if {[catch {close $fd}]} { + set err $readtree_d regsub {^fatal: } $err {} err + $::main_status stop "Aborted checkout of '[_name $this]' (file level merging is required)." warn_popup "File level merge required. $err Staying on branch '$current_branch'." - ui_status "Aborted checkout of '$name' (file level merging is required)." unlock_index delete_this return } + $::main_status stop + _after_readtree $this +} + +method _after_readtree {} { + global selected_commit_type commit_type HEAD MERGE_HEAD PARENT + global current_branch is_detached + global ui_comm + + set name [_name $this] set log "checkout: moving" if {!$is_detached} { append log " from $current_branch" diff --git a/lib/status_bar.tcl b/lib/status_bar.tcl index 0e2ac07a5e..72a8fe1fd3 100644 --- a/lib/status_bar.tcl +++ b/lib/status_bar.tcl @@ -9,6 +9,7 @@ field w_c ; # canvas we draw a progress bar into field status {}; # single line of text we show field prefix {}; # text we format into status field units {}; # unit of progress +field meter {}; # current core git progress meter (if active) constructor new {path} { set w $path @@ -45,6 +46,7 @@ method start {msg uds} { set status $msg set prefix $msg set units $uds + set meter {} } method update {have total} { @@ -58,9 +60,25 @@ method update {have total} { $w_c coords bar 0 0 $pdone 20 } -method stop {msg} { +method update_meter {buf} { + append meter $buf + set r [string last "\r" $meter] + if {$r == -1} { + return + } + + set prior [string range $meter 0 $r] + set meter [string range $meter [expr {$r + 1}] end] + if {[regexp "\\((\\d+)/(\\d+)\\)\\s+done\r\$" $prior _j a b]} { + update $this $a $b + } +} + +method stop {{msg {}}} { destroy $w_c - set status $msg + if {$msg ne {}} { + set status $msg + } } method show {msg {test {}}} { |