예제 #1
0
        /// <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
                                                                         ()));
            }
        }
예제 #2
0
 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);
 }
예제 #3
0
        /// <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");
                }
            }
        }
예제 #4
0
 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);
 }
예제 #5
0
 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);
 }
예제 #6
0
 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);
 }
예제 #7
0
        /// <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");
            }
        }
예제 #8
0
 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);
 }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
 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);
 }
예제 #12
0
 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);
 }