Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
 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])
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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)