From: Frederic Massart Date: Tue, 7 Aug 2012 07:51:02 +0000 (+0800) Subject: Added command to backport an issue X-Git-Tag: v0.1~69 X-Git-Url: https://git.cameron1729.xyz/?a=commitdiff_plain;h=4c80a64563cf62cacfc270049a466248e29aa007;p=mdk.git Added command to backport an issue --- diff --git a/lib/git.py b/lib/git.py index 8d2e847..0c6a4e8 100644 --- a/lib/git.py +++ b/lib/git.py @@ -66,8 +66,11 @@ class Git(): cmd = 'fetch %s %s' % (remote, ref) return self.execute(cmd) - def hasBranch(self, branch): - cmd = 'show-ref --verify --quiet "refs/heads/%s"' % branch + def hasBranch(self, branch, remote = ''): + if remote != '': + cmd = 'show-ref --verify --quiet "refs/remotes/%s/%s"' % (remote, branch) + else: + cmd = 'show-ref --verify --quiet "refs/heads/%s"' % branch (returncode, stdout, stderr) = self.execute(cmd) return returncode == 0 @@ -84,6 +87,10 @@ class Git(): proc.wait() return proc.returncode == 0 + def pick(self, refs): + cmd = 'cherry-pick %s' % refs + return self.execute(cmd) + def pull(self, remote = '', ref = ''): cmd = 'pull %s %s' % (remote, ref) return self.execute(cmd) @@ -96,6 +103,14 @@ class Git(): cmd = 'push %s%s %s' % (force, toremote, tobranch) return self.execute(cmd) + def reset(self, to, hard = False): + mode = '' + if hard: + mode == '--hard' + cmd = 'reset --hard %s' % (to) + result = self.execute(cmd) + return result[0] == 0 + def status(self): return self.execute('status') diff --git a/lib/moodle.py b/lib/moodle.py index 0cf1f7e..31572a0 100644 --- a/lib/moodle.py +++ b/lib/moodle.py @@ -16,8 +16,8 @@ class Moodle(): identifier = None path = None installed = False - version = {} - config = {} + version = None + config = None _dbo = None _git = None @@ -26,6 +26,8 @@ class Moodle(): def __init__(self, path, identifier = None): self.path = path self.identifier = identifier + self.version = {} + self.config = {} self._load() def addConfig(self, name, value): @@ -71,6 +73,16 @@ class Moodle(): pass return self._dbo + def generateBranchName(self, issue, suffix='', version=''): + """Generates a branch name""" + mdl = re.sub(r'MDL(-|_)?', '', issue, flags=re.I) + if version == '': + version = self.get('branch') + branch = C('wording.branchFormat') % (mdl, version) + if suffix != None and suffix != '': + branch += C('wording.branchSuffixSeparator') + suffix + return branch + def get(self, param, default = None): """Returns a property of this instance""" info = self.info() diff --git a/lib/workplace.py b/lib/workplace.py index 0a1db74..ed1efab 100644 --- a/lib/workplace.py +++ b/lib/workplace.py @@ -132,6 +132,27 @@ class Workplace(): if DB and dbname: DB.dropdb(dbname) + def generateInstanceName(self, version, integration=False, suffix=''): + """Creates a name (identifier) from arguments""" + + # Wording version + if version == 'master': + prefixVersion = C('wording.prefixMaster') + else: + prefixVersion = version + + # Generating name + if integration: + name = C('wording.prefixIntegration') + prefixVersion + else: + name = C('wording.prefixStable') + prefixVersion + + # Append the suffix + if suffix != None and suffix != '': + name += C('wording.suffixSeparator') + suffix + + return name + def get(self, name): """Returns an instance defined by its name, or by path""" # Extracts name from path diff --git a/moodle-backport.py b/moodle-backport.py new file mode 100755 index 0000000..11d8d48 --- /dev/null +++ b/moodle-backport.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import argparse +import re +from lib import config, workplace, moodle, tools +from lib.tools import debug + +C = config.Conf().get +Wp = workplace.Workplace() + +# Arguments +parser = argparse.ArgumentParser(description="Backports a branch") +parser.add_argument('-i', '--issue', metavar='issue', required=True, help='the issue to backport') +parser.add_argument('-s', '--suffix', metavar='suffix', help='the suffix of the branch of this issue') +parser.add_argument('-r', '--remote', metavar='remote', help='the remote to fetch from. Default is %s.' % C('mineRepo')) +parser.add_argument('-v', '--versions', metavar='version', required=True, nargs='+', choices=[ str(x) for x in range(13, C('masterBranch')) ] + ['master'], help='versions to backport to') +parser.add_argument('name', metavar='name', default=None, nargs='?', help='name of the instance to work on') +args = parser.parse_args() + +M = Wp.resolve(args.name) +if not M: + debug('This is not a Moodle instance') + sys.exit(1) + +remote = args.remote +if remote == None: + remote = C('mineRepo') + + +branch = M.generateBranchName(args.issue, suffix=args.suffix) +originaltrack = M.get('stablebranch') +if not M.git().hasBranch(branch): + debug('Could not find original branch %s.' % (branch, remote)) + sys.exit(1) +if not M.git().hasBranch(branch): + debug('Could not find original branch %s.' % (branch, remote)) + sys.exit(1) + +# Begin backport +for v in args.versions: + + # Gets the instance to cherry-pick to + name = Wp.generateInstanceName(v, integration=M.get('integration')) + if not Wp.isMoodle(name): + debug('Could not find instance %s for version %s' % (name, v)) + continue + M2 = Wp.get(name) + + debug("Preparing cherry-pick of %s/%s in %s" % (remote, branch, name)) + + # Fetch the remote to get reference to the branch to backport + debug("Fetching remote %s..." % remote) + M2.git().fetch(remote) + + # Creates a new branch if necessary + newbranch = M2.generateBranchName(args.issue, suffix=args.suffix) + track = 'origin/%s' % M2.get('stablebranch') + if not M2.git().hasBranch(newbranch): + debug('Creating branch %s' % newbranch) + if not M2.git().createBranch(newbranch, track=track): + debug('Could not create branch %s tracking %s in %s' % (newbranch, track, name)) + continue + M2.git().checkout(newbranch) + else: + M2.git().checkout(newbranch) + debug('Hard reset to %s' % (track)) + M2.git().reset(to=track, hard=True) + + # Picking the diff origin/MOODLE_23_STABLE..github/MDL-12345-master + cherry = 'origin/%s..%s/%s' % (originaltrack, remote, branch) + debug('Cherry-picking %s' % (cherry)) + result = M2.git().pick(cherry) + if result[0] != 0: + debug('Error while cherry-picking %s/%s in %s.' % (remote, branch, name)) + debug(result[2]) + continue + + debug('Instance %s successfully patched!' % name) + debug('') + +debug('Done.')