t5010-update-local.sh: test non-remote update handling
[topgit/pro.git] / awk / ref_prefixes.awk
blob3679d51fd57ae6d3e705fb9361cd76cd316e9535
1 #!/usr/bin/awk -f
3 # ref_prefixes - TopGit awk utility script used by tg--awksome
4 # Copyright (C) 2017 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
22 # if prefixh is non-empty then matches for prefix1 or prefix2 must also match
23 # another line from the input after replacing the prefix1/prefix2 part with
24 # prefixh or they are discarded and do not participate in choosing the output
26 # note that the input need not be sorted in any particular order or be
27 # duplicate free even when prefixh is non-empty
29 # a prefix will only match at a "/" boundary
31 # ontput according to this table:
33 # any refs match any refs match noerr exit output
34 # prefix1 prefix prefix2 prefix value status value
35 # -------------- -------------- ----- ------ -------
36 # no no any 0 prefix1
37 # yes no any 0 prefix1
38 # no yes any 0 prefix2
39 # yes yes false 1
40 # yes yes true 0 prefix1
42 # there is no output when exit status is 1
43 # the output value, if any, will have any trailing slash(es) removed from it
46 BEGIN { exitcode = "" }
47 function exitnow(e) { exitcode=e; exit e }
48 END { if (exitcode != "") exit exitcode }
50 BEGIN {
51 sub(/\/+$/, "", prefix1)
52 sub(/\/+$/, "", prefix2)
53 sub(/\/+$/, "", prefixh)
54 if (prefix1 == "" || prefix2 == "" ||
55 prefix1 == prefix2 ||
56 prefix1 == prefixh || prefix2 == prefixh)
57 exitnow(2)
58 if (substr(prefix1, 1, 5) != "refs/" ||
59 substr(prefix2, 1, 5) != "refs/" ||
60 (prefixh != "" && substr(prefixh, 1, 5) != "refs/"))
61 exitnow(2)
62 plen1 = length(prefix1)
63 plen2 = length(prefix2)
64 plenh = length(prefixh)
65 if (plen1 < 6 || plen2 < 6) exitnow(2)
66 prefix1 = prefix1 "/"
67 prefix2 = prefix2 "/"
68 ++plen1
69 ++plen2
70 if (prefixh != "") {
71 prefixh = prefixh "/"
72 ++plenh
74 if (plen1 < plen2 && plen1 == substr(plen2, 1, plen1)) exitnow(2)
75 if (plen1 > plen2 && substr(plen1, 1, plen2) == plen2) exitnow(2)
76 sawp1 = 0
77 sawp2 = 0
78 cnt = 0
81 function check(r) {
82 if (length(r) > plen1 && prefix1 == substr(r, 1, plen1)) {
83 if (prefixh && !heads[substr(r, plen1)]) return 0
84 sawp1 = 1
85 } else if (length(r) > plen2 && prefix2 == substr(r, 1, plen2)) {
86 if (prefixh && !heads[substr(r, plen2)]) return 0
87 sawp2 = 1
89 if (sawp1 && sawp2) return 1
90 return 0
94 if (pckdrefs) ref = $2
95 else ref = $1
96 sub(/\/+$/, "", ref)
97 if (length(ref) < 6 || substr(ref, 1, 5) != "refs/") next
98 if (prefixh) {
99 refs[++cnt] = ref
100 if (length(ref) > plenh && prefixh == substr(ref, 1, plenh))
101 heads[substr(ref, plenh)] = 1
102 } else {
103 if (check(ref)) exit
107 END {
108 for (i = 1; i <= cnt && !check(refs[i]); ++i) ;
109 if (!noerr && sawp1 && sawp2) exit 65
110 if (!sawp1 && !sawp2 && nodef) exit 66
111 if (sawp1 || !sawp2)
112 print substr(prefix1, 1, plen1 - 1)
113 else
114 print substr(prefix2, 1, plen2 - 1)