def run(self, args): M = self.Wp.resolve(args.name) if not M: raise Exception('This is not a Moodle instance') # Setting remote remote = args.remote # Setting branch if args.branch == None: branch = M.currentBranch() if branch == 'HEAD': raise Exception('Cannot push HEAD branch') else: branch = args.branch # Extra test to see if the commit message is correct. This prevents easy typos in branch or commit messages. parsedbranch = tools.parseBranch(branch, self.C.get('wording.branchRegex')) if parsedbranch or branch != M.get('stablebranch'): message = M.git().messages(count=1)[0] mdl = message.split(' ')[0] if parsedbranch: branchmdl = 'MDL-%s' % (parsedbranch['issue']) else: branchmdl = branch if mdl != branchmdl: print 'The MDL number in the last commit does not match the branch being pushed to.' print 'Branch: %s vs. commit: %s' % (branchmdl, mdl) answer = tools.question('Are you sure you want to continue?', default='n') if answer.lower()[0] != 'y': print 'Exiting...' return # Pushing current branch logging.info('Pushing branch %s to remote %s...' % (branch, remote)) result = M.git().push(remote, branch, force=args.force) if result[0] != 0: raise Exception(result[2]) # Update the tracker if args.updatetracker: M.updateTrackerGitInfo(branch=branch) # Pushing stable branch if args.includestable: branch = M.get('stablebranch') logging.info('Pushing branch %s to remote %s...' % (branch, remote)) result = M.git().push(remote, branch, force=args.forcestable) if result[0] != 0: raise Exception(result[2]) logging.info('Done.')
def run(self, args): issue = None if not args.issue: M = self.Wp.resolve() if M: parsedbranch = parseBranch(M.currentBranch(), self.C.get('wording.branchRegex')) if parsedbranch: issue = parsedbranch['issue'] else: issue = args.issue if not issue or not re.match('(MDL|mdl)?(-|_)?[1-9]+', issue): raise Exception('Invalid or unknown issue number') self.Jira = Jira() self.mdl = 'MDL-' + re.sub(r'(MDL|mdl)(-|_)?', '', issue) self.info(args)
integration = args.integration if remote == None: remote = C.get('myRemote') # If we don't have a branch, we need an instance M = Wp.resolve(args.name) if not M and not branch: debug('This is not a Moodle instance') sys.exit(1) # Getting issue number if M and not branch: branch = M.currentBranch() # Parsing the branch parsedbranch = tools.parseBranch(branch, C.get('wording.branchRegex')) if not parsedbranch: debug('Could not extract issue number from %s' % branch) sys.exit(1) issue = parsedbranch['issue'] suffix = parsedbranch['suffix'] version = parsedbranch['version'] # Original track originaltrack = tools.stableBranch(version) # Pushes the branch to the remote first if M and not args.dontpush: debug('Pushing %s to %s' % (branch, remote)) if not M.git().push(remote, branch): debug('Could not push %s to %s' % (branch, remote))
debug('Cannot push HEAD branch') sys.exit(1) else: branch = args.branch # Pushing current branch debug('Pushing branch %s to remote %s...' % (branch, remote)) result = M.git().push(remote, branch, force=args.force) if result[0] != 0: debug(result[2]) sys.exit(1) if args.updatetracker: # Getting issue number # Parsing the branch parsedbranch = tools.parseBranch(branch, C.get('wording.branchRegex')) if not parsedbranch: debug('Could not extract issue number from %s' % branch) sys.exit(1) issue = 'MDL-%s' % (parsedbranch['issue']) version = parsedbranch['version'] # Get the jira config repositoryurl = C.get('repositoryUrl') diffurltemplate = C.get('diffUrlTemplate') stablebranch = M.get('stablebranch') upstreamremote = C.get('upstreamRemote') # Get the hash of the last upstream commit ref = '%s/%s' % (upstreamremote, stablebranch) headcommit = M.git().hashes(ref=ref, limit=1)[0]
def run(self, args): M = None branch = args.branch versions = args.versions integration = args.integration # If we don't have a branch, we need an instance M = self.Wp.resolve(args.name) if not M and not branch: raise Exception('This is not a Moodle instance') # Getting issue number if M and not branch: branch = M.currentBranch() # Parsing the branch parsedbranch = tools.parseBranch(branch, self.C.get('wording.branchRegex')) if not parsedbranch: raise Exception('Could not extract issue number from %s' % branch) issue = parsedbranch['issue'] suffix = parsedbranch['suffix'] version = parsedbranch['version'] # Original track originaltrack = tools.stableBranch(version) # Integration? if M: integration = M.isIntegration() def stashPop(stash): """Small helper to pop the stash has we have to do it in some different places""" if not stash[1].startswith('No local changes'): pop = M2.git().stash(command='pop') if pop[0] != 0: logging.error('An error ocured while unstashing your changes') else: logging.info('Popped the stash') # Begin backport for v in versions: # Gets the instance to cherry-pick to name = self.Wp.generateInstanceName(v, integration=integration) if not self.Wp.isMoodle(name): logging.warning('Could not find instance %s for version %s' % (name, v)) continue M2 = self.Wp.get(name) logging.info("Preparing cherry-pick of %s/%s in %s" % (M.get('identifier'), branch, name)) # Get hash list cherry = '%s/%s..%s' % (self.C.get('upstreamRemote'), originaltrack, branch) hashes = M.git().hashes(cherry) hashes.reverse() # Stash stash = M2.git().stash(untracked=False) if stash[0] != 0: logging.error('Error while trying to stash your changes. Skipping %s.' % M2.get('identifier')) logging.debug(stash[2]) continue elif not stash[1].startswith('No local changes'): logging.info('Stashed your local changes') # Fetch the remote to get reference to the branch to backport logging.info("Fetching remote %s..." % (M.get('path'))) M2.git().fetch(M.get('path'), branch) # Creates a new branch if necessary newbranch = M2.generateBranchName(issue, suffix=suffix) track = '%s/%s' % (self.C.get('upstreamRemote'), M2.get('stablebranch')) if not M2.git().hasBranch(newbranch): logging.info('Creating branch %s' % newbranch) if not M2.git().createBranch(newbranch, track=track): logging.error('Could not create branch %s tracking %s in %s' % (newbranch, track, name)) stashPop(stash) continue M2.git().checkout(newbranch) else: M2.git().checkout(newbranch) logging.info('Hard reset %s to %s' % (newbranch, track)) M2.git().reset(to=track, hard=True) # Picking the diff upstream/MOODLE_23_STABLE..github/MDL-12345-master logging.info('Cherry-picking %s' % (cherry)) result = M2.git().pick(hashes) if result[0] != 0: logging.error('Error while cherry-picking %s in %s.' % (cherry, name)) logging.debug(result[2]) if yesOrNo('The cherry-pick might still be in progress, would you like to abort it?'): result = M2.git().pick(abort=True) if result[0] > 0 and result[0] != 128: logging.error('Could not abort the cherry-pick!') else: stashPop(stash) logging.info('') continue # Pushing branch if args.push: pushremote = args.pushremote if pushremote == None: pushremote = self.C.get('myRemote') logging.info('Pushing %s to %s' % (newbranch, pushremote)) result = M2.git().push(remote=pushremote, branch=newbranch, force=args.forcepush) if result[0] != 0: logging.warning('Error while pushing to remote %s' % (pushremote)) logging.debug(result[2]) stashPop(stash) continue # Update the tracker if args.updatetracker: M2.updateTrackerGitInfo(branch=newbranch) stashPop(stash) logging.info('Instance %s successfully patched!' % name) logging.info('') logging.info('Done.')
def run(self, args): M = self.Wp.resolve() if not M: raise Exception('This is not a Moodle instance') if (args.testing and args.integration) or (args.testing and args.nomerge) or (args.integration and args.nomerge): raise Exception('You cannot combine --integration, --testing or --no-merge') # Tracker issue number. issuenb = args.issue if not issuenb: parsedbranch = tools.parseBranch(M.currentBranch(), self.C.get('wording.branchRegex')) if not parsedbranch: raise Exception('Could not extract issue number from %s' % M.currentBranch()) issuenb = parsedbranch['issue'] issue = re.sub(r'(MDL|mdl)(-|_)?', '', issuenb) mdl = 'MDL-' + issue # Reading the information about the current instance. branch = M.get('branch') # Get information from Tracker logging.info('Retrieving information about %s from Moodle Tracker' % (mdl)) J = jira.Jira() issueInfo = J.getIssue(mdl) mode = 'pull' remoteUrl = issueInfo.get('named').get(self.C.get('tracker.fieldnames.repositoryurl')) remoteBranch = issueInfo.get('named').get(self.C.get('tracker.fieldnames.%s.branch' % (branch))) patchesToApply = [] if not args.nomerge and (not remoteUrl or not remoteBranch): mode = None attachments = issueInfo.get('fields').get('attachment') patches = {} for attachment in attachments: if attachment['filename'].endswith('.patch'): patches[attachment['filename']] = attachment if len(patches) > 0: mapping = {} i = 1 for key in sorted(patches.keys()): patch = patches[key] mapping[i] = patch date = jira.Jira.parseDate(patch['created']) print '{0:<2}: {1:<60} {2}'.format(i, patch['filename'][:60], datetime.strftime(date, '%Y-%m-%d %H:%M')) i += 1 ids = question('What patches would you like to apply?') if ids: ids = re.split(r'\s*[, ]\s*', ids) for i in ids: i = int(i) if not i in mapping.keys(): continue j = 0 while True: mapping[i]['mdk-filename'] = mapping[i]['filename'] + (('.' + str(j)) if j > 0 else '') j += 1 if not os.path.isfile(mapping[i]['mdk-filename']): break patchesToApply.append(mapping[i]) mode = 'patch' else: mode = False if not mode: raise Exception('Did not find enough information to pull a patch.') # Stash stash = M.git().stash(untracked=True) if stash[0] != 0: raise Exception('Error while trying to stash your changes. Exiting...') elif not stash[1].startswith('No local changes'): logging.info('Stashed your local changes') # Create a testing branch if args.testing: i = 0 while True: i += 1 suffix = 'test' if i <= 1 else 'test' + str(i) newBranch = M.generateBranchName(issue, suffix=suffix, version=branch) if not M.git().hasBranch(newBranch): break track = '%s/%s' % (self.C.get('upstreamRemote'), M.get('stablebranch')) M.git().createBranch(newBranch, track=track) if not M.git().checkout(newBranch): raise Exception('Could not checkout branch %s' % (newBranch)) logging.info('Checked out branch %s' % (newBranch)) # Checkout the stable branch elif args.integration: if not M.git().checkout(M.get('stablebranch')): logging.error('Could not checkout branch %s' % (M.get('stablebranch'))) logging.info('Checked out branch %s' % (M.get('stablebranch'))) # Create a no-merge branch elif args.nomerge: i = 0 while True: i += 1 suffix = 'nomerge' if i <= 1 else 'nomerge' + str(i) newBranch = M.generateBranchName(issue, suffix=suffix, version=branch) if not M.git().hasBranch(newBranch): break track = '%s/%s' % (self.C.get('upstreamRemote'), M.get('stablebranch')) M.git().createBranch(newBranch, track=track) if not M.git().checkout(newBranch): raise Exception('Could not checkout branch %s' % (newBranch)) logging.info('Checked out branch %s' % (newBranch)) mode = 'nomerge' if mode == 'pull': # Pull branch from tracker logging.info('Pulling branch %s from %s into %s' % (remoteBranch, remoteUrl, M.currentBranch())) M.git().pull(remote=remoteUrl, ref=remoteBranch) elif mode == 'patch': # Apply a patch from tracker files = [] for patch in patchesToApply: dest = patch['mdk-filename'] logging.info('Downloading %s' % (patch['filename'])) if not J.download(patch['content'], dest): logging.error('Failed to download. Aborting...') files = [] break files.append(dest) if len(files) > 0: logging.info('Applying patch(es)...') if not M.git().apply(files): logging.warning('Could not apply the patch(es), please apply manually') else: for f in files: os.remove(f) elif mode == 'nomerge': # Checking out the patch without merging it. logging.info('Fetching %s %s' % (remoteUrl, remoteBranch)) M.git().fetch(remote=remoteUrl, ref=remoteBranch) logging.info('Hard reset to FETCH_HEAD') M.git().reset('FETCH_HEAD', hard=True) # Stash pop if not stash[1].startswith('No local changes'): pop = M.git().stash(command='pop') if pop[0] != 0: logging.error('An error ocured while unstashing your changes') else: logging.info('Popped the stash') logging.info('Done.')
def run(self, args): M = self.Wp.resolve(args.name) if not M: raise Exception('This is not a Moodle instance') # Setting remote remote = args.remote # Setting branch if args.branch == None: branch = M.currentBranch() if branch == 'HEAD': raise Exception('Cannot push HEAD branch') else: branch = args.branch # Extra test to see if the commit message is correct. This prevents easy typos in branch or commit messages. parsedbranch = tools.parseBranch(branch, self.C.get('wording.branchRegex')) if parsedbranch or branch != M.get('stablebranch'): message = M.git().messages(count=1)[0] mdl = getMDLFromCommitMessage(message) if parsedbranch: branchmdl = 'MDL-%s' % (parsedbranch['issue']) else: branchmdl = branch if not mdl or mdl != branchmdl: if not mdl: print 'The MDL number could not be found in the commit message.' print 'Commit: %s' % (message) elif mdl != branchmdl: print 'The MDL number in the last commit does not match the branch being pushed to.' print 'Branch: \'%s\' vs. commit: \'%s\'' % (branchmdl, mdl) answer = tools.question('Are you sure you want to continue?', default='n') if answer.lower()[0] != 'y': print 'Exiting...' return J = jira.Jira() # If the mode is not set to patch yet, and we can identify the MDL number. if not args.patch and parsedbranch: mdlIssue = 'MDL-%s' % (parsedbranch['issue']) args.patch = J.isSecurityIssue(mdlIssue) if args.patch: logging.info('%s appears to be a security issue, switching to patch mode...' % (mdlIssue)) if args.patch: if not M.pushPatch(branch): return else: # Pushing current branch logging.info('Pushing branch %s to remote %s...' % (branch, remote)) result = M.git().push(remote, branch, force=args.force) if result[0] != 0: raise Exception(result[2]) # Update the tracker if args.updatetracker != None: ref = None if args.updatetracker == True else args.updatetracker M.updateTrackerGitInfo(branch=branch, ref=ref) # Pushing stable branch if args.includestable: branch = M.get('stablebranch') logging.info('Pushing branch %s to remote %s...' % (branch, remote)) result = M.git().push(remote, branch, force=args.forcestable) if result[0] != 0: raise Exception(result[2]) logging.info('Done.')
parser.add_argument('issue', metavar='issue', default=None, nargs='?', help='tracker issue to pull from (MDL-12345, 12345). If not specified, read from current branch.') args = parser.parse_args() M = Wp.resolve() if not M: debug('This is not a Moodle instance') sys.exit(1) if args.testing and args.integration: debug('You cannot combine --integration and --testing') sys.exit(1) # Tracker issue number. issuenb = args.issue if not issuenb: parsedbranch = tools.parseBranch(M.currentBranch(), C.get('wording.branchRegex')) if not parsedbranch: debug('Could not extract issue number from %s' % M.currentBranch()) sys.exit(1) issuenb = parsedbranch['issue'] issue = re.sub(r'(MDL|mdl)(-|_)?', '', issuenb) mdl = 'MDL-' + issue # Reading the information about the current instance. branch = M.get('branch') # Get information from Tracker debug('Retrieving information about %s from Moodle Tracker' % (mdl)) J = jira.Jira() issueInfo = J.getIssue(mdl)
) args = parser.parse_args() M = Wp.resolve() if not M: debug('This is not a Moodle instance') sys.exit(1) if args.testing and args.integration: debug('You cannot combine --integration and --testing') sys.exit(1) # Tracker issue number. issuenb = args.issue if not issuenb: parsedbranch = tools.parseBranch(M.currentBranch(), C.get('wording.branchRegex')) if not parsedbranch: debug('Could not extract issue number from %s' % M.currentBranch()) sys.exit(1) issuenb = parsedbranch['issue'] issue = re.sub(r'(MDL|mdl)(-|_)?', '', issuenb) mdl = 'MDL-' + issue # Reading the information about the current instance. branch = M.get('branch') # Get information from Tracker debug('Retrieving information about %s from Moodle Tracker' % (mdl)) J = jira.Jira() issueInfo = J.getIssue(mdl)
def run(self, args): M = None branch = args.branch versions = args.versions integration = args.integration # If we don't have a branch, we need an instance M = self.Wp.resolve(args.name) if not M and not branch: raise Exception("This is not a Moodle instance") # Getting issue number if M and not branch: branch = M.currentBranch() # Parsing the branch parsedbranch = tools.parseBranch(branch, self.C.get("wording.branchRegex")) if not parsedbranch: raise Exception("Could not extract issue number from %s" % branch) issue = parsedbranch["issue"] suffix = parsedbranch["suffix"] version = parsedbranch["version"] if args.push and not args.patch: mdlIssue = "MDL-%s" % (issue) J = jira.Jira() args.patch = J.isSecurityIssue(mdlIssue) args.push = False if args.patch: logging.info("%s appears to be a security issue, switching to patch mode..." % (mdlIssue)) # Original track originaltrack = tools.stableBranch(version) # Integration? if M: integration = M.isIntegration() def stashPop(stash): """Small helper to pop the stash has we have to do it in some different places""" if not stash[1].startswith("No local changes"): pop = M2.git().stash(command="pop") if pop[0] != 0: logging.error("An error ocured while unstashing your changes") else: logging.info("Popped the stash") # Begin backport for v in versions: # Gets the instance to cherry-pick to name = self.Wp.generateInstanceName(v, integration=integration) if not self.Wp.isMoodle(name): logging.warning("Could not find instance %s for version %s" % (name, v)) continue M2 = self.Wp.get(name) logging.info("Preparing cherry-pick of %s/%s in %s" % (M.get("identifier"), branch, name)) # Get hash list cherry = "%s/%s..%s" % (self.C.get("upstreamRemote"), originaltrack, branch) hashes = M.git().hashes(cherry) hashes.reverse() # Stash stash = M2.git().stash(untracked=False) if stash[0] != 0: logging.error("Error while trying to stash your changes. Skipping %s." % M2.get("identifier")) logging.debug(stash[2]) continue elif not stash[1].startswith("No local changes"): logging.info("Stashed your local changes") # Fetch the remote to get reference to the branch to backport logging.info("Fetching remote %s..." % (M.get("path"))) M2.git().fetch(M.get("path"), branch) # Creates a new branch if necessary newbranch = M2.generateBranchName(issue, suffix=suffix) track = "%s/%s" % (self.C.get("upstreamRemote"), M2.get("stablebranch")) if not M2.git().hasBranch(newbranch): logging.info("Creating branch %s" % newbranch) if not M2.git().createBranch(newbranch, track=track): logging.error("Could not create branch %s tracking %s in %s" % (newbranch, track, name)) stashPop(stash) continue M2.git().checkout(newbranch) else: M2.git().checkout(newbranch) logging.info("Hard reset %s to %s" % (newbranch, track)) M2.git().reset(to=track, hard=True) # Picking the diff upstream/MOODLE_23_STABLE..github/MDL-12345-master logging.info("Cherry-picking %s" % (cherry)) result = M2.git().pick(hashes) if result[0] != 0: # Try to resolve the conflicts if any. resolveConflicts = True conflictsResolved = False while resolveConflicts: # Check the list of possible conflicting files. conflictingFiles = M2.git().conflictingFiles() if ( conflictingFiles and len(conflictingFiles) == 1 and "theme/bootstrapbase/style/moodle.css" in conflictingFiles ): logging.info("Conflicts found in bootstrapbase moodle CSS, trying to auto resolve...") cssCompiler = css.Css(M2) if cssCompiler.compile(theme="bootstrapbase", sheets=["moodle"]): M2.git().add("theme/bootstrapbase/style/moodle.css") # We need to commit manually to prevent the editor to open. M2.git().commit(filepath=".git/MERGE_MSG") result = M2.git().pick(continu=True) if result[0] == 0: resolveConflicts = False conflictsResolved = True else: resolveConflicts = False # We still have a dirty repository. if not conflictsResolved: logging.error("Error while cherry-picking %s in %s." % (cherry, name)) logging.debug(result[2]) if yesOrNo("The cherry-pick might still be in progress, would you like to abort it?"): result = M2.git().pick(abort=True) if result[0] > 0 and result[0] != 128: logging.error("Could not abort the cherry-pick!") else: stashPop(stash) logging.info("") continue # Pushing branch if args.push: pushremote = args.pushremote if pushremote == None: pushremote = self.C.get("myRemote") logging.info("Pushing %s to %s" % (newbranch, pushremote)) result = M2.git().push(remote=pushremote, branch=newbranch, force=args.forcepush) if result[0] != 0: logging.warning("Error while pushing to remote %s" % (pushremote)) logging.debug(result[2]) stashPop(stash) continue # Update the tracker if args.updatetracker != None: ref = None if args.updatetracker == True else args.updatetracker M2.updateTrackerGitInfo(branch=newbranch, ref=ref) elif args.patch: if not M2.pushPatch(newbranch): continue stashPop(stash) logging.info("Instance %s successfully patched!" % name) logging.info("") logging.info("Done.")