def synthesize_loop( toolbox: SynthesizeLoopToolbox, multiple_prs: bool, change_pusher: AbstractChangePusher, synthesizer: AbstractSynthesizer, ) -> int: """Loops through all source versions and creates a commit for every version changed that caused a change in the generated code. Arguments: toolbox {SynthesizeLoopToolbox} -- a toolbox multiple_prs {bool} -- True to create one pull request per source. change_pusher {AbstractChangePusher} -- Used to push changes to github. synthesizer {AbstractSynthesizer} -- Invokes synthesize. Returns: int -- Number of commits committed to this repo. """ if not toolbox.versions: return 0 # No versions, nothing to synthesize. try: if multiple_prs: commit_count = 0 for fork in toolbox.fork(): if change_pusher.check_if_pr_already_exists(fork.branch): continue executor.check_call(["git", "checkout", fork.branch]) synthesize_inner_loop(fork, synthesizer) commit_count += fork.commit_count if fork.source_name == "self" or fork.count_commits_with_context( ) > 0: fork.push_changes(change_pusher) return commit_count except Exception as e: logger.error(e) pass # Fall back to non-forked loop below. if change_pusher.check_if_pr_already_exists(toolbox.branch): return 0 synthesize_inner_loop(toolbox, synthesizer) toolbox.push_changes(change_pusher) return toolbox.commit_count
def push_changes(self, change_pusher: AbstractChangePusher) -> None: """Composes a PR title and pushes changes to github.""" if self.commit_count < 1: return pr_title = _compose_pr_title(self.count_commits_with_context(), self._synth_path, self.source_name) pr = change_pusher.push_changes(self.commit_count, self.branch, pr_title) # Add a label to make it easy to collect statistics about commits with context. if self.count_commits_with_context() == 0: label = "context: none" elif self.count_commits_with_context() == self.commit_count: label = "context: full" else: label = "context: partial" pr.add_labels([label])
def synthesize_loop_single_pr( toolbox: SynthesizeLoopToolbox, change_pusher: AbstractChangePusher, synthesizer: AbstractSynthesizer, ) -> int: """Loops through all source versions and creates a commit for every version changed that caused a change in the generated code. This function creates a single pull request for all sources. Arguments: toolbox {SynthesizeLoopToolbox} -- a toolbox change_pusher {AbstractChangePusher} -- Used to push changes to github. synthesizer {AbstractSynthesizer} -- Invokes synthesize. Returns: int -- Number of commits committed to this repo. """ if change_pusher.check_if_pr_already_exists(toolbox.branch): return 0 synthesize_inner_loop(toolbox, synthesizer) toolbox.push_changes(change_pusher) return toolbox.commit_count
def synthesize_loop( toolbox: SynthesizeLoopToolbox, multiple_prs: bool, change_pusher: AbstractChangePusher, synthesizer: AbstractSynthesizer, ) -> int: """Loops through all source versions and creates a commit for every version changed that caused a change in the generated code. Arguments: toolbox {SynthesizeLoopToolbox} -- a toolbox multiple_prs {bool} -- True to create one pull request per source. change_pusher {AbstractChangePusher} -- Used to push changes to github. synthesizer {AbstractSynthesizer} -- Invokes synthesize. Returns: int -- Number of commits committed to this repo. """ if not toolbox.versions: return 0 # No versions, nothing to synthesize. # Synthesize the library with the most recent versions of all sources. youngest = len(toolbox.versions) - 1 has_changes = toolbox.synthesize_version_in_new_branch( synthesizer, youngest) if not has_changes: if (not toolbox.metadata_contains_generated_files(toolbox.branch) and toolbox.metadata_contains_generated_files( toolbox.sub_branch(youngest)) and not change_pusher.check_if_pr_already_exists(toolbox.branch)): # Special case: the repo owner turned on obsolete file tracking. # Generate a one-time PR containing only metadata changes. executor.check_call(["git", "checkout", toolbox.branch]) executor.check_call( ["git", "merge", "--squash", toolbox.sub_branch(youngest)]) pr_title = "chore: start tracking obsolete files" executor.check_call(["git", "commit", "-m", pr_title]) pr = change_pusher.push_changes(1, toolbox.branch, pr_title) pr.add_labels(["context: full"]) return 1 return 0 # No changes, nothing to do. try: if multiple_prs: commit_count = 0 for fork in toolbox.fork(): if change_pusher.check_if_pr_already_exists(fork.branch): continue executor.check_call(["git", "checkout", fork.branch]) synthesize_inner_loop(fork, synthesizer) commit_count += fork.commit_count if fork.source_name == "self" or fork.count_commits_with_context( ) > 0: fork.push_changes(change_pusher) return commit_count except Exception as e: logger.error(e) # Fallback to the single_pr loop to try to make some progress. synthesize_loop_single_pr(toolbox, change_pusher, synthesizer) # But still report the failure. raise return synthesize_loop_single_pr(toolbox, change_pusher, synthesizer)