public boolean changesSince()

in src/main/java/org/apache/jenkins/gitpubsub/ASFGitSCMFileSystem.java [186:300]


    public boolean changesSince(SCMRevision revision, @NonNull OutputStream changeLogStream)
            throws UnsupportedOperationException, IOException, InterruptedException {
        if (revision == null ? getRevision() == null : revision.equals(getRevision())) {
            // special case where somebody is asking one of two stupid questions:
            // 1. what has changed between the latest and the latest
            // 2. what has changed between the current revision and the current revision
            return false;
        }
        int count = 0;
        SimpleDateFormat rfc = new SimpleDateFormat(RFC_2822);
        FastDateFormat iso = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZ");
        StringBuilder log = new StringBuilder(1024);
        StringBuilder para = new StringBuilder(1024);
        String endHash;
        if (revision instanceof AbstractGitSCMSource.SCMRevisionImpl) {
            endHash = ((AbstractGitSCMSource.SCMRevisionImpl) revision).getHash().toLowerCase(Locale.ENGLISH);
        } else {
            endHash = null;
        }
        // this is the format expected by GitSCM, so we need to format each GHCommit with the same format
        // commit %H%ntree %T%nparent %P%nauthor %aN <%aE> %ai%ncommitter %cN <%cE> %ci%n%n%w(76,4,4)%s%n%n%b
        UriTemplate shortLogTemplate = buildTemplateWithRemote("{+server}{?p}{;a,h,pg}", remote)
                .set("a", "shortlog")
                .set("h", refOrHash);
        UriTemplate commitTemplate = buildTemplateWithRemote("{+server}{?p}{;a,h}", remote)
                .set("a", "commit");
        int pg = 0;
        while (count < GitSCM.MAX_CHANGELOG) {
            if (pg > 0) {
                shortLogTemplate.set("pg", pg);
            }
            pg++;
            Document doc = fetchDocument(shortLogTemplate.expand());
            for (Element element : doc.select("table.shortlog tr td a.subject")) {
                Matcher href = URL_EXTRACT_H.matcher(element.attr("href"));
                if (!href.matches()) {
                    continue;
                }
                if (href.group(1).toLowerCase(Locale.ENGLISH).equals(endHash)) {
                    return count > 0;
                }
                commitTemplate.set("h", href.group(1));
                Document commit = fetchDocument(commitTemplate.expand());
                log.setLength(0);
                Elements sha1s = commit.select("table.object_header tr td.sha1");
                log.append("commit ").append(sha1s.get(0).text().trim()).append('\n');
                log.append("tree ").append(sha1s.get(1).text().trim()).append('\n');
                log.append("parent");
                for (int i = 2; i < sha1s.size(); i++) {
                    log.append(' ').append(sha1s.get(i).text().trim());
                }
                log.append('\n');
                Elements persons = commit.select("table.object_header tr");
                try {
                    log.append("author ")
                            .append(persons.get(0).child(1).text().trim())
                            .append(' ')
                            .append(iso.format(rfc.parse(persons.get(1).child(1).text())))
                            .append('\n');
                    log.append("committer ")
                            .append(persons.get(2).child(1).text().trim())
                            .append(' ')
                            .append(iso.format(rfc.parse(persons.get(3).child(1).text())))
                            .append('\n');
                } catch (ParseException e) {
                    throw new IOException(e);
                }
                log.append('\n');
                Element messageDiv = commit.select("div.page_body").get(0);
                para.setLength(0);
                boolean inPara = false;
                for (Node node : messageDiv.childNodes()) {
                    if (node instanceof TextNode) {
                        String s = ((TextNode) node).text().trim();
                        if (!s.isEmpty()) {
                            if (para.length() > 0) {
                                para.append(' ');
                            }
                            para.append(s.replace('\u00a0', '\u0020'));
                            inPara = true;
                        }
                    } else if (node instanceof Element) {
                        if (((Element) node).tagName().equalsIgnoreCase("br")) {
                            if (inPara) {
                                inPara = false;
                            } else {
                                if (para.length() > 0) {
                                    log.append("    ")
                                            .append(WordUtils.wrap(para.toString(), 72, "\n    ", false));
                                    para.setLength(0);
                                }
                                log.append("\n\n");
                            }
                        }
                    }
                }
                if (para.length() > 0) {
                    log.append("    ")
                            .append(WordUtils.wrap(para.toString(), 72, "\n    ", false));
                    log.append('\n');
                }
                if (inPara) {
                    log.append('\n');
                }
                log.append('\n');
                changeLogStream.write(log.toString().getBytes(StandardCharsets.UTF_8));
                changeLogStream.flush();
                count++;
                if (count >= GitSCM.MAX_CHANGELOG) {
                    break;
                }
            }
        }
        return count > 0;
    }