Control: tags -1 patch

Hi!

On Fri, 2016-11-18 at 12:57:12 +0100, Guillem Jover wrote:
> On Sun, 2016-11-06 at 14:16:14 +0100, Helmut Grohne wrote:
> > Package: reprepro
> > Version: 4.17.1-1
> > Severity: important
> > User: helm...@debian.org
> > Usertags: rebootstrap
> > 
> > Since dpkg 1.18.11, a .buildinfo file is generated as part of package
> > builds and referenced by .changes files. Supplying such a .changes file
> > to "reprepro include" results in an error:
> > 
> > | Unknown file type: '2d3e9992648837b6a4a8a5b819e6da8e 4791 devel optional 
> > binutils_2.27.51.20161105-1_20161106T104833z-2d3e9992.buildinfo', assuming 
> > source format...
> > | .changes put in a
> > | distribution not listed within it!
> > | Ignoring as --ignore=wrongdistribution given.
> > | 'binutils_2.27.51.20161105-1_20161106T104833z-2d3e9992.buildinfo' looks 
> > like part of an source package, but no dsc file listed in the .changes file!
> > | There have been errors!                                                   
> >                                                                             
> >                   
> > 
> > So any workflow based on importing .changes files from unstable (soon
> > stretch) is now broken.
> 
> I've just prepared a patch supposedly fixing this, but I've never used
> reprepro and don't even know how it works, so it's just built-tested.
> We are now performing some tests, and will update the report once this
> is confirmed to work.
> 
> (The preliminary and perhaps non-working patch can be found for now at
> https://www.hadrons.org/~guillem/tmp/0001-Add-preliminary-.buildinfo-support.patch)

Ok, Michael Prokop deployed it on jenkins.grml.org and retriggered at
least the dpkg jobs and they seem to work now. I've fixed an inversion
logic error in the previous patch and I'm including the good one here.
Review and more testing would be very appreciated.

Thanks,
Guillem
From c059c721863ad0b33ab44417640c37f6f8cfabf1 Mon Sep 17 00:00:00 2001
From: Guillem Jover <gjo...@sipwise.com>
Date: Fri, 18 Nov 2016 14:11:58 +0100
Subject: [PATCH] Add preliminary .buildinfo support

---
 changes.c       |  5 +++-
 changes.h       |  3 ++-
 checkin.c       | 51 +++++++++++++++++++++++++++++++------
 distribution.h  |  1 +
 docs/reprepro.1 |  3 +++
 incoming.c      | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 needbuild.c     |  2 +-
 tracking.c      | 10 ++++++--
 trackingt.h     |  1 +
 9 files changed, 141 insertions(+), 13 deletions(-)

diff --git a/changes.c b/changes.c
index 5d01754..2cafca3 100644
--- a/changes.c
+++ b/changes.c
@@ -237,6 +237,9 @@ retvalue changes_parsefileline(const char *fileline, /*@out@*/filetype *result_t
 		} else if (l > 6 && strncmp(p-6, ".build", 6) == 0) {
 			type = fe_LOG;
 			eoi = p - 6;
+		} else if (l > 10 && strncmp(p-10, ".buildinfo", 10) == 0) {
+			type = fe_BUILDINFO;
+			eoi = p - 10;
 		}
 		if (type != fe_UNKNOWN) {
 			/* check for a proper version */
@@ -255,7 +258,7 @@ retvalue changes_parsefileline(const char *fileline, /*@out@*/filetype *result_t
 					return RET_ERROR;
 				}
 				checkfilename = true;
-			} else if (type == fe_LOG) {
+			} else if (type == fe_LOG || type == fe_BUILDINFO) {
 				if (*p == '_') {
 					archstart = p + 1;
 					archend = eoi;
diff --git a/changes.h b/changes.h
index 30ad136..f2b72c3 100644
--- a/changes.h
+++ b/changes.h
@@ -10,7 +10,8 @@ typedef enum {
 	fe_DEB, fe_UDEB,
 	fe_DSC, fe_DIFF, fe_ORIG, fe_TAR,
 	fe_ALTSRC,
-	fe_BYHAND, fe_LOG, fe_CHANGES
+	fe_BYHAND, fe_LOG, fe_CHANGES,
+	fe_BUILDINFO
 } filetype;
 
 #define FE_PACKAGE(ft) ((ft) == fe_DEB || (ft) == fe_UDEB || (ft) == fe_DSC)
diff --git a/checkin.c b/checkin.c
index 3b1ec32..3eb552e 100644
--- a/checkin.c
+++ b/checkin.c
@@ -161,7 +161,7 @@ static void changes_free(/*@only@*/struct changes *changes) {
 }
 
 
-static retvalue newentry(struct fileentry **entry, const char *fileline, const struct atomlist *packagetypes, const struct atomlist *forcearchitectures, const char *sourcename, bool includebyhand, bool includelogs, bool *ignoredlines_p, bool skip_binaries) {
+static retvalue newentry(struct fileentry **entry, const char *fileline, const struct atomlist *packagetypes, const struct atomlist *forcearchitectures, const char *sourcename, bool includebyhand, bool includelogs, bool includebuildinfos, bool *ignoredlines_p, bool skip_binaries) {
 	struct fileentry *e;
 	retvalue r;
 
@@ -207,7 +207,7 @@ static retvalue newentry(struct fileentry **entry, const char *fileline, const s
 		*ignoredlines_p = true;
 		return RET_NOTHING;
 	}
-	if (e->type != fe_LOG &&
+	if (e->type != fe_LOG && e->type != fe_BUILDINFO &&
 			e->architecture_into == architecture_source &&
 			strcmp(e->name, sourcename) != 0) {
 		fprintf(stderr,
@@ -242,6 +242,34 @@ static retvalue newentry(struct fileentry **entry, const char *fileline, const s
 			*ignoredlines_p = true;
 			return RET_NOTHING;
 		}
+	} else if (e->type == fe_BUILDINFO) {
+		if (strcmp(e->name, sourcename) != 0) {
+			fprintf(stderr,
+"Warning: File '%s' looks like buildinfo but does not start with '%s_'!\n",
+					e->basename, sourcename);
+		}
+		if (!includebuildinfos) {
+			// TODO: at least check them and fail if wrong?
+			fprintf(stderr, "Ignoring buildinfo file: '%s'!\n",
+							e->basename);
+			freeentries(e);
+			*ignoredlines_p = true;
+			return RET_NOTHING;
+		}
+		if (atom_defined(e->architecture_into) &&
+				limitations_missed(forcearchitectures,
+					e->architecture_into)) {
+			if (verbose > 1)
+				fprintf(stderr,
+"Skipping '%s' as not for architecture ",
+					e->basename);
+			atomlist_fprint(stderr, at_architecture,
+					forcearchitectures);
+			fputs(".\n", stderr);
+			freeentries(e);
+			*ignoredlines_p = true;
+			return RET_NOTHING;
+		}
 	} else if (forcearchitectures != NULL) {
 		if (e->architecture_into == architecture_all &&
 				!skip_binaries) {
@@ -275,7 +303,7 @@ static retvalue newentry(struct fileentry **entry, const char *fileline, const s
 }
 
 /* Parse the Files-header to see what kind of files we carry around */
-static retvalue changes_parsefilelines(const char *filename, struct changes *changes, const struct strlist *filelines, const struct atomlist *packagetypes, const struct atomlist *forcearchitectures, bool includebyhand, bool includelogs, bool *ignoredlines_p, bool skip_binaries) {
+static retvalue changes_parsefilelines(const char *filename, struct changes *changes, const struct strlist *filelines, const struct atomlist *packagetypes, const struct atomlist *forcearchitectures, bool includebyhand, bool includelogs, bool includebuildinfos, bool *ignoredlines_p, bool skip_binaries) {
 	retvalue result, r;
 	int i;
 
@@ -287,7 +315,8 @@ static retvalue changes_parsefilelines(const char *filename, struct changes *cha
 
 		r = newentry(&changes->files, fileline,
 				packagetypes, forcearchitectures,
-				changes->source, includebyhand, includelogs,
+				changes->source,
+				includebyhand, includelogs, includebuildinfos,
 				ignoredlines_p, skip_binaries);
 		RET_UPDATE(result, r);
 		if (r == RET_ERROR)
@@ -374,7 +403,7 @@ static retvalue check(const char *filename, struct changes *changes, const char
 	return r;
 }
 
-static retvalue changes_read(const char *filename, /*@out@*/struct changes **changes, const struct atomlist *packagetypes, const struct atomlist *forcearchitectures, bool includebyhand, bool includelogs) {
+static retvalue changes_read(const char *filename, /*@out@*/struct changes **changes, const struct atomlist *packagetypes, const struct atomlist *forcearchitectures, bool includebyhand, bool includelogs, bool includebuildinfos) {
 	retvalue r;
 	struct changes *c;
 	struct strlist filelines[cs_hashCOUNT];
@@ -467,8 +496,8 @@ static retvalue changes_read(const char *filename, /*@out@*/struct changes **cha
 	}
 	r = changes_parsefilelines(filename, c, &filelines[cs_md5sum],
 			packagetypes, forcearchitectures,
-			includebyhand, includelogs, &ignoredlines,
-			skip_binaries);
+			includebyhand, includelogs, includebuildinfos,
+			&ignoredlines, skip_binaries);
 	if (RET_WAS_ERROR(r)) {
 		strlist_done(&filelines[cs_md5sum]);
 		changes_free(c);
@@ -1242,6 +1271,11 @@ static retvalue changes_includepkgs(struct distribution *distribution, struct ch
 					distribution, trackingdata);
 			if (r == RET_NOTHING)
 				*missed_p = true;
+		} else if (e->type == fe_BUILDINFO && trackingdata != NULL) {
+			r = trackedpackage_addfilekey(trackingdata->tracks,
+					trackingdata->pkg,
+					ft_BUILDINFO, e->filekey, false);
+			e->filekey = NULL;
 		} else if (e->type == fe_LOG && trackingdata != NULL) {
 			r = trackedpackage_addfilekey(trackingdata->tracks,
 					trackingdata->pkg,
@@ -1359,7 +1393,8 @@ retvalue changes_add(trackingdb const tracks, const struct atomlist *packagetype
 	r = changes_read(changesfilename, &changes,
 			packagetypes, forcearchitectures,
 			distribution->trackingoptions.includebyhand,
-			distribution->trackingoptions.includelogs);
+			distribution->trackingoptions.includelogs,
+			distribution->trackingoptions.includebuildinfos);
 	if (RET_WAS_ERROR(r))
 		return r;
 
diff --git a/distribution.h b/distribution.h
index 2a2ba64..733a68e 100644
--- a/distribution.h
+++ b/distribution.h
@@ -70,6 +70,7 @@ struct distribution {
 	enum trackingtype { dt_NONE=0, dt_KEEP, dt_ALL, dt_MINIMAL } tracking;
 	struct trackingoptions { bool includechanges;
 		bool includebyhand;
+		bool includebuildinfos;
 		bool includelogs;
 		bool needsources;
 		bool keepsources;
diff --git a/docs/reprepro.1 b/docs/reprepro.1
index 485b449..6b37826 100644
--- a/docs/reprepro.1
+++ b/docs/reprepro.1
@@ -1514,6 +1514,9 @@ Thus it is also put into the pool.
 Add \fBbyhand\fP and \fBraw\-\fP\fI*\fP files to the tracked
 files and thus in the pool.
 .br
+.B includebuildinfos
+Add buildinfo files to the tracked files and thus in the pool.
+.br
 .B includelogs
 Add log files to the tracked files and thus in the pool.
 (Not that putting log files in changes files is a reprepro
diff --git a/incoming.c b/incoming.c
index 029931b..0b2c221 100644
--- a/incoming.c
+++ b/incoming.c
@@ -1116,6 +1116,73 @@ static retvalue candidate_read_files(struct incoming *i, struct candidate *c) {
 	return RET_OK;
 }
 
+static retvalue candidate_preparebuildinfos(const struct incoming *i, const struct candidate *c, struct candidate_perdistribution *per) {
+	retvalue r;
+	struct candidate_package *package;
+	struct candidate_file *firstbuildinfo = NULL, *file;
+	component_t component = component_strange;
+	int count = 0;
+
+	for (file = c->files ; file != NULL ; file = file->next) {
+		if (file->type == fe_BUILDINFO) {
+			count++;
+			if (firstbuildinfo == NULL)
+				firstbuildinfo = file;
+		}
+	}
+	if (count == 0)
+		return RET_NOTHING;
+
+	/* search for a component to use */
+	for (package = per->packages ; package != NULL ;
+	                               package = package->next) {
+		if (atom_defined(package->component)) {
+			component = package->component;
+			break;
+		}
+	}
+
+	/* pseudo package containing buildinfo files */
+	package = candidate_newpackage(per, firstbuildinfo);
+	if (FAILEDTOALLOC(package))
+		return RET_ERROR_OOM;
+	r = strlist_init_n(count, &package->filekeys);
+	if (RET_WAS_ERROR(r))
+		return r;
+	package->files = nzNEW(count, const struct candidate_file *);
+	if (FAILEDTOALLOC(package->files))
+		return RET_ERROR_OOM;
+
+	for (file = c->files ; file != NULL ; file = file->next) {
+		char *filekey;
+
+		if (file->type != fe_BUILDINFO)
+			continue;
+
+		r = candidate_usefile(i, c, file);
+		if (RET_WAS_ERROR(r))
+			return r;
+
+		// TODO: add same checks on the basename contents?
+
+		filekey = calc_filekey(component, c->source, BASENAME(i, file->ofs));
+		if (FAILEDTOALLOC(filekey))
+			return RET_ERROR_OOM;
+
+		r = files_canadd(filekey, file->checksums);
+		if (RET_WAS_ERROR(r))
+			return r;
+		if (RET_IS_OK(r))
+			package->files[package->filekeys.count] = file;
+		r = strlist_add(&package->filekeys, filekey);
+		assert (r == RET_OK);
+	}
+	assert (package->filekeys.count == count);
+	return RET_OK;
+}
+
+
+
 static retvalue candidate_preparechangesfile(const struct candidate *c, struct candidate_perdistribution *per) {
 	retvalue r;
 	char *basefilename, *filekey;
@@ -1614,6 +1681,11 @@ static retvalue prepare_for_distribution(const struct incoming *i, const struct
 			if (RET_WAS_ERROR(r))
 				return r;
 		}
+		if (d->into->trackingoptions.includebuildinfos) {
+			r = candidate_preparebuildinfos(i, c, d);
+			if (RET_WAS_ERROR(r))
+				return r;
+		}
 		if (d->into->trackingoptions.includechanges) {
 			r = candidate_preparechangesfile(c, d);
 			if (RET_WAS_ERROR(r))
@@ -1795,6 +1867,12 @@ static retvalue candidate_add_into(const struct incoming *i, const struct candid
 			r = trackedpackage_adddupfilekeys(trackingdata.tracks,
 					trackingdata.pkg,
 					ft_XTRA_DATA, &p->filekeys, false);
+		} else if (p->master->type == fe_BUILDINFO) {
+			assert (tracks != NULL);
+
+			r = trackedpackage_adddupfilekeys(trackingdata.tracks,
+					trackingdata.pkg,
+					ft_BUILDINFO, &p->filekeys, false);
 		} else if (p->master->type == fe_LOG) {
 			assert (tracks != NULL);
 
diff --git a/needbuild.c b/needbuild.c
index 8aaa52d..2001221 100644
--- a/needbuild.c
+++ b/needbuild.c
@@ -90,7 +90,7 @@ static retvalue tracked_source_needs_build(architecture_t architecture, const ch
 			   so nothing is to be done */
 			return RET_NOTHING;
 		}
-		if (ft == ft_LOG || ft == ft_CHANGES) {
+		if (ft == ft_LOG || ft == ft_BUILDINFO || ft == ft_CHANGES) {
 			const char *a = strrchr(fk, '_');
 			const char *e;
 
diff --git a/tracking.c b/tracking.c
index c231e90..ab1fcfa 100644
--- a/tracking.c
+++ b/tracking.c
@@ -85,6 +85,7 @@ retvalue tracking_initialize(/*@out@*/trackingdb *db, const struct distribution
 static inline enum filetype filetypechar(enum filetype filetype) {
 	switch (filetype) {
 		case ft_LOG:
+		case ft_BUILDINFO:
 		case ft_CHANGES:
 		case ft_ALL_BINARY:
 		case ft_ARCH_BINARY:
@@ -697,6 +698,7 @@ retvalue tracking_foreach_ro(struct distribution *d, tracking_foreach_ro_action
 retvalue tracking_parse(struct distribution *d, struct configiterator *iter) {
 	enum trackingflags { tf_keep, tf_all, tf_minimal,
 		tf_includechanges, tf_includebyhand, tf_includelogs,
+		tf_includebuildinfos,
 		tf_keepsources,
 		tf_needsources, tf_embargoalls,
 		tf_COUNT /* must be last */
@@ -706,6 +708,7 @@ retvalue tracking_parse(struct distribution *d, struct configiterator *iter) {
 		{"all",		tf_all},
 		{"minimal",	tf_minimal},
 		{"includechanges",	tf_includechanges},
+		{"includebuildinfos",	tf_includebuildinfos},
 		{"includelogs",		tf_includelogs},
 		{"includebyhand",	tf_includebyhand},
 		{"keepsources",		tf_keepsources},
@@ -749,6 +752,7 @@ retvalue tracking_parse(struct distribution *d, struct configiterator *iter) {
 
 	d->trackingoptions.includechanges = flags[tf_includechanges];
 	d->trackingoptions.includebyhand = flags[tf_includebyhand];
+	d->trackingoptions.includebuildinfos = flags[tf_includebuildinfos];
 	d->trackingoptions.includelogs = flags[tf_includelogs];
 	d->trackingoptions.keepsources = flags[tf_keepsources];
 	d->trackingoptions.needsources = flags[tf_needsources];
@@ -953,10 +957,12 @@ static inline retvalue trackedpackage_removeall(trackingdb tracks, struct tracke
 static inline bool tracking_needed(trackingdb tracks, struct trackedpackage *pkg, int ofs) {
 	if (pkg->refcounts[ofs] > 0)
 		return true;
-	// TODO: add checks so that only .changes and .log files belonging
-	// to still existing binaries are kept in minimal mode
+	// TODO: add checks so that only .changes, .buildinfo and .log files
+	// belonging to still existing binaries are kept in minimal mode
 	if (pkg->filetypes[ofs] == ft_LOG && tracks->options.includelogs)
 		return true;
+	if (pkg->filetypes[ofs] == ft_BUILDINFO && tracks->options.includebuildinfos)
+		return true;
 	if (pkg->filetypes[ofs] == ft_CHANGES && tracks->options.includechanges)
 		return true;
 	if (pkg->filetypes[ofs] == ft_XTRA_DATA)
diff --git a/trackingt.h b/trackingt.h
index ce7670c..6faf093 100644
--- a/trackingt.h
+++ b/trackingt.h
@@ -5,6 +5,7 @@ enum filetype { ft_ALL_BINARY='a',
 		ft_ARCH_BINARY='b',
 		ft_CHANGES = 'c',
 		ft_LOG='l',
+		ft_BUILDINFO='i',
 		ft_SOURCE='s',
 		ft_XTRA_DATA='x'};
 
-- 
2.10.2

Reply via email to