Debian: Use --showformat flag to get status of packages and ignore n(not-inst… (#484)
* Use --showformat flag to get status of packages and ignore n(not-installed) and c(removed, only has config files remaining) packages. * Ignoring all packages that are not in 'Installed' status. * Simplify char escaping in the command. * Fix typo.
This commit is contained in:
		@@ -240,18 +240,32 @@ func (o *debian) rebootRequired() (bool, error) {
 | 
			
		||||
 | 
			
		||||
func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, error) {
 | 
			
		||||
	installed, updatable := models.Packages{}, models.Packages{}
 | 
			
		||||
	r := o.exec("dpkg-query -W", noSudo)
 | 
			
		||||
	r := o.exec(`dpkg-query -W -f='${binary:Package}\t${db:Status-Abbrev}\t${Version}\n'`, noSudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, nil, fmt.Errorf("Failed to SSH: %s", r)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//  e.g.
 | 
			
		||||
	//  curl	7.19.7-40.el6_6.4
 | 
			
		||||
	//  openldap	2.4.39-8.el6
 | 
			
		||||
	//  curl	ii 	7.47.0-1ubuntu2.2
 | 
			
		||||
	//  openssh-server	rc 	1:7.2p2-4ubuntu2.2
 | 
			
		||||
	lines := strings.Split(r.Stdout, "\n")
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
		if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
 | 
			
		||||
			name, version, err := o.parseScannedPackagesLine(trimmed)
 | 
			
		||||
			name, status, version, err := o.parseScannedPackagesLine(trimmed)
 | 
			
		||||
			packageStatus := status[1]
 | 
			
		||||
			// Package status:
 | 
			
		||||
			//     n = Not-installed
 | 
			
		||||
			//     c = Config-files
 | 
			
		||||
			//     H = Half-installed
 | 
			
		||||
			//     U = Unpacked
 | 
			
		||||
			//     F = Half-configured
 | 
			
		||||
			//     W = Triggers-awaiting
 | 
			
		||||
			//     t = Triggers-pending
 | 
			
		||||
			//     i = Installed
 | 
			
		||||
			if packageStatus != 'i' {
 | 
			
		||||
				o.log.Debugf("%s package status is '%c', ignoring", name, packageStatus)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, nil, fmt.Errorf(
 | 
			
		||||
					"Debian: Failed to parse package line: %s", line)
 | 
			
		||||
@@ -286,21 +300,22 @@ func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, erro
 | 
			
		||||
	return installed, updatable, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var packageLinePattern = regexp.MustCompile(`^([^\t']+)\t(.+)$`)
 | 
			
		||||
var packageLinePattern = regexp.MustCompile(`^([^\t']+)\t(.+)\t(.+)$`)
 | 
			
		||||
 | 
			
		||||
func (o *debian) parseScannedPackagesLine(line string) (name, version string, err error) {
 | 
			
		||||
func (o *debian) parseScannedPackagesLine(line string) (name, status, version string, err error) {
 | 
			
		||||
	result := packageLinePattern.FindStringSubmatch(line)
 | 
			
		||||
	if len(result) == 3 {
 | 
			
		||||
	if len(result) == 4 {
 | 
			
		||||
		// remove :amd64, i386...
 | 
			
		||||
		name = result[1]
 | 
			
		||||
		if i := strings.IndexRune(name, ':'); i >= 0 {
 | 
			
		||||
			name = name[:i]
 | 
			
		||||
		}
 | 
			
		||||
		version = result[2]
 | 
			
		||||
		status = result[2]
 | 
			
		||||
		version = result[3]
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return "", "", fmt.Errorf("Unknown format: %s", line)
 | 
			
		||||
	return "", "", "", fmt.Errorf("Unknown format: %s", line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *debian) aptGetUpdate() error {
 | 
			
		||||
 
 | 
			
		||||
@@ -34,23 +34,27 @@ func TestParseScannedPackagesLineDebian(t *testing.T) {
 | 
			
		||||
	var packagetests = []struct {
 | 
			
		||||
		in      string
 | 
			
		||||
		name    string
 | 
			
		||||
		status  string
 | 
			
		||||
		version string
 | 
			
		||||
	}{
 | 
			
		||||
		{"base-passwd	3.5.33", "base-passwd", "3.5.33"},
 | 
			
		||||
		{"bzip2	1.0.6-5", "bzip2", "1.0.6-5"},
 | 
			
		||||
		{"adduser	3.113+nmu3ubuntu3", "adduser", "3.113+nmu3ubuntu3"},
 | 
			
		||||
		{"bash	4.3-7ubuntu1.5", "bash", "4.3-7ubuntu1.5"},
 | 
			
		||||
		{"bsdutils	1:2.20.1-5.1ubuntu20.4", "bsdutils", "1:2.20.1-5.1ubuntu20.4"},
 | 
			
		||||
		{"ca-certificates	20141019ubuntu0.14.04.1", "ca-certificates", "20141019ubuntu0.14.04.1"},
 | 
			
		||||
		{"apt	1.0.1ubuntu2.8", "apt", "1.0.1ubuntu2.8"},
 | 
			
		||||
		{"base-passwd	ii 	3.5.33", "base-passwd", "ii ", "3.5.33"},
 | 
			
		||||
		{"bzip2	ii 	1.0.6-5", "bzip2", "ii ", "1.0.6-5"},
 | 
			
		||||
		{"adduser	ii 	3.113+nmu3ubuntu3", "adduser", "ii ", "3.113+nmu3ubuntu3"},
 | 
			
		||||
		{"bash	ii 	4.3-7ubuntu1.5", "bash", "ii ", "4.3-7ubuntu1.5"},
 | 
			
		||||
		{"bsdutils	ii 	1:2.20.1-5.1ubuntu20.4", "bsdutils", "ii ", "1:2.20.1-5.1ubuntu20.4"},
 | 
			
		||||
		{"ca-certificates	ii 	20141019ubuntu0.14.04.1", "ca-certificates", "ii ", "20141019ubuntu0.14.04.1"},
 | 
			
		||||
		{"apt	rc 	1.0.1ubuntu2.8", "apt", "rc ", "1.0.1ubuntu2.8"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d := newDebian(config.ServerInfo{})
 | 
			
		||||
	for _, tt := range packagetests {
 | 
			
		||||
		n, v, _ := d.parseScannedPackagesLine(tt.in)
 | 
			
		||||
		n, s, v, _ := d.parseScannedPackagesLine(tt.in)
 | 
			
		||||
		if n != tt.name {
 | 
			
		||||
			t.Errorf("name: expected %s, actual %s", tt.name, n)
 | 
			
		||||
		}
 | 
			
		||||
		if s != tt.status {
 | 
			
		||||
			t.Errorf("status: expected %s, actual %s", tt.status, s)
 | 
			
		||||
		}
 | 
			
		||||
		if v != tt.version {
 | 
			
		||||
			t.Errorf("version: expected %s, actual %s", tt.version, v)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user