-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit-add-progress.tcl
More file actions
executable file
·114 lines (106 loc) · 2.8 KB
/
Copy pathgit-add-progress.tcl
File metadata and controls
executable file
·114 lines (106 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/tclsh
proc usage {} {
puts stderr "git-add-progress: shows progress while doing 'git add'"
puts stderr "USAGE: git-add-progress [PATH ...]"
exit 1
}
namespace eval gap {
namespace eval v {}
}
proc gap::run {} {
set takeoff [clock clicks -milliseconds]
set d [open [concat "|git status --porcelain" $::argv] r]
upvar #0 gap::state$d state
array set state {paths? {} pathsM {} pathsD {} pathsT {} size 0}
set state(takeoff) $takeoff
updateTime $d
fileevent $d readable [list gap::handleRead $d]
vwait done
set landing [clock clicks -milliseconds]
puts stderr "Done in [formatNum [expr $landing - $takeoff]] ms"
}
proc gap::updateTime {d} {
upvar #0 gap::state$d state
after 1000 gap::updateTime $d
set t [expr {([clock clicks -milliseconds] - $state(takeoff))/1000}]
puts -nonewline stderr "[clock format $t -format %M:%S] "
puts -nonewline stderr "Running 'git status'...\r"
}
proc gap::formatNum {n} {
string reverse [regsub -all "...(?=.)" [string reverse $n] "&,"]
}
proc gap::handleRead {d} {
upvar #0 gap::state$d state
set s [gets $d]
if [fblocked $d] {
return
}
if [regexp {^[AMDT? ]([AMDT? ]) (.+)$} $s -> mode p] {
if {$mode != " "} {
if [regexp {^"(.*)"$} $p -> p] {
set p [subst -nocommands -novariables $p]
}
if {![string match $p */]} {
lappend state(paths$mode)\
[encoding convertfrom utf-8 $p]
incr state(size)
}
}
} elseif [regexp {^[RC] } $s] {
# These are in the index already
} elseif {$s != ""} {
puts stderr "Unparsed: $s"
}
if [eof $d] {
after cancel gap::updateTime $d
puts stderr ""
if [catch {close $d} m] {
puts stderr "$m"
exit 1
}
doGitAdd $d
}
}
proc gap::putsTime {d} {
upvar #0 gap::state$d state
set t [expr {([clock clicks -milliseconds] - $state(takeoff))/1000}]
if {$t >= 24*3600} {
puts -nonewline stderr "[expr {$t/(24*3600)}]d "
}
puts -nonewline stderr\
"[clock format $t -format %H:%M:%S -gmt 1] "
}
proc gap::doGitAdd {d} {
upvar #0 gap::state$d state
set count 0
set opmax 64
set errors {}
set conds {
M changing add ? adding add T changing add D removing {rm --cached}}
foreach {m verb command} $conds {
set start 0
while {$start < [llength $state(paths$m)]} {
set paths [lrange $state(paths$m) $start [expr $start+$opmax-1]]
puts -nonewline stderr\
"[formatNum $count] / [formatNum $state(size)] "
putsTime $d
puts -nonewline stderr "$verb [llength $paths] files... "
if [catch [concat exec git $command $paths] message] {
puts stderr "error: $message"
lappend errors "$m $message"
} else {
puts stderr "[regsub {ing$} $verb ed] $paths"
}
incr start $opmax
incr count [llength $paths]
}
}
if [llength $errors] {
foreach message $errors {
puts stderr " error: $message"
}
puts stderr "[llength $errors] errors"
}
set ::done 1
}
gap::run