/// <exception cref="System.IO.IOException"></exception> private void OnOpenPack() { PackIndex idx = Idx(); byte[] buf = new byte[20]; fd.Seek(0); fd.ReadFully(buf, 0, 12); if (RawParseUtils.Match(buf, 0, Constants.PACK_SIGNATURE) != 4) { throw new IOException(JGitText.Get().notAPACKFile); } long vers = NB.DecodeUInt32(buf, 4); long packCnt = NB.DecodeUInt32(buf, 8); if (vers != 2 && vers != 3) { throw new IOException(MessageFormat.Format(JGitText.Get().unsupportedPackVersion, Sharpen.Extensions.ValueOf(vers))); } if (packCnt != idx.GetObjectCount()) { throw new PackMismatchException(MessageFormat.Format(JGitText.Get().packObjectCountMismatch , Sharpen.Extensions.ValueOf(packCnt), Sharpen.Extensions.ValueOf(idx.GetObjectCount ()), GetPackFile())); } fd.Seek(length - 20); fd.ReadFully(buf, 0, 20); if (!Arrays.Equals(buf, packChecksum)) { throw new PackMismatchException(MessageFormat.Format(JGitText.Get().packObjectCountMismatch , ObjectId.FromRaw(buf).Name, ObjectId.FromRaw(idx.packChecksum).Name, GetPackFile ())); } }
internal virtual int ParseTraditionalHeaders(int ptr, int end) { while (ptr < end) { int eol = RawParseUtils.NextLF(buf, ptr); if (IsHunkHdr(buf, ptr, eol) >= 1) { // First hunk header; break out and parse them later. break; } else { if (RawParseUtils.Match(buf, ptr, OLD_NAME) >= 0) { ParseOldName(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, NEW_NAME) >= 0) { ParseNewName(ptr, eol); } else { // Possibly an empty patch. break; } } } ptr = eol; } return(ptr); }
/// <summary>Check an annotated tag for errors.</summary> /// <remarks>Check an annotated tag for errors.</remarks> /// <param name="raw">the tag data. The array is never modified.</param> /// <exception cref="NGit.Errors.CorruptObjectException">if any error was detected.</exception> public virtual void CheckTag(byte[] raw) { int ptr = 0; if ((ptr = RawParseUtils.Match(raw, ptr, @object)) < 0) { throw new CorruptObjectException("no object header"); } if ((ptr = Id(raw, ptr)) < 0 || raw[ptr++] != '\n') { throw new CorruptObjectException("invalid object"); } if ((ptr = RawParseUtils.Match(raw, ptr, type)) < 0) { throw new CorruptObjectException("no type header"); } ptr = RawParseUtils.NextLF(raw, ptr); if ((ptr = RawParseUtils.Match(raw, ptr, tag)) < 0) { throw new CorruptObjectException("no tag header"); } ptr = RawParseUtils.NextLF(raw, ptr); if ((ptr = RawParseUtils.Match(raw, ptr, tagger)) > 0) { if ((ptr = PersonIdent(raw, ptr)) < 0 || raw[ptr++] != '\n') { throw new CorruptObjectException("invalid tagger"); } } }
private static int SkipFile(byte[] buf, int ptr) { ptr = RawParseUtils.NextLF(buf, ptr); if (RawParseUtils.Match(buf, ptr, FileHeader.OLD_NAME) >= 0) { ptr = RawParseUtils.NextLF(buf, ptr); } return(ptr); }
private static bool MatchAny(byte[] buf, int c, byte[][] srcs) { foreach (byte[] s in srcs) { if (RawParseUtils.Match(buf, c, s) >= 0) { return(true); } } return(false); }
internal virtual int ParseHunk(int ptr, int end) { byte[] buf = file.buf; if (RawParseUtils.Match(buf, ptr, LITERAL) >= 0) { type = BinaryHunk.Type.LITERAL_DEFLATED; length = RawParseUtils.ParseBase10(buf, ptr + LITERAL.Length, null); } else { if (RawParseUtils.Match(buf, ptr, DELTA) >= 0) { type = BinaryHunk.Type.DELTA_DEFLATED; length = RawParseUtils.ParseBase10(buf, ptr + DELTA.Length, null); } else { // Not a valid binary hunk. Signal to the caller that // we cannot parse any further and that this line should // be treated otherwise. // return(-1); } } ptr = RawParseUtils.NextLF(buf, ptr); // Skip until the first blank line; that is the end of the binary // encoded information in this hunk. To save time we don't do a // validation of the binary data at this point. // while (ptr < end) { bool empty = (buf[ptr] == '\n') || (buf[ptr] == '\r' && ptr + 1 < end && buf[ptr + 1] == '\n'); ptr = RawParseUtils.NextLF(buf, ptr); if (empty) { break; } } return(ptr); }
/// <summary>Check a commit for errors.</summary> /// <remarks>Check a commit for errors.</remarks> /// <param name="raw">the commit data. The array is never modified.</param> /// <exception cref="NGit.Errors.CorruptObjectException">if any error was detected.</exception> public virtual void CheckCommit(byte[] raw) { int ptr = 0; if ((ptr = RawParseUtils.Match(raw, ptr, tree)) < 0) { throw new CorruptObjectException("no tree header"); } if ((ptr = Id(raw, ptr)) < 0 || raw[ptr++] != '\n') { throw new CorruptObjectException("invalid tree"); } while (RawParseUtils.Match(raw, ptr, parent) >= 0) { ptr += parent.Length; if ((ptr = Id(raw, ptr)) < 0 || raw[ptr++] != '\n') { throw new CorruptObjectException("invalid parent"); } } if ((ptr = RawParseUtils.Match(raw, ptr, author)) < 0) { throw new CorruptObjectException("no author"); } if ((ptr = PersonIdent(raw, ptr)) < 0 || raw[ptr++] != '\n') { throw new CorruptObjectException("invalid author"); } if ((ptr = RawParseUtils.Match(raw, ptr, committer)) < 0) { throw new CorruptObjectException("no committer"); } if ((ptr = PersonIdent(raw, ptr)) < 0 || raw[ptr++] != '\n') { throw new CorruptObjectException("invalid committer"); } }
internal virtual int ParseGitHeaders(int ptr, int end) { while (ptr < end) { int eol = RawParseUtils.NextLF(buf, ptr); if (IsHunkHdr(buf, ptr, eol) >= 1) { // First hunk header; break out and parse them later. break; } else { if (RawParseUtils.Match(buf, ptr, OLD_NAME) >= 0) { ParseOldName(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, NEW_NAME) >= 0) { ParseNewName(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, OLD_MODE) >= 0) { oldMode = ParseFileMode(ptr + OLD_MODE.Length, eol); } else { if (RawParseUtils.Match(buf, ptr, NEW_MODE) >= 0) { newMode = ParseFileMode(ptr + NEW_MODE.Length, eol); } else { if (RawParseUtils.Match(buf, ptr, DELETED_FILE_MODE) >= 0) { oldMode = ParseFileMode(ptr + DELETED_FILE_MODE.Length, eol); newMode = FileMode.MISSING; changeType = DiffEntry.ChangeType.DELETE; } else { if (RawParseUtils.Match(buf, ptr, NEW_FILE_MODE) >= 0) { ParseNewFileMode(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, COPY_FROM) >= 0) { oldPath = ParseName(oldPath, ptr + COPY_FROM.Length, eol); changeType = DiffEntry.ChangeType.COPY; } else { if (RawParseUtils.Match(buf, ptr, COPY_TO) >= 0) { newPath = ParseName(newPath, ptr + COPY_TO.Length, eol); changeType = DiffEntry.ChangeType.COPY; } else { if (RawParseUtils.Match(buf, ptr, RENAME_OLD) >= 0) { oldPath = ParseName(oldPath, ptr + RENAME_OLD.Length, eol); changeType = DiffEntry.ChangeType.RENAME; } else { if (RawParseUtils.Match(buf, ptr, RENAME_NEW) >= 0) { newPath = ParseName(newPath, ptr + RENAME_NEW.Length, eol); changeType = DiffEntry.ChangeType.RENAME; } else { if (RawParseUtils.Match(buf, ptr, RENAME_FROM) >= 0) { oldPath = ParseName(oldPath, ptr + RENAME_FROM.Length, eol); changeType = DiffEntry.ChangeType.RENAME; } else { if (RawParseUtils.Match(buf, ptr, RENAME_TO) >= 0) { newPath = ParseName(newPath, ptr + RENAME_TO.Length, eol); changeType = DiffEntry.ChangeType.RENAME; } else { if (RawParseUtils.Match(buf, ptr, SIMILARITY_INDEX) >= 0) { score = RawParseUtils.ParseBase10(buf, ptr + SIMILARITY_INDEX.Length, null); } else { if (RawParseUtils.Match(buf, ptr, DISSIMILARITY_INDEX) >= 0) { score = RawParseUtils.ParseBase10(buf, ptr + DISSIMILARITY_INDEX.Length, null); } else { if (RawParseUtils.Match(buf, ptr, INDEX) >= 0) { ParseIndexLine(ptr + INDEX.Length, eol); } else { // Probably an empty patch (stat dirty). break; } } } } } } } } } } } } } } } } ptr = eol; } return(ptr); }
internal virtual int ParseBody(NGit.Patch.Patch script, int end) { byte[] buf = file.buf; int c = RawParseUtils.NextLF(buf, startOffset); int last = c; old.nDeleted = 0; old.nAdded = 0; for (; c < end; last = c, c = RawParseUtils.NextLF(buf, c)) { switch (buf[c]) { case (byte)(' '): case (byte)('\n'): { nContext++; continue; goto case (byte)('-'); } case (byte)('-'): { old.nDeleted++; continue; goto case (byte)('+'); } case (byte)('+'): { old.nAdded++; continue; goto case (byte)('\\'); } case (byte)('\\'): { // Matches "\ No newline at end of file" continue; goto default; } default: { goto SCAN_break; break; } } SCAN_continue :; } SCAN_break :; if (last < end && nContext + old.nDeleted - 1 == old.lineCount && nContext + old. nAdded == newLineCount && RawParseUtils.Match(buf, last, NGit.Patch.Patch.SIG_FOOTER ) >= 0) { // This is an extremely common occurrence of "corruption". // Users add footers with their signatures after this mark, // and git diff adds the git executable version number. // Let it slide; the hunk otherwise looked sound. // old.nDeleted--; return(last); } if (nContext + old.nDeleted < old.lineCount) { int missingCount = old.lineCount - (nContext + old.nDeleted); script.Error(buf, startOffset, MessageFormat.Format(JGitText.Get().truncatedHunkOldLinesMissing , missingCount)); } else { if (nContext + old.nAdded < newLineCount) { int missingCount = newLineCount - (nContext + old.nAdded); script.Error(buf, startOffset, MessageFormat.Format(JGitText.Get().truncatedHunkNewLinesMissing , missingCount)); } else { if (nContext + old.nDeleted > old.lineCount || nContext + old.nAdded > newLineCount) { string oldcnt = old.lineCount + ":" + newLineCount; string newcnt = (nContext + old.nDeleted) + ":" + (nContext + old.nAdded); script.Warn(buf, startOffset, MessageFormat.Format(JGitText.Get().hunkHeaderDoesNotMatchBodyLineCountOf , oldcnt, newcnt)); } } } return(c); }
private int ParseHunks(FileHeader fh, int c, int end) { 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 (RawParseUtils.Match(buf, c, DIFF_GIT) >= 0) { break; } if (RawParseUtils.Match(buf, c, DIFF_CC) >= 0) { break; } if (RawParseUtils.Match(buf, c, DIFF_COMBINED) >= 0) { break; } if (RawParseUtils.Match(buf, c, FileHeader.OLD_NAME) >= 0) { break; } if (RawParseUtils.Match(buf, c, FileHeader.NEW_NAME) >= 0) { break; } if (FileHeader.IsHunkHdr(buf, c, end) == fh.GetParentCount()) { 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 (byte)('@'): case (byte)('d'): case (byte)('\n'): { break; } default: { if (RawParseUtils.Match(buf, c, SIG_FOOTER) < 0 && RawParseUtils.Match(buf, c, SIG_FOOTER_WINDOWS) < 0) { Warn(buf, c, JGitText.Get().unexpectedHunkTrailer); } break; } } } continue; } int eol = RawParseUtils.NextLF(buf, c); if (fh.GetHunks().IsEmpty() && (RawParseUtils.Match(buf, c, GIT_BINARY) >= 0 || RawParseUtils.Match(buf, c, GIT_BINARY_WINDOWS) >= 0)) { fh.patchType = FileHeader.PatchType.GIT_BINARY; return(ParseGitBinary(fh, eol, end)); } if (fh.GetHunks().IsEmpty() && ((BIN_TRAILER.Length < eol - c && RawParseUtils.Match(buf, eol - BIN_TRAILER.Length, BIN_TRAILER) >= 0) || (BIN_TRAILER_WINDOWS.Length < eol - c && RawParseUtils.Match(buf, eol - BIN_TRAILER_WINDOWS.Length, BIN_TRAILER_WINDOWS) >= 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); }
private int ParseFile(byte[] buf, int c, int end) { while (c < end) { if (FileHeader.IsHunkHdr(buf, c, end) >= 1) { // If we find a disconnected hunk header we might // have missed a file header previously. The hunk // isn't valid without knowing where it comes from. // Error(buf, c, JGitText.Get().hunkDisconnectedFromFile); c = RawParseUtils.NextLF(buf, c); continue; } // Valid git style patch? // if (RawParseUtils.Match(buf, c, DIFF_GIT) >= 0) { return(ParseDiffGit(buf, c, end)); } if (RawParseUtils.Match(buf, c, DIFF_CC) >= 0) { return(ParseDiffCombined(DIFF_CC, buf, c, end)); } if (RawParseUtils.Match(buf, c, DIFF_COMBINED) >= 0) { return(ParseDiffCombined(DIFF_COMBINED, buf, c, end)); } // Junk between files? Leading junk? Traditional // (non-git generated) patch? // int n = RawParseUtils.NextLF(buf, c); if (n >= end) { // Patches cannot be only one line long. This must be // trailing junk that we should ignore. // return(end); } if (n - c < 6) { // A valid header must be at least 6 bytes on the // first line, e.g. "--- a/b\n". // c = n; continue; } if (RawParseUtils.Match(buf, c, FileHeader.OLD_NAME) >= 0 && RawParseUtils.Match( buf, n, FileHeader.NEW_NAME) >= 0) { // Probably a traditional patch. Ensure we have at least // a "@@ -0,0" smelling line next. We only check the "@@ -". // int f = RawParseUtils.NextLF(buf, n); if (f >= end) { return(end); } if (FileHeader.IsHunkHdr(buf, f, end) == 1) { return(ParseTraditionalPatch(buf, c, end)); } } c = n; } return(c); }
internal override int ParseGitHeaders(int ptr, int end) { while (ptr < end) { int eol = RawParseUtils.NextLF(buf, ptr); if (IsHunkHdr(buf, ptr, end) >= 1) { // First hunk header; break out and parse them later. break; } else { if (RawParseUtils.Match(buf, ptr, OLD_NAME) >= 0) { ParseOldName(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, NEW_NAME) >= 0) { ParseNewName(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, INDEX) >= 0) { ParseIndexLine(ptr + INDEX.Length, eol); } else { if (RawParseUtils.Match(buf, ptr, MODE) >= 0) { ParseModeLine(ptr + MODE.Length, eol); } else { if (RawParseUtils.Match(buf, ptr, NEW_FILE_MODE) >= 0) { ParseNewFileMode(ptr, eol); } else { if (RawParseUtils.Match(buf, ptr, DELETED_FILE_MODE) >= 0) { ParseDeletedFileMode(ptr + DELETED_FILE_MODE.Length, eol); } else { // Probably an empty patch (stat dirty). break; } } } } } } } ptr = eol; } return(ptr); }