/** * Parse the footer lines (e.g. "Signed-off-by") for machine processing. * * <p>This method splits all of the footer lines out of the last paragraph of the commit message, * providing each line as a key-value pair, ordered by the order of the line's appearance in the * commit message itself. * * <p>A footer line's key must match the pattern {@code ^[A-Za-z0-9-]+:}, while the value is * free-form, but must not contain an LF. Very common keys seen in the wild are: * * <ul> * <li>{@code Signed-off-by} (agrees to Developer Certificate of Origin) * <li>{@code Acked-by} (thinks change looks sane in context) * <li>{@code Reported-by} (originally found the issue this change fixes) * <li>{@code Tested-by} (validated change fixes the issue for them) * <li>{@code CC}, {@code Cc} (copy on all email related to this change) * <li>{@code Bug} (link to project's bug tracking system) * </ul> * * @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<FooterLine>(4); final Charset enc = getEncoding(); 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; }
/* (non-Javadoc) * @see org.eclipse.jgit.internal.storage.file.ReflogReaader#getReverseEntries(int) */ public List<ReflogEntry> getReverseEntries(int max) throws IOException { final byte[] log; try { log = IO.readFully(logName); } catch (FileNotFoundException e) { if (logName.exists()) { throw e; } return Collections.emptyList(); } int rs = RawParseUtils.prevLF(log, log.length); List<ReflogEntry> ret = new ArrayList<ReflogEntry>(); while (rs >= 0 && max-- > 0) { rs = RawParseUtils.prevLF(log, rs); ReflogEntry entry = new ReflogEntryImpl(log, rs < 0 ? 0 : rs + 2); ret.add(entry); } return ret; }
/* (non-Javadoc) * @see org.eclipse.jgit.internal.storage.file.ReflogReaader#getReverseEntry(int) */ public ReflogEntry getReverseEntry(int number) throws IOException { if (number < 0) throw new IllegalArgumentException(); final byte[] log; try { log = IO.readFully(logName); } catch (FileNotFoundException e) { if (logName.exists()) { throw e; } return null; } int rs = RawParseUtils.prevLF(log, log.length); int current = 0; while (rs >= 0) { rs = RawParseUtils.prevLF(log, rs); if (number == current) return new ReflogEntryImpl(log, rs < 0 ? 0 : rs + 2); current++; } return null; }