func TestDependsUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Depends: foo, bar
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.Depends.Relations[0].Possibilities[0].Name == "foo")

	/* Actually invalid below */
	notok(t, control.Unmarshal(&foo, strings.NewReader(`Depends: foo (>= 1.0) (<= 1.0)
`)))
}
func TestBasicUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Foo-Bar: baz
`)))
	assert(t, foo.Value == "foo")
}
Beispiel #3
0
// Load a Debian 2.x series .deb control file and write it out to
// the deb.Deb.Control member.
func loadDeb2Control(archive *Ar, deb *Deb) error {
	for {
		member, err := archive.Next()
		if err == io.EOF {
			return fmt.Errorf("Missing or out of order .deb member 'control'")
		}
		if err != nil {
			return err
		}
		if strings.HasPrefix(member.Name, "control.") {
			archive, err := member.Tarfile()
			if err != nil {
				return err
			}
			for {
				member, err := archive.Next()
				if err != nil {
					return err
				}
				if path.Clean(member.Name) == "control" {
					return control.Unmarshal(&deb.Control, archive)
				}
			}
		}
	}
}
func TestNestedUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Fnord-Foo-Bar: Thing
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.Fnord.FooBar == "Thing")
}
func TestArchUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Arch: amd64
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.Arch.CPU == "amd64")

	foo = TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Arches: amd64 sparc any
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.Arches[0].CPU == "amd64")
	assert(t, foo.Arches[1].CPU == "sparc")
	assert(t, foo.Arches[2].CPU == "any")
}
func TestVersionUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Version: 1.0-1
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.Version.Revision == "1")
}
func TestTagUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Value-Two: baz
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.ValueTwo == "baz")
}
func TestListUnmarshal(t *testing.T) {
	foo := TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
ValueThree: foo bar baz
`)))
	assert(t, foo.Value == "foo")
	assert(t, foo.ValueThree[0] == "foo")
}
func TestBasicArrayUnmarshal(t *testing.T) {
	foo := []TestStruct{}
	isok(t, control.Unmarshal(&foo, strings.NewReader(`Value: foo
Foo-Bar: baz

Value: Bar

Value: Baz
`)))
	assert(t, len(foo) == 3)
	assert(t, foo[0].Value == "foo")
}
Beispiel #10
0
func Load(name string, data interface{}) error {
	localUser, err := user.Current()
	if err != nil {
		return nil
	}
	rcPath := path.Join(localUser.HomeDir, fmt.Sprintf(".%src", name))
	fd, err := os.Open(rcPath)
	if err != nil {
		return nil
	}
	defer fd.Close()
	err = control.Unmarshal(data, fd)
	return err
}
func TestExtraMarshal(t *testing.T) {
	el := TestParaMarshalStruct{}

	isok(t, control.Unmarshal(&el, strings.NewReader(`Foo: test
X-A-Test: Foo
`)))

	assert(t, el.Foo == "test")

	writer := bytes.Buffer{}
	isok(t, control.Marshal(&writer, el))
	assert(t, writer.String() == `Foo: test
X-A-Test: Foo
`)
}
func TestExternalMarshal(t *testing.T) {
	testStruct := SomeComplexStruct{}
	isok(t, control.Unmarshal(&testStruct, strings.NewReader(`Version: 1.0-1
Dependency: foo, bar
X-Foo: bar

`)))
	writer := bytes.Buffer{}

	err := control.Marshal(&writer, testStruct)
	isok(t, err)

	assert(t, testStruct.Dependency.Relations[0].Possibilities[0].Name == "foo")

	assert(t, writer.String() == `Version: 1.0-1
Dependency: foo, bar
X-Foo: bar
`)
}
Beispiel #13
0
func ParseNew(reader *bufio.Reader) ([]NewEntry, error) {
	ret := []NewEntry{}
	err := control.Unmarshal(&ret, reader)
	return ret, err
}
func TestRequiredUnmarshal(t *testing.T) {
	foo := TestStruct{}
	notok(t, control.Unmarshal(&foo, strings.NewReader(`Foo-Bar: baz
`)))
}
Beispiel #15
0
func main() {
	flag.Parse()

	if flag.NArg() != 1 {
		log.Fatalf("Usage: %s [options] <path-to-changes-file>\n", os.Args[0])
	}

	changesPath := flag.Arg(0)
	log.Printf("Loading changes file %q\n", changesPath)

	c, err := os.Open(changesPath)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()
	changes, err := control.ParseChanges(bufio.NewReader(c), changesPath)
	if err != nil && err != io.EOF {
		log.Fatal(err)
	}

	binaries := make(map[string]bool)
	var debs []string
	for _, file := range changes.Files {
		if filepath.Ext(file.Filename) == ".deb" {
			debs = append(debs, file.Filename)
		}
	}
	for _, binary := range changes.Binaries {
		binaries[binary] = true
	}

	log.Printf(" - %d binary packages: %s\n", len(changes.Binaries), strings.Join(changes.Binaries, " "))
	log.Printf(" - corresponding .debs (will be injected when building):\n")
	for _, deb := range debs {
		log.Printf("    %s\n", deb)
	}

	var sourcesPaths []string
	var packagesPaths []string
	indexTargets := exec.Command("apt-get",
		"indextargets",
		"--format",
		"$(FILENAME)",
		"Codename: sid",
		"ShortDesc: Sources")
	if lines, err := indexTargets.Output(); err == nil {
		for _, line := range strings.Split(string(lines), "\n") {
			trimmed := strings.TrimSpace(line)
			if trimmed != "" {
				sourcesPaths = append(sourcesPaths, line)
			}
		}
		binaryIndexTargets := exec.Command(
			"apt-get",
			"indextargets",
			"--format",
			"$(FILENAME)",
			"Codename: sid",
			"ShortDesc: Packages")
		lines, err = binaryIndexTargets.Output()
		if err != nil {
			log.Fatal("Could not get packages files using %+v: %v", binaryIndexTargets.Args, err)
		}
		for _, line := range strings.Split(string(lines), "\n") {
			trimmed := strings.TrimSpace(line)
			if trimmed != "" {
				packagesPaths = append(packagesPaths, line)
			}
		}
	} else {
		// Fallback for older versions of apt-get. See
		// https://bugs.debian.org/801594 for context.
		releaseMatches, err := filepath.Glob("/var/lib/apt/lists/*_InRelease")
		if err != nil {
			log.Fatal(err)
		}
		for _, releasepath := range releaseMatches {
			r, err := os.Open(releasepath)
			if err != nil {
				log.Fatal(err)
			}
			defer r.Close()
			var inRelease struct {
				Suite string
			}
			if err := control.Unmarshal(&inRelease, bufio.NewReader(r)); err != nil {
				log.Fatal(err)
			}
			if inRelease.Suite != "unstable" {
				continue
			}

			listsPrefix := listsPrefixRe.FindStringSubmatch(releasepath)
			if len(listsPrefix) != 2 {
				log.Fatalf("release file path %q does not match regexp %q\n", releasepath, listsPrefixRe)
			}
			sourceMatches, err := filepath.Glob(fmt.Sprintf("/var/lib/apt/lists/%s_*_Sources", listsPrefix[1]))
			if err != nil {
				log.Fatal(err)
			}
			sourcesPaths = append(sourcesPaths, sourceMatches...)
			packagesMatches, err := filepath.Glob(fmt.Sprintf("/var/lib/apt/lists/%s_*_Packages", listsPrefix[1]))
			if err != nil {
				log.Fatal(err)
			}
			packagesPaths = append(packagesPaths, packagesMatches...)
		}
	}

	if len(sourcesPaths) == 0 {
		log.Fatal("Could not find InRelease file for unstable. Are you missing unstable in your /etc/apt/sources.list?")
	}

	rebuild := make(map[string][]version.Version)

	archCmd := exec.Command(
		"dpkg-architecture",
		"--query=DEB_BUILD_ARCH")
	archOut, err := archCmd.Output()
	if err != nil {
		log.Fatal(err)
	}
	arch := strings.TrimSpace(string(archOut))

	// TODO: Cache this output based on the .changes file. dose-ceve takes quite a while.
	ceve := exec.Command(
		"dose-ceve",
		"--deb-native-arch="+arch,
		"-T", "debsrc",
		"-r", strings.Join(changes.Binaries, ","),
		"-G", "pkg")
	for _, packagesPath := range packagesPaths {
		ceve.Args = append(ceve.Args, "deb://"+packagesPath)
	}
	for _, sourcesPath := range sourcesPaths {
		ceve.Args = append(ceve.Args, "debsrc://"+sourcesPath)
	}

	log.Printf("Figuring out reverse build dependencies using dose-ceve(1). This might take a while\n")
	if out, err := ceve.Output(); err == nil {
		var doseCeves []struct {
			Package string
			Version version.Version
		}
		r := bufio.NewReader(strings.NewReader(string(out)))
		if err := control.Unmarshal(&doseCeves, r); err != nil {
			log.Fatal(err)
		}
		for _, doseCeve := range doseCeves {
			rebuild[doseCeve.Package] = append(rebuild[doseCeve.Package], doseCeve.Version)
		}
	} else {
		log.Printf("dose-ceve(1) failed (%v), falling back to interpreting Sources directly\n", err)
		for _, sourcesPath := range sourcesPaths {
			if err := addReverseBuildDeps(sourcesPath, binaries, rebuild); err != nil {
				log.Fatal(err)
			}
		}
	}

	// TODO: add -recursive flag to also cover dependencies which are not DIRECT dependencies. use http://godoc.org/pault.ag/go/debian/control#OrderDSCForBuild (topsort) to build dependencies in the right order (saving CPU time).

	// TODO: what’s a good integration method for doing this in more setups, e.g. on a cloud provider or something? mapreri from #debian-qa says jenkins.debian.net is suitable.

	if strings.TrimSpace(*sbuildDist) == "" {
		*sbuildDist = changes.Distribution
		log.Printf("Setting -sbuild_dist=%s (from .changes file)\n", *sbuildDist)
	}

	buildresults := make(map[string]bool)
	for src, versions := range rebuild {
		sort.Sort(sort.Reverse(version.Slice(versions)))
		newest := versions[0]
		target := fmt.Sprintf("%s_%s", src, newest)
		// TODO: discard resulting package immediately?
		args := []string{
			"--arch-all",
			"--dist=" + *sbuildDist,
			"--nolog",
			target,
		}
		for _, filename := range debs {
			args = append(args, fmt.Sprintf("--extra-package=%s", filename))
		}
		cmd := exec.Command("sbuild", args...)
		if err := os.MkdirAll(*logDir, 0755); err != nil {
			log.Fatal(err)
		}
		log.Printf("Building %s (commandline: %v)\n", target, cmd.Args)
		if *dryRun {
			continue
		}
		buildlog, err := os.Create(filepath.Join(*logDir, target))
		if err != nil {
			log.Fatal(err)
		}
		defer buildlog.Close()
		cmd.Stdout = buildlog
		cmd.Stderr = buildlog
		if err := cmd.Run(); err != nil {
			log.Printf("building %s failed: %v\n", target, err)
			buildresults[target] = false
		} else {
			buildresults[target] = true
		}
	}

	log.Printf("Build results:\n")
	// Print all successful builds first (not as interesting), then failed ones.
	for target, result := range buildresults {
		if !result {
			continue
		}
		log.Printf("PASSED: %s\n", target)
	}

	for target, result := range buildresults {
		if result {
			continue
		}
		log.Printf("FAILED: %s (see %s)\n", target, filepath.Join(*logDir, target))
	}
}