Esempio n. 1
0
    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.')
Esempio n. 2
0
    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)
Esempio n. 3
0
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))
Esempio n. 4
0
        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]
Esempio n. 5
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.')
Esempio n. 6
0
    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.')
Esempio n. 7
0
    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.')
Esempio n. 8
0
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)
Esempio n. 9
0
)
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)
Esempio n. 10
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"]

        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.")