aboutsummaryrefslogtreecommitdiffstats
path: root/.github/workflows/aur-graph
blob: c4e5beb7871499ff58bae5eb3adda7cc93e2f063 (plain) (blame)
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
#!/bin/awk -f
# Taken from https://github.com/AladW/aurutils/blob/master/lib/aur-graph
# (ISC License)
#
# aur-graph - print package/dependency pairs

# < 0 : if ver1 < ver2
# = 0 : if ver1 == ver2
# > 0 : if ver1 > ver2
function get_vercmp(ver1, ver2, op) {
    command = ("vercmp " ver1 " " ver2)

    if (op == "-" || ver2 == "-") {
        return "true" # dependency is unversioned
    } else if (op == "=") {
        return (ver1 == ver2) # common case
    } else if (op == "<") {
        command | getline
        close(command)
        return ($1 < 0)
    } else if (op == ">") {
        command | getline
        close(command)
        return ($1 > 0)
    } else if (op == "<=") {
        command | getline
        close(command)
        return ($1 <= 0)
    } else if (op == ">=") {
        command | getline
        close(command)
        return ($1 >= 0)
    } else {
        printf("invalid operation\n") > "/dev/stderr"
        exit 1
    }
}

/pkgbase/ {
    in_split_pkg = 0
    pkgbase = $3
    pkgver  = ""

    # track both the pkgbases themselves and their number of deps
    dep_counts[pkgbase] = 0
}

/^\tpkgver/ {
    if (!in_split_pkg) {
        pkgver = $3
    }
}

/^\t(make|check)?depends/ {
    if (!in_split_pkg) {
        # POSIX array of arrays!
        pkg_deps[pkgbase, ++dep_counts[pkgbase]] = $3 # versioned
    }
}

/^$/ {
    in_split_pkg = 1
}

/pkgname/ {
    pkg_map[$3] = pkgbase # node
    ver_map[$3] = pkgver  # weight
}

/^\tprovides/ {
    split($3, prov, "=")

    # if provider is unversioned, use pkgver
    if ("2" in prov)
        ver_map[prov[1]] = prov[2]
    else
        ver_map[prov[1]] = pkgver

    # append node
    pkg_map[prov[1]] = pkgbase
}

END {
    _vercmp_exit = 0

    for (pkgbase in dep_counts) {
        # add a loop to isolated nodes (#402)
        printf("%s\t%s\n", pkgbase, pkgbase)

        for (dep = 1; dep <= dep_counts[pkgbase]; dep++) {
            dep_op = "-" # unversioned / no comparison

            # valid operators (important: <= before <)
            split("<=|>=|<|=|>", cmp, "|")

            # split: fourth argument is gawk extension
            for (i in cmp) {
                split(pkg_deps[pkgbase, dep], dep_split, cmp[i])

                if ("2" in dep_split) {
                    dep_op = cmp[i]
                    break
                }
            }

            if ("1" in dep_split)
                dep_pkgname = dep_split[1]
            else
                exit 2

            if ("2" in dep_split)
                dep_pkgver = dep_split[2]
            else
                dep_pkgver = "-"

            # only print dependency if it was encountered before
            if (dep_pkgname in pkg_map == 0)
                continue

            # run vercmp with provider and versioned dependency
            if (get_vercmp(ver_map[dep_pkgname], dep_pkgver, dep_op)) {
                printf("%s\t%s\n", pkgbase, pkg_map[dep_pkgname])
            } else {
                printf("invalid node: %s %s (required: %s%s)\n",
                       dep_pkgname, ver_map[dep_pkgname], dep_op, dep_pkgver) > "/dev/stderr"
                close("/dev/stderr")

                # delay mismatches to loop end
                _vercmp_exit = 1
            }
        }
    }

    if (_vercmp_exit)
        exit _vercmp_exit
}