test_class.file: dockerfile-image-update/src/test/java/com/salesforce/dockerfileimageupdate/process/GitHubPullRequestSenderTest.java
test_class.identifier: GitHubPullRequestSenderTest
test_case.body: @Test
      public void forkRepositoriesFoundAndGetPathToDockerfiles_unableToforkRepo() throws Exception {
          /**
           * Suppose we have multiple dockerfiles that need to updated in a repo and we fail to fork such repo,
           * we should not add those repos to pathToDockerfilesInParentRepo.
           *
           * Note: Sometimes GitHub search API returns the same result twice. This test covers such cases as well.
           */
          DockerfileGitHubUtil dockerfileGitHubUtil = mock(DockerfileGitHubUtil.class);
  
          GHRepository contentRepo1 = mock(GHRepository.class);
          when(contentRepo1.getFullName()).thenReturn("1");
  
          GHRepository duplicateContentRepo1 = mock(GHRepository.class);
          // Say we have multiple dockerfiles to be updated in repo "1"
          // Or sometimes GitHub search API returns same result twice.
          when(duplicateContentRepo1.getFullName()).thenReturn("1");
  
          GHRepository contentRepo2 = mock(GHRepository.class);
          when(contentRepo2.getFullName()).thenReturn("2");
  
          GHContent content1 = mock(GHContent.class);
          when(content1.getOwner()).thenReturn(contentRepo1);
          when(content1.getPath()).thenReturn("1"); // path to 1st dockerfile in repo "1"
  
          GHContent content2 = mock(GHContent.class);
          when(content2.getOwner()).thenReturn(duplicateContentRepo1);
          when(content2.getPath()).thenReturn("2"); // path to 2st dockerfile in repo "1"
  
          GHContent content3 = mock(GHContent.class);
          when(content3.getOwner()).thenReturn(contentRepo2);
          when(content3.getPath()).thenReturn("3");
  
          PagedSearchIterable<GHContent> contentsWithImage = mock(PagedSearchIterable.class);
  
          PagedIterator<GHContent> contentsWithImageIterator = mock(PagedIterator.class);
          when(contentsWithImageIterator.hasNext()).thenReturn(true, true, true, false);
          when(contentsWithImageIterator.next()).thenReturn(content1, content2, content3, null);
          when(contentsWithImage.iterator()).thenReturn(contentsWithImageIterator);
          when(dockerfileGitHubUtil.getOrCreateFork(contentRepo1)).thenReturn(null); // repo1 is unforkable
          when(dockerfileGitHubUtil.getOrCreateFork(duplicateContentRepo1)).thenReturn(null); // repo1 is unforkable
          when(dockerfileGitHubUtil.getOrCreateFork(contentRepo2)).thenReturn(mock(GHRepository.class));
          when(dockerfileGitHubUtil.getRepo(contentRepo1.getFullName())).thenReturn(contentRepo1);
          when(dockerfileGitHubUtil.getRepo(duplicateContentRepo1.getFullName())).thenReturn(duplicateContentRepo1);
          when(dockerfileGitHubUtil.getRepo(contentRepo2.getFullName())).thenReturn(contentRepo2);
  
          ForkableRepoValidator forkableRepoValidator = mock(ForkableRepoValidator.class);
          when(forkableRepoValidator.shouldFork(any(), any(), any())).thenReturn(ShouldForkResult.shouldForkResult());
  
          GitHubPullRequestSender pullRequestSender = new GitHubPullRequestSender(dockerfileGitHubUtil, forkableRepoValidator);
          Multimap<String, GitHubContentToProcess> repoMap =
                  pullRequestSender.forkRepositoriesFoundAndGetPathToDockerfiles(contentsWithImage, null);
  
          // Since repo "1" is unforkable, we will only try to update repo "2"
          verify(dockerfileGitHubUtil, times(3)).getOrCreateFork(any());
          assertEquals(repoMap.size(), 1);
      }
test_case.class_method_signature: GitHubPullRequestSenderTest.forkRepositoriesFoundAndGetPathToDockerfiles_unableToforkRepo()
test_case.full_signature: @Test public void forkRepositoriesFoundAndGetPathToDockerfiles_unableToforkRepo()
test_case.identifier: forkRepositoriesFoundAndGetPathToDockerfiles_unableToforkRepo
test_case.invocations: mock mock thenReturn when getFullName mock thenReturn when getFullName mock thenReturn when getFullName mock thenReturn when getOwner thenReturn when getPath mock thenReturn when getOwner thenReturn when getPath mock thenReturn when getOwner thenReturn when getPath mock mock thenReturn when hasNext thenReturn when next thenReturn when iterator thenReturn when getOrCreateFork thenReturn when getOrCreateFork thenReturn when getOrCreateFork mock thenReturn when getRepo getFullName thenReturn when getRepo getFullName thenReturn when getRepo getFullName mock thenReturn when shouldFork any any any shouldForkResult forkRepositoriesFoundAndGetPathToDockerfiles getOrCreateFork verify times any assertEquals size
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void forkRepositoriesFoundAndGetPathToDockerfiles_unableToforkRepo()
focal_class.declarator: log = LoggerFactory.getLogger(GitHubPullRequestSender.class)
focal_class.modifier: private static final
focal_class.original_string: private static final Logger log = LoggerFactory.getLogger(GitHubPullRequestSender.class);
focal_class.type: Logger
focal_class.var_name: log
focal_class.declarator: REPO_IS_FORK = "it's a fork already. Sending a PR to a fork is unsupported at the moment."
focal_class.modifier: public static final
focal_class.original_string: public static final String REPO_IS_FORK = "it's a fork already. Sending a PR to a fork is unsupported at the moment.";
focal_class.type: String
focal_class.var_name: REPO_IS_FORK
focal_class.declarator: dockerfileGitHubUtil
focal_class.modifier: private final
focal_class.original_string: private final DockerfileGitHubUtil dockerfileGitHubUtil;
focal_class.type: DockerfileGitHubUtil
focal_class.var_name: dockerfileGitHubUtil
focal_class.declarator: forkableRepoValidator
focal_class.modifier: private final
focal_class.original_string: private final ForkableRepoValidator forkableRepoValidator;
focal_class.type: ForkableRepoValidator
focal_class.var_name: forkableRepoValidator
focal_class.file: dockerfile-image-update/src/main/java/com/salesforce/dockerfileimageupdate/process/GitHubPullRequestSender.java
focal_class.identifier: GitHubPullRequestSender
focal_class.class_method_signature: GitHubPullRequestSender.GitHubPullRequestSender(DockerfileGitHubUtil dockerfileGitHubUtil, ForkableRepoValidator forkableRepoValidator)
focal_class.full_signature: public  GitHubPullRequestSender(DockerfileGitHubUtil dockerfileGitHubUtil, ForkableRepoValidator forkableRepoValidator)
focal_class.identifier: GitHubPullRequestSender
focal_class.modifiers: public
focal_class.parameters: (DockerfileGitHubUtil dockerfileGitHubUtil, ForkableRepoValidator forkableRepoValidator)
focal_class.signature:  GitHubPullRequestSender(DockerfileGitHubUtil dockerfileGitHubUtil, ForkableRepoValidator forkableRepoValidator)
focal_class.class_method_signature: GitHubPullRequestSender.forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_class.full_signature: public Multimap<String, GitHubContentToProcess> forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_class.identifier: forkRepositoriesFoundAndGetPathToDockerfiles
focal_class.modifiers: public
focal_class.parameters: (
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_class.return: Multimap<String, GitHubContentToProcess>
focal_class.signature: Multimap<String, GitHubContentToProcess> forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_class.class_method_signature: GitHubPullRequestSender.ensureForkedAndAddToListForProcessing(Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                         GHRepository parent,
                                                         String parentRepoName,
                                                         GHContent ghContent)
focal_class.full_signature: private void ensureForkedAndAddToListForProcessing(Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                         GHRepository parent,
                                                         String parentRepoName,
                                                         GHContent ghContent)
focal_class.identifier: ensureForkedAndAddToListForProcessing
focal_class.modifiers: private
focal_class.parameters: (Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                         GHRepository parent,
                                                         String parentRepoName,
                                                         GHContent ghContent)
focal_class.return: void
focal_class.signature: void ensureForkedAndAddToListForProcessing(Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                         GHRepository parent,
                                                         String parentRepoName,
                                                         GHContent ghContent)
focal_class.class_method_signature: GitHubPullRequestSender.getForkFromExistingRecordToProcess(Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                              String parentRepoName)
focal_class.full_signature: protected GHRepository getForkFromExistingRecordToProcess(Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                              String parentRepoName)
focal_class.identifier: getForkFromExistingRecordToProcess
focal_class.modifiers: protected
focal_class.parameters: (Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                              String parentRepoName)
focal_class.return: GHRepository
focal_class.signature: GHRepository getForkFromExistingRecordToProcess(Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo,
                                                              String parentRepoName)
focal_method.body: public Multimap<String, GitHubContentToProcess> forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch) {
          log.info("Forking repositories...");
          Multimap<String, GitHubContentToProcess> pathToDockerfilesInParentRepo = HashMultimap.create();
          GHRepository parent;
          String parentRepoName;
          int totalContentsFound = 0;
          int contentsShouldFork = 0;
          for (GHContent ghContent : contentsWithImage) {
              /* Kohsuke's GitHub API library, when retrieving the forked repository, looks at the name of the parent to
               * retrieve. The issue with that is: GitHub, when forking two or more repositories with the same name,
               * automatically fixes the names to be unique (by appending "-#" to the end). Because of this edge case, we
               * cannot save the forks and iterate over the repositories; else, we end up missing/not updating the
               * repositories that were automatically fixed by GitHub. Instead, we save the names of the parent repos
               * in the map above, find the list of repositories under the authorized user, and iterate through that list.
               */
              totalContentsFound++;
              parent = ghContent.getOwner();
              parentRepoName = parent.getFullName();
              // Refresh the repo to ensure that the object has full details
              try {
                  parent = dockerfileGitHubUtil.getRepo(parentRepoName);
                  ShouldForkResult shouldForkResult = forkableRepoValidator.shouldFork(parent, ghContent, gitForkBranch);
                  if (shouldForkResult.isForkable()) {
                      contentsShouldFork++;
                      // fork the parent if not already forked
                      ensureForkedAndAddToListForProcessing(pathToDockerfilesInParentRepo, parent, parentRepoName, ghContent);
                  } else {
                      log.warn("Skipping {} because {}", parentRepoName, shouldForkResult.getReason());
                  }
              } catch (IOException exception) {
                  log.warn("Could not refresh details of {}", parentRepoName);
              }
          }
  
          log.info("Out of {} content search results processed, {} were deemed eligible for forking to yield {} repositories to fork.",
                  totalContentsFound, contentsShouldFork, pathToDockerfilesInParentRepo.keys().size());
          log.info("Path to Dockerfiles in repos: {}", pathToDockerfilesInParentRepo);
  
          return pathToDockerfilesInParentRepo;
      }
focal_method.class_method_signature: GitHubPullRequestSender.forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_method.full_signature: public Multimap<String, GitHubContentToProcess> forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_method.identifier: forkRepositoriesFoundAndGetPathToDockerfiles
focal_method.invocations: info create getOwner getFullName getRepo shouldFork isForkable ensureForkedAndAddToListForProcessing warn getReason warn info size keys info
focal_method.modifiers: public
focal_method.parameters: (
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)
focal_method.return: Multimap<String, GitHubContentToProcess>
focal_method.signature: Multimap<String, GitHubContentToProcess> forkRepositoriesFoundAndGetPathToDockerfiles(
              PagedSearchIterable<GHContent> contentsWithImage,
              GitForkBranch gitForkBranch)