Ejemplo n.º 1
0
func ComputeBuildStatus(
	repo reprepro.Repo,
	index resolver.Candidates,
	packages []reprepro.BuildNeedingPackage,
) []BuildStatus {
	ret := []BuildStatus{}

	for _, pkg := range packages {
		dsc, err := control.ParseDscFile(repo.Basedir + "/" + pkg.Location)
		if err != nil {
			continue
		}

		arch, err := dependency.ParseArch(pkg.Arch)
		if err != nil {
			/// XXX: ERROR OUT
			continue
		}

		buildable, why := index.ExplainSatisfiesBuildDepends(*arch, dsc.BuildDepends)

		ret = append(ret, BuildStatus{
			Package:   pkg,
			Buildable: buildable,
			Why:       why,
		})
	}

	return ret
}
Ejemplo n.º 2
0
// Take a DSC, and a log file, and create a fake .changes to upload
// the log to the archive. This relies on a reprepro extension.
func LogChangesFromDsc(logPath, dscPath, suite, arch string) (string, error) {
	dsc, err := control.ParseDscFile(dscPath)
	if err != nil {
		return "", nil
	}

	return FakeChanges(
		"Fri, 31 Jul 2015 12:53:50 -0400",
		dsc.Source,
		strings.Join(dsc.Binaries, " "),
		arch,
		dsc.Version.String(),
		suite,
		"low",
		[]string{logPath},
	)
}
Ejemplo n.º 3
0
Archivo: main.go Proyecto: paultag/nmr
func BuildPackage(dscFile, arch, suite, repoRoot string, verbose bool) (bool, error) {
	// done := fancytext.FormatSpinner(fmt.Sprintf("%%s  -  building %s", dscFile))
	// defer done()

	incomingLocation, err := GetIncoming(repoRoot, suite)
	if err != nil {
		return false, err
	}

	dsc, err := control.ParseDscFile(dscFile)
	if err != nil {
		return false, err
	}

	source := dsc.Source
	version := dsc.Version

	cmd, err := SbuildCommand(suite, suite, arch, dscFile, repoRoot, verbose)
	if err != nil {
		return false, err
	}

	err = cmd.Run()
	ftbfs := err != nil

	changesFile := helpers.Filename(source, version, arch, "changes")
	logPath := helpers.Filename(source, version, arch, "build")

	if ftbfs {
		return true, nil

		// fmt.Printf(" FTBFS!\n")
		// return
		// changes, err := helpers.LogChangesFromDsc(logPath, dscFile, suite, arch)
		// if err != nil {
		// 	panic(err)
		// }
		// fd, err := os.Create(changesFile)
		// if err != nil {
		// 	panic(err)
		// }
		// defer fd.Close()
		// _, err = fd.Write([]byte(changes))
		// if err != nil {
		// 	panic(err)
		// }
	} else {
		helpers.AppendLogToChanges(logPath, changesFile, arch)
	}

	if IsArchAllArch(repoRoot, arch) && dsc.HasArchAll() {
		archAllLogPath := helpers.Filename(source, version, "all", "build")
		Copy(logPath, archAllLogPath)
		helpers.AppendLogToChanges(archAllLogPath, changesFile, "all")
	}

	changes, err := control.ParseChangesFile(changesFile)
	if err != nil {
		return ftbfs, err
	}

	err = changes.Copy(incomingLocation)
	if err != nil {
		return ftbfs, err
	}

	return ftbfs, nil
}
Ejemplo n.º 4
0
func buildBin(dscFile string) (control.DSC, string) {
	dscDir := filepath.Dir(dscFile)
	dsc, err := control.ParseDscFile(dscFile)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	if err := dsc.Validate(); err != nil {
		log.Fatalf("error, validation failed: %v\n", err)
	}

	hasArch := false
	hasIndep := false
	for _, arch := range dsc.Architectures {
		if arch.CPU == "all" {
			hasIndep = true
		} else {
			hasArch = true
		}
	}

	img := fmt.Sprintf("gdbuild/bin:%s_%s", dsc.Source, scrubForDockerTag(dsc.Version.String()))

	// TODO parse this information from an image?  optional commandline parameters?
	suite := "unstable"
	sources := aptsources.DebianSources(suite, "main")
	arch := "amd64"

	// prepend incoming so we get the latest and greatest
	sources = sources.Prepend(aptsources.Source{
		Types:      []string{"deb", "deb-src"},
		URIs:       []string{"http://incoming.debian.org/debian-buildd"},
		Suites:     []string{"buildd-" + suite},
		Components: []string{"main"},
	})

	index, err := sources.FetchCandidates(arch)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	depArch, err := dependency.ParseArch(arch)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	buildEssential, err := dependency.Parse("build-essential, dpkg-dev, fakeroot")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	allCan := true
	bins := map[string]control.BinaryIndex{}
	binsSlice := []string{} // ugh Go
RelLoop:
	for _, rel := range append(buildEssential.Relations, dsc.BuildDepends.Relations...) {
		canRel := false
		for _, possi := range rel.Possibilities {
			if possi.Substvar {
				continue
			}
			if bin, ok := bins[possi.Name]; ok && binSatPossi(depArch, bin, possi) {
				continue RelLoop
			}
		}
	PossiLoop:
		for _, possi := range rel.Possibilities {
			if possi.Substvar {
				continue
			}
			entries, ok := map[string][]control.BinaryIndex(*index)[possi.Name]
			if !ok {
				continue
			}
			for _, bin := range entries {
				if binSatPossi(depArch, bin, possi) {
					if existBin, ok := bins[bin.Package]; ok {
						log.Printf("uh oh, already chose %s=%s but want %s=%s for %q\n", existBin.Package, existBin.Version, bin.Package, bin.Version, possi)
						continue PossiLoop
					}
					bins[bin.Package] = bin
					binsSlice = append(binsSlice, bin.Package)
					canRel = true
					break PossiLoop
				}
			}
		}
		if !canRel {
			log.Printf("warning: unable to satisfy %q\n", rel)
			allCan = false
		}
	}
	sort.Strings(binsSlice)

	if !allCan {
		//log.Fatalf("Unsatisfied possi; exiting.\n")
		log.Println()
		log.Println("WARNING: Unsatisfied possi!")
		log.Println()
	}

	dockerfile := fmt.Sprintf("FROM debian:%s\n", suite)
	// TODO allow this to instead be "FROM scratch\nADD some-chroot-tarball.tar.* /\n"

	// see https://sources.debian.net/src/pbuilder/jessie/pbuilder-modules/#L306
	// and https://sources.debian.net/src/pbuilder/jessie/pbuilder-modules/#L408
	dockerfile += `
# setup environment configuration
RUN { echo '#!/bin/sh'; echo 'exit 101'; } > /usr/sbin/policy-rc.d \
	&& chmod +x /usr/sbin/policy-rc.d
RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/15gdbuild

# put /tmp in a volume so it's always ephemeral (and performant)
VOLUME /tmp
`

	// setup sources.list explicitly -- don't trust the tarball/base image
	dockerfile += fmt.Sprintf(`
# setup sources.list
RUN find /etc/apt/sources.list.d -type f -exec rm -v '{}' + \
	&& echo %q | tee /etc/apt/sources.list >&2
`, sources.ListString())

	eatMyDataPrefix := ""
	if doEatMyData {
		eatMyDataPrefix = "eatmydata "
		dockerfile += `
RUN apt-get update && apt-get install -y \
		eatmydata \
	&& rm -rf /var/lib/apt/lists/*
`
	}

	dockerfile += fmt.Sprintf(`
RUN %sapt-get update && %sapt-get install -y \
`, eatMyDataPrefix, eatMyDataPrefix)
	for _, pkg := range binsSlice {
		bin := bins[pkg]
		dockerfile += fmt.Sprintf("\t\t%s=%s \\\n", bin.Package, bin.Version)
	}
	dockerfile += "\t&& rm -rf /var/lib/apt/lists/*\n"

	files := []string{dsc.Filename}
	for _, f := range dsc.Files {
		files = append(files, filepath.Join(dscDir, f.Filename))
	}

	dockerfile += "COPY"
	for _, f := range files {
		dockerfile += " " + filepath.Base(f)
	}
	dockerfile += " /usr/src/.in/\n"

	if debBuildOptions := os.Getenv("DEB_BUILD_OPTIONS"); debBuildOptions != "" {
		dockerfile += fmt.Sprintf("\nENV DEB_BUILD_OPTIONS %s\n", debBuildOptions)
	}

	buildCommand := fmt.Sprintf("%sdpkg-buildpackage -uc -us -d -sa", eatMyDataPrefix)

	if doSASBS {
		buildCommandParts := []string{}
		if hasIndep {
			buildCommandParts = append(
				buildCommandParts,
				buildCommand+" -S",
				buildCommand+" -A",
			)
		}
		if hasArch {
			buildCommandParts = append(
				buildCommandParts,
				buildCommand+" -S",
				buildCommand+" -B",
			)
		}
		buildCommandParts = append(
			buildCommandParts,
			buildCommand+" -S",
			// end with a full build of "ALL THE THINGS" so we have good, consistent .changes and .dsc
			"rm ../*.changes ../*.dsc ../*.deb",
			buildCommand,
		)
		buildCommand = strings.Join(buildCommandParts, " && ")
	}

	dockerfile += fmt.Sprintf(`
WORKDIR /usr/src
RUN chown -R nobody:nogroup .
USER nobody:nogroup
RUN dpkg-source -x %q pkg

# work around overlayfs bugs (data inconsistency issues; see https://github.com/docker/docker/issues/10180)
VOLUME /usr/src/pkg
# rm: cannot remove 'pkg/.pc/xyz.patch': Directory not empty

RUN (cd pkg && set -x && %s) \
	&& mkdir .out \
	&& { \
		echo *.changes; \
		awk '$1 == "Files:" { files = 1; next } /^ / && files { print $5 } /^[^ ]/ { files = 0 }' *.changes; \
		echo .out/; \
	} | xargs ln -v
`, ".in/"+filepath.Base(dsc.Filename), buildCommand)

	err = dockerBuild(img, dockerfile, files...)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	return *dsc, img
}