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))
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")
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))
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()
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
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
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))
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
def merged(self): log.warning("branch is out of sync with original") self.sync_replica() self.update_target_branch()