diff options
author | Guido Günther <agx@sigxcpu.org> | 2011-04-09 22:38:40 +0200 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2011-04-09 22:38:40 +0200 |
commit | 943686c8c059f6aa90cb03a86862ddd0253f46de (patch) | |
tree | 5b5d393b1144a30b625771460265cb291b20b1d6 /gbp | |
parent | 61513e6869a0c6d9036da3fe255bf2e2d3f5796a (diff) | |
parent | aa72b4f43d64e9669752441d13d12add743907df (diff) |
Merge branch 'master' into experimental
Diffstat (limited to 'gbp')
-rw-r--r-- | gbp/command_wrappers.py | 60 | ||||
-rw-r--r-- | gbp/config.py | 14 | ||||
-rw-r--r-- | gbp/deb.py | 40 | ||||
-rw-r--r-- | gbp/git.py | 164 | ||||
-rw-r--r-- | gbp/log.py | 16 | ||||
-rw-r--r-- | gbp/notifications.py | 1 |
6 files changed, 185 insertions, 110 deletions
diff --git a/gbp/command_wrappers.py b/gbp/command_wrappers.py index 545380c..64300cf 100644 --- a/gbp/command_wrappers.py +++ b/gbp/command_wrappers.py @@ -159,6 +159,16 @@ class RepackTarArchive(Command): self.run_error = 'Couldn\'t repack "%s"' % self.archive +class CatenateTarArchive(Command): + """Wrap tar to catenate a tar file with the next""" + def __init__(self, archive, **kwargs): + self.archive = archive + Command.__init__(self, 'tar', ['-A', '-f', archive], **kwargs) + + def __call__(self, target): + Command.__call__(self, [target]) + + class RemoveTree(Command): "Wrap rm to remove a whole directory tree" def __init__(self, tree): @@ -197,6 +207,7 @@ class GitCommand(Command): self.run_error = "Couldn't run git %s" % cmd +# FIXME: move to gbp.git.__init__ class GitInit(GitCommand): """Wrap git init""" def __init__(self): @@ -204,20 +215,14 @@ class GitInit(GitCommand): self.run_error = "Couldn't init git repository" +# FIXME: move to gbp.git.__init__ class GitClone(GitCommand): """Wrap git clone""" def __init__(self): GitCommand.__init__(self, 'clone') self.run_error = "Couldn't clone git repository" - -class GitShowBranch(GitCommand): - """Wrap git show-branch""" - def __init__(self): - GitCommand.__init__(self, 'branch') - self.run_error = "Couldn't list branches" - - +# FIXME: move to gbp.git.create_branch class GitBranch(GitCommand): """Wrap git branch""" def __init__(self): @@ -231,21 +236,7 @@ class GitBranch(GitCommand): GitCommand.__call__(self, options) -class GitCheckoutBranch(GitCommand): - """Wrap git checkout in order tos switch to a certain branch""" - def __init__(self, branch): - GitCommand.__init__(self, 'checkout', [branch]) - self.branch = branch - self.run_error = 'Couldn\'t switch to branch "%s"' % self.branch - - -class GitPull(GitCommand): - """Wrap git pull""" - def __init__(self, repo, branch): - GitCommand.__init__(self, 'pull', [repo, branch]) - self.run_error = 'Couldn\'t pull "%s" to "%s"' % (branch, repo) - - +# FIXME: move to gbp.git.fetch class GitFetch(GitCommand): """Wrap git fetch""" def __init__(self, remote = None): @@ -255,6 +246,7 @@ class GitFetch(GitCommand): GitCommand.__init__(self, 'fetch', opts) +# FIXME: move to gbp.git.merge class GitMerge(GitCommand): """Wrap git merge""" def __init__(self, branch, verbose=False): @@ -263,6 +255,7 @@ class GitMerge(GitCommand): self.run_error = 'Couldn\'t merge from "%s"' % (branch,) +# FIXME: move to gbp.git.create_tag class GitTag(GitCommand): """Wrap git tag""" def __init__(self, sign_tag=False, keyid=None): @@ -285,6 +278,7 @@ class GitTag(GitCommand): GitCommand.__call__(self, cmd) +# FIXME: move to gbp.git.add class GitAdd(GitCommand): """Wrap git add to add new files""" def __init__(self, extra_env=None): @@ -292,26 +286,6 @@ class GitAdd(GitCommand): self.run_error = "Couldn't add files" -class GitRm(GitCommand): - """Wrap git rm to remove files""" - def __init__(self, verbose=False): - args = [ ['--quiet'], [] ][verbose] - GitCommand.__init__(self, cmd='rm', args=args) - self.run_error = "Couldn't remove files" - - -class GitCommitAll(GitCommand): - """Wrap git commit to commit all changes""" - def __init__(self, verbose=False, **kwargs): - args = ['-a'] + [ ['-q'], [] ][verbose] - GitCommand.__init__(self, cmd='commit', args=args, **kwargs) - - def __call__(self, msg=''): - args = [ [], ['-m', msg] ][len(msg) > 0] - self.run_error = "Couldn't %s %s" % (self.cmd, " ".join(self.args + args)) - GitCommand.__call__(self, args) - - def copy_from(orig_dir, filters=[]): """ copy a source tree over via tar diff --git a/gbp/config.py b/gbp/config.py index d121133..9f3d169 100644 --- a/gbp/config.py +++ b/gbp/config.py @@ -1,6 +1,6 @@ # vim: set fileencoding=utf-8 : # -# (C) 2006,2007,2010 Guido Guenther <agx@sigxcpu.org> +# (C) 2006,2007,2010,2011 Guido Guenther <agx@sigxcpu.org> """handles command line and config file option parsing for the gbp commands""" from optparse import OptionParser, OptionGroup, Option, OptionValueError @@ -13,6 +13,12 @@ except ImportError: gbp_version = "[Unknown version]" import gbp.tristate +no_upstream_branch_msg = """ +Repository does not have branch '%s' for upstream sources. If there is none see +file:///usr/share/doc/git-buildpackage/manual-html/gbp.import.html#GBP.IMPORT.CONVERT +on howto create it otherwise use --upstream-branch to specify it. +""" + def expand_path(option, opt, value): value = os.path.expandvars(value) return os.path.expanduser(value) @@ -99,6 +105,8 @@ class GbpOptionParser(OptionParser): 'track' : 'True', 'author-is-committer': 'False', 'author-date-is-committer-date': 'False', + 'create-missing-branches': 'False', + 'submodules' : 'True', } help = { 'debian-branch': @@ -163,6 +171,10 @@ class GbpOptionParser(OptionParser): "Use the authors's name also as the comitter's name, default is '%(author-is-committer)s'", 'author-date-is-committer-date': "Use the authors's date as the comitter's date, default is '%(author-date-is-committer-date)s'", + 'create-missing-branches': + "Create missing branches automatically, default is '%(create-missing-branches)s'", + 'submodules': + "Transparently handle submodules in the upstream tree" } config_files = [ '/etc/git-buildpackage/gbp.conf', os.path.expanduser('~/.gbp.conf'), @@ -244,8 +244,14 @@ def orig_file(cp, compression): def is_native(cp): - "Is this a debian native package" - return [ True, False ]['-' in cp['Version']] + """ + Is this a debian native package + >>> is_native(dict(Version="1")) + True + >>> is_native(dict(Version="1-1")) + False + """ + return not '-' in cp['Version'] def is_valid_packagename(name): "Is this a valid Debian package name?" @@ -256,8 +262,19 @@ def is_valid_upstreamversion(version): return upstreamversion_re.match(version) def get_compression(orig_file): - "Given an orig file return the compression used" - ext = orig_file.rsplit('.',1)[1] + """ + Given an orig file return the compression used + >>> get_compression("abc.tar.gz") + 'gzip' + >>> get_compression("abc.tar.bz2") + 'bzip2' + >>> get_compression("abc.tar.foo") + >>> get_compression("abc") + """ + try: + ext = orig_file.rsplit('.',1)[1] + except IndexError: + return None for (c, o) in compressor_opts.iteritems(): if o[1] == ext: return c @@ -265,12 +282,15 @@ def get_compression(orig_file): def has_epoch(cp): - """does the topmost version number contain an epoch""" - try: - if cp['Epoch']: - return True - except KeyError: - return False + """ + Does the topmost version number in the changelog contain an epoch + >>> has_epoch(dict(Epoch="1")) + True + >>> has_epoch(dict()) + False + """ + return cp.has_key("Epoch") + def has_orig(cp, compression, dir): "Check if orig.tar.gz exists in dir" @@ -1,12 +1,12 @@ # vim: set fileencoding=utf-8 : # -# (C) 2006,2007,2008 Guido Guenther <agx@sigxcpu.org> +# (C) 2006,2007,2008,2011 Guido Guenther <agx@sigxcpu.org> """provides git repository related helpers""" import re import subprocess import os.path -from command_wrappers import (GitAdd, GitRm, GitCheckoutBranch, GitInit, GitCommand, copy_from) +from command_wrappers import (GitCommand, GitInit, GitAdd, GitBranch, copy_from) from errors import GbpError import log import dateutil.parser @@ -39,14 +39,14 @@ class GitRepository(object): env.update(extra_env) return env - def __git_getoutput(self, command, args=[], extra_env=None): + def __git_getoutput(self, command, args=[], extra_env=None, cwd=None): """exec a git command and return the output""" output = [] env = self.__build_env(extra_env) cmd = ['git', command] + args log.debug(cmd) - popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env) + popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env, cwd=cwd) while popen.poll() == None: output += popen.stdout.readlines() ret = popen.poll() @@ -63,9 +63,7 @@ class GitRepository(object): stdout=subprocess.PIPE, env=env) (stdout, stderr) = popen.communicate(input) - if popen.returncode: - stdout = None - return stdout + return stdout, stderr, popen.returncode def base_dir(self): """Base of the repository""" @@ -174,7 +172,8 @@ class GitRepository(object): has_local = False # local repo has new commits has_remote = False # remote repo has new commits out = self.__git_getoutput('rev-list', ["--left-right", - "%s...%s" % (from_branch, to_branch)])[0] + "%s...%s" % (from_branch, to_branch), + "--"])[0] if not out: # both branches have the same commits return True, True @@ -196,7 +195,16 @@ class GitRepository(object): """switch to branch 'branch'""" self.__check_path() if self.get_branch() != branch: - GitCheckoutBranch(branch)() + GitCommand("checkout", [ branch ])() + + def create_branch(self, branch, rev=None): + """create a new branch + @param rev: where to start the branch from + + if param is None the branch starts form the current HEAD + """ + self.__check_path() + GitBranch()(branch, rev) def delete_branch(self, branch): self.__check_path() @@ -344,20 +352,6 @@ class GitRepository(object): raise GitRepositoryError, "can't write out current index" return tree[0].strip() - def replace_tree(self, src_dir, filters, verbose=False): - """ - make the current wc match what's in src_dir - @return: True if wc was modified - @rtype: boolean - """ - old = set(self.index_files()) - new = set(copy_from(src_dir, filters)) - GitAdd()(['-f', '.']) - files = [ obj for obj in old - new if not os.path.isdir(obj)] - if files: - GitRm(verbose=verbose)(files) - return not self.is_clean()[0] - def update_ref(self, ref, new, old=None, msg=None): """Update ref 'ref' to commit 'new'""" args = [ ref, new ] @@ -367,45 +361,37 @@ class GitRepository(object): args = [ '-m', msg ] + args GitCommand("update-ref")(args) - def commit_tree(self, tree, msg, parents, author=None, email=None, - date=None, committer_name=None, committer_email=None, - committer_date=None): + def commit_tree(self, tree, msg, parents, author={}, committer={}): """Commit a tree with commit msg 'msg' and parents 'parents'""" extra_env = {} - if author: - extra_env['GIT_AUTHOR_NAME'] = author - if email: - extra_env['GIT_AUTHOR_EMAIL'] = email - if date: - extra_env['GIT_AUTHOR_DATE'] = date - if committer_name: - extra_env['GIT_COMMITTER_NAME'] = committer_name - if committer_email: - extra_env['GIT_COMMITTER_EMAIL'] = committer_email - if committer_date: - extra_env['GIT_COMMITTER_DATE'] = committer_date + for key, val in author.items(): + if val: + extra_env['GIT_AUTHOR_%s' % key.upper()] = val + for key, val in committer.items(): + if val: + extra_env['GIT_COMMITTER_%s' % key.upper()] = val args = [ tree ] for parent in parents: args += [ '-p' , parent ] - sha1 = self.__git_inout('commit-tree', args, msg, extra_env).strip() - return sha1 + sha1, stderr, ret = self.__git_inout('commit-tree', args, msg, extra_env) + if not ret: + return sha1.strip() + else: + raise GbpError, "Failed to commit tree: %s" % stderr def commit_dir(self, unpack_dir, msg, branch, other_parents=None, - author = None, email = None, date = None, - committer_name = None, committer_email = None, - committer_date = None): + author={}, committer={}): """Replace the current tip of branch 'branch' with the contents from 'unpack_dir' @param unpack_dir: content to add @param msg: commit message to use @param branch: branch to add the contents of unpack_dir to @param parents: additional parents of this commit - @param author: commit with author name 'author' - @param email: commit with author email 'email' - @param date: set author date to 'date' - @param committer_author: commit with committer name 'commiter_name' - @param committer_email: commit with committer email 'commiter_email' - @param committer_date: set commit date to 'date'""" + @param author: commit with author information from author + @type author: dict with keys 'name', 'email', 'date' + @param committer_author: commit with committer information from committer + @type comitter: dict with keys 'name', 'email', 'date'""" + self.__check_path() git_index_file = os.path.join(self.path, '.git', 'gbp_index') try: @@ -434,10 +420,7 @@ class GitRepository(object): parents += [ sha ] commit = self.commit_tree(tree=tree, msg=msg, parents=parents, - author=author, email=email, date=date, - committer_name=committer_name, - committer_email=committer_email, - committer_date=committer_date) + author=author, committer=committer) if not commit: raise GbpError, "Failed to commit tree" self.update_ref("refs/heads/%s" % branch, commit, cur) @@ -486,6 +469,81 @@ class GitRepository(object): output, ret = self.__git_getoutput('format-patch', options) return [ line.strip() for line in output ] + def apply_patch(self, patch, index=True, context=None): + """Apply a patch using git apply""" + + args = [] + if context: + args += [ '-C', context ] + if index: + args.append("--index") + args.append(patch) + GitCommand("apply", args)() + + def archive(self, format, prefix, output, treeish, **kwargs): + args = [ '--format=%s' % format, '--prefix=%s' % prefix, + '--output=%s' % output, treeish ] + out, ret = self.__git_getoutput('archive', args, **kwargs) + if ret: + raise GitRepositoryError, "unable to archive %s"%(treeish) + + + def has_submodules(self): + """Does the repo have submodules""" + if os.path.exists('.gitmodules'): + return True + else: + return False + + + def add_submodule(self, repo_path): + """Add a submodule""" + GitCommand("submodule", [ "add", repo_path ])() + + + def update_submodules(self, init=True, recursive=True, fetch=False): + """Update all submodules""" + if not self.has_submodules(): + return + args = [ "update" ] + if recursive: + args.append("--recursive") + if init: + args.append("--init") + if not fetch: + args.append("--no-fetch") + + GitCommand("submodule", args)() + + + def get_submodules(self, treeish, path=None, recursive=True): + """ list the submodules of treeish + + returns a list of submodule/commit-id tuples + """ + # Note that we is lstree instead of submodule commands because + # there's no way to list the submodules of another branch with + # the latter. + submodules = [] + if path is None: + path = "." + + args = [ treeish ] + if recursive: + args += ['-r'] + + out, ret = self.__git_getoutput('ls-tree', args, cwd=path) + for line in out: + mode, objtype, commit, name = line.split() + # A submodules is shown as "commit" object in ls-tree: + if objtype == "commit": + nextpath = os.path.sep.join([path, name]) + submodules.append( (nextpath, commit) ) + if recursive: + submodules += self.get_submodules(commit, path=nextpath, + recursive=recursive) + return submodules + class FastImport(object): """Invoke git-fast-import""" @@ -17,6 +17,7 @@ # """Simple colored logging classes""" +import os import sys import gbp.tristate @@ -50,6 +51,17 @@ class Logger(object): def set_level(self, level): self.level = level + def _is_tty(self): + if (os.getenv("EMACS") and + os.getenv("INSIDE_EMACS", "").endswith(",comint")): + return False + + if (sys.stderr.isatty() and + sys.stdout.isatty()): + return True + + return False + def set_color(self, color): if type(color) == type(True): self.color = color @@ -57,9 +69,7 @@ class Logger(object): if color.is_on(): self.color = True elif color.is_auto(): - if (sys.stderr.isatty() and - sys.stdout.isatty()): - self.color = True + self.color = self._is_tty() else: self.color = False diff --git a/gbp/notifications.py b/gbp/notifications.py index b2534e3..9115ac3 100644 --- a/gbp/notifications.py +++ b/gbp/notifications.py @@ -45,6 +45,7 @@ def build_msg(cp, success): def send_notification(summary, msg): n = notify_module.Notification(summary, msg) + n.set_hint('transient', True) try: if not n.show(): return False |