コード例 #1
0
ファイル: src.go プロジェクト: tianon/gdbuild
func buildSrc(dir string) (control.Control, changelog.ChangelogEntry, string) {
	con, err := control.ParseControlFile(filepath.Join(dir, "debian/control"))
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	chg, err := changelog.ParseFileOne(filepath.Join(dir, "debian/changelog"))
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	img := fmt.Sprintf("gdbuild/src:%s_%s", con.Source.Source, scrubForDockerTag(chg.Version.String()))

	dockerfile := "FROM debian:unstable\n"
	// TODO allow this to instead be "FROM scratch\nADD some-chroot-tarball.tar.* /\n"

	dockerfile += `
RUN apt-get update && apt-get install -y --no-install-recommends \
		dpkg-dev \
	&& rm -rf /var/lib/apt/lists/*

WORKDIR /usr/src

`
	files := []string{}

	if !chg.Version.IsNative() {
		origBase := fmt.Sprintf("%s_%s.orig", con.Source.Source, chg.Version.Version)
		origs := []string{}
		for _, tarballDir := range tarballDirs {
			if !filepath.IsAbs(tarballDir) {
				tarballDir = filepath.Join(dir, tarballDir)
			}
			tarballs, err := filepath.Glob(filepath.Join(tarballDir, origBase+".tar.*"))
			if err != nil {
				log.Fatalf("error: %v\n", err)
			}
			if len(tarballs) > 0 {
				if len(tarballs) > 1 {
					log.Fatalf("error: found multiple base orig tarballs: %v\n", tarballs)
				}
				orig := tarballs[0]
				origs = append(origs, orig)
				tarballs, err = filepath.Glob(filepath.Join(tarballDir, origBase+"-*.tar.*"))
				if err != nil {
					log.Fatalf("error: %v\n", err)
				}
				origs = append(origs, tarballs...)
				break
			}
		}
		if len(origs) < 1 {
			log.Fatalf("error: unable to find orig tarball(s); searched for %s in %v\n", origBase+".tar.*", tarballDirs)
		}

		files = append(files, origs...)
		files = append(files, filepath.Join(dir, "debian"))

		dockerfile += "COPY"
		for _, f := range origs {
			dockerfile += " " + filepath.Base(f)
		}
		dockerfile += " /usr/src/.out/\n"
		dockerfile += fmt.Sprintf(`RUN set -ex \
	&& for f in .out/%q.tar.* .out/%q-*.tar.*; do \
		if [ -e "$f" ]; then \
			ln -s "$f" ./; \
		fi; \
	done
`, origBase, origBase)

		dockerfile += "\n# origtargz --unpack\n"
		re := regexp.MustCompile(fmt.Sprintf(`^%s(?:-(.*))?\.tar\..*$`, regexp.QuoteMeta(origBase)))
		dockerfile += "RUN set -ex"
		for _, f := range origs {
			orig := filepath.Base(f)
			targetDir := "pkg"
			matches := re.FindStringSubmatch(orig)
			if matches != nil && matches[1] != "" {
				targetDir += "/" + matches[1]
			}
			dockerfile += fmt.Sprintf(" \\\n\t&& mkdir %q && tar -xC %q -f %q --strip-components=1", targetDir, targetDir, orig)
		}
		dockerfile += " \\\n\t&& rm -rf /usr/src/pkg/debian\n"

		dockerfile += "\nCOPY debian /usr/src/pkg/debian\n"
	} else {
		absDir, err := filepath.Abs(dir)
		if err != nil {
			log.Fatalf("error: %v\n", err)
		}
		files = append(files, absDir)
		dockerfile += fmt.Sprintf("COPY %s /usr/src/pkg\n", filepath.Base(absDir))
	}

	outVer := chg.Version
	outVer.Epoch = 0
	pkgVer := con.Source.Source + "_" + outVer.String()
	links := fmt.Sprintf("%q %q", pkgVer+".dsc", pkgVer+"_source.changes")
	if chg.Version.IsNative() {
		links += fmt.Sprintf(" %q.tar.*", pkgVer)
	} else {
		links += fmt.Sprintf(" %q.debian.tar.*", pkgVer)
		links += fmt.Sprintf(" %q.diff.*", pkgVer)
	}
	dockerfile += fmt.Sprintf(`
# 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 && dpkg-buildpackage -uc -us -S -nc) \
	&& mkdir -p .out \
	&& set -ex \
	&& for f in %s; do \
		if [ -e "$f" ]; then \
			ln "$f" .out/; \
		fi; \
	done
`, links)

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

	return *con, *chg, img
}
コード例 #2
0
ファイル: main.go プロジェクト: tianon/dtodo
func main() {
	log.SetFlags(log.Lshortfile)

	// TODO configurable path?  perhaps allow for an optional *.dsc instead?
	con, err := control.ParseControlFile("debian/control")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	chg, err := changelog.ParseFileOne("debian/changelog")
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	// TODO configurable or something to avoid guesswork
	targetSuite := chg.Target
	if targetSuite == "UNRELEASED" {
		// check for "Upload to XYZ." or "Rebuild for XYZ." in changelog
		re := regexp.MustCompile(`^\s*\*?\s*(Upload\s+to|Rebuild\s+for)\s+(\S+?)\.?(\s+|$)`)
		matches := re.FindStringSubmatch(chg.Changelog)
		if matches != nil {
			targetSuite = matches[2]
		} else {
			targetSuite = "unstable"
		}
	}

	// TODO configurable (or auto-sensed from the mirror and/or package source)
	arches := []string{"amd64", "i386"}
	components := []string{"main", "contrib", "non-free"}

	fmt.Printf("Target: %s (%s)\n", targetSuite, chg.Target)
	fmt.Printf("Architectures: %s\n", strings.Join(arches, " "))
	fmt.Printf("Components: %s\n", strings.Join(components, " "))
	fmt.Printf("Source: %s\n", con.Source.Source)
	fmt.Printf("Version: %s\n", chg.Version)
	fmt.Printf("\n")

	indexSources := aptsources.DebianSources(targetSuite, components...)
	index, err := indexSources.FetchCandidates(arches...)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}

	incoming := NewTarget(
		"http://incoming.debian.org/debian-buildd",
		[]string{"buildd-" + targetSuite},
		components,
		arches,
	)
	if err = incoming.Fetch(); err != nil {
		log.Fatalf("error: %v\n", err)
	}

	newQueue, err := dnew.ParseNewUrl(dnew.New822)
	if err != nil {
		log.Fatalf("error: %v\n", err)
	}
	newBinaries := map[string]dnew.NewEntry{}
	for _, newPkg := range newQueue {
		for _, newBin := range newPkg.Binary {
			newBinaries[newBin] = newPkg
		}
	}

	allDeps := dependency.Dependency{}

	binRelation := dependency.Relation{}
	for _, bin := range con.Binaries {
		binRelation.Possibilities = append(binRelation.Possibilities, dependency.Possibility{
			Name: bin.Package,
			Version: &dependency.VersionRelation{
				Operator: "=",
				Number:   chg.Version.String(),
			},
		})
	}
	allDeps.Relations = append(allDeps.Relations, binRelation)

	allDeps.Relations = append(allDeps.Relations, con.Source.BuildDepends.Relations...)
	allDeps.Relations = append(allDeps.Relations, con.Source.BuildDependsIndep.Relations...)

	for _, bin := range con.Binaries {
		allDeps.Relations = append(allDeps.Relations, bin.Depends.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Recommends.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Suggests.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.Enhances.Relations...)
		allDeps.Relations = append(allDeps.Relations, bin.PreDepends.Relations...)
	}

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

	seenRelations := map[string]bool{}
	for _, relation := range allDeps.Relations {
		relationString := relation.String()
		if seenRelations[relationString] {
			continue
		}
		seenRelations[relationString] = true

		oneCan := false
		notes := []string{}
		for _, possi := range relation.Possibilities {
			if possi.Substvar {
				//fmt.Printf("ignoring substvar %s\n", possi)
				continue
			}
			can, why, _ := index.ExplainSatisfies(*depArch, possi)
			if !can {
				inCan, _, incomingBins := incoming.ExplainSatisfies(*depArch, possi)
				if !inCan {
					if newPkg, ok := newBinaries[possi.Name]; ok {
						newUrl := fmt.Sprintf("https://ftp-master.debian.org/new/%s_%s.html", newPkg.Source, newPkg.Version[0])
						notes = append(notes, fmt.Sprintf("NEW (%s): %s", possi.Name, newUrl))
					} else {
						notes = append(notes, why)
					}
				} else {
					notes = append(notes, fmt.Sprintf("incoming (%s): %s", possi.Name, incoming.UrlTo(incomingBins[0])))
				}
			} else {
				oneCan = true

				// TODO figure out how we can incorporate this ("Section: oldlibs" from debian/control doesn't propagate to the Packages file on the mirror, so we'd have to parse the .deb itself to get this info, which is fairly untenable)
				/*
					// NOTE "bins" is the last return value in the call to "index.ExplainSatisfies" above
					for _, bin := range bins {
						if bin.Section == "oldlibs" {
							oneCan = false
							notes = append(notes, fmt.Sprintf(`%s (%s) is "Section: oldlibs", which suggests it is likely transitional`, bin.Package, bin.Version.String()))
						}
					}
				*/
			}
		}
		if ignoreRelationSecondaryFails && oneCan {
			continue
		}
		if len(notes) > 0 {
			fmt.Printf("Relation: %s\n", relation)
			if len(notes) > 1 {
				fmt.Printf("Notes:\n %s\n", strings.Join(notes, "\n "))
			} else {
				fmt.Printf("Notes: %s\n", notes[0])
			}
			fmt.Printf("\n")
		}
	}
}