Depends.pm: refactor extract to solve
[aurutils.git] / lib / aur-graph
blobea48aabedbb70b494ca2ecba146e7721b5f83e5d
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 BEGIN {
51 DEPENDS = setopt(DEPENDS, 1)
52 MAKEDEPENDS = setopt(MAKEDEPENDS, 1)
53 CHECKDEPENDS = setopt(CHECKDEPENDS, 1)
54 OPTDEPENDS = setopt(OPTDEPENDS, 0)
55 PRINTALL = setopt(PRINTALL, 0)
58 $1 == "pkgbase" {
59 pkgbase = $3
61 pkgver = ""
62 in_split_pkg = 0
63 delete(arch)
65 # track both the pkgbases themselves and their number of deps
66 dep_counts[pkgbase] = 0
69 $1 == "pkgver" && !in_split_pkg {
70 pkgver = $3
73 $1 == "arch" {
74 arch[$3]
77 index($1, "depends") == 1 && !in_split_pkg {
78 if (DEPENDS && has_valid_arch($1))
79 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
82 index($1, "makedepends") == 1 && !in_split_pkg {
83 if (MAKEDEPENDS && has_valid_arch($1))
84 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
87 index($1, "checkdepends") == 1 && !in_split_pkg {
88 if (CHECKDEPENDS && has_valid_arch($1))
89 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
92 index($1, "optdepends") == 1 && !in_split_pkg {
93 if (OPTDEPENDS && has_valid_arch($1))
94 pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3
97 NF == 0 {
98 in_split_pkg = 1
101 $1 == "pkgname" {
102 pkg_map[$3] = pkgbase # node
103 ver_map[$3] = pkgver # weight
106 index($1, "provides") == 1 && has_valid_arch($1) {
107 split($3, prov, "=")
109 # if provider is unversioned, use pkgver
110 if ("2" in prov)
111 ver_map[prov[1]] = prov[2]
112 else
113 ver_map[prov[1]] = pkgver
115 # append node
116 pkg_map[prov[1]] = pkgbase
119 END {
120 _vercmp_exit = 0
122 for (pkgbase in dep_counts) {
123 # add a loop to isolated nodes (#402)
124 printf("%s\t%s\n", pkgbase, pkgbase)
126 for (dep = 1; dep <= dep_counts[pkgbase]; dep++) {
127 if (PRINTALL) {
128 printf("%s\t%s\n", pkgbase, pkg_deps[pkgbase, dep])
129 continue
131 dep_op = "-" # unversioned / no comparison
133 # valid operators (important: <= before <)
134 split("<=|>=|<|=|>", cmp, "|")
136 # split: fourth argument is gawk extension
137 for (i in cmp) {
138 split(pkg_deps[pkgbase, dep], dep_split, cmp[i])
140 if ("2" in dep_split) {
141 dep_op = cmp[i]
142 break
146 if ("1" in dep_split)
147 dep_pkgname = dep_split[1]
148 else
149 exit 2
151 if ("2" in dep_split)
152 dep_pkgver = dep_split[2]
153 else
154 dep_pkgver = "-"
156 # only print dependency if it was encountered before
157 if (dep_pkgname in pkg_map == 0)
158 continue
160 # run vercmp with provider and versioned dependency
161 if (get_vercmp(ver_map[dep_pkgname], dep_pkgver, dep_op)) {
162 printf("%s\t%s\n", pkgbase, pkg_map[dep_pkgname])
163 } else {
164 printf("invalid node: %s %s (required: %s%s)\n",
165 dep_pkgname, ver_map[dep_pkgname], dep_op, dep_pkgver) > "/dev/stderr"
166 close("/dev/stderr")
168 # delay mismatches to loop end
169 _vercmp_exit = 1
174 exit _vercmp_exit