@@ -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