README_DOCS.rst: wordsmith some of the commentary
[topgit/pro.git] / awk / ref_prefixes.awk
blob62f50d311408fd4292cf117520e6708543a7c534
1 #!/usr/bin/awk -f
3 # ref_prefixes - TopGit awk utility script used by tg--awksome
4 # Copyright (C) 2017,2019,2021 Kyle J. McKay <mackyle@gmail.com>
5 # All rights reserved.
6 # License GPLv2
8 # ref_prefixes
10 # pckdrefs input refs are in packed-refs format (instead of just full ref name)
11 # prefix1 first ref prefix to look for and the default
12 # prefix2 second ref prefix to look for
13 # prefixh ignore prefix1/prefix2 matches without corresponding prefixh
14 # noerr instead of error 65 (EX_DATAERR) output default (prefix1) when both
15 # nodef instead of defaulting to prefix1, exit with error 66 (EX_NOINPUT)
17 # input is a list of full ref names one per line; if pckdrefs is true then the
18 # second field of the line will be used otherwise the first
20 # prefix1 may not be a prefix of prefix2 or vice versa
21 # if prefix1, prefix2 and/or prefixh are invalid exit status will be 2
23 # if prefixh is non-empty then matches for prefix1 or prefix2 must also match
24 # another line from the input after replacing the prefix1/prefix2 part with
25 # prefixh or they are discarded and do not participate in choosing the output
27 # note that the input need not be sorted in any particular order or be
28 # duplicate free even when prefixh is non-empty
30 # a prefix will only match at a "/" boundary
32 # ontput according to this table:
34 # any refs match any refs match noerr nodef exit output
35 # prefix1 prefix prefix2 prefix value value status value
36 # -------------- -------------- ----- ------ ------ -------
37 # no no any false 0 prefix1
38 # no no any true 66
39 # yes no any any 0 prefix1
40 # no yes any any 0 prefix2
41 # yes yes false any 65
42 # yes yes true any 0 prefix1
44 # there is no output when exit status is not 0
45 # the output value, if any, will have any trailing slash(es) removed from it
48 BEGIN { exitcode = "" }
49 function exitnow(e) { exitcode=e; exit e }
50 END { if (exitcode != "") exit exitcode }
52 BEGIN {
53 sub(/\/+$/, "", prefix1)
54 sub(/\/+$/, "", prefix2)
55 sub(/\/+$/, "", prefixh)
56 if (prefix1 == "" || prefix2 == "" ||
57 prefix1 == prefix2 ||
58 prefix1 == prefixh || prefix2 == prefixh)
59 exitnow(2)
60 if (substr(prefix1, 1, 5) != "refs/" ||
61 substr(prefix2, 1, 5) != "refs/" ||
62 (prefixh != "" && substr(prefixh, 1, 5) != "refs/"))
63 exitnow(2)
64 plen1 = length(prefix1)
65 plen2 = length(prefix2)
66 plenh = length(prefixh)
67 if (plen1 < 6 || plen2 < 6) exitnow(2)
68 prefix1 = prefix1 "/"
69 prefix2 = prefix2 "/"
70 ++plen1
71 ++plen2
72 if (prefixh != "") {
73 prefixh = prefixh "/"
74 ++plenh
76 if (plen1 < plen2 && plen1 == substr(plen2, 1, plen1)) exitnow(2)
77 if (plen1 > plen2 && substr(plen1, 1, plen2) == plen2) exitnow(2)
78 sawp1 = 0
79 sawp2 = 0
80 cnt = 0
83 function check(r) {
84 if (length(r) > plen1 && prefix1 == substr(r, 1, plen1)) {
85 if (prefixh && !(substr(r, plen1) in heads)) return 0
86 sawp1 = 1
87 } else if (length(r) > plen2 && prefix2 == substr(r, 1, plen2)) {
88 if (prefixh && !(substr(r, plen2) in heads)) return 0
89 sawp2 = 1
91 if (sawp1 && sawp2) return 1
92 return 0
96 if (pckdrefs) ref = $2
97 else ref = $1
98 sub(/\/+$/, "", ref)
99 if (length(ref) < 6 || substr(ref, 1, 5) != "refs/") next
100 if (prefixh) {
101 refs[++cnt] = ref
102 if (length(ref) > plenh && prefixh == substr(ref, 1, plenh))
103 heads[substr(ref, plenh)] = 1
104 } else {
105 if (check(ref)) exit
109 END {
110 for (i = 1; i <= cnt && !check(refs[i]); ++i) ;
111 if (!noerr && sawp1 && sawp2) exit 65
112 if (!sawp1 && !sawp2 && nodef) exit 66
113 if (sawp1 || !sawp2)
114 print substr(prefix1, 1, plen1 - 1)
115 else
116 print substr(prefix2, 1, plen2 - 1)