summaryrefslogtreecommitdiff
path: root/gbp
diff options
context:
space:
mode:
authorSoonKyu Park <sk7.park@samsung.com>2016-04-11 13:21:01 +0900
committerSoonKyu Park <sk7.park@samsung.com>2016-04-11 13:21:01 +0900
commit8e7c90b9ae69aad55495a8f5be4e94b498052166 (patch)
tree214b01911f079ba147da9ddb48449ad75842e2f0 /gbp
parent96398c46398eec541b59df3997e5b8b2a392ee56 (diff)
parent8456b886b0fcd8ce465c3e3c44b47beeaf436afb (diff)
downloadgit-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.py16
-rw-r--r--gbp/deb/git.py3
-rw-r--r--gbp/format.py44
-rw-r--r--gbp/git/repository.py27
-rw-r--r--gbp/git/vfs.py2
-rw-r--r--gbp/log.py32
-rw-r--r--gbp/patch_series.py8
-rw-r--r--gbp/pkg/__init__.py39
-rw-r--r--gbp/rpm/__init__.py2
-rw-r--r--gbp/rpm/lib_rpm.py1
-rw-r--r--gbp/rpm/linkedlist.py4
-rwxr-xr-xgbp/scripts/buildpackage.py12
-rwxr-xr-xgbp/scripts/buildpackage_rpm.py13
-rwxr-xr-xgbp/scripts/clone.py2
-rw-r--r--gbp/scripts/common/buildpackage.py1
-rw-r--r--gbp/scripts/common/import_orig.py105
-rwxr-xr-xgbp/scripts/create_remote_repo.py2
-rwxr-xr-xgbp/scripts/dch.py35
-rwxr-xr-xgbp/scripts/import_dsc.py2
-rw-r--r--gbp/scripts/import_dscs.py2
-rw-r--r--gbp/scripts/import_orig.py16
-rwxr-xr-xgbp/scripts/import_srpm.py2
-rwxr-xr-xgbp/scripts/pq.py87
-rwxr-xr-xgbp/scripts/pq_rpm.py7
-rwxr-xr-xgbp/scripts/pull.py2
-rw-r--r--gbp/scripts/supercommand.py59
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):
"""
diff --git a/gbp/log.py b/gbp/log.py
index 17cd680d..7b9a4aa8 100644
--- a/gbp/log.py
+++ b/gbp/log.py
@@ -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\:·: