aboutsummaryrefslogtreecommitdiffhomepage
path: root/gbp/deb
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2011-11-25 15:51:52 +0100
committerGuido Günther <agx@sigxcpu.org>2011-11-28 22:29:48 +0100
commitc9a1595a666cc83f9e9e523f0b4f27502f61b998 (patch)
tree83334959f3559d8836d8caecc5db7205b795a3bf /gbp/deb
parentf7a6b073a43e144d43550e92fc111d456c8bc973 (diff)
Add ChangeLog class
making it easier to query versions. Add tests.
Diffstat (limited to 'gbp/deb')
-rw-r--r--gbp/deb/__init__.py85
-rw-r--r--gbp/deb/changelog.py124
2 files changed, 127 insertions, 82 deletions
diff --git a/gbp/deb/__init__.py b/gbp/deb/__init__.py
index 881d1ae9..dc3ba8b6 100644
--- a/gbp/deb/__init__.py
+++ b/gbp/deb/__init__.py
@@ -27,6 +27,7 @@ import glob
import gbp.command_wrappers as gbpc
from gbp.errors import GbpError
from gbp.git import GitRepositoryError
+from gbp.deb.changelog import ChangeLog, NoChangeLogError
# When trying to parse a version-number from a dsc or changes file, these are
# the valid characters.
@@ -64,15 +65,6 @@ compressor_opts = { 'gzip' : [ '-n', 'gz' ],
compressor_aliases = { 'bz2' : 'bzip2',
'gz' : 'gzip', }
-class NoChangelogError(Exception):
- """no changelog found"""
- pass
-
-class ParseChangeLogError(Exception):
- """problem parsing changelog"""
- pass
-
-
class DpkgCompareVersions(gbpc.Command):
cmd='/usr/bin/dpkg'
@@ -390,58 +382,10 @@ def parse_changelog_repo(repo, branch, filename):
# repository errors.
sha = repo.rev_parse("%s:%s" % (branch, filename))
except GitRepositoryError:
- raise NoChangelogError, "Changelog %s not found in branch %s" % (filename, branch)
+ raise NoChangeLogError, "Changelog %s not found in branch %s" % (filename, branch)
lines = repo.show(sha)
- return parse_changelog('\n'.join(lines))
-
-def parse_changelog(contents=None, filename=None):
- """
- Parse the content of a changelog file. Either contents, containing
- the contents of a changelog file, or filename, pointing to a
- changelog file must be passed.
-
- Returns:
-
- cp['Version']: full version string including epoch
- cp['Upstream-Version']: upstream version, if not debian native
- cp['Debian-Version']: debian release
- cp['Epoch']: epoch, if any
- cp['NoEpoch-Version']: full version string excluding epoch
- """
- # Check that either contents or filename is passed (but not both)
- if (not filename and not contents) or (filename and contents):
- raise Exception("Either filename or contents must be passed to parse_changelog")
-
- # If a filename was passed, check if it exists
- if filename and not os.access(filename, os.F_OK):
- raise NoChangelogError, "Changelog %s not found" % (filename, )
-
- # If no filename was passed, let parse_changelog read from stdin
- if not filename:
- filename = '-'
-
- # Note that if contents is None, stdin will just be closed right
- # away by communicate.
- cmd = subprocess.Popen(['dpkg-parsechangelog', '-l%s' % filename], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (output, errors) = cmd.communicate(contents)
- if cmd.returncode:
- raise ParseChangeLogError, "Failed to parse changelog. dpkg-parsechangelog said:\n%s" % (errors, )
- # Parse the result of dpkg-parsechangelog (which looks like
- # email headers)
- cp = email.message_from_string(output)
- try:
- if ':' in cp['Version']:
- cp['Epoch'], cp['NoEpoch-Version'] = cp['Version'].split(':', 1)
- else:
- cp['NoEpoch-Version'] = cp['Version']
- if '-' in cp['NoEpoch-Version']:
- cp['Upstream-Version'], cp['Debian-Version'] = cp['NoEpoch-Version'].rsplit('-', 1)
- else:
- cp['Debian-Version'] = cp['NoEpoch-Version']
- except TypeError:
- raise ParseChangeLogError, output.split('\n')[0]
- return cp
+ return ChangeLog('\n'.join(lines))
def orig_file(cp, compression):
@@ -456,18 +400,6 @@ def orig_file(cp, compression):
ext = compressor_opts[compression][1]
return "%s_%s.orig.tar.%s" % (cp['Source'], cp['Upstream-Version'], ext)
-
-def is_native(cp):
- """
- Is this a debian native package
-
- >>> is_native(dict(Version="1"))
- True
- >>> is_native(dict(Version="1-1"))
- False
- """
- return not '-' in cp['Version']
-
def is_valid_packagename(name):
"Is this a valid Debian package name?"
return packagename_re.match(name)
@@ -497,17 +429,6 @@ def get_compression(orig_file):
return None
-def has_epoch(cp):
- """
- Does the topmost version number in the changelog contain an epoch
- >>> has_epoch(dict(Epoch="1"))
- True
- >>> has_epoch(dict())
- False
- """
- return cp.has_key("Epoch")
-
-
def has_orig(cp, compression, dir):
"Check if orig.tar.gz exists in dir"
try:
diff --git a/gbp/deb/changelog.py b/gbp/deb/changelog.py
new file mode 100644
index 00000000..bba8fa9a
--- /dev/null
+++ b/gbp/deb/changelog.py
@@ -0,0 +1,124 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2011 Guido Günther <agx@sigxcpu.org>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""A Debian Changelog"""
+
+import email
+import os
+import subprocess
+
+class NoChangeLogError(Exception):
+ """No changelog found"""
+ pass
+
+class ParseChangeLogError(Exception):
+ """Problem parsing changelog"""
+ pass
+
+class ChangeLog(object):
+ """A Debian changelog"""
+
+ def __init__(self, contents=None, filename=None):
+ """
+ Parse an existing changelog, Either contents, containing the contents
+ of a changelog file, or filename, pointing to a changelog file must be
+ passed.
+ """
+ # Check that either contents or filename is passed (but not both)
+ if (not filename and not contents) or (filename and contents):
+ raise Exception("Either filename or contents must be passed")
+
+ # If a filename was passed, check if it exists
+ if filename and not os.access(filename, os.F_OK):
+ raise NoChangeLogError, "Changelog %s not found" % (filename, )
+
+ # If no filename was passed, let's read from stdin
+ if not filename:
+ filename = '-'
+
+ # Note that if contents is None, stdin will just be closed right
+ # away by communicate.
+ cmd = subprocess.Popen(['dpkg-parsechangelog', '-l%s' % filename],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (output, errors) = cmd.communicate(contents)
+ if cmd.returncode:
+ raise ParseChangeLogError("Failed to parse changelog. "
+ "dpkg-parsechangelog said:\n%s" % (errors, ))
+ # Parse the result of dpkg-parsechangelog (which looks like
+ # email headers)
+ cp = email.message_from_string(output)
+ try:
+ if ':' in cp['Version']:
+ cp['Epoch'], cp['NoEpoch-Version'] = cp['Version'].split(':', 1)
+ else:
+ cp['NoEpoch-Version'] = cp['Version']
+ if '-' in cp['NoEpoch-Version']:
+ cp['Upstream-Version'], cp['Debian-Version'] = cp['NoEpoch-Version'].rsplit('-', 1)
+ else:
+ cp['Debian-Version'] = cp['NoEpoch-Version']
+ except TypeError:
+ raise ParseChangeLogError, output.split('\n')[0]
+
+ self._cp = cp
+
+ def __getitem__(self, item):
+ return self._cp[item]
+
+ def __setitem__(self, item, value):
+ self._cp[item] = value
+
+
+ @property
+ def version(self):
+ """The full version string"""
+ return self._cp['Version']
+
+ @property
+ def upstream_version(self):
+ """The upstream version"""
+ return self._cp['Upstream-Version']
+
+ @property
+ def debian_version(self):
+ """The Debian part of the version number"""
+ return self._cp['Debian-Version']
+
+ @property
+ def epoch(self):
+ """The package's epoch"""
+ return self._cp['Epoch']
+
+ @property
+ def noepoch(self):
+ """The version string without the epoch"""
+ return self._cp['NoEpoch-Version']
+
+ def has_epoch(self):
+ """
+ Whether the version has an epoch
+
+ @return: C{True} if the version has an epoch, C{False} otherwise
+ @rtype: C{bool}
+ """
+ return self._cp.has_key('Epoch')
+
+ def is_native(self):
+ """
+ Whether this is a native Debian package
+ """
+ return not '-' in self.version