[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: simple next step for getting .buildinfo files into Debian



Holger Levsen:
> Hi ftp folks,
> 

Hi,

> while we still appreciate your comments on this proposal as last week 
> described in https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=763822 I'd like 
> to make a intermediate very simple proposal, so that reproducible builds in 
> Debian get one step forward:
> 

I have started a git branch, build-info-support, available from:

* ssh://release.debian.org/~nthykier/dak

I realise that not every one have access to that machine, so the patches
are also attached (@FTP: The branch have signed commits, so you may
prefer merging form that).

> - modify dak, so that it will not rejects uploads with a .buildinfo file 
> included. 

I got patches to have dak accept these and do some trivial validation
(but not every validation proposed).  I will extend my branch as time
permits with additional checks.

> - still, for now, throw the .buildinfo file immediately away.

I have assumed this happens if you do no nothing explicitly with the
file after it being accepted.

 * @FTP: If not, please let me know how I can have dak discard the file.

> - only do this for experimental at the beginning. (maybe this restriction is 
> not even needed/useful.)
> 

 * Given the file is discarded, I have not added any such restrictions
   in my patch series.

> That's it.
> 
> This would allow the dpkg maintainers to enable .buildinfo file creation, at 
> least for builds for experimental.
> 
> What do you think?
> 

FWIW, I agree. :)

> As I see it, this should be a rather trivial code change for dak and yet bring 
> us forward quite enourmously. Also it should be rather uncontroversial as we 
> all agreed in Heidelberg at DebConf15 that we want .buildinfo files in Debian… 
> 
> 
> cheers,
> 	Holger
> 


Thanks,
~Niels


From 10bc29c42eb36916aba1290c155126755837d903 Mon Sep 17 00:00:00 2001
From: Niels Thykier <niels@thykier.net>
Date: Mon, 14 Dec 2015 20:46:28 +0000
Subject: [PATCH 1/2] daklib/upload.py: Silently accept and discard .buildinfo
 files

Besides some very trivial validation of the filename, accept
.buildinfo files without really looking at them.

Signed-off-by: Niels Thykier <niels@thykier.net>
---
 daklib/regexes.py | 4 ++++
 daklib/upload.py  | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/daklib/regexes.py b/daklib/regexes.py
index ae8fd91..63d2ee6 100644
--- a/daklib/regexes.py
+++ b/daklib/regexes.py
@@ -141,6 +141,10 @@ re_file_source = re.compile(_re_file_prefix + r'(?:(?:\.orig(?:-[a-zA-Z0-9-]+)?|
 # Groups: package, version
 re_file_orig = re.compile(_re_file_prefix + r'\.orig(?:-[a-zA-Z0-9-]+)?(?:\.tar\.(?:bz2|gz|xz)|\.asc)')
 
+# Match buildinfo file
+# Groups: package, version, suffix
+re_file_buildinfo = re.compile(_re_file_prefix + r'_(?P<suffix>[a-zA-Z0-9+]+)\.changes$')
+
 ######################################################################
 # Patterns matching fields                                           #
 ######################################################################
diff --git a/daklib/upload.py b/daklib/upload.py
index b78d100..4c10f45 100644
--- a/daklib/upload.py
+++ b/daklib/upload.py
@@ -374,6 +374,8 @@ class Changes(object):
         for f in self.files.itervalues():
             if re_file_dsc.match(f.filename) or re_file_source.match(f.filename) or re_file_binary.match(f.filename):
                 continue
+            if re_file_buildinfo.match(f.filename):
+                continue
             if f.section != 'byhand' and f.section[:4] != 'raw-':
                 raise InvalidChangesException("{0}: {1} looks like a byhand package, but is in section {2}".format(self.filename, f.filename, f.section))
             byhand.append(f)
-- 
2.6.2

From 603ab424528a6f698332636ef3c80031a4e8c39c Mon Sep 17 00:00:00 2001
From: Niels Thykier <niels@thykier.net>
Date: Mon, 14 Dec 2015 21:06:55 +0000
Subject: [PATCH 2/2] Do very basic validation of .buildinfo files

Validate that .buildinfo:

 * Have a valid signature (if signed)
 * Are Deb822 control files (UTF-8 encoded)
 * Have a Source and Version field equal to that of the .changes
   file.
---
 daklib/archive.py |  1 +
 daklib/checks.py  | 25 +++++++++++++++++++++++++
 daklib/upload.py  | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)

diff --git a/daklib/archive.py b/daklib/archive.py
index 4226ce9..6a044db 100644
--- a/daklib/archive.py
+++ b/daklib/archive.py
@@ -951,6 +951,7 @@ class ArchiveUpload(object):
                     checks.BinaryCheck,
                     checks.BinaryTimestampCheck,
                     checks.SingleDistributionCheck,
+                    checks.BuildinfoCheck,
                     ):
                 chk().check(self)
 
diff --git a/daklib/checks.py b/daklib/checks.py
index b187f03..07c43f9 100644
--- a/daklib/checks.py
+++ b/daklib/checks.py
@@ -500,6 +500,31 @@ class SourceCheck(Check):
 
         return True
 
+
+class BuildinfoCheck(Check):
+    """Check buildinfo file for syntax errors."""
+
+    def check(self, upload):
+        buildinfo_files = upload.changes.buildinfo_files
+        if not buildinfo_files:
+            return True
+
+        changes = upload.changes.changes
+
+        for buildinfo_file in buildinfo_files:
+            control = buildinfo_file.buildinfo
+            bi_fn = buildinfo_file.filename
+            check_fields_for_valid_utf8(bi_fn, control)
+
+            # check fields
+            if not re_field_package.match(control['Source']):
+                raise Reject('{0}: Invalid Source field'.format(bi_fn))
+            if control['Source'] != changes['Source']:
+                raise Reject('{0}: Source field does not match Source field in changes'.format(bi_fn))
+            if control['Version'] != changes['Version']:
+                raise Reject('{0}: Version field does not match Version field in changes'.format(bi_fn))
+        return True
+
 class SingleDistributionCheck(Check):
     """Check that the .changes targets only a single distribution."""
     def check(self, upload):
diff --git a/daklib/upload.py b/daklib/upload.py
index 4c10f45..361febf 100644
--- a/daklib/upload.py
+++ b/daklib/upload.py
@@ -276,6 +276,7 @@ class Changes(object):
 
         self._binaries = None
         self._source = None
+        self._buildinfo_files = None
         self._files = None
         self._keyrings = keyrings
         self._require_signature = require_signature
@@ -365,6 +366,16 @@ class Changes(object):
         return self._binaries
 
     @property
+    def buildinfo_files(self):
+        if self._buildinfo_files is None:
+            buildinfo_files = []
+            for f in self.files.itervalues():
+                if re_file_buildinfo.match(f.filename):
+                    buildinfo_files.append(Binary(self.directory, f))
+            self._buildinfo_files = buildinfo_files
+        return self._buildinfo_files
+
+    @property
     def byhand_files(self):
         """included byhand files
         @type: list of L{daklib.upload.HashedFile}
@@ -596,3 +607,41 @@ class Source(object):
         @type: str
         """
         return self._dsc_file.filename
+
+
+class Buildinfo(object):
+    """Representation of a buildinfo file
+    """
+    def __init__(self, directory, hashed_file):
+        self.hashed_file = hashed_file
+        """the buildinfo file
+        @type: L{HashedFile}
+        """
+
+        buildinfo_file_path = os.path.join(directory, self.hashed_file.input_filename)
+        with open(buildinfo_file_path, 'r') as fd:
+            data = fd.read()
+        self._buildinfo = apt_pkg.TagSection(data)
+        """dict to access fields in the .dsc file
+        @type: dict-like
+        """
+
+    @classmethod
+    def from_file(cls, directory, filename):
+        hashed_file = HashedFile.from_file(directory, filename)
+        return cls(directory, hashed_file)
+
+    @property
+    def buildinfo(self):
+        """dict mapping of the .buildinfo file as a deb822 control file
+
+        @type: dict
+        """
+        return self._buildinfo
+
+    @property
+    def filename(self):
+        """filename of .buildinfo file
+        @type: str
+        """
+        return self.hashed_file.filename
-- 
2.6.2

Attachment: signature.asc
Description: OpenPGP digital signature


Reply to: