diff options
author | SoonKyu Park <sk7.park@samsung.com> | 2016-04-11 13:21:01 +0900 |
---|---|---|
committer | SoonKyu Park <sk7.park@samsung.com> | 2016-04-11 13:21:01 +0900 |
commit | 8e7c90b9ae69aad55495a8f5be4e94b498052166 (patch) | |
tree | 214b01911f079ba147da9ddb48449ad75842e2f0 /gbp | |
parent | 96398c46398eec541b59df3997e5b8b2a392ee56 (diff) | |
parent | 8456b886b0fcd8ce465c3e3c44b47beeaf436afb (diff) | |
download | git-buildpackage-8e7c90b9ae69aad55495a8f5be4e94b498052166.tar.gz git-buildpackage-8e7c90b9ae69aad55495a8f5be4e94b498052166.tar.bz2 git-buildpackage-8e7c90b9ae69aad55495a8f5be4e94b498052166.zip |
Handle conflicts from git merge release-20160315release-20160411
Diffstat (limited to 'gbp')
-rw-r--r-- | gbp/config.py | 16 | ||||
-rw-r--r-- | gbp/deb/git.py | 3 | ||||
-rw-r--r-- | gbp/format.py | 44 | ||||
-rw-r--r-- | gbp/git/repository.py | 27 | ||||
-rw-r--r-- | gbp/git/vfs.py | 2 | ||||
-rw-r--r-- | gbp/log.py | 32 | ||||
-rw-r--r-- | gbp/patch_series.py | 8 | ||||
-rw-r--r-- | gbp/pkg/__init__.py | 39 | ||||
-rw-r--r-- | gbp/rpm/__init__.py | 2 | ||||
-rw-r--r-- | gbp/rpm/lib_rpm.py | 1 | ||||
-rw-r--r-- | gbp/rpm/linkedlist.py | 4 | ||||
-rwxr-xr-x | gbp/scripts/buildpackage.py | 12 | ||||
-rwxr-xr-x | gbp/scripts/buildpackage_rpm.py | 13 | ||||
-rwxr-xr-x | gbp/scripts/clone.py | 2 | ||||
-rw-r--r-- | gbp/scripts/common/buildpackage.py | 1 | ||||
-rw-r--r-- | gbp/scripts/common/import_orig.py | 105 | ||||
-rwxr-xr-x | gbp/scripts/create_remote_repo.py | 2 | ||||
-rwxr-xr-x | gbp/scripts/dch.py | 35 | ||||
-rwxr-xr-x | gbp/scripts/import_dsc.py | 2 | ||||
-rw-r--r-- | gbp/scripts/import_dscs.py | 2 | ||||
-rw-r--r-- | gbp/scripts/import_orig.py | 16 | ||||
-rwxr-xr-x | gbp/scripts/import_srpm.py | 2 | ||||
-rwxr-xr-x | gbp/scripts/pq.py | 87 | ||||
-rwxr-xr-x | gbp/scripts/pq_rpm.py | 7 | ||||
-rwxr-xr-x | gbp/scripts/pull.py | 2 | ||||
-rw-r--r-- | gbp/scripts/supercommand.py | 59 |
26 files changed, 394 insertions, 131 deletions
diff --git a/gbp/config.py b/gbp/config.py index 90c5068d..9fd31b73 100644 --- a/gbp/config.py +++ b/gbp/config.py @@ -112,6 +112,7 @@ class GbpOptionParser(OptionParser): 'build' : 'True', 'hooks' : 'True', 'debian-tag' : 'debian/%(version)s', + 'debian-tag-msg' : '%(pkg)s Debian release %(version)s', 'upstream-tag' : 'upstream/%(version)s', 'import-msg' : 'Imported Upstream version %(version)s', 'commit-msg' : 'Update changelog for %(version)s release', @@ -159,6 +160,8 @@ class GbpOptionParser(OptionParser): 'allow-unauthenticated': 'False', 'symlink-orig': 'True', 'purge': 'True', + 'drop': 'False', + 'commit': 'False', 'tmp-dir' : '/var/tmp/gbp/', } help = { @@ -177,6 +180,9 @@ class GbpOptionParser(OptionParser): 'debian-tag': ("Format string for debian tags, " "default is '%(debian-tag)s'"), + 'debian-tag-msg': + ("Format string for signed debian-tag messages, " + "default is '%(debian-tag-msg)s'"), 'upstream-tag': ("Format string for upstream tags, " "default is '%(upstream-tag)s'"), @@ -206,6 +212,8 @@ class GbpOptionParser(OptionParser): "Include the full commit message instead of only the first line, default is '%(full)s'", 'meta': "Parse meta tags in commit messages, default is '%(meta)s'", + 'meta-closes': + "Meta tags for the bts close commands, default is '%(meta-closes)s'", 'ignore-new': "Build with uncommited changes in the source tree, default is '%(ignore-new)s'", 'ignore-branch': @@ -302,7 +310,12 @@ class GbpOptionParser(OptionParser): "'%(symlink-orig)s'"), 'purge': "Purge exported package build directory. Default is '%(purge)s'", - 'tmp-dir': + 'drop': + ("In case of 'export' drop the patch-queue branch " + "after export. Default is '%(drop)s'"), + 'commit': + "commit changes after export, Default is '%(commit)s'", + 'tmp-dir': ("Base directory under which temporary directories are " "created, default is '%(tmp-dir)s'"), } @@ -672,4 +685,5 @@ class GbpOptionParserRpm(GbpOptionParser): "'%(meta-bts)s'"), } ) + # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/deb/git.py b/gbp/deb/git.py index 6105fe7d..2a848d4f 100644 --- a/gbp/deb/git.py +++ b/gbp/deb/git.py @@ -19,6 +19,7 @@ import re from gbp.git import GitRepository, GitRepositoryError from gbp.deb.pristinetar import DebianPristineTar +from gbp.format import format_msg class DebianGitRepository(GitRepository): """A git repository that holds the source of a Debian package""" @@ -104,7 +105,7 @@ class DebianGitRepository(GitRepository): >>> DebianGitRepository.version_to_tag("debian/%(version)s", "0:0~0") 'debian/0%0_0' """ - return format % dict(version=DebianGitRepository._sanitize_version(version)) + return format_msg(format, dict(version=DebianGitRepository._sanitize_version(version))) @staticmethod def _sanitize_version(version): diff --git a/gbp/format.py b/gbp/format.py new file mode 100644 index 00000000..2a4af15c --- /dev/null +++ b/gbp/format.py @@ -0,0 +1,44 @@ +# vim: set fileencoding=utf-8 : +# +# (C) 2014 Guido Guenther <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 +"""Format a message""" + +from gbp.errors import GbpError + +def format_msg(msg, args): + """ + Format a strin with the given dict. Be a bit more verbose than + default python about the error cause. + + >>> format_msg("%(foo)", {}) + Traceback (most recent call last): + ... + GbpError: Failed to format %(foo): Missing value 'foo' in {} + >>> format_msg("%(foo)", {'foo': 'bar'}) + Traceback (most recent call last): + ... + GbpError: Failed to format %(foo) with {'foo': 'bar'}: incomplete format + >>> format_msg("A %(foo)s is a %(bar)s", {'foo': 'dog', 'bar': 'mamal'}) + 'A dog is a mamal' + """ + try: + return msg % args + except ValueError as e: + raise GbpError("Failed to format %s with %s: %s" % (msg, args, e)) + except KeyError as e: + raise GbpError("Failed to format %s: Missing value %s in %s" % (msg, e, args)) + + diff --git a/gbp/git/repository.py b/gbp/git/repository.py index 6b21c252..20251a00 100644 --- a/gbp/git/repository.py +++ b/gbp/git/repository.py @@ -252,7 +252,12 @@ class GitRepository(object): ready = select.select(out_fds, in_fds, []) # Write in chunks of 512 bytes if ready[1]: - popen.stdin.write(stdin[w_ind:w_ind+512]) + try: + popen.stdin.write(stdin[w_ind:w_ind+512]) + except IOError: + # Ignore, we want to read buffers to e.g. get error message + # Git should give an error code so that we catch an error + pass w_ind += 512 if w_ind > len(stdin): rm_polled_fd(popen.stdin, in_fds) @@ -695,7 +700,8 @@ class GitRepository(object): #{ Tags - def create_tag(self, name, msg=None, commit=None, sign=False, keyid=None): + def create_tag(self, name, msg=None, commit=None, sign=False, keyid=None, + annotate=False): """ Create a new tag. @@ -710,15 +716,18 @@ class GitRepository(object): @type sign: C{bool} @param keyid: the GPG keyid used to sign the tag @type keyid: C{str} + @param annotate: Create an annotated tag + @type annotate: C{bool} """ - args = [] - args += [ '-m', msg ] if msg else [] + args = GitArgs() + args.add_true(msg, ['-m', msg]) if sign: - args += [ '-s' ] - args += [ '-u', keyid ] if keyid else [] - args += [ name ] - args += [ commit ] if commit else [] - self._git_command("tag", args) + args.add('-s') + args.add_true(keyid, ['-u', keyid]) + args.add_true(annotate, '-a') + args.add(name) + args.add_true(commit, commit) + self._git_command("tag", args.args, interactive=True) def delete_tag(self, tag): """ diff --git a/gbp/git/vfs.py b/gbp/git/vfs.py index 81649eb9..5d5e1323 100644 --- a/gbp/git/vfs.py +++ b/gbp/git/vfs.py @@ -41,7 +41,7 @@ class GitVfs(object): return self._data.read(size) def close(self): - return self.close() + return self._data.close() def __init__(self, repo, committish=None): """ @@ -96,29 +96,35 @@ class GbpStreamHandler(logging.StreamHandler): class GbpLogger(logging.Logger): """Logger class for git-buildpackage""" - def __init__(self, name, color='auto', *args, **kwargs): + def __init__(self, name, *args, **kwargs): logging.Logger.__init__(self, name, *args, **kwargs) - self._default_handlers = [GbpStreamHandler(sys.stdout, color), - GbpStreamHandler(sys.stderr, color)] - self._default_handlers[0].addFilter(GbpFilter([DEBUG, INFO])) - self._default_handlers[1].addFilter(GbpFilter([WARNING, ERROR, - CRITICAL])) - for hdlr in self._default_handlers: + self.default_handlers = [] + + def init_default_handlers(self, color='auto'): + """Initialize and set default handlers to logger""" + self.default_handlers = [GbpStreamHandler(sys.stdout, color), + GbpStreamHandler(sys.stderr, color)] + self.default_handlers[0].addFilter(GbpFilter([DEBUG, INFO])) + self.default_handlers[1].addFilter(GbpFilter([WARNING, ERROR, + CRITICAL])) + for hdlr in self.default_handlers: self.addHandler(hdlr) + # We don't want to propagate as we add our own handlers + self.propagate = False def set_color(self, color): """Set/unset colorized output of the default handlers""" - for hdlr in self._default_handlers: + for hdlr in self.default_handlers: hdlr.set_color(color) def set_color_scheme(self, color_scheme={}): """Set the color scheme of the default handlers""" - for hdlr in self._default_handlers: + for hdlr in self.default_handlers: hdlr.set_color_scheme(color_scheme) def set_format(self, fmt): """Set the format of the default handlers""" - for hdlr in self._default_handlers: + for hdlr in self.default_handlers: hdlr.set_format(fmt) @@ -168,7 +174,11 @@ def getLogger(*args, **kwargs): """Gbp-specific function""" if not issubclass(logging.getLoggerClass(), GbpLogger): logging.setLoggerClass(GbpLogger) - return logging.getLogger(*args, **kwargs) + color = kwargs.pop('color') if 'color' in kwargs else 'auto' + logger = logging.getLogger(*args, **kwargs) + if hasattr(logger, 'default_handlers') and not logger.default_handlers: + logger.init_default_handlers(color) + return logger def setup(color, verbose, color_scheme=""): """Basic logger setup""" diff --git a/gbp/patch_series.py b/gbp/patch_series.py index 10fccfc6..327997f5 100644 --- a/gbp/patch_series.py +++ b/gbp/patch_series.py @@ -95,6 +95,12 @@ class Patch(object): >>> p = Patch('debian/patches/foo') >>> p._get_subject_from_filename() 'foo' + >>> Patch('0123-foo.patch')._get_subject_from_filename() + 'foo' + >>> Patch('0123.patch')._get_subject_from_filename() + '0123' + >>> Patch('0123-foo-0123.patch')._get_subject_from_filename() + 'foo-0123' @return: the patch's subject @rtype: C{str} @@ -107,7 +113,7 @@ class Patch(object): subject = base except ValueError: pass # No ext so keep subject as is - return subject + return subject.lstrip('0123456789-') or subject def _get_info_field(self, key, get_val=None): """ diff --git a/gbp/pkg/__init__.py b/gbp/pkg/__init__.py index f02caf01..8162286b 100644 --- a/gbp/pkg/__init__.py +++ b/gbp/pkg/__init__.py @@ -38,9 +38,9 @@ compressor_aliases = { 'bz2' : 'bzip2', 'gz' : 'gzip', } # Supported archive formats -arhive_formats = [ 'tar', 'zip' ] +archive_formats = [ 'tar', 'zip' ] -# Map combined file extensions to arhive and compression format +# Map combined file extensions to archive and compression format archive_ext_aliases = { 'tgz' : ('tar', 'gzip'), 'tbz2' : ('tar', 'bzip2'), 'tlz' : ('tar', 'lzma'), @@ -82,7 +82,7 @@ def parse_archive_filename(filename): if split[-1] in archive_ext_aliases: base_name = ".".join(split[:-1]) (archive_fmt, compression) = archive_ext_aliases[split[-1]] - elif split[-1] in arhive_formats: + elif split[-1] in archive_formats: base_name = ".".join(split[:-1]) (archive_fmt, compression) = (split[-1], None) else: @@ -90,7 +90,7 @@ def parse_archive_filename(filename): if o[1] == split[-1]: base_name = ".".join(split[:-1]) compression = c - if len(split) > 2 and split[-2] in arhive_formats: + if len(split) > 2 and split[-2] in archive_formats: base_name = ".".join(split[:-2]) archive_fmt = split[-2] @@ -142,8 +142,8 @@ class PkgPolicy(object): return True return False - @classmethod - def guess_upstream_src_version(cls, filename, extra_regex=r''): + @staticmethod + def guess_upstream_src_version(filename, extra_regex=r''): """ Guess the package name and version from the filename of an upstream archive. @@ -158,7 +158,7 @@ class PkgPolicy(object): >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.orig.tar.gz') ('foo-bar', '0.2') >>> PkgPolicy.guess_upstream_src_version('foo-Bar_0.2.orig.tar.gz') - ('foo-Bar', '0.2.orig') + ('', '') >>> PkgPolicy.guess_upstream_src_version('git-bar-0.2.tar.gz') ('git-bar', '0.2') >>> PkgPolicy.guess_upstream_src_version('git-bar-0.2-rc1.tar.gz') @@ -175,14 +175,14 @@ class PkgPolicy(object): ('', '') >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.orig.tar.xz') ('foo-bar', '0.2') - >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.tar.gz') - ('foo-bar', '0.2') >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.orig.tar.lzma') ('foo-bar', '0.2') >>> PkgPolicy.guess_upstream_src_version('foo-bar-0.2.zip') ('foo-bar', '0.2') >>> PkgPolicy.guess_upstream_src_version('foo-bar-0.2.tlz') ('foo-bar', '0.2') + >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.tar.gz') + ('foo-bar', '0.2') """ version_chars = r'[a-zA-Z\d\.\~\-\:\+]' basename = parse_archive_filename(os.path.basename(filename))[0] @@ -190,10 +190,11 @@ class PkgPolicy(object): version_filters = map ( lambda x: x % version_chars, ( # Debian upstream tarball: package_'<version>.orig.tar.gz' r'^(?P<package>[a-z\d\.\+\-]+)_(?P<version>%s+)\.orig', + # Debian native: 'package_<version>.tar.gz' + r'^(?P<package>[a-z\d\.\+\-]+)_(?P<version>%s+)', # Upstream 'package-<version>.tar.gz' - # or Debian native 'package_<version>.tar.gz' # or directory 'package-<version>': - r'^(?P<package>[a-zA-Z\d\.\+\-]+)(-|_)(?P<version>[0-9]%s*)')) + r'^(?P<package>[a-zA-Z\d\.\+\-]+)(-)(?P<version>[0-9]%s*)')) if extra_regex: version_filters = extra_regex + version_filters @@ -358,7 +359,7 @@ class UpstreamSource(object): files.append((typ, info.filename)) elif self._archive_fmt == 'tar': popen = subprocess.Popen(['tar', '-t', '-v', '-f', self.path], - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, _err = popen.communicate() if popen.returncode: raise GbpError("Listing tar archive content failed") @@ -379,11 +380,25 @@ class UpstreamSource(object): @property def archive_fmt(self): """Archive format of the sources, e.g. 'tar'""" + """ + >>> UpstreamSource('foo/bar.tar.gz').archive_fmt + 'tar' + >>> UpstreamSource('foo.bar.zip').archive_fmt + 'zip' + >>> UpstreamSource('foo.bar.baz').archive_fmt + """ return self._archive_fmt @property def compression(self): """Compression format of the sources, e.g. 'gzip'""" + """ + >>> UpstreamSource('foo/bar.tar.gz').compression + 'gzip' + >>> UpstreamSource('foo.bar.zip').compression + >>> UpstreamSource('foo.bz2').compression + 'bzip2' + """ return self._compression @property diff --git a/gbp/rpm/__init__.py b/gbp/rpm/__init__.py index 0e04b4df..4c5c22bf 100644 --- a/gbp/rpm/__init__.py +++ b/gbp/rpm/__init__.py @@ -100,7 +100,7 @@ class SrcRpmFile(object): """ gbpc.RunAtCommand('rpm2cpio', [self.srpmfile, '|', 'cpio', '-id'], - shell=True)(dir=dest_dir) + shell=True, capture_stderr=True)(dir=dest_dir) class SpecFile(object): diff --git a/gbp/rpm/lib_rpm.py b/gbp/rpm/lib_rpm.py index 4bad44e7..da914207 100644 --- a/gbp/rpm/lib_rpm.py +++ b/gbp/rpm/lib_rpm.py @@ -25,6 +25,7 @@ try: # Try to load special RPM lib to be used for GBP (only) librpm = __import__(RpmPkgPolicy.python_rpmlib_module_name) except ImportError: + gbp.log.getLogger("gbp") gbp.log.warn("Failed to import '%s' as rpm python module, using host's " "default rpm library instead" % RpmPkgPolicy.python_rpmlib_module_name) diff --git a/gbp/rpm/linkedlist.py b/gbp/rpm/linkedlist.py index ca000453..74d897bc 100644 --- a/gbp/rpm/linkedlist.py +++ b/gbp/rpm/linkedlist.py @@ -36,7 +36,7 @@ class LinkedListNode(object): def data(self): """Get data stored into node""" if self._data is None: - gbp.log.err("BUG: referencing a deleted node!") + gbp.log.debug("BUG: referencing a deleted node!") return("") return self._data @@ -55,7 +55,7 @@ class LinkedListNode(object): '' """ if data is None: - gbp.log.err("BUG: trying to store 'None', not allowed") + gbp.log.debug("BUG: trying to store 'None', not allowed") data = "" self._data = data diff --git a/gbp/scripts/buildpackage.py b/gbp/scripts/buildpackage.py index a92e7ca8..cef0584f 100755 --- a/gbp/scripts/buildpackage.py +++ b/gbp/scripts/buildpackage.py @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -"""run commands to build a debian package out of a git repository""" +"""Build a debian package out of a GIT repository""" import ConfigParser import errno @@ -29,6 +29,7 @@ from gbp.command_wrappers import (Command, from gbp.config import (GbpOptionParserDebian, GbpOptionGroup) from gbp.deb.git import (GitRepositoryError, DebianGitRepository) from gbp.deb.source import DebianSource, DebianSourceError +from gbp.format import format_msg from gbp.git.vfs import GitVfs from gbp.deb.upstreamsource import DebianUpstreamSource from gbp.errors import GbpError @@ -415,6 +416,7 @@ def build_parser(name, prefix=None): tag_group.add_boolean_config_file_option(option_name="sign-tags", dest="sign_tags") tag_group.add_config_file_option(option_name="keyid", dest="keyid") tag_group.add_config_file_option(option_name="debian-tag", dest="packaging_tag") + tag_group.add_config_file_option(option_name="debian-tag-msg", dest="debian_tag_msg") tag_group.add_config_file_option(option_name="upstream-tag", dest="upstream_tag") orig_group.add_config_file_option(option_name="upstream-tree", dest="upstream_tree") orig_group.add_boolean_config_file_option(option_name="pristine-tar", dest="pristine_tar") @@ -615,13 +617,15 @@ def main(argv): extra_env={'GBP_CHANGES_FILE': changes, 'GBP_BUILD_DIR': build_dir})() if options.tag or options.tag_only: - gbp.log.info("Tagging %s" % source.changelog.version) tag = repo.version_to_tag(options.packaging_tag, source.changelog.version) + gbp.log.info("Tagging %s as %s" % (source.changelog.version, tag)) if options.retag and repo.has_tag(tag): repo.delete_tag(tag) + tag_msg = format_msg(options.debian_tag_msg, + dict(pkg=source.sourcepkg, + version=source.changelog.version)) repo.create_tag(name=tag, - msg="%s Debian release %s" % (source.sourcepkg, - source.changelog.version), + msg=tag_msg, sign=options.sign_tags, keyid=options.keyid) if options.posttag: sha = repo.rev_parse("%s^{}" % tag) diff --git a/gbp/scripts/buildpackage_rpm.py b/gbp/scripts/buildpackage_rpm.py index b8c1e0d1..8fb0b2a4 100755 --- a/gbp/scripts/buildpackage_rpm.py +++ b/gbp/scripts/buildpackage_rpm.py @@ -288,7 +288,17 @@ def export_patches(repo, spec, export_treeish, options): def is_native(repo, options): """Determine whether a package is native or non-native""" if options.native.is_auto(): - return not repo.has_branch(options.upstream_branch) + if repo.has_branch(options.upstream_branch): + return False + # Check remotes, too + for remote_branch in repo.get_remote_branches(): + remote, branch = remote_branch.split('/', 1) + if branch == options.upstream_branch: + gbp.log.debug("Found upstream branch '%s' from remote '%s'" % + (remote, branch)) + return False + return True + return options.native.is_on() @@ -698,6 +708,7 @@ def main(argv): if not options.tag_only: if spec and options.notify: summary = "Gbp-rpm %s" % ["failed", "successful"][not retval] + pkg_evr = {'upstreamversion': spec.version} message = ("Build of %s %s %s" % (spec.name, RpmPkgPolicy.compose_full_version(spec.version), ["failed", "succeeded"][not retval])) diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py index 9dd0ae9c..2810a310 100755 --- a/gbp/scripts/clone.py +++ b/gbp/scripts/clone.py @@ -17,7 +17,7 @@ # # inspired by dom-git-checkout # -"""clone a repo and set it up for gbp""" +"""Clone a GIT repository and set it up for gbp""" import ConfigParser import sys diff --git a/gbp/scripts/common/buildpackage.py b/gbp/scripts/common/buildpackage.py index f95837c1..d089df5a 100644 --- a/gbp/scripts/common/buildpackage.py +++ b/gbp/scripts/common/buildpackage.py @@ -142,7 +142,6 @@ def untar_data(outdir, data): if popen.wait(): raise GbpError("Error extracting tar to %s" % outdir) - #{ Functions to handle export-dir def dump_tree(repo, export_dir, treeish, with_submodules, recursive=True): """Dump a git tree-ish to output_dir""" diff --git a/gbp/scripts/common/import_orig.py b/gbp/scripts/common/import_orig.py index adbfff5e..16244423 100644 --- a/gbp/scripts/common/import_orig.py +++ b/gbp/scripts/common/import_orig.py @@ -78,59 +78,6 @@ def ask_package_version(default, ver_validator_func, err_msg): # bit clearer. gbp.log.warn("\nNot a valid upstream version: '%s'.\n%s" % (version, err_msg)) - -def prepare_pristine_tar(source, pkg_name, pkg_version, pristine_commit_name, - filters=None, prefix=None, tmpdir=None): - """ - Prepare the upstream sources for pristine-tar import - - @param source: original upstream sources - @type source: C{UpstreamSource} - @param pkg_name: package name - @type pkg_name: C{str} - @param pkg_version: upstream version of the package - @type pkg_version: C{str} - @param pristine_commit_name: archive filename to commit to pristine-tar - @type pristine_commit_name: C{str} or C{None} - @param filters: filter to exclude files - @type filters: C{list} of C{str} or C{None} - @param prefix: prefix (i.e. leading directory of files) to use in - pristine-tar, set to C{None} to not mangle orig archive - @type prefix: C{str} or C{None} - @param tmpdir: temporary working dir (cleanup left to caller) - @type tmpdir: C{str} - @return: prepared source archive - @rtype: C{UpstreamSource} - """ - need_repack = False - if source.is_dir(): - if prefix is None: - prefix = '%s-%s' % (pkg_name, pkg_version) - gbp.log.info("Using guessed prefix '%s/' for pristine-tar" % prefix) - need_repack = True - else: - if prefix is not None and prefix == source.prefix: - prefix = None - comp = parse_archive_filename(pristine_commit_name)[2] - if filters or prefix is not None or source.compression != comp: - if not source.unpacked: - unpack_dir = tempfile.mkdtemp(prefix='pristine_unpack_', - dir=tmpdir) - source.unpack(unpack_dir) - need_repack = True - pristine_path = os.path.join(tmpdir, pristine_commit_name) - if need_repack: - gbp.log.debug("Packing '%s' from '%s' for pristine-tar" % - (pristine_path, source.unpacked)) - pristine = source.pack(pristine_path, filters, prefix) - else: - # Just create symlink for mangling the pristine tarball name - os.symlink(source.path, pristine_path) - pristine = source.__class__(pristine_path) - - return pristine - - def prepare_sources(source, pkg_name, pkg_version, pristine_commit_name, filters, filter_pristine, prefix, tmpdir): """ @@ -201,3 +148,55 @@ def prepare_sources(source, pkg_name, pkg_version, pristine_commit_name, pristine_path = pristine.path if pristine else '' return (filtered.unpacked, pristine_path) +def prepare_pristine_tar(source, pkg_name, pkg_version, pristine_commit_name, + filters=None, prefix=None, tmpdir=None): + """ + Prepare the upstream sources for pristine-tar import + + @param source: original upstream sources + @type source: C{UpstreamSource} + @param pkg_name: package name + @type pkg_name: C{str} + @param pkg_version: upstream version of the package + @type pkg_version: C{str} + @param pristine_commit_name: archive filename to commit to pristine-tar + @type pristine_commit_name: C{str} or C{None} + @param filters: filter to exclude files + @type filters: C{list} of C{str} or C{None} + @param prefix: prefix (i.e. leading directory of files) to use in + pristine-tar, set to C{None} to not mangle orig archive + @type prefix: C{str} or C{None} + @param tmpdir: temporary working dir (cleanup left to caller) + @type tmpdir: C{str} + @return: prepared source archive + @rtype: C{UpstreamSource} + """ + need_repack = False + if source.is_dir(): + if prefix is None: + prefix = '%s-%s' % (pkg_name, pkg_version) + gbp.log.info("Using guessed prefix '%s/' for pristine-tar" % prefix) + need_repack = True + else: + if prefix is not None and prefix == source.prefix: + prefix = None + comp = parse_archive_filename(pristine_commit_name)[2] + if filters or prefix is not None or source.compression != comp: + if not source.unpacked: + unpack_dir = tempfile.mkdtemp(prefix='pristine_unpack_', + dir=tmpdir) + source.unpack(unpack_dir) + need_repack = True + pristine_path = os.path.join(tmpdir, pristine_commit_name) + if need_repack: + gbp.log.debug("Packing '%s' from '%s' for pristine-tar" % + (pristine_path, source.unpacked)) + pristine = source.pack(pristine_path, filters, prefix) + else: + # Just create symlink for mangling the pristine tarball name + os.symlink(source.path, pristine_path) + pristine = source.__class__(pristine_path) + + return pristine + + diff --git a/gbp/scripts/create_remote_repo.py b/gbp/scripts/create_remote_repo.py index 0d2345cd..a9832a1d 100755 --- a/gbp/scripts/create_remote_repo.py +++ b/gbp/scripts/create_remote_repo.py @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Based on the aa-create-git-repo and dom-new-git-repo shell scripts -"""Create a remote repo based on the current one""" +"""Create a remote GIT repository based on the current one""" import ConfigParser import sys diff --git a/gbp/scripts/dch.py b/gbp/scripts/dch.py index 0cf2e452..b8a86a77 100755 --- a/gbp/scripts/dch.py +++ b/gbp/scripts/dch.py @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -"""Generate Debian changelog entries from git commit messages""" +"""Generate Debian changelog entries from GIT commit messages""" import ConfigParser import os.path @@ -64,17 +64,19 @@ def get_author_email(repo, use_git_config): return author, email -def fixup_section(repo, git_author, options, dch_options): +def fixup_section(repo, use_git_author, options, dch_options): """ Fixup the changelog header and trailer's committer and email address It might otherwise point to the last git committer instead of the person creating the changelog - This apply --distribution and --urgency options passed to git-dch + + This also applies --distribution and --urgency options passed to gbp dch """ - author, email = get_author_email(repo, git_author) + author, email = get_author_email(repo, use_git_author) used_options = ['distribution', 'urgency'] - header_opts = [] + opts = [] + mainttrailer_opts = [ '--nomainttrailer', '--mainttrailer', '-t' ] # This must not be done for snapshots or snapshots changelog entries # will not be concatenated @@ -83,11 +85,17 @@ def fixup_section(repo, git_author, options, dch_options): val = getattr(options, opt) if val: gbp.log.debug("Set header option '%s' to '%s'" % (opt, val)) - header_opts.append("--%s=%s" % (opt, val)) + opts.append("--%s=%s" % (opt, val)) else: gbp.log.debug("Snapshot enabled: do not fixup options in header") - ChangeLog.spawn_dch(msg='', author=author, email=email, dch_options=dch_options+header_opts) + if use_git_author: + for opt in mainttrailer_opts: + if opt in dch_options: + break + else: + opts.append(mainttrailer_opts[0]) + ChangeLog.spawn_dch(msg='', author=author, email=email, dch_options=dch_options+opts) def snapshot_version(version): @@ -153,9 +161,9 @@ def mangle_changelog(changelog, cp, snapshot=''): raise GbpError("Error mangling changelog %s" % e) -def do_release(changelog, repo, cp, git_author, dch_options): +def do_release(changelog, repo, cp, use_git_author, dch_options): """Remove the snapshot header and set the distribution""" - author, email = get_author_email(repo, git_author) + author, email = get_author_email(repo, use_git_author) (release, snapshot) = snapshot_version(cp['Version']) if snapshot: cp['MangledVersion'] = release @@ -343,10 +351,9 @@ def build_parser(name): help="Increment the Debian release number for a Debian Team upload, and add a Team upload changelog comment.") version_group.add_option("--security", dest="security", action="store_true", default=False, help="Increment the Debian release number for a security upload and add a security upload changelog comment.") - version_group.add_boolean_config_file_option(option_name="git-author", dest="git_author") + version_group.add_boolean_config_file_option(option_name="git-author", dest="use_git_author") commit_group.add_boolean_config_file_option(option_name="meta", dest="meta") - commit_group.add_config_file_option(option_name="meta-closes", dest="meta_closes", - help="Meta tags for the bts close commands, default is '%(meta-closes)s'") + commit_group.add_config_file_option(option_name="meta-closes", dest="meta_closes") commit_group.add_boolean_config_file_option(option_name="full", dest="full") commit_group.add_config_file_option(option_name="id-length", dest="idlen", help="include N digits of the commit id in the changelog entry, default is '%(id-length)s'", @@ -507,11 +514,11 @@ def main(argv): version=version_change, dch_options=dch_options) - fixup_section(repo, git_author=options.git_author, options=options, + fixup_section(repo, use_git_author=options.use_git_author, options=options, dch_options=dch_options) if options.release: - do_release(changelog, repo, cp, git_author=options.git_author, + do_release(changelog, repo, cp, use_git_author=options.use_git_author, dch_options=dch_options) elif options.snapshot: (snap, version) = do_snapshot(changelog, repo, options.snapshot_number) diff --git a/gbp/scripts/import_dsc.py b/gbp/scripts/import_dsc.py index e6f72105..b19d95fc 100755 --- a/gbp/scripts/import_dsc.py +++ b/gbp/scripts/import_dsc.py @@ -14,7 +14,7 @@ # 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 -"""Import a Debian source package into a git repository""" +"""Import a Debian source package into a GIT repository""" import ConfigParser import sys diff --git a/gbp/scripts/import_dscs.py b/gbp/scripts/import_dscs.py index f480fea4..5409ca11 100644 --- a/gbp/scripts/import_dscs.py +++ b/gbp/scripts/import_dscs.py @@ -14,7 +14,7 @@ # 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 -"""Import multiple dsc files in one go""" +"""Import multiple dsc files into GIT in one go""" import glob import os diff --git a/gbp/scripts/import_orig.py b/gbp/scripts/import_orig.py index 78bbf476..9d183b6d 100644 --- a/gbp/scripts/import_orig.py +++ b/gbp/scripts/import_orig.py @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -"""Import a new upstream version into a git repository""" +"""Import a new upstream version into a GIT repository""" import ConfigParser import os @@ -29,12 +29,12 @@ from gbp.deb.changelog import ChangeLog, NoChangeLogError from gbp.deb.git import (GitRepositoryError, DebianGitRepository) from gbp.config import GbpOptionParserDebian, GbpOptionGroup, no_upstream_branch_msg from gbp.errors import GbpError +from gbp.format import format_msg import gbp.log from gbp.pkg import compressor_opts from gbp.scripts.common.import_orig import (cleanup_tmp_tree, ask_package_name, - ask_package_version, - prepare_sources) - + ask_package_version, + prepare_sources) def upstream_import_commit_msg(options, version): return options.import_msg % dict(version=version) @@ -270,6 +270,12 @@ def main(argv): source, pkg_name, version, prepare_pristine, options.filters, options.filter_pristine_tar, None, tmpdir) + # Prepare sources for importing + pristine_name = pristine_tarball_name(source, pkg_name, version) + prepare_pristine = pristine_name if options.pristine_tar else None + unpacked_orig, pristine_orig = prepare_sources( + source, pkg_name, version, prepare_pristine, options.filters, + options.filter_pristine_tar, None, tmpdir) # Don't mess up our repo with git metadata from an upstream tarball try: if os.path.isdir(os.path.join(unpacked_orig, '.git/')): @@ -331,7 +337,7 @@ def main(argv): epoch = '%s:' % cp.epoch info = { 'version': "%s%s-1" % (epoch, version) } env = { 'GBP_BRANCH': options.packaging_branch } - gbpc.Command(options.postimport % info, extra_env=env, shell=True)() + gbpc.Command(format_msg(options.postimport, info), extra_env=env, shell=True)() # Update working copy and index if we've possibly updated the # checked out branch current_branch = repo.get_branch() diff --git a/gbp/scripts/import_srpm.py b/gbp/scripts/import_srpm.py index 5a1d9d64..85f1225f 100755 --- a/gbp/scripts/import_srpm.py +++ b/gbp/scripts/import_srpm.py @@ -15,7 +15,7 @@ # 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 -"""Import an RPM source package into a git repository""" +"""Import an RPM source package into a GIT repository""" import ConfigParser import sys diff --git a/gbp/scripts/pq.py b/gbp/scripts/pq.py index 75348501..7053d0af 100755 --- a/gbp/scripts/pq.py +++ b/gbp/scripts/pq.py @@ -1,6 +1,6 @@ # vim: set fileencoding=utf-8 : # -# (C) 2011 Guido Günther <agx@sigxcpu.org> +# (C) 2011,2014 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 @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -"""manage patches in a patch queue""" +"""Manage Debian patches on a patch queue branch""" import ConfigParser import errno @@ -35,6 +35,7 @@ from gbp.scripts.common.pq import (is_pq_branch, pq_branch_name, pq_branch_base, switch_to_pq_branch, apply_single_patch, apply_and_commit_patch, drop_pq, get_maintainer_from_control) +from gbp.dch import extract_bts_cmds PATCH_DIR = "debian/patches/" SERIES_FILE = os.path.join(PATCH_DIR,"series") @@ -90,6 +91,71 @@ def generate_patches(repo, start, end, outdir, options): return patches +def compare_series(old, new): + """ + Compare new pathes to lists of patches already exported + + >>> compare_series(['a', 'b'], ['b', 'c']) + (['c'], ['a']) + >>> compare_series([], []) + ([], []) + """ + added = set(new).difference(old) + removed = set(old).difference(new) + return (list(added), list(removed)) + + +def format_series_diff(added, removed, options): + """ + Format the patch differences into a suitable commit message + + >>> format_series_diff(['a'], ['b'], None) + 'Rediff patches\\n\\nAdded a: <REASON>\\nDropped b: <REASON>\\n' + """ + if len(added) == 1 and not removed: + # Single patch added, create a more thorough commit message + patch = Patch(os.path.join('debian', 'patches', added[0])) + msg = patch.subject + bugs, dummy = extract_bts_cmds(patch.long_desc.split('\n'), options) + if bugs: + msg += '\n' + for k, v in bugs.items(): + msg += '\n%s: %s' % (k, ', '.join(v)) + else: + msg = "Rediff patches\n\n" + for p in added: + msg += 'Added %s: <REASON>\n' % p + for p in removed: + msg += 'Dropped %s: <REASON>\n' % p + return msg + + +def commit_patches(repo, branch, patches, options): + """ + Commit chanages exported from patch queue + """ + clean, dummy = repo.is_clean() + if clean: + return ([], []) + + vfs = gbp.git.vfs.GitVfs(repo, branch) + try: + oldseries = vfs.open('debian/patches/series') + oldpatches = [ p.strip() for p in oldseries.readlines() ] + oldseries.close() + except IOError: + # No series file yet + oldpatches = [] + newpatches = [ p[len(PATCH_DIR):] for p in patches ] + + # FIXME: handle case were only the contents of the patches changed + added, removed = compare_series(oldpatches, newpatches) + msg = format_series_diff(added, removed, options) + repo.add_files(PATCH_DIR) + repo.commit_staged(msg=msg) + return added, removed + + def export_patches(repo, branch, options): """Export patches from the pq branch into a patch series""" if is_pq_branch(branch, options): @@ -113,10 +179,22 @@ def export_patches(repo, branch, options): with open(SERIES_FILE, 'w') as seriesfd: for patch in patches: seriesfd.write(os.path.relpath(patch, PATCH_DIR) + '\n') - GitCommand('status')(['--', PATCH_DIR]) + if options.commit: + added, removed = commit_patches(repo, branch, patches, options) + if added: + what = 'patches' if len(added) > 1 else 'patch' + gbp.log.info("Added %s %s to patch series" % (what, ', '.join(added))) + if removed: + what = 'patches' if len(removed) > 1 else 'patch' + gbp.log.info("Removed %s %s from patch series" % (what, ', '.join(removed))) + else: + GitCommand('status')(['--', PATCH_DIR]) else: gbp.log.info("No patches on '%s' - nothing to do." % pq_branch) + if options.drop: + drop_pq(repo, branch, options) + def safe_patches(series, tmpdir_base): """ @@ -257,11 +335,14 @@ def build_parser(name): help="verbose command execution") parser.add_option("--topic", dest="topic", help="in case of 'apply' topic (subdir) to put patch into") parser.add_config_file_option(option_name="time-machine", dest="time_machine", type="int") + parser.add_boolean_config_file_option("drop", dest='drop') + parser.add_boolean_config_file_option(option_name="commit", dest="commit") parser.add_option("--force", dest="force", action="store_true", default=False, help="in case of import even import if the branch already exists") parser.add_config_file_option(option_name="color", dest="color", type='tristate') parser.add_config_file_option(option_name="color-scheme", dest="color_scheme") + parser.add_config_file_option(option_name="meta-closes", dest="meta_closes") parser.add_config_file_option(option_name="tmp-dir", dest="tmp_dir") return parser diff --git a/gbp/scripts/pq_rpm.py b/gbp/scripts/pq_rpm.py index 6380ee22..e19218a9 100755 --- a/gbp/scripts/pq_rpm.py +++ b/gbp/scripts/pq_rpm.py @@ -27,11 +27,10 @@ import re import gzip import bz2 import subprocess - import gbp.tmpfile as tempfile from gbp.config import GbpOptionParserRpm from gbp.rpm.git import GitRepositoryError, RpmGitRepository -from gbp.git.modifier import GitModifier +from gbp.git.modifier import GitModifier, GitTz from gbp.command_wrappers import GitCommand, CommandExecFailed from gbp.errors import GbpError import gbp.log @@ -269,6 +268,8 @@ def export_patches(repo, options): upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag) export_treeish = options.export_rev if options.export_rev else pq_branch + if not repo.has_treeish(export_treeish): + raise GbpError('Invalid treeish object %s' % export_treeish) update_patch_series(repo, spec, upstream_commit, export_treeish, options) @@ -384,7 +385,7 @@ def import_spec_patches(repo, options): # Create pq-branch if repo.has_branch(pq_branch) and not options.force: raise GbpError("Patch-queue branch '%s' already exists. " - "Try 'rebase' instead." % pq_branch) + "Try 'switch' instead." % pq_branch) try: if repo.get_branch() == pq_branch: repo.force_head(upstream_commit, hard=True) diff --git a/gbp/scripts/pull.py b/gbp/scripts/pull.py index 12da8c5f..166955a9 100755 --- a/gbp/scripts/pull.py +++ b/gbp/scripts/pull.py @@ -17,7 +17,7 @@ # # heavily inspired by dom-safe-pull which is © 2009 Stéphane Glondu <steph@glondu.net> # -"""fast forward debian, upstream and pristine-tar branch""" +"""Pull remote changes and fast forward debian, upstream and pristine-tar branch""" import ConfigParser import sys diff --git a/gbp/scripts/supercommand.py b/gbp/scripts/supercommand.py index 2eb64de2..83c8446b 100644 --- a/gbp/scripts/supercommand.py +++ b/gbp/scripts/supercommand.py @@ -17,6 +17,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Supercommand for all gbp commands""" +import glob +import os import re import sys @@ -42,8 +44,18 @@ The most commonly used commands are: import-orig - import a new upstream tarball import-dsc - import a single Debian source package import-dscs - import multiple Debian source packages + +Use '--list-cmds' to list all available commands. """ +def version(prog): + try: + from gbp.version import gbp_version + except ImportError: + gbp_version = '[Unknown version]' + print("%s %s" % (os.path.basename(prog), gbp_version)) + + def import_command(cmd): """ Import the module that implements the given command @@ -56,6 +68,40 @@ def import_command(cmd): return __import__('gbp.scripts.%s' % modulename, fromlist='main', level=0) +def pymod_to_cmd(mod): + """ + >>> pymod_to_cmd('/x/y/z/a_cmd.py') + 'a-cmd' + """ + return os.path.basename(mod.rsplit('.', 1)[0]).replace('_','-') + + +def get_available_commands(path): + cmds = [] + for f in glob.glob(os.path.join(path, '*.py')): + if os.path.basename(f) in ['__init__.py', 'supercommand.py']: + continue + cmds.append((pymod_to_cmd(f), f)) + return cmds + + +def list_available_commands(): + mod = __import__('gbp.scripts', fromlist='main', level=0) + path = os.path.dirname(mod.__file__) + maxlen = 0 + + print("Available commands in %s\n" % path) + cmds = sorted(get_available_commands(path)) + for cmd in cmds: + if len(cmd[0]) > maxlen: + maxlen = len(cmd[0]) + for cmd in cmds: + mod = import_command(cmd[0]) + doc = mod.__doc__ + print(" %s - %s" % (cmd[0].rjust(maxlen), doc)) + print('') + + def supercommand(argv=None): argv = argv or sys.argv @@ -63,12 +109,18 @@ def supercommand(argv=None): usage() return 1 - cmd = argv[1] + prg, cmd = argv[0:2] args = argv[1:] - if cmd in ['--help', '-h']: + if cmd in ['--help', '-h', 'help' ]: usage() return 0 + elif cmd in [ '--version', 'version' ]: + version(argv[0]) + return 0 + elif cmd in [ '--list-cmds', 'list-cmds' ]: + list_available_commands() + return 0 try: module = import_command(cmd) @@ -81,4 +133,7 @@ def supercommand(argv=None): return module.main(args) +if __name__ == '__main__': + sys.exit(supercommand()) + # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: |