String getScriptText(Charset[] charsetGuess) { if (getHunks().isEmpty()) { // If we have no hunks then we can safely assume the entire // patch is a binary style patch, or a meta-data only style // patch. Either way the encoding of the headers should be // strictly 7-bit US-ASCII and the body is either 7-bit ASCII // (due to the base 85 encoding used for a BinaryHunk) or is // arbitrary noise we have chosen to ignore and not understand // (e.g. the message "Binary files ... differ"). // return extractBinaryString(buf, startOffset, endOffset); } if (charsetGuess != null && charsetGuess.length != getParentCount() + 1) throw new IllegalArgumentException( MessageFormat.format( JGitText.get().expectedCharacterEncodingGuesses, Integer.valueOf(getParentCount() + 1))); if (trySimpleConversion(charsetGuess)) { Charset cs = charsetGuess != null ? charsetGuess[0] : null; if (cs == null) cs = Constants.CHARSET; try { return decodeNoFallback(cs, buf, startOffset, endOffset); } catch (CharacterCodingException cee) { // Try the much slower, more-memory intensive version which // can handle a character set conversion patch. } } final StringBuilder r = new StringBuilder(endOffset - startOffset); // Always treat the headers as US-ASCII; Git file names are encoded // in a C style escape if any character has the high-bit set. // final int hdrEnd = getHunks().get(0).getStartOffset(); for (int ptr = startOffset; ptr < hdrEnd; ) { final int eol = Math.min(hdrEnd, nextLF(buf, ptr)); r.append(extractBinaryString(buf, ptr, eol)); ptr = eol; } final String[] files = extractFileLines(charsetGuess); final int[] offsets = new int[files.length]; for (final HunkHeader h : getHunks()) h.extractFileLines(r, files, offsets); return r.toString(); }
private String[] extractFileLines(final Charset[] csGuess) { final TemporaryBuffer[] tmp = new TemporaryBuffer[getParentCount() + 1]; try { for (int i = 0; i < tmp.length; i++) tmp[i] = new TemporaryBuffer.LocalFile(); for (final HunkHeader h : getHunks()) h.extractFileLines(tmp); final String[] r = new String[tmp.length]; for (int i = 0; i < tmp.length; i++) { Charset cs = csGuess != null ? csGuess[i] : null; if (cs == null) cs = Constants.CHARSET; r[i] = RawParseUtils.decode(cs, tmp[i].toByteArray()); } return r; } catch (IOException ioe) { throw new RuntimeException(JGitText.get().cannotConvertScriptToText, ioe); } finally { for (final TemporaryBuffer b : tmp) { if (b != null) b.destroy(); } } }
private int parseHunks(final FileHeader fh, int c, final int end) { final byte[] buf = fh.buf; while (c < end) { // If we see a file header at this point, we have all of the // hunks for our current file. We should stop and report back // with this position so it can be parsed again later. // if (match(buf, c, DIFF_GIT) >= 0) break; if (match(buf, c, DIFF_CC) >= 0) break; if (match(buf, c, DIFF_COMBINED) >= 0) break; if (match(buf, c, OLD_NAME) >= 0) break; if (match(buf, c, NEW_NAME) >= 0) break; if (isHunkHdr(buf, c, end) == fh.getParentCount()) { final HunkHeader h = fh.newHunkHeader(c); h.parseHeader(); c = h.parseBody(this, end); h.endOffset = c; fh.addHunk(h); if (c < end) { switch (buf[c]) { case '@': case 'd': case '\n': break; default: if (match(buf, c, SIG_FOOTER) < 0) warn(buf, c, JGitText.get().unexpectedHunkTrailer); } } continue; } final int eol = nextLF(buf, c); if (fh.getHunks().isEmpty() && match(buf, c, GIT_BINARY) >= 0) { fh.patchType = FileHeader.PatchType.GIT_BINARY; return parseGitBinary(fh, eol, end); } if (fh.getHunks().isEmpty() && BIN_TRAILER.length < eol - c && match(buf, eol - BIN_TRAILER.length, BIN_TRAILER) >= 0 && matchAny(buf, c, BIN_HEADERS)) { // The patch is a binary file diff, with no deltas. // fh.patchType = FileHeader.PatchType.BINARY; return eol; } // Skip this line and move to the next. Its probably garbage // after the last hunk of a file. // c = eol; } if (fh.getHunks().isEmpty() && fh.getPatchType() == FileHeader.PatchType.UNIFIED && !fh.hasMetaDataChanges()) { // Hmm, an empty patch? If there is no metadata here we // really have a binary patch that we didn't notice above. // fh.patchType = FileHeader.PatchType.BINARY; } return c; }
/** @return a list describing the content edits performed on this file. */ public EditList toEditList() { final EditList r = new EditList(); for (final HunkHeader hunk : hunks) r.addAll(hunk.toEditList()); return r; }
void addHunk(final HunkHeader h) { if (h.getFileHeader() != this) throw new IllegalArgumentException(JGitText.get().hunkBelongsToAnotherFile); if (hunks == null) hunks = new ArrayList<HunkHeader>(); hunks.add(h); }