forked from SUSE/saptune
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rpm.go
152 lines (144 loc) · 4.4 KB
/
rpm.go
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package system
// wrapper to rpm command
import (
"fmt"
"os/exec"
"regexp"
"strings"
"unicode"
)
var alphanumPattern = regexp.MustCompile("([a-zA-Z]+)|([0-9]+)|(~)")
// GetRpmVers return the version of an installed RPM
func GetRpmVers(rpm string) string {
// rpm -q --qf '%{VERSION}-%{RELEASE}\n' glibc
notInstalled := fmt.Sprintf("package %s is not installed", rpm)
rpmVers := ""
cmdName := "/bin/rpm"
cmdArgs := []string{"-q", "--qf", "%{VERSION}-%{RELEASE}\n", rpm}
cmdOut, err := exec.Command(cmdName, cmdArgs...).CombinedOutput()
if err != nil {
if len(string(cmdOut)) == 0 || strings.TrimSpace(string(cmdOut)) != notInstalled {
WarningLog("There was an error running external command 'rpm -q --qf '%%{VERSION}-%%{RELEASE}' %s': %v, output: %s", rpm, err, cmdOut)
}
return ""
}
for _, line := range strings.Split(strings.TrimSpace(string(cmdOut)), "\n") {
// ANGI: TODO - was, wenn mehr als eine Paketversion installiert ist
rpmVers = line
}
return rpmVers
}
/* compare rpm versions
func CmpRpmVers, func CheckRpmVers
build on base of information from http://rpm.org/user_doc/dependencies.html
and https://github.com/rpm-software-management/rpm/blob/master/lib/rpmvercmp.c
Equal == 0, GreaterThan > 0, LessThan < 0
vers1 is '228-150.22.1', vers2 is '228-142.1'
*/
// CmpRpmVers compare versions of 2 RPMs (installed version, expected version)
// Return true, if installed package version is equal or higher than expected
// Return false, if installed package version is less than expected
func CmpRpmVers(vers1, vers2 string) bool {
if vers1 == "" {
// package not installed
return false
}
if vers1 == vers2 {
// rpm version and release are equal
return true
}
// actV is 228-150.22.1, expV is 228-142.1
actV := strings.Split(vers1, "-")
expV := strings.Split(vers2, "-")
// check rpm version
ret := CheckRpmVers(actV[0], expV[0])
if ret > 0 {
// installed package version is higher than expected
return true
} else if ret < 0 {
// installed package version is less than expected
return false
}
// rpm version is equal, so check rpm release
ret = CheckRpmVers(actV[1], expV[1])
//lint:ignore S1008 we want to keep the comments
if ret < 0 {
// installed package release is less than expected
return false
}
// installed package release is equal or higher than expected
return true
}
// CheckRpmVers compare versions of 2 RPMs (installed version, expected version)
// Return 0 (Equal), 1 (GreaterThan) or -1 (LessThan)
func CheckRpmVers(vers1, vers2 string) int {
// per definition numbers are greater than alphas
if vers1 == vers2 {
return 0
}
// get bunches of numbers or characters for comparison
partsV1 := alphanumPattern.FindAllString(vers1, -1)
partsV2 := alphanumPattern.FindAllString(vers2, -1)
nrParts := len(partsV1)
if len(partsV1) > len(partsV2) {
nrParts = len(partsV2)
}
// compare each bunche of numbers or characters
for i := 0; i < nrParts; i++ {
p1 := partsV1[i]
p2 := partsV2[i]
r10 := []rune(p1)[0]
r20 := []rune(p2)[0]
// searching for 'tildes'
// first character in bunch - []rune(p1)[0]
if r10 == '~' || r20 == '~' {
if r10 != '~' {
return 1
}
if r20 != '~' {
return -1
}
}
if unicode.IsNumber(r10) {
// actual vers part is a number
if !unicode.IsNumber(r20) {
// actual vers is numeric, expected vers is alpha, so actual vers is higher
return 1
}
// both are numbers, trim leading zeros
p1 = strings.TrimLeft(p1, "0")
p2 = strings.TrimLeft(p2, "0")
// longest string wins, no need for further comparison
if len(p1) > len(p2) {
return 1
} else if len(p2) > len(p1) {
return -1
}
} else if unicode.IsNumber(r20) {
// actual vers part is a alpha, but expected vers part is a number
return -1
}
// both parts are alpha, so use simple string compare
if p1 < p2 {
return -1
} else if p1 > p2 {
return 1
}
}
// the bunches were all the same. Check, if separators of bunches have been different
if len(partsV1) == len(partsV2) {
return 0
}
// look for a tilde in a bunch/part past the minimal number of bunches/parts
// could not be found in the for loop above because it's outside of the loop range
if len(partsV1) > nrParts && []rune(partsV1[nrParts])[0] == '~' {
return -1
} else if len(partsV2) > nrParts && []rune(partsV2[nrParts])[0] == '~' {
return 1
}
// at least the highest number of bunches/parts wins
if len(partsV1) > len(partsV2) {
return 1
}
return -1
}