diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | gbp/config.py | 14 | ||||
-rw-r--r-- | gbp/git_utils.py | 13 | ||||
-rwxr-xr-x | git-buildpackage | 132 |
4 files changed, 125 insertions, 35 deletions
@@ -1,5 +1,4 @@ - git-buildpackage: - - allow to export the hole source tree to tmpdir before building - allow to fetch and build from a signed tag even when it's in a remote repo - git-import-orig: - show untracked files using 'git-ls-files -o' after import diff --git a/gbp/config.py b/gbp/config.py index 694aceb7..d1686fa6 100644 --- a/gbp/config.py +++ b/gbp/config.py @@ -35,6 +35,7 @@ class GbpOptionParser(OptionParser): 'filter' : '', 'snapshot-number' : 'snapshot + 1', 'git-log' : '--no-merges', + 'export-dir' : '', } config_files=[ '/etc/git-buildpackage/gbp.conf', os.path.expanduser('~/.gbp.conf'), @@ -43,19 +44,18 @@ class GbpOptionParser(OptionParser): def __parse_config_files(self): """parse the possible config files and set appropriate values default values""" - parser=SafeConfigParser(self.defaults) + parser = SafeConfigParser(self.defaults) parser.read(self.config_files) - self.config=dict(parser.defaults()) + self.config = dict(parser.defaults()) if parser.has_section(self.command): - self.config=dict(parser.items(self.command, raw=True)) + self.config.update(dict(parser.items(self.command, raw=True))) def __init__(self, command, prefix='', usage=None): - self.command=command - self.prefix=prefix + self.command = command + self.prefix = prefix self.__parse_config_files() OptionParser.__init__(self, usage=usage) - def add_config_file_option(self, option_name, dest, help, **kwargs): """ set a option for the command line parser, the default is read from the config file @@ -67,7 +67,7 @@ class GbpOptionParser(OptionParser): @type help: string """ OptionParser.add_option(self,"--%s%s" % (self.prefix, option_name), dest=dest, - default=self.config[option_name], + default=self.config[option_name], help=help % self.config, **kwargs) # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/git_utils.py b/gbp/git_utils.py index f52550b3..9cfb0ec5 100644 --- a/gbp/git_utils.py +++ b/gbp/git_utils.py @@ -27,10 +27,10 @@ class GitRepository(object): raise GitRepositoryError - def __git_getoutput(self, command): - """Exec a git command and return the output""" + def __git_getoutput(self, command, args=[]): + """exec a git command and return the output""" output = [] - popen = subprocess.Popen(['git', command], stdout=subprocess.PIPE) + popen = subprocess.Popen(['git', command] + args, stdout=subprocess.PIPE) while popen.poll() == None: output += popen.stdout.readlines() ret = popen.poll() @@ -47,6 +47,13 @@ class GitRepository(object): return False + def has_treeish(self, treeish): + """check if the repository has the treeish object treeish""" + self.__check_path() + out, ret = self.__git_getoutput('ls-tree', [ treeish ]) + return [ True, False ][ret != 0] + + def get_branch(self): """on what branch is the current working copy""" self.__check_path() diff --git a/git-buildpackage b/git-buildpackage index e6c544df..91ce2b3e 100755 --- a/git-buildpackage +++ b/git-buildpackage @@ -20,20 +20,19 @@ import sys import os, os.path +import errno import pipes +import time from gbp.git_utils import (GitRepositoryError, GitRepository, build_tag) from gbp.deb_utils import (parse_changelog, is_native, orig_file, has_orig) -from gbp.command_wrappers import (GitTag, Command, CommandExecFailed) +from gbp.command_wrappers import (GitTag, Command, CommandExecFailed, RemoveTree) from gbp.config import GbpOptionParser from gbp.errors import GbpError -def create_orig(cp, output_dir, branch): - "create an orig.tar.gz in output_dir" - output = os.path.join(output_dir, orig_file(cp)) - pipe = pipes.Template() - pipe.prepend('git-archive --format=tar --prefix=%s-%s/ %s' % (cp['Source'], cp['Upstream-Version'], branch), '.-') - pipe.append('gzip -c -9', '--') +def git_archive_pipe(prefix, pipe, output, treeish): + """run the git_archive pipe""" + pipe.prepend('git-archive --format=tar --prefix=%s/ %s' % (prefix, treeish), '.-') try: ret = pipe.copy('', output) if ret: @@ -48,9 +47,52 @@ def create_orig(cp, output_dir, branch): return True +def create_orig(cp, output_dir, treeish): + "create an orig.tar.gz in output_dir" + output = os.path.join(output_dir, orig_file(cp)) + prefix = "%s-%s" % (cp['Source'], cp['Upstream-Version']) + + pipe = pipes.Template() + pipe.append('gzip -c -9', '--') + return git_archive_pipe(prefix, pipe, output, treeish) + + +def dump_tree(export_dir, treeish): + "dump a tree to output_dir" + output_dir = os.path.dirname(export_dir) + prefix = os.path.basename(export_dir) + pipe = pipes.Template() + pipe.append('tar -C %s -xf -' % output_dir, '-.') + return git_archive_pipe(prefix, pipe, '', treeish) + + +def move_old_export(target): + """move a build tree away if it exists""" + try: + os.mkdir(target) + except OSError, (e, msg): + if e == errno.EEXIST: + os.rename(target, "%s.obsolete.%s" % (target, time.time())) + + +def prepare_output_dir(dir): + output_dir = dir + if not dir: + output_dir = '..' + output_dir = os.path.abspath(output_dir) + + try: + os.mkdir(output_dir) + except OSError, (e, msg): + if e != errno.EEXIST: + raise GbpError, "Cannot create output dir %s" % output_dir + return output_dir + + def main(argv): - output_dir = '..' changelog = 'debian/changelog' + default_tree = 'HEAD' + retval = 0 args = [ arg for arg in argv[1:] if arg.find('--git-') == 0 ] dpkg_args = [ arg for arg in argv[1:] if arg.find('--git-') == -1 ] @@ -77,23 +119,31 @@ def main(argv): parser.add_config_file_option(option_name="sign-tags", dest="sign_tag", help="sign git tags", action="store_true") parser.add_config_file_option(option_name="no-create-orig", dest="no_create_orig", - help="create orig.tar.gz", action="store_true") + help="don't create orig.tar.gz", action="store_true") parser.add_config_file_option(option_name="posttag", dest="posttag_hook", help="hook to execute after a successfull tag operation") parser.add_config_file_option(option_name="keyid", dest="keyid", help="GPG keyid to sign tags with") parser.add_config_file_option(option_name="debian-tag", dest="debian_tag", - help="Format string for debian tags, default is '%(debian-tag)s'") + help="format string for debian tags, default is '%(debian-tag)s'") + parser.add_config_file_option(option_name="upstream-tag", dest="upstream_tag", + help="format string for upstream tags, default is '%(upstream-tag)s'") + parser.add_config_file_option(option_name="export-dir", dest="export_dir", + help="before building export into EXPORT_DIR") + parser.add_option("--git-export", dest="treeish", default=default_tree, + help="export treeish object TREEISH, default is '%s'" % default_tree) (options, args) = parser.parse_args(args) if options.verbose: Command.verbose = True try: - repo = GitRepository('.') + repo = GitRepository(os.path.curdir) except GitRepositoryError: print >>sys.stderr, "%s is not a git repository" % (os.path.abspath('.')) return 1 + else: + repo_dir = os.path.abspath(os.path.curdir) try: if not options.ignore_new: @@ -103,20 +153,48 @@ def main(argv): print >>sys.stderr, "You have uncommitted changes in your source tree:" print >>sys.stderr, out raise GbpError, "Use --git-ignore-new to ignore." - branch = repo.get_branch() - if branch != options.debian_branch and not options.ignore_new: - print >>sys.stderr, "You are not on branch '%s' but on '%s'" % (options.debian_branch, branch) - raise GbpError, "Use --git-ignore-new to ignore or --git-debian-branch to set the branch name." + + branch = repo.get_branch() + if branch != options.debian_branch: + print >>sys.stderr, "You are not on branch '%s' but on '%s'" % (options.debian_branch, branch) + raise GbpError, "Use --git-ignore-new to ignore or --git-debian-branch to set the branch name." cp = parse_changelog(changelog) if not cp: raise GbpError,"'%s' does not exist, not a debian package" % changelog + + output_dir = prepare_output_dir(options.export_dir) + if not repo.has_treeish(options.treeish): + raise GbpError # git-ls-tree printed an error message already + # Export to another build dir if requested: + if options.export_dir: + tmp_dir = os.path.join(output_dir, "%s-tmp" % cp['Source']) + print "Exporting '%s' to '%s'" % (options.treeish, tmp_dir) + dump_tree(tmp_dir, options.treeish) + cp = parse_changelog(os.path.join(tmp_dir, 'debian', 'changelog')) + if is_native(cp): + version = cp['Debian-Version'] + else: + version = cp['Upstream-Version'] + export_dir = os.path.join(output_dir, "%s-%s" % (cp['Source'], version)) + print "Moving '%s' to '%s'" % (tmp_dir, export_dir) + move_old_export(export_dir) + os.rename(tmp_dir, export_dir) + + # Build the orig.tar.gz if necessary: if not is_native(cp) and not has_orig(cp, output_dir) and not options.no_create_orig: - print "%s does not exist, creating from branch '%s'" % (orig_file(cp), options.upstream_branch) - if not repo.has_branch(options.upstream_branch): - raise GbpError, "Upstream branch '%s' does not exist" % options.upstream_branch - if not create_orig(cp, output_dir, options.upstream_branch): - raise GbpError + if options.upstream_branch != GbpOptionParser.defaults['upstream-branch']: + upstream_tree = options.upstream_branch + else: + upstream_tree = build_tag(options.upstream_tag, cp['Upstream-Version']) + print "%s does not exist, creating from '%s'" % (orig_file(cp), upstream_tree) + if not repo.has_treeish(upstream_tree): + raise GbpError # git-ls-tree printed an error message already + if not create_orig(cp, output_dir, upstream_tree): + raise GbpError, "Cannot create upstream tarball at '%s'" % output_dir + + if options.export_dir: + os.chdir(export_dir) Command(options.build_cmd, dpkg_args, shell=True)() if options.tag: @@ -125,18 +203,24 @@ def main(argv): except KeyError: raise GbpError, "Can't parse version from changelog" else: - print "Tagging", version + print "Tagging %s" % version GitTag(options.sign_tag, options.keyid)(build_tag(options.debian_tag, version), msg="Debian release %s" % version) if(options.posttag_hook): Command(options.posttag_hook, shell=True)() + except CommandExecFailed: - return 1 + retval = 1 except GbpError, err: if len(err.__str__()): print >>sys.stderr, err - return 1 - return 0 + retval = 1 + + if options.export_dir and not retval: + RemoveTree(export_dir)() + + os.chdir(repo_dir) + return retval if __name__ == '__main__': sys.exit(main(sys.argv)) |