Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.

Commit 3cca858

Browse files
author
Muhammad Ibrahim
committed
dnf improvements
1 parent 8553866 commit 3cca858

1 file changed

Lines changed: 74 additions & 21 deletions

File tree

internal/packages/dnf.go

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (m *DNFManager) GetPackages() []models.Package {
6363
var upgradablePackages []models.Package
6464
if len(checkOutput) > 0 {
6565
m.logger.Debug("Parsing DNF/yum check-update output...")
66-
upgradablePackages = m.parseUpgradablePackages(string(checkOutput), packageManager)
66+
upgradablePackages = m.parseUpgradablePackages(string(checkOutput), packageManager, installedPackages)
6767
m.logger.WithField("count", len(upgradablePackages)).Debug("Found upgradable packages")
6868
} else {
6969
m.logger.Debug("No updates available")
@@ -78,7 +78,7 @@ func (m *DNFManager) GetPackages() []models.Package {
7878
}
7979

8080
// parseUpgradablePackages parses dnf/yum check-update output
81-
func (m *DNFManager) parseUpgradablePackages(output string, packageManager string) []models.Package {
81+
func (m *DNFManager) parseUpgradablePackages(output string, packageManager string, installedPackages map[string]string) []models.Package {
8282
var packages []models.Package
8383

8484
scanner := bufio.NewScanner(strings.NewReader(output))
@@ -100,31 +100,84 @@ func (m *DNFManager) parseUpgradablePackages(output string, packageManager strin
100100
availableVersion := fields[1]
101101
repo := fields[2]
102102

103-
// Get current version
104-
getCurrentCmd := exec.Command(packageManager, "list", "installed", packageName)
105-
getCurrentOutput, err := getCurrentCmd.Output()
106-
var currentVersion string
107-
if err == nil {
108-
for currentLine := range strings.SplitSeq(string(getCurrentOutput), "\n") {
109-
if strings.Contains(currentLine, packageName) && !strings.Contains(currentLine, "Installed") {
110-
currentFields := slices.Collect(strings.FieldsSeq(currentLine))
111-
if len(currentFields) >= 2 {
112-
currentVersion = currentFields[1]
103+
// Get current version from installed packages map (already collected)
104+
// Try exact match first
105+
currentVersion := installedPackages[packageName]
106+
107+
// If not found, try to find by base name (handles architecture suffixes)
108+
// e.g., if packageName is "package" but installed has "package.x86_64"
109+
// or if packageName is "package.x86_64" but installed has "package"
110+
if currentVersion == "" {
111+
// Try to find by removing architecture suffix from packageName (if present)
112+
basePackageName := packageName
113+
if idx := strings.LastIndex(packageName, "."); idx > 0 {
114+
archSuffix := packageName[idx+1:]
115+
if archSuffix == "x86_64" || archSuffix == "i686" || archSuffix == "i386" ||
116+
archSuffix == "noarch" || archSuffix == "aarch64" || archSuffix == "arm64" {
117+
basePackageName = packageName[:idx]
118+
currentVersion = installedPackages[basePackageName]
119+
}
120+
}
121+
122+
// If still not found, search through installed packages for matching base name
123+
if currentVersion == "" {
124+
for installedName, version := range installedPackages {
125+
// Remove architecture suffix if present (e.g., .x86_64, .noarch, .i686)
126+
baseName := installedName
127+
if idx := strings.LastIndex(installedName, "."); idx > 0 {
128+
// Check if the part after the last dot looks like an architecture
129+
archSuffix := installedName[idx+1:]
130+
if archSuffix == "x86_64" || archSuffix == "i686" || archSuffix == "i386" ||
131+
archSuffix == "noarch" || archSuffix == "aarch64" || archSuffix == "arm64" {
132+
baseName = installedName[:idx]
133+
}
134+
}
135+
136+
// Compare base names (handles both cases: package vs package.x86_64)
137+
if baseName == basePackageName || baseName == packageName {
138+
currentVersion = version
113139
break
114140
}
115141
}
116142
}
117143
}
144+
145+
// If still not found in installed packages, try to get it with a command as fallback
146+
if currentVersion == "" {
147+
getCurrentCmd := exec.Command(packageManager, "list", "installed", packageName)
148+
getCurrentOutput, err := getCurrentCmd.Output()
149+
if err == nil {
150+
for currentLine := range strings.SplitSeq(string(getCurrentOutput), "\n") {
151+
if strings.Contains(currentLine, packageName) && !strings.Contains(currentLine, "Installed") && !strings.Contains(currentLine, "Available") {
152+
currentFields := slices.Collect(strings.FieldsSeq(currentLine))
153+
if len(currentFields) >= 2 {
154+
currentVersion = currentFields[1]
155+
break
156+
}
157+
}
158+
}
159+
}
160+
}
118161

119-
isSecurityUpdate := strings.Contains(strings.ToLower(repo), "security")
120-
121-
packages = append(packages, models.Package{
122-
Name: packageName,
123-
CurrentVersion: currentVersion,
124-
AvailableVersion: availableVersion,
125-
NeedsUpdate: true,
126-
IsSecurityUpdate: isSecurityUpdate,
127-
})
162+
// Only add package if we have both current and available versions
163+
// This prevents empty currentVersion errors on the server
164+
if packageName != "" && currentVersion != "" && availableVersion != "" {
165+
isSecurityUpdate := strings.Contains(strings.ToLower(repo), "security")
166+
167+
packages = append(packages, models.Package{
168+
Name: packageName,
169+
CurrentVersion: currentVersion,
170+
AvailableVersion: availableVersion,
171+
NeedsUpdate: true,
172+
IsSecurityUpdate: isSecurityUpdate,
173+
})
174+
} else {
175+
m.logger.WithFields(logrus.Fields{
176+
"package": packageName,
177+
"currentVersion": currentVersion,
178+
"availableVersion": availableVersion,
179+
}).Debug("Skipping package due to missing version information")
180+
}
128181
}
129182

130183
return packages

0 commit comments

Comments
 (0)