7 AWK is great. All hail AWK!
9 Now, some utility functions. parsehdr parse extracts the number of
10 lines (old or new) in the following hunk.
12 function parsehdr(s) {
13 s = gensub(".*,", "", 1, s)
14 s = gensub("^-", "", 1, s)
18 Switches the current file to the one provided. It's a great place where
19 accumulate part of the summary showed at the end and to reset the
22 function switchfile(newfile) {
24 summary = sprintf("%s+%d -%d\t%s\n",
25 summary, add, rem, file)
33 Now, the real "parser". It start in the "out" state
39 Match the start of a diff on the "+++" line.
41 state == "out" && /^\+\+\+ / {
42 nfile = gensub("\\\+\\\+\\\+ ", "", 1)
43 if (nfile == "/dev/null") {
45 When deleting a file, the name will be "/dev/null", but that's not a
46 great name for the stats. Let's use the "old" name instead.
55 Let's save the old name in case it's needed.
57 state == "out" && /^--- / && file == "" {
58 delfile = gensub("--- ", "", 1)
61 Match the start of a hunk and switch the state to "in"
63 state == "out" && /^@@ / {
65 This part is a bit complicated, but all it does is extracting the number
66 of "new" and "old" lines showed in the hunk. A hunk header looks like this
67 (except for the initial '#' character)
69 # @@ -55,7 +55,19 @@ ...
71 So first extract the text inside the pair of "@@"
73 s = gensub("@@ ", "", 1)
74 s = gensub(" @@.*", "", 1, s)
76 and then parse each number.
78 old = gensub(" .*", "", 1, s)
81 new = gensub(".* ", "", 1, s)
84 Don't forget to switch the state of the parser, now we're reading a
90 Keep count of the added and removed line. Also, decrement the "old" and
91 "new" lines when needed, to know when we're done with the hunk.
93 state == "in" && /^ / {
98 state == "in" && /^-/ {
104 state == "in" && /^\+/ {
110 When there are no more "new" and "old" lines to read, go back to the
111 "out" state, ready to read another hunk or another file.
113 state == "in" && old <= 0 && new <= 0 {
117 Don't be a sink! Continue the pipeline so we can further save or apply
122 At the end, print the stats to standard error to avoid mangling the
123 input. Unfortunately, there doesn't seem to be a "built-in" way of
124 printing to stderr other than using the pseudo-device.
130 printf("%s", summary) > "/dev/stderr"
131 printf("+%d -%d\ttotal\n", totadd, totrem) > "/dev/stderr"
136 * cvs -q di | diffstat | tee /tmp/diff | less
137 * git diff | diffstat > /tmp/diff
138 * got di | diffstat | ssh foo 'cd xyz && got patch'