예제 #1
0
    def scan_replica_patches(self, patches_branch=None):
        # Mutations are only handled one at a time per branch
        if patches_branch:
            patches_branches = [patches_branch]
        else:
            patches_branches = list()
            for original_branch in self.original_branches:
                patches_branches.append(
                    self.underlayer.branch_maps['original->patches']
                    [original_branch])

        for patches_branch in patches_branches:
            recombination, remaining_changes = self.underlayer.get_recombination_from_patches(
                patches_branch)
            # TODO: handle new patchset on same branch-patches review.
            if recombination:
                recomb = recombination.__dict__
                log.debugvar('recomb')
                recombination.handle_status()
                if remaining_changes:
                    log.warning(
                        "Remaining mutation changes %s will be handled in order one at a time after recombination %s is completed "
                        % (' '.join(remaining_changes), recombination.uuid))
            else:
                logsummary.info(
                    "Project %s no new patches in patches branch %s" %
                    (self.project_name, patches_branch))
예제 #2
0
 def approved(self):
     if self.mutation_change.remote_status != "MERGED":
         try:
             self.mutation_change.approve()
             self.mutation_change.submit()
         except RecombinationApproveError:
             log.error("Originating change approval failed")
         except RecombinationSubmitError:
             log.error("Originating change submission failed")
     self.update_target_branch()
     if self.remote_status != "MERGED":
         self.submit()
     else:
         log.warning("Recombination already submitted")
예제 #3
0
    def scan_replica_patches(self, patches_branch=None):
        # Mutations are only handled one at a time per branch
        if patches_branch:
            patches_branches = [patches_branch]
        else:
            patches_branches = list()
            for original_branch in self.original_branches:
                patches_branches.append(self.underlayer.branch_maps['original->patches'][original_branch])

        for patches_branch in patches_branches:
            recombination, remaining_changes = self.underlayer.get_recombination_from_patches(patches_branch)
            # TODO: handle new patchset on same branch-patches review.
            if recombination:
                recomb = recombination.__dict__
                log.debugvar('recomb')
                recombination.handle_status()
                if remaining_changes:
                    log.warning("Remaining mutation changes %s will be handled in order one at a time after recombination %s is completed " % (' '.join(remaining_changes), recombination.uuid))
            else:
                logsummary.info("Project %s no new patches in patches branch %s" % (self.project_name, patches_branch))
예제 #4
0
 def initialize(self, remote, evolution_change=None, diversity_change=None, backport_change=None):
     super(EvolutionDiversityRecombination, self).initialize(remote)
     try:
         self.evolution_change = evolution_change
         self.diversity_change = diversity_change
         self.backport_change = backport_change
         self.branch = "recomb-evolution-%s-%s" % (self.evolution_change.branch, self.evolution_change.revision)
         self.topic = self.evolution_change.uuid
     except NameError:
         raise MissingInfoError
     self.main_source = self.evolution_change
     self.patches_source = self.diversity_change
     self.main_source_name = 'evolution'
     self.patches_source_name = 'diversity'
     self.set_status()
     if self.backport_change.remote_status is not None:
         log.warning("recombination already backported in patches branch")
         self.status = ""
     else:
         self.backport_change.commit_message = self.mangle_commit_message(self.evolution_change.commit_message)
     self.follow_backport_status()
예제 #5
0
    def scan_original_distance(self, original_branch):
        replica_branch = self.underlayer.branch_maps['original->replica'][original_branch]
        target_branch = self.underlayer.branch_maps['original->target'][original_branch]
        log.debug("Scanning distance from original branch %s" % original_branch)
#        if self.replication_strategy == "change-by-change" and revision_exists(self.ref_locks[replica_branch], replica_branch):
#                log.info("Cannot replicate branch past the specified lock")

        self.recombinations[original_branch] = self.get_recombinations_by_interval(original_branch)
        slices = self.get_slices(self.recombinations[original_branch])
        recombinations = self.recombinations[original_branch]


        log.debugvar('slices')
        # Master sync on merged changes
        # we really need only the last commit in the slice
        # we advance the master to that, and all the others will be merged too
        if slices['MERGED']:
            # one or more changes are merged in midstream, but missing in master
            # master is out of sync, changes need to be pushed
            # but check first if the change was changed with a merge commit
            # if yes, push THAT to master, if not, it's just a fast forward
            segment = slices['MERGED'][0]
            recomb_id = list(recombinations)[segment['end'] - 1]
            recombination = recombinations[recomb_id]
            recombination.handle_status()

        # Gerrit operations from approved changes
        # NOthing 'approved' can be merged if it has some "present" before in the history
        skip_list = set()
        for index, approved_segment in enumerate(slices['APPROVED']):
            for present_segment in slices['PRESENT']:
                if present_segment['start'] < approved_segment['start']:
                    skip_list.add(index)

        for index in list(skip_list)[::-1]:
            segment = slices['APPROVED'].pop(index)
            for recomb_id in list(recombinations)[segment['start']:segment['end']]:
                log.warning("Recombination %s is approved but waiting for previous unapproved changes, skipping" % recomb_id)

        # Merge what remains
        for segment in slices['APPROVED']:
            for recomb_id in list(recombinations)[segment['start']:segment['end']]:
                recombination = recombinations[recomb_id]
                recombination.handle_status()

        # Notify of presence
        for segment in slices['PRESENT']:
            for recomb_id in list(recombinations)[segment['start']:segment['end']]:
                recombination = recombinations[recomb_id]
                log.warning("Recombination %s already present in replica gerrit as change %s and waiting for approval" % (recomb_id, recombination.number))
                recombination.handle_status()

        # Gerrit operations for missing changes
        for segment in slices['MISSING']:
            for recomb_id in list(recombinations)[segment['start']:segment['end']]:
                log.warning("Recombination %s is missing from replica gerrit" % recomb_id)
                recombination = recombinations[recomb_id]
                recombination.handle_status()

        return True
예제 #6
0
 def set_status(self, metadata=None):
     self.status = "MISSING"
     if metadata and 'recombine-status' in metadata:
         self.status = metadata['recombine-status']
     if self.remote_status == 'NEW' or self.remote_status == 'DRAFT' and self.status == "SUCCESSFUL":
         self.status = 'PRESENT'
     if self.remote_status != "MERGED" and self.is_approved():
         self.status = "APPROVED"
     if self.status == "DISCARDED" and self.remote_status == "ABANDONED":
         # This combination of statuses means that this recombination attempt
         # was canceled and will not be reattempted
         log.warning("Recombination %s was discarded by user request, not reattempting" % self.uuid)
     if self.status == "ABANDONED" and self.remote_status == "ABANDONED":
         # this combination of statuses means that this recombination attempt
         # is completely abanoned and will be reattempted
         log.warning("Recombination %s was completely trashed, skipping and reattempting" % self.uuid)
         raise RecombinationCanceledError
     try:
         if self.backport_change:
             pass
     except AttributeError:
         pass
예제 #7
0
    def __init__(self,
                 projects_conf,
                 base_dir,
                 filter_projects=None,
                 filter_method=None,
                 filter_branches=None,
                 fetch=True):
        self.projects = dict()
        self.projects_conf = projects_conf
        self.base_dir = base_dir
        # extract reverse dependencies
        for project in self.projects_conf:
            self.projects_conf[project]["rev-deps"] = {}
        for project in self.projects_conf:
            if "test-teps" in self.projects_conf[project]:
                for test_dep in self.projects_conf[project]["test-deps"]:
                    rev_dep = {
                        project: {
                            "tags":
                            self.projects_conf[project]["test-deps"][test_dep],
                            "tests":
                            self.projects_conf[project]["replica"]["tests"]
                        }
                    }
                    self.projects_conf[test_dep]["rev-deps"].update(rev_dep)

        # restrict project to operate on
        projects = copy.deepcopy(projects_conf)
        project_list = list(projects)
        if filter_method:
            new_projects = dict()
            log.info('Filtering projects with watch method: %s' %
                     filter_method)
            for project_name in projects:
                if projects[project_name]['original'][
                        'watch-method'] == filter_method:
                    new_projects[project_name] = projects[project_name]
            projects = new_projects
        if filter_projects:
            new_projects = dict()
            log.info('Filtering projects with names: %s' % filter_projects)
            project_names = filter_projects.split(',')
            for project_name in project_names:
                if project_name not in project_list:
                    log.error(
                        "Project %s is not present in projects configuration" %
                        project_name)
                try:
                    new_projects[project_name] = projects[project_name]
                except KeyError:
                    log.warning(
                        "Project %s already discarded by previous filter" %
                        project_name)
            projects = new_projects
        if filter_branches:
            log.info("Filtering branches: %s" % filter_branches)
            branches = filter_branches.split(',')
            for project_name in projects:
                projects[project_name]['original']['watch-branches'] = branches

        if not projects:
            log.error("Project list to operate on is empty")
            raise ValueError
        log.debugvar('projects')

        logsummary.info(
            "initializing and updating local repositories for relevant projects"
        )

        for project_name in projects:
            try:
                self.projects[project_name] = Project(project_name,
                                                      projects[project_name],
                                                      self.base_dir + "/" +
                                                      project_name,
                                                      fetch=fetch)
                logsummary.info("Project: %s initialized" % project_name)
            except Exception, e:
                traceback.print_exc(file=sys.stdout)
                log.error(e)
                logsummary.error("Project %s skipped, reason: %s" %
                                 (project_name, e))
예제 #8
0
    def scan_original_distance(self, original_branch):
        replica_branch = self.underlayer.branch_maps['original->replica'][
            original_branch]
        target_branch = self.underlayer.branch_maps['original->target'][
            original_branch]
        log.debug("Scanning distance from original branch %s" %
                  original_branch)
        #        if self.replication_strategy == "change-by-change" and revision_exists(self.ref_locks[replica_branch], replica_branch):
        #                log.info("Cannot replicate branch past the specified lock")

        self.recombinations[
            original_branch] = self.get_recombinations_by_interval(
                original_branch)
        slices = self.get_slices(self.recombinations[original_branch])
        recombinations = self.recombinations[original_branch]

        log.debugvar('slices')
        # Master sync on merged changes
        # we really need only the last commit in the slice
        # we advance the master to that, and all the others will be merged too
        if slices['MERGED']:
            # one or more changes are merged in midstream, but missing in master
            # master is out of sync, changes need to be pushed
            # but check first if the change was changed with a merge commit
            # if yes, push THAT to master, if not, it's just a fast forward
            segment = slices['MERGED'][0]
            recomb_id = list(recombinations)[segment['end'] - 1]
            recombination = recombinations[recomb_id]
            recombination.handle_status()

        # Gerrit operations from approved changes
        # NOthing 'approved' can be merged if it has some "present" before in the history
        skip_list = set()
        for index, approved_segment in enumerate(slices['APPROVED']):
            for present_segment in slices['PRESENT']:
                if present_segment['start'] < approved_segment['start']:
                    skip_list.add(index)

        for index in list(skip_list)[::-1]:
            segment = slices['APPROVED'].pop(index)
            for recomb_id in list(
                    recombinations)[segment['start']:segment['end']]:
                log.warning(
                    "Recombination %s is approved but waiting for previous unapproved changes, skipping"
                    % recomb_id)

        # Merge what remains
        for segment in slices['APPROVED']:
            for recomb_id in list(
                    recombinations)[segment['start']:segment['end']]:
                recombination = recombinations[recomb_id]
                recombination.handle_status()

        # Notify of presence
        for segment in slices['PRESENT']:
            for recomb_id in list(
                    recombinations)[segment['start']:segment['end']]:
                recombination = recombinations[recomb_id]
                log.warning(
                    "Recombination %s already present in replica gerrit as change %s and waiting for approval"
                    % (recomb_id, recombination.number))
                recombination.handle_status()

        # Gerrit operations for missing changes
        for segment in slices['MISSING']:
            for recomb_id in list(
                    recombinations)[segment['start']:segment['end']]:
                log.warning("Recombination %s is missing from replica gerrit" %
                            recomb_id)
                recombination = recombinations[recomb_id]
                recombination.handle_status()

        return True
예제 #9
0
 def merged(self):
     log.warning("branch is out of sync with original")
     self.sync_replica()
     self.update_target_branch()