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
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"
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
set status $msg
set prefix $msg
set units $uds
+ set meter {}
}
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 {}}} {