public static void processPullRequest()

in prs/handler/impl/src/org/netbeans/modules/jackpot/prs/handler/impl/HandlePullRequest.java [96:280]


    public static void processPullRequest(String inputData, String oauthToken, String oauthAppToken) throws Exception {
        File tempDir = Places.getCacheSubdirectory("checkout");
        Map<String, Object> inputParsed = new ObjectMapper().readValue(inputData, Map.class);
        Object action = inputParsed.get("action");
        if (!"opened".equals(action))
            return ;
        Map<String, Object> pullRequest = (Map<String, Object>) inputParsed.get("pull_request");
        if (pullRequest == null) {
            return ;
        }
        Map<String, Object> base = (Map<String, Object>) pullRequest.get("base");
        Map<String, Object> baseRepo = (Map<String, Object>) base.get("repo");
        Map<String, Object> head = (Map<String, Object>) pullRequest.get("head");
        Map<String, Object> headRepo = (Map<String, Object>) head.get("repo");
        
        SiteWrapper statusGithub = factory.create(oauthToken);
        String fullRepoName = (String) baseRepo.get("full_name");
        String sha = (String) head.get("sha");
        
        statusGithub.createCommitStatusPending(fullRepoName, sha, "Running Jackpot verification");

        String cloneURL = (String) headRepo.get("clone_url");
        new ProcessBuilder("git", "clone", cloneURL, "workdir").directory(tempDir).inheritIO().start().waitFor();
        FileObject workdir = FileUtil.toFileObject(new File(tempDir, "workdir"));
        new ProcessBuilder("git", "checkout", sha).directory(FileUtil.toFile(workdir)).inheritIO().start().waitFor();
        FileObject jlObject = workdir.getFileObject("src/java.base/share/classes/java/lang/Object.java");
        if (jlObject != null) {
            Project prj = FileOwnerQuery.getOwner(jlObject); //ensure external roots (tests) are registered
            ProjectUtils.getSources(prj).getSourceGroups(Sources.TYPE_GENERIC); //register external roots
        }
        FileObject jlmSourceVersion = workdir.getFileObject("src/java.compiler/share/classes/javax/lang/model/SourceVersion.java");
        if (jlmSourceVersion != null) {
            Project prj = FileOwnerQuery.getOwner(jlmSourceVersion); //ensure external roots (tests) are registered
            ProjectUtils.getSources(prj).getSourceGroups(Sources.TYPE_GENERIC); //register external roots
        }
        Set<Project> projects = new HashSet<>();
        Map<FileObject, FileData> file2Remap = new HashMap<>();
        String diffURL = (String) pullRequest.get("diff_url");
        URLConnection conn = new URL(diffURL).openConnection();
        String text;
        try (InputStream in = conn.getInputStream()) {
            String encoding = conn.getContentEncoding();
            if (encoding == null) encoding = "UTF-8";
            //workaround for the diff parser, which does not handle git diffs properly:
            text = new String(in.readAllBytes(), encoding)
                    .replace("\ndiff --git", "\n\ndiff --git");
        }
        List<Diff> diffs = new UnifiedDiffParser().parse(text.getBytes());
        for (Diff diff : diffs) {
            String filename = diff.getToFileName().substring(2);
            if (filename.endsWith(".java")) {
                FileObject file = workdir.getFileObject(filename);
                if (file == null) {
                    //TODO: how to handle? log?
                    continue;
                }
                Project project = FileOwnerQuery.getOwner(file);
                if (project != null) {
                    int[] remap = new int[file.asLines().size() + 1]; //TODO: encoding?
                    Arrays.fill(remap, -1);
                    int idx = 1;
                    for (Hunk hunk : diff.getHunks()) {
                        int pointer = hunk.getToFileRange().getLineStart();
                        for (Line line : hunk.getLines()) {
                            switch (line.getLineType()) {
                                case NEUTRAL: pointer++; idx++; break;
                                case TO: remap[pointer++] = idx++; break;
                            }
                        }
                    }
                    projects.add(project);
                    file2Remap.put(file, new FileData(filename, remap));
                } else {
                    System.err.println("no project found for: " + filename);
                }
            }
        }
        int prId = (int) pullRequest.get("number");
        SiteWrapper[] commentGitHub = new SiteWrapper[1];
        boolean[] hasWarnings = {false};
        for (Project project : projects) {
            switch (project.getClass().getName()) {//XXX: ensure that the environment variables are dropped here!
                case "org.netbeans.modules.maven.NbMavenProjectImpl":
                    new ProcessBuilder("mvn", "dependency:go-offline").directory(FileUtil.toFile(project.getProjectDirectory())).inheritIO().start().waitFor();
                    break;
                case "org.netbeans.modules.apisupport.project.NbModuleProject":
                    FileObject nbbuild = project.getProjectDirectory().getFileObject("../../nbbuild");
                    if (nbbuild == null) {
                        nbbuild = project.getProjectDirectory().getFileObject("../nbbuild");
                    }
                    if (nbbuild != null) { //TODO: only once
                        new ProcessBuilder("ant", "-autoproxy", "download-all-extbins").directory(FileUtil.toFile(nbbuild)).inheritIO().start().waitFor();
                    }
                    //TODO: download extbins!
                    break;
                case "org.netbeans.modules.java.openjdk.project.JDKProject":
                    //no bootstrap at this time
                    break;
                default:
                    System.err.println("project name: " + project.getClass().getName());
                    break;
            }
        }
        OpenProjects.getDefault().open(projects.toArray(new Project[0]), false);
        Map<ClasspathInfo, Collection<FileObject>> sorted = BatchUtilities.sortFiles(file2Remap.keySet());
        for (Entry<ClasspathInfo, Collection<FileObject>> e : sorted.entrySet()) {
            System.err.println("Running hints for:");
            System.err.println("files: " + e.getValue());
            System.err.println("classpath: " + e.getKey());
            try {
                JavaSource.create(e.getKey(), e.getValue()).runWhenScanFinished(cc -> {
                    FileData fileData = file2Remap.get(cc.getFileObject());

                    if (fileData == null)
                        return ;

                    cc.toPhase(JavaSource.Phase.RESOLVED); //XXX

                    List<ErrorDescription> warnings = new HintsInvoker(HintsSettings.getGlobalSettings(), new AtomicBoolean()).computeHints(cc);
                    System.err.println("warnings=" + warnings);
                    for (ErrorDescription ed : warnings) {
                        int startLine = ed.getRange().getBegin().getLine() + 1;
                        int targetPosition = fileData.remap[startLine];
                        if (targetPosition == (-1))
                            continue;
                        String comment = "Jackpot:\nwarning: " + ed.getDescription();
                        //TODO: fixes
    //                    if (additions != null) {
    //                        comment += "```suggestion\n" + additions.toString() + "```";
    //                    }
                        hasWarnings[0] = true;
                        if (commentGitHub[0] == null) {
                            commentGitHub[0] = factory.create(oauthAppToken);
                        }
                        commentGitHub[0].createReviewComment(fullRepoName, prId, comment, sha, fileData.filename, targetPosition);
                    }
                }, false).get();
            } catch (Throwable ex) {
                System.err.println("error while processing: " + e.getValue());
                Exceptions.printStackTrace(ex);
            }
        }
//                String file = (String) m.get("file");
//                int startLine = (Integer) m.get("startLine");
//                List<String> fixes = (List<String>) m.get("fixes");
//                StringBuilder additions = null;
//                if (fixes != null && fixes.size() > 1) { //TODO: or == 1?
//                    List<Diff> fixDiffs = new UnifiedDiffParser().parse(fixes.get(0).getBytes("UTF-8"));
//                    if (fixDiffs.size() == 1 && fixDiffs.get(0).getHunks().size() == 1) {
//                        int start = fixDiffs.get(0).getHunks().get(0).getToFileRange().getLineStart();
//                        additions = new StringBuilder();
//                        boolean seenRemoval = false;
//                        for (Line line : fixDiffs.get(0).getHunks().get(0).getLines()) {
//                            if (line.getLineType() == Line.LineType.FROM) {
//                                if (seenRemoval) {
//                                    start = -1;
//                                    break;
//                                } else {
//                                    seenRemoval = true;
//                                }
//                            } else if (line.getLineType() == Line.LineType.TO) {
//                                additions.append(line.getContent());
//                                additions.append("\n");
//                            }
//                        }
//                        if (start != (-1) && seenRemoval) {
//                            startLine = start;
//                        } else {
//                            additions = null;
//                        }
//                    }
//                }
//            }
//        }
//        
        String mainComment;
        if (!hasWarnings[0]) {
            mainComment = "Jackpot: no warnings.";
        } else {
            mainComment = "Jackpot: warnings found.";
        }

        //TODO: set status on crash/error!
        statusGithub.createCommitStatusSuccess(fullRepoName, sha, mainComment);
    }