aur.1: split into high and low level commands
[aurutils.git] / lib / aur-graph
blob25ece19825c0874254a3a69f83b1733fa226dc3b
1 #!/bin/gawk -f
2 # aur-graph - print package/dependency pairs
4 # shellcheck disable=all
6 # < 0 : if ver1 < ver2
7 # = 0 : if ver1 == ver2
8 # > 0 : if ver1 > ver2
9 function get_vercmp(ver1, ver2, op) {
10 command = ("vercmp " ver1 " " ver2)
12 if (op == "-" || ver2 == "-") {
13 return "true" # dependency is unversioned
14 } else if (op == "=") {
15 return (ver1 == ver2) # common case
16 } else if (op == "<") {
17 command | getline
18 close(command)
19 return ($1 < 0)
20 } else if (op == ">") {
21 command | getline
22 close(command)
23 return ($1 > 0)
24 } else if (op == "<=") {
25 command | getline
26 close(command)
27 return ($1 <= 0)
28 } else if (op == ">=") {
29 command | getline
30 close(command)
31 return ($1 >= 0)
32 } else {
33 printf("invalid operation\n") > "/dev/stderr"
34 exit 1
38 function setopt(opt, default) {
39 if(opt ~ /[01]/)
40 return opt
41 else
42 return default
45 function has_valid_arch(attr) {
46 i = index(attr, "_")
47 return !i || (substr(attr, i+1) in arch)
50 function print2(str1, str2) {
51 if (REVERSE)
52 printf("%s\t%s\n", str2, str1)
53 else
54 printf("%s\t%s\n", str1, str2)
57 BEGIN {
58 DEPENDS = setopt(DEPENDS, 1)
59 MAKEDEPENDS = setopt(MAKEDEPENDS, 1)
60 CHECKDEPENDS = setopt(CHECKDEPENDS, 1)
61 OPTDEPENDS = setopt(OPTDEPENDS, 0)
62 PRINTALL = setopt(PRINTALL, 0)
63 REVERSE = setopt(REVERSE, 0)
66 $1 == "pkgbase" {
67 pkgbase = $3
69 pkgver = ""
70 in_split_pkg = 0
71 delete(arch)
73 # track both the pkgbases themselves and their number of deps
74 dep_counts[pkgbase] = 0
77 $1 == "pkgver" && !in_split_pkg {
78 pkgver = $3
81 $1 == "arch" {
82 arch[$3]
85 index($1, "depends") == 1 && !in_split_pkg {
86 if (DEPENDS && has_valid_arch($1)) {
87 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
91 index($1, "makedepends") == 1 && !in_split_pkg {
92 if (MAKEDEPENDS && has_valid_arch($1)) {
93 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
97 index($1, "checkdepends") == 1 && !in_split_pkg {
98 if (CHECKDEPENDS && has_valid_arch($1)) {
99 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
103 index($1, "optdepends") == 1 && !in_split_pkg {
104 if (OPTDEPENDS && has_valid_arch($1)) {
105 split($3, optname, ":") # split optdepends name from description
106 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = optname[1]
110 NF == 0 {
111 in_split_pkg = 1
114 $1 == "pkgname" {
115 pkg_map[$3] = pkgbase # node
116 ver_map[$3] = pkgver # weight
119 index($1, "provides") == 1 && has_valid_arch($1) {
120 split($3, prov, "=")
122 # if provider is unversioned, use pkgver
123 if ("2" in prov)
124 ver_map[prov[1]] = prov[2]
125 else
126 ver_map[prov[1]] = pkgver
128 # append node
129 pkg_map[prov[1]] = pkgbase
132 END {
133 _vercmp_exit = 0
135 for (pkgbase in dep_counts) {
136 # add a loop to isolated nodes (#402)
137 print2(pkgbase, pkgbase)
139 for (dep = 1; dep <= dep_counts[pkgbase]; dep++) {
140 if (PRINTALL) {
141 print2(pkgbase, pkg_deps[pkgbase, dep])
142 continue
144 dep_op = "-" # unversioned / no comparison
146 # valid operators (important: <= before <)
147 split("<=|>=|<|=|>", cmp, "|")
149 # split: fourth argument is gawk extension
150 for (i in cmp) {
151 split(pkg_deps[pkgbase, dep], dep_split, cmp[i])
153 if ("2" in dep_split) {
154 dep_op = cmp[i]
155 break
159 if ("1" in dep_split)
160 dep_pkgname = dep_split[1]
161 else
162 exit 2
164 if ("2" in dep_split)
165 dep_pkgver = dep_split[2]
166 else
167 dep_pkgver = "-"
169 # only print dependency if it was encountered before
170 if (dep_pkgname in pkg_map == 0)
171 continue
173 # run vercmp with provider and versioned dependency
174 if (get_vercmp(ver_map[dep_pkgname], dep_pkgver, dep_op)) {
175 print2(pkgbase, pkg_map[dep_pkgname])
176 } else {
177 printf("invalid node: %s %s (required: %s%s)\n",
178 dep_pkgname, ver_map[dep_pkgname], dep_op, dep_pkgver) > "/dev/stderr"
179 close("/dev/stderr")
181 # delay mismatches to loop end
182 _vercmp_exit = 1
187 exit _vercmp_exit