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
|
package main
import (
"fmt"
"log"
"regexp"
"strings"
)
const (
// TODO: drop these in favor of strings.Fields()
nonSpaceToken = "[^\t\n\f\r ]+" // equivalent to perl's \S
spaceToken = "[\t\n\f\r ]+" // equivalent to perl's \s
)
// packageProvides returns a map from package name to a string slice of
// provided packages, for all of the specified packages (or all of the
// installed ones, if none are specified).
func packageProvides(ignoreMissing bool, pkgs []string) map[string]map[string]bool {
lines, err := runCommand(append([]string{
"/usr/bin/dpkg-query",
"-Wf", "${binary:Package} ${Package};${Status};${Provides}\n",
"--"},
pkgs...))
if err != nil {
log.Fatal(err)
}
// sample input:
// libparted-fs-resize0:amd64 libparted-fs-resize0;install ok installed;
// xserver-xorg-core xserver-xorg-core;deinstall ok config-files;xorg-input-abi-24, xorg-video-abi-25, xserver-xorg-video-modesetting
// ^(\S+).*;.*\s(\S+);(.*)$
pkgStatusProvides := regexp.MustCompile("^(" + nonSpaceToken + ").*;.*" + spaceToken + "(" + nonSpaceToken + ");(.*)$")
pkgProvides := make(map[string]map[string]bool)
for _, line := range lines {
m := pkgStatusProvides.FindStringSubmatch(line)
if len(m) != 4 {
log.Fatalf("Unexpected output from dpkg-query: %q\n", line)
continue
}
pkg := string(m[1])
status := string(m[2])
providedPkgs := strings.Split(strings.Replace(string(m[3]), " ", "", -1), ",")
if status == "installed" {
provides := make(map[string]bool)
for _, pr := range providedPkgs {
provides[pr] = true
}
pkgProvides[pkg] = provides
} else if len(pkgs) > 0 {
fmt.Printf("Skipping %s because it's not installed", pkg)
}
}
return pkgProvides
}
// packageFiles returns a map from deb (binary) package name to string slice of
// package files, and the total number of files.
func packageFiles(pkgs []string) (map[string][]string, int64, error) {
lines, err := runCommand(append([]string{"/usr/bin/dpkg", "-L"}, pkgs...))
if err != nil {
log.Fatal(err)
}
pkg2files := make(map[string][]string)
i := 0
var totalFiles int64
diverted := regexp.MustCompile("^(?:locally diverted|diverted by " + nonSpaceToken + ") to: (/.+)$")
for _, line := range lines {
if line == "" {
i++
continue
}
pkg := pkgs[i]
file := line
if m := diverted.FindStringSubmatch(line); len(m) == 2 {
file = string(m[1])
}
if len(file) == 0 || file[0] != '/' {
continue
}
pkg2files[pkg] = append(pkg2files[pkg], file)
totalFiles += 1
}
return pkg2files, totalFiles, nil
}
|