diff options
author | Nitzan Gur-Furman <nitzan@google.com> | 2023-07-19 10:37:39 +0200 |
---|---|---|
committer | Nitzan Gur-Furman <nitzan@google.com> | 2023-08-01 10:37:24 +0200 |
commit | c353645a09b677644c55daa9dcff7df54529dc04 (patch) | |
tree | d0302970bcafa12fdf9167b0575514d895dad6e9 /org.eclipse.jgit | |
parent | ec11129b1d2ff5f7a909c05deb84e422fcd83084 (diff) | |
download | jgit-c353645a09b677644c55daa9dcff7df54529dc04.tar.gz jgit-c353645a09b677644c55daa9dcff7df54529dc04.zip |
Move footer-line parsing methods from RevCommit to FooterLine
This allows extracting footers from a messages not associated with a
commit.
The public API of RevCommit is kept intact.
Change-Id: I5809c23df7b7d49641a4be3a26d6f987d3d57c9b
Bug: Google b/287891316
Diffstat (limited to 'org.eclipse.jgit')
3 files changed, 136 insertions, 64 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java index 676573c2f2..eeaccc6d33 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java @@ -11,6 +11,9 @@ package org.eclipse.jgit.revwalk; import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.eclipse.jgit.util.RawParseUtils; @@ -47,6 +50,108 @@ public final class FooterLine { } /** + * Extract the footer lines from the given message. + * + * @param str + * the message to extract footers from. + * @return ordered list of footer lines; empty list if no footers found. + * @see RevCommit#getFooterLines() + */ + public static List<FooterLine> fromMessage( + String str) { + return fromMessage(str.getBytes()); + } + + /** + * Extract the footer lines from the given message. + * + * @param raw + * the raw message to extract footers from. + * @return ordered list of footer lines; empty list if no footers found. + * @see RevCommit#getFooterLines() + */ + public static List<FooterLine> fromMessage( + byte[] raw) { + int ptr = raw.length - 1; + while (raw[ptr] == '\n') // trim any trailing LFs, not interesting + ptr--; + + int msgB = RawParseUtils.commitMessage(raw, 0); + ArrayList<FooterLine> r = new ArrayList<>(4); + Charset enc = RawParseUtils.guessEncoding(raw); + for (;;) { + ptr = RawParseUtils.prevLF(raw, ptr); + if (ptr <= msgB) + break; // Don't parse commit headers as footer lines. + + int keyStart = ptr + 2; + if (raw[keyStart] == '\n') + break; // Stop at first paragraph break, no footers above it. + + int keyEnd = RawParseUtils.endOfFooterLineKey(raw, keyStart); + if (keyEnd < 0) + continue; // Not a well formed footer line, skip it. + + // Skip over the ': *' at the end of the key before the value. + // + int valStart = keyEnd + 1; + while (valStart < raw.length && raw[valStart] == ' ') + valStart++; + + // Value ends at the LF, and does not include it. + // + int valEnd = RawParseUtils.nextLF(raw, valStart); + if (raw[valEnd - 1] == '\n') + valEnd--; + + r.add(new FooterLine(raw, enc, keyStart, keyEnd, valStart, valEnd)); + } + Collections.reverse(r); + return r; + } + + /** + * Get the values of all footer lines with the given key. + * + * @param footers + * list of footers to find the values in. + * @param keyName + * footer key to find values of, case-insensitive. + * @return values of footers with key of {@code keyName}, ordered by their + * order of appearance. Duplicates may be returned if the same + * footer appeared more than once. Empty list if no footers appear + * with the specified key, or there are no footers at all. + * @see #fromMessage + */ + public static List<String> getValues(List<FooterLine> footers, String keyName) { + return getValues(footers, new FooterKey(keyName)); + } + + /** + * Get the values of all footer lines with the given key. + * + * @param footers + * list of footers to find the values in. + * @param key + * footer key to find values of, case-insensitive. + * @return values of footers with key of {@code keyName}, ordered by their + * order of appearance. Duplicates may be returned if the same + * footer appeared more than once. Empty list if no footers appear + * with the specified key, or there are no footers at all. + * @see #fromMessage + */ + public static List<String> getValues(List<FooterLine> footers, FooterKey key) { + if (footers.isEmpty()) + return Collections.emptyList(); + ArrayList<String> r = new ArrayList<>(footers.size()); + for (FooterLine f : footers) { + if (f.matches(key)) + r.add(f.getValue()); + } + return r; + } + + /** * Whether keys match * * @param key diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java index 4619938147..0392ea428c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java @@ -11,15 +11,13 @@ package org.eclipse.jgit.revwalk; -import static java.nio.charset.StandardCharsets.UTF_8; +import static org.eclipse.jgit.util.RawParseUtils.guessEncoding; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.eclipse.jgit.annotations.Nullable; @@ -484,7 +482,8 @@ public class RevCommit extends RevObject { if (msgB < 0) { return ""; //$NON-NLS-1$ } - return RawParseUtils.decode(guessEncoding(), raw, msgB, raw.length); + return RawParseUtils.decode(guessEncoding(buffer), raw, msgB, + raw.length); } /** @@ -510,7 +509,8 @@ public class RevCommit extends RevObject { } int msgE = RawParseUtils.endOfParagraph(raw, msgB); - String str = RawParseUtils.decode(guessEncoding(), raw, msgB, msgE); + String str = RawParseUtils.decode(guessEncoding(buffer), raw, msgB, + msgE); if (hasLF(raw, msgB, msgE)) { str = StringUtils.replaceLineBreaksWithSpace(str); } @@ -562,14 +562,6 @@ public class RevCommit extends RevObject { return RawParseUtils.parseEncoding(buffer); } - private Charset guessEncoding() { - try { - return getEncoding(); - } catch (IllegalCharsetNameException | UnsupportedCharsetException e) { - return UTF_8; - } - } - /** * Parse the footer lines (e.g. "Signed-off-by") for machine processing. * <p> @@ -592,50 +584,14 @@ public class RevCommit extends RevObject { * @return ordered list of footer lines; empty list if no footers found. */ public final List<FooterLine> getFooterLines() { - final byte[] raw = buffer; - int ptr = raw.length - 1; - while (raw[ptr] == '\n') // trim any trailing LFs, not interesting - ptr--; - - final int msgB = RawParseUtils.commitMessage(raw, 0); - final ArrayList<FooterLine> r = new ArrayList<>(4); - final Charset enc = guessEncoding(); - for (;;) { - ptr = RawParseUtils.prevLF(raw, ptr); - if (ptr <= msgB) - break; // Don't parse commit headers as footer lines. - - final int keyStart = ptr + 2; - if (raw[keyStart] == '\n') - break; // Stop at first paragraph break, no footers above it. - - final int keyEnd = RawParseUtils.endOfFooterLineKey(raw, keyStart); - if (keyEnd < 0) - continue; // Not a well formed footer line, skip it. - - // Skip over the ': *' at the end of the key before the value. - // - int valStart = keyEnd + 1; - while (valStart < raw.length && raw[valStart] == ' ') - valStart++; - - // Value ends at the LF, and does not include it. - // - int valEnd = RawParseUtils.nextLF(raw, valStart); - if (raw[valEnd - 1] == '\n') - valEnd--; - - r.add(new FooterLine(raw, enc, keyStart, keyEnd, valStart, valEnd)); - } - Collections.reverse(r); - return r; + return FooterLine.fromMessage(buffer); } /** * Get the values of all footer lines with the given key. * * @param keyName - * footer key to find values of, case insensitive. + * footer key to find values of, case-insensitive. * @return values of footers with key of {@code keyName}, ordered by their * order of appearance. Duplicates may be returned if the same * footer appeared more than once. Empty list if no footers appear @@ -643,30 +599,22 @@ public class RevCommit extends RevObject { * @see #getFooterLines() */ public final List<String> getFooterLines(String keyName) { - return getFooterLines(new FooterKey(keyName)); + return FooterLine.getValues(getFooterLines(), keyName); } /** * Get the values of all footer lines with the given key. * - * @param keyName - * footer key to find values of, case insensitive. + * @param key + * footer key to find values of, case-insensitive. * @return values of footers with key of {@code keyName}, ordered by their * order of appearance. Duplicates may be returned if the same * footer appeared more than once. Empty list if no footers appear * with the specified key, or there are no footers at all. * @see #getFooterLines() */ - public final List<String> getFooterLines(FooterKey keyName) { - final List<FooterLine> src = getFooterLines(); - if (src.isEmpty()) - return Collections.emptyList(); - final ArrayList<String> r = new ArrayList<>(src.size()); - for (FooterLine f : src) { - if (f.matches(keyName)) - r.add(f.getValue()); - } - return r; + public final List<String> getFooterLines(FooterKey key) { + return FooterLine.getValues(getFooterLines(), key); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java index 0e8e9b3d84..1c98336b99 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RawParseUtils.java @@ -868,6 +868,25 @@ public final class RawParseUtils { } /** + * Parse the "encoding " header into a character set reference. + * <p> + * If unsuccessful, return UTF-8. + * + * @param buffer + * buffer to scan. + * @return the Java character set representation. Never null. Default to + * UTF-8. + * @see #parseEncoding(byte[]) + */ + public static Charset guessEncoding(byte[] buffer) { + try { + return parseEncoding(buffer); + } catch (IllegalCharsetNameException | UnsupportedCharsetException e) { + return UTF_8; + } + } + + /** * Parse a name string (e.g. author, committer, tagger) into a PersonIdent. * <p> * Leading spaces won't be trimmed from the string, i.e. will show up in the |