| /* |
| * Copyright (C) 2020 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| import replaceAll from "replaceall"; |
| import {escapeForSlackText} from "./Utility.mjs"; |
| |
| function findAndRemove(change, regExp) |
| { |
| let matched = change.match(regExp); |
| if (matched) { |
| change = change.replace(regExp, ""); |
| return [matched[1], change]; |
| } |
| return [null, change]; |
| } |
| |
| function cleanUpChange(change, contributors) |
| { |
| for (let entry of contributors.entries) { |
| if (!entry.nicks) |
| continue; |
| |
| let nameWithNicks = `${entry.name} (@${entry.nicks[0]})`; |
| if (change.includes(entry.name)) { |
| change = replaceAll(entry.name, nameWithNicks, change); |
| for (let email of entry.emails) |
| change = replaceAll(`<${email}>`, "", change); |
| } else { |
| for (let email of entry.emails) |
| change = replaceAll(` ${email} `, ` ${nameWithNicks} `, change); |
| } |
| } |
| return change; |
| } |
| |
| export default class Commit { |
| constructor(feedItem, contributors) |
| { |
| let originalChange = feedItem.contentSnippet; |
| let change = cleanUpChange(originalChange, contributors); |
| [this._revision, change] = findAndRemove(change, /^git-svn-id: https:\/\/svn\.webkit\.org\/repository\/webkit\/trunk@(\d+) /im); |
| [this._patchBy, change] = findAndRemove(change, /^Patch\s+by\s+(.+?)\s+on(?:\s+\d{4}-\d{2}-\d{2})?\n?/im); |
| [this._revert, change] = findAndRemove(change, /(?:rolling out|reverting) (r?\d+(?:(?:,\s*|,?\s*and\s+)?r?\d+)*)\.?\s*/im); |
| [this._bugzilla, change] = findAndRemove(change, /https?:\/\/(?:bugs\.webkit\.org\/show_bug\.cgi\?id=|webkit\.org\/b\/)(\d+)/im); |
| [this._radar, change] = findAndRemove(change, /<rdar:\/\/(?:problem\/)?(\d+)>/im); |
| this._email = feedItem.author; |
| |
| let lines = originalChange.split("\n"); |
| this._title = feedItem.title; |
| if (lines.length) |
| this._title = lines[0]; |
| |
| if (this._patchBy) |
| this._author = this._patchBy; |
| if (!this._author) { |
| this._author = this._email; |
| if (this._email) { |
| let entry = contributors.queryWithEmail(this._email); |
| if (entry) { |
| if (entry.nicks && entry.nicks[0]) |
| this._author = `${entry.name} (@${entry.nicks[0]})`; |
| if (entry.slackId) |
| this._authorSlackId = entry.slackId; |
| } |
| } |
| } |
| if (this._revert) { |
| let matched = change.match(/^"?(.+?)"? \(Requested\s+by\s+(.+?)\s+on\s+#webkit\)\./im); |
| if (matched) { |
| // FIXME: Implement more descriptive message when we detect that this commit is revert commit. |
| // let reason = matched[0]; |
| // let author = matched[1]; |
| } |
| } |
| |
| if (!this._revision) |
| throw new Error("Cannot find revision"); |
| this._revision = Number.parseInt(this._revision, 10); |
| this._bugzilla = this._bugzilla ? Number.parseInt(this._bugzilla, 10) : null; |
| this._radar = this._radar ? Number.parseInt(this._radar, 10) : null; |
| this._url = `https://trac.webkit.org/r${this._revision}`; |
| } |
| |
| get revision() { return this._revision; } |
| get patchBy() { return this._patchBy; } |
| get revert() { return this._revert; } |
| get bugzilla() { return this._bugzilla; } |
| get email() { return this._email; } |
| get radar() { return this._radar; } |
| get title() { return this._title; } |
| get author() { return this._author; } |
| get authorSlackId() { return this._authorSlackId; } |
| get url() { return this._url; } |
| |
| message() |
| { |
| let results = []; |
| results.push(escapeForSlackText(`${this._title}`)); |
| if (!this._authorSlackId) |
| results.push(escapeForSlackText(`${this._url} by ${this._author}`)); |
| else |
| results.push(`${escapeForSlackText(this._url)} by <@${this._authorSlackId}>`); |
| let urls = []; |
| if (this._bugzilla !== null) |
| urls.push(escapeForSlackText(`https://webkit.org/b/${this._bugzilla}`)); |
| if (this._radar !== null) { |
| // Link it in Slack format `<>`. |
| urls.push(`<rdar://problem/${this._radar}>`); |
| } |
| if (urls.length !== 0) |
| results.push(urls.join(" ")); |
| return results.join("\n"); |
| } |
| } |