-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathref_prepare.awk
163 lines (151 loc) · 4.94 KB
/
ref_prepare.awk
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/awk -f
# ref_prepare - TopGit awk utility script used by tg--awksome
# Copyright (C) 2017,2019 Kyle J. McKay <[email protected]>
# All rights reserved.
# License GPLv2
# ref_prepare
#
# variable arguments (-v):
#
# topbases the full target topbases prefix (e.g. "refs/top-bases")
# headbase the full heads prefix (default is based on topbases value)
# chkblob if set spit out a verification line for this blob first
# depsblob if true include 6th line ".topdeps" blob otherwise not
# msgblob if true include 6th or 7th line ".topmsg" blob otherwise not
# refsfile ref definitions are read from here and used to output hashes
# pckdrefs ref table is in packed-refs format (ignored without refsfile)
# rmrf if true run system rm on refsfile (after reading)
# topdeps if in form <branch>:<hash> substitute <hash> for branch:.topdeps
# topmsg if in form <branch>:<hash> substitute <hash> for branch:.topmsg
# teeout if non-empty output lines are written here too
#
# if refsfile is non-empty, each line of the file it names must be 2+ fields:
#
# <full-ref-name> <full-hash-for-ref> <anything-else-on-line-ignored>
#
# Unless pckdrefs is true and then packed-refs format is expected instead
#
# if refsfile is non-empty, instead of outputting refnames, the name will be
# looked up in the refsfile table and the corresponding hash (or a value
# guaranteed to generate a "missing" result) used
#
# if topdeps is provided (and matches <branch>:<hash> e.g. "t/foo:1234") then
# when depsblob is requested and the current branch is <branch> then instead
# of the normal output, <hash>^{blob} will be output instead which can be
# used to substitute an index or working tree version of a .topdeps file
#
# input must be a list of full ref names one per line
#
# output is 5, 6 or 7 lines per input line matching /^$topbases/
# to feed to:
#
# git cat-file --batch-check='%(objectname) %(objecttype) %(rest)'
#
# if both depsblob and msgblob are true depsblob is output before msgblob and
# both always come after the fixed first 5 lines
#
# if chkblob is not empty an additional line will precede all other output
# that verifies the existence of the chkblob object (and resolves it to a hash)
#
# note that if teeout is non-empty it will always be truncated before starting
# to write the output even if no output is produced; also note that unlike the
# other scripts this one writes to teeout simultaneously with stdout
#
BEGIN { exitcode = "" }
function exitnow(e) { exitcode=e; exit e }
END { if (exitcode != "") exit exitcode }
BEGIN {
sub(/\/+$/, "", topbases)
if (topbases == "") exitnow(2)
topbases = topbases "/"
tblen = length(topbases)
tbdrop = tblen + 1
if (headbase == "") {
if (topbases !~ /^refs\//) exitnow(2)
if (topbases ~ /^refs\/remotes\//) {
if (topbases !~ /^refs\/remotes\/[^\/]+\/[^\/]+\//) exitnow(2)
headbase = topbases
sub(/\/[^\/]+\/$/, "/", headbase)
} else {
headbase = "refs/heads/"
}
} else {
sub(/\/+$/, "", headbase)
if (headbase == "") exitnow(2)
headbase = headbase "/"
}
if (topdeps ~ /^[^ \t\r\n:]+:[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]+$/) {
colonat = index(topdeps, ":")
topdepsbr = substr(topdeps, 1, colonat - 1)
topdepsha = tolower(substr(topdeps, colonat + 1))
}
if (topmsg ~ /^[^ \t\r\n:]+:[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]+$/) {
colonat = index(topmsg, ":")
topmsgbr = substr(topmsg, 1, colonat - 1)
topmsgha = tolower(substr(topmsg, colonat + 1))
}
if (teeout != "") printf "" >teeout
}
function doprint(line) {
if (teeout != "") print line >teeout
print line
}
function quotevar(v) {
gsub(/\047/, "\047\\\047\047", v)
return "\047" v "\047"
}
function rmrefs() {
if (refsfile != "" && rmrf) {
system("rm -f " quotevar(refsfile))
rmrf = 0
refsfile = ""
}
}
END { rmrefs() }
function init(_e) {
if (refsfile != "") {
while ((_e = (getline info <refsfile)) > 0) {
cnt = split(info, scratch, " ")
if (cnt < 2 || scratch[1] == "" || scratch[2] == "") continue
if (pckdrefs) {
swapfield = scratch[1]
scratch[1] = scratch[2]
scratch[2] = swapfield
}
if (scratch[1] ~ /^refs\/./ &&
scratch[2] ~ /^[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]+$/)
refs[scratch[1]] = scratch[2]
}
close(refsfile)
if (_e < 0) exitnow(2)
}
rmrefs()
}
BEGIN {
if (chkblob != "") doprint(chkblob "^{blob}" " check ?")
}
NR == 1 {init()}
function getref(r) { return refsfile == "" ? r : ((r in refs) ? refs[r] : "?") }
NF == 1 && substr($1, 1, tblen) == topbases {
bn = substr($1, tbdrop)
if (bn == "") next
baseref = getref(topbases bn)
headref = getref(headbase bn)
doprint(baseref " " bn " :")
doprint(baseref "^0")
doprint(headref "^0")
doprint(baseref "^{tree}")
doprint(headref "^{tree}")
if (depsblob) {
if (bn == topdepsbr)
doprint(topdepsha "^{blob}")
else
doprint(headref "^{tree}:.topdeps")
}
if (msgblob) {
if (bn == topmsgbr)
doprint(topmsgha "^{blob}")
else
doprint(headref "^{tree}:.topmsg")
}
}