Description of an object stored in a pack file, including offset.

When objects are stored in packs Git needs the ObjectId and the offset (starting position of the object data) to perform random-access reads of objects from the pack. This extension of ObjectId includes the offset.

Inheritance: ObjectId
Example #1
0
        private void GrowEntries()
        {
            var newEntries = new PackedObjectInfo[(int)_objectCount + _baseById.Count];

            Array.Copy(_entries, 0, newEntries, 0, _entryCount);
            _entries = newEntries;
        }
Example #2
0
 private void ResolveDeltas(PackedObjectInfo objectInfo)
 {
     if (_baseById.Get(objectInfo) != null || _baseByPos.containsKey(objectInfo.Offset))
     {
         int oldCrc = objectInfo.CRC;
         ResolveDeltas(objectInfo.Offset, oldCrc, Constants.OBJ_BAD, null, objectInfo);
     }
 }
Example #3
0
 private void addObjectAndTrack(PackedObjectInfo oe)
 {
     _entries[_entryCount++] = oe;
     if (needNewObjectIds())
     {
         _newObjectIds.Add(oe);
     }
 }
Example #4
0
        private void FixThinPack(ProgressMonitor progress)
        {
            GrowEntries();

            _packDigest.Reset();
            _originalEof = _packOut.Length - 20;
            var  def     = new Deflater(Deflater.DEFAULT_COMPRESSION, false);
            var  missing = new List <DeltaChain>(64);
            long end     = _originalEof;

            foreach (DeltaChain baseId in _baseById)
            {
                if (baseId.Head == null)
                {
                    continue;
                }

                ObjectLoader ldr = _repo.OpenObject(_windowCursor, baseId);
                if (ldr == null)
                {
                    missing.Add(baseId);
                    continue;
                }

                byte[] data     = ldr.CachedBytes;
                int    typeCode = ldr.Type;

                _crc.Reset();
                _packOut.Seek(end, SeekOrigin.Begin);
                WriteWhole(def, typeCode, data);
                var oe = new PackedObjectInfo(end, (int)_crc.Value, baseId);
                _entries[_entryCount++] = oe;
                end = _packOut.Position;

                ResolveChildDeltas(oe.Offset, typeCode, data, oe);
                if (progress.IsCancelled)
                {
                    throw new IOException("Download cancelled during indexing");
                }
            }

            def.Finish();

            foreach (DeltaChain baseDeltaChain in missing)
            {
                if (baseDeltaChain.Head != null)
                {
                    throw new MissingObjectException(baseDeltaChain, "delta base");
                }
            }

            FixHeaderFooter(_packcsum, _packDigest.Digest());
        }
Example #5
0
        private void Whole(int type, long pos, long sz)
        {
            byte[] data = InflateFromInput((int)sz);
            _objectDigest.Update(Constants.encodedTypeString(type));
            _objectDigest.Update((byte)' ');
            _objectDigest.Update(Constants.encodeASCII(sz));
            _objectDigest.Update(0);
            _objectDigest.Update(data);
            _tempObjectId.FromRaw(_objectDigest.Digest(), 0);

            VerifySafeObject(_tempObjectId, type, data);
            var crc32 = (int)_crc.Value;

            _entries[_entryCount++] = new PackedObjectInfo(pos, crc32, _tempObjectId);
        }
 public static bool CanStore(PackedObjectInfo objectInfo)
 {
     // We are limited to 4 GB per pack as offset is 32 bit unsigned int.
     //
     return objectInfo.Offset.UnsignedRightShift(1) < int.MaxValue;
 }
Example #7
0
        private void ResolveDeltas(long pos, int oldCrc, int type, byte[] data, PackedObjectInfo oe)
        {
            _crc.Reset();
            Position(pos);
            int c = ReadFromFile();
            int typecode = (c >> 4) & 7;
            long sz = c & 15;
            int shift = 4;
            while ((c & 0x80) != 0)
            {
                c = ReadFromFile();
                sz += (c & 0x7f) << shift;
                shift += 7;
            }

            switch (typecode)
            {
                case Constants.OBJ_COMMIT:
                case Constants.OBJ_TREE:
                case Constants.OBJ_BLOB:
                case Constants.OBJ_TAG:
                    type = typecode;
                    data = InflateFromFile((int)sz);
                    break;

                case Constants.OBJ_OFS_DELTA:
                    c = ReadFromFile() & 0xff;
                    while ((c & 128) != 0)
                    {
                        c = ReadFromFile() & 0xff;
                    }
                    data = BinaryDelta.Apply(data, InflateFromFile((int)sz));
                    break;

                case Constants.OBJ_REF_DELTA:
                    _crc.Update(_buffer, FillFromFile(20), 20);
                    Use(20);
                    data = BinaryDelta.Apply(data, InflateFromFile((int)sz));
                    break;

                default:
                    throw new IOException("Unknown object type " + typecode + ".");
            }

            var crc32 = (int)_crc.Value;
            if (oldCrc != crc32)
            {
                throw new IOException("Corruption detected re-reading at " + pos);
            }

            if (oe == null)
            {
                _objectDigest.Update(Constants.encodedTypeString(type));
                _objectDigest.Update((byte)' ');
                _objectDigest.Update(Constants.encodeASCII(data.Length));
                _objectDigest.Update(0);
                _objectDigest.Update(data);
                _tempObjectId.FromRaw(_objectDigest.Digest(), 0);

                VerifySafeObject(_tempObjectId, type, data);
                oe = new PackedObjectInfo(pos, crc32, _tempObjectId);
                _entries[_entryCount++] = oe;
            }

            ResolveChildDeltas(pos, type, data, oe);
        }
Example #8
0
 private void ResolveDeltas(PackedObjectInfo objectInfo)
 {
     if (_baseById.Get(objectInfo) != null || _baseByPos.containsKey(objectInfo.Offset))
     {
         int oldCrc = objectInfo.CRC;
         ResolveDeltas(objectInfo.Offset, oldCrc, Constants.OBJ_BAD, null, objectInfo);
     }
 }
Example #9
0
 private void GrowEntries()
 {
     var newEntries = new PackedObjectInfo[(int)_objectCount + _baseById.Count];
     Array.Copy(_entries, 0, newEntries, 0, _entryCount);
     _entries = newEntries;
 }
Example #10
0
        private void FixThinPack(ProgressMonitor progress)
        {
            GrowEntries();

            _packDigest.Reset();
            _originalEof = _packOut.Length - 20;
            var def = new Deflater(Deflater.DEFAULT_COMPRESSION, false);
            var missing = new List<DeltaChain>(64);
            long end = _originalEof;

            foreach (DeltaChain baseId in _baseById)
            {
                if (baseId.Head == null)
                {
                    continue;
                }

                ObjectLoader ldr = _repo.OpenObject(_windowCursor, baseId);
                if (ldr == null)
                {
                    missing.Add(baseId);
                    continue;
                }

                byte[] data = ldr.CachedBytes;
                int typeCode = ldr.Type;

                _crc.Reset();
                _packOut.Seek(end, SeekOrigin.Begin);
                WriteWhole(def, typeCode, data);
                var oe = new PackedObjectInfo(end, (int)_crc.Value, baseId);
                _entries[_entryCount++] = oe;
                end = _packOut.Position;

                ResolveChildDeltas(oe.Offset, typeCode, data, oe);
                if (progress.IsCancelled)
                {
                    throw new IOException("Download cancelled during indexing");
                }
            }

            def.Finish();

            foreach (DeltaChain baseDeltaChain in missing)
            {
                if (baseDeltaChain.Head != null)
                {
                    throw new MissingObjectException(baseDeltaChain, "delta base");
                }
            }

            FixHeaderFooter(_packcsum, _packDigest.Digest());
        }
Example #11
0
        private void Whole(int type, long pos, long sz)
        {
            byte[] data = InflateFromInput((int)sz);
            _objectDigest.Update(Constants.encodedTypeString(type));
            _objectDigest.Update((byte)' ');
            _objectDigest.Update(Constants.encodeASCII(sz));
            _objectDigest.Update(0);
            _objectDigest.Update(data);
            _tempObjectId.FromRaw(_objectDigest.Digest(), 0);

            VerifySafeObject(_tempObjectId, type, data);
            var crc32 = (int)_crc.Value;
            _entries[_entryCount++] = new PackedObjectInfo(pos, crc32, _tempObjectId);
        }
Example #12
0
        private void ResolveDeltas(long pos, int oldCrc, int type, byte[] data, PackedObjectInfo oe)
        {
            _crc.Reset();
            Position(pos);
            int  c        = ReadFromFile();
            int  typecode = (c >> 4) & 7;
            long sz       = c & 15;
            int  shift    = 4;

            while ((c & 0x80) != 0)
            {
                c      = ReadFromFile();
                sz    += (c & 0x7f) << shift;
                shift += 7;
            }

            switch (typecode)
            {
            case Constants.OBJ_COMMIT:
            case Constants.OBJ_TREE:
            case Constants.OBJ_BLOB:
            case Constants.OBJ_TAG:
                type = typecode;
                data = InflateFromFile((int)sz);
                break;

            case Constants.OBJ_OFS_DELTA:
                c = ReadFromFile() & 0xff;
                while ((c & 128) != 0)
                {
                    c = ReadFromFile() & 0xff;
                }
                data = BinaryDelta.Apply(data, InflateFromFile((int)sz));
                break;

            case Constants.OBJ_REF_DELTA:
                _crc.Update(_buffer, FillFromFile(20), 20);
                Use(20);
                data = BinaryDelta.Apply(data, InflateFromFile((int)sz));
                break;

            default:
                throw new IOException("Unknown object type " + typecode + ".");
            }

            var crc32 = (int)_crc.Value;

            if (oldCrc != crc32)
            {
                throw new IOException("Corruption detected re-reading at " + pos);
            }

            if (oe == null)
            {
                _objectDigest.Update(Constants.encodedTypeString(type));
                _objectDigest.Update((byte)' ');
                _objectDigest.Update(Constants.encodeASCII(data.Length));
                _objectDigest.Update(0);
                _objectDigest.Update(data);
                _tempObjectId.FromRaw(_objectDigest.Digest(), 0);

                VerifySafeObject(_tempObjectId, type, data);
                oe = new PackedObjectInfo(pos, crc32, _tempObjectId);
                addObjectAndTrack(oe);
            }

            ResolveChildDeltas(pos, type, data, oe);
        }
Example #13
0
        /// <summary>
        /// Rename the pack to it's final name and location and open it.
        /// <para/>
        /// If the call completes successfully the repository this IndexPack instance
        /// was created with will have the objects in the pack available for reading
        /// and use, without needing to scan for packs.
        /// </summary>
        /// <param name="lockMessage">
        /// message to place in the pack-*.keep file. If null, no lock
        /// will be created, and this method returns null.
        /// </param>
        /// <returns>the pack lock object, if lockMessage is not null.</returns>
        public PackLock renameAndOpenPack(string lockMessage)
        {
            if (!_keepEmpty && _entryCount == 0)
            {
                CleanupTemporaryFiles();
                return(null);
            }

            MessageDigest d       = Constants.newMessageDigest();
            var           oeBytes = new byte[Constants.OBJECT_ID_LENGTH];

            for (int i = 0; i < _entryCount; i++)
            {
                PackedObjectInfo oe = _entries[i];
                oe.copyRawTo(oeBytes, 0);
                d.Update(oeBytes);
            }

            string name      = ObjectId.FromRaw(d.Digest()).Name;
            var    packDir   = PathUtil.CombineDirectoryPath(_repo.ObjectsDirectory, "pack");
            var    finalPack = PathUtil.CombineFilePath(packDir, "pack-" + GetPackFileName(name));
            var    finalIdx  = PathUtil.CombineFilePath(packDir, "pack-" + GetIndexFileName(name));
            var    keep      = new PackLock(finalPack);

            if (!packDir.Exists && !packDir.Mkdirs() && !packDir.Exists)
            {
                // The objects/pack directory isn't present, and we are unable
                // to create it. There is no way to move this pack in.
                //
                CleanupTemporaryFiles();
                throw new IOException("Cannot Create " + packDir);
            }

            if (finalPack.Exists)
            {
                // If the pack is already present we should never replace it.
                //
                CleanupTemporaryFiles();
                return(null);
            }

            if (lockMessage != null)
            {
                // If we have a reason to create a keep file for this pack, do
                // so, or fail fast and don't put the pack in place.
                //
                try
                {
                    if (!keep.Lock(lockMessage))
                    {
                        throw new IOException("Cannot lock pack in " + finalPack);
                    }
                }
                catch (IOException)
                {
                    CleanupTemporaryFiles();
                    throw;
                }
            }

            if (!_dstPack.RenameTo(finalPack.ToString()))
            {
                CleanupTemporaryFiles();
                keep.Unlock();
                throw new IOException("Cannot move pack to " + finalPack);
            }

            if (!_dstIdx.RenameTo(finalIdx.ToString()))
            {
                CleanupTemporaryFiles();
                keep.Unlock();
                finalPack.DeleteFile();
                //if (finalPack.Exists)
                // TODO: [caytchen]  finalPack.deleteOnExit();
                throw new IOException("Cannot move index to " + finalIdx);
            }

            try
            {
                _repo.OpenPack(finalPack, finalIdx);
            }
            catch (IOException)
            {
                keep.Unlock();
                finalPack.DeleteFile();
                finalIdx.DeleteFile();
                throw;
            }

            return(lockMessage != null ? keep : null);
        }
Example #14
0
 private void addObjectAndTrack(PackedObjectInfo oe)
 {
     _entries[_entryCount++] = oe;
     if (needNewObjectIds())
         _newObjectIds.Add(oe);
 }
Example #15
0
        public PackLock renameAndOpenPack(string lockMessage)
        {
            if (!_keepEmpty && _entryCount == 0)
            {
                CleanupTemporaryFiles();
                return(null);
            }

            MessageDigest d       = Constants.newMessageDigest();
            var           oeBytes = new byte[Constants.OBJECT_ID_LENGTH];

            for (int i = 0; i < _entryCount; i++)
            {
                PackedObjectInfo oe = _entries[i];
                oe.copyRawTo(oeBytes, 0);
                d.Update(oeBytes);
            }

            string name      = ObjectId.FromRaw(d.Digest()).Name;
            var    packDir   = new DirectoryInfo(Path.Combine(_repo.ObjectsDirectory.ToString(), "pack"));
            var    finalPack = new FileInfo(Path.Combine(packDir.ToString(), "pack-" + GetPackFileName(name)));
            var    finalIdx  = new FileInfo(Path.Combine(packDir.ToString(), "pack-" + GetIndexFileName(name)));
            var    keep      = new PackLock(finalPack);

            if (!packDir.Exists && !packDir.Mkdirs() && !packDir.Exists)
            {
                CleanupTemporaryFiles();
                throw new IOException("Cannot Create " + packDir);
            }

            if (finalPack.Exists)
            {
                CleanupTemporaryFiles();
                return(null);
            }

            if (lockMessage != null)
            {
                try
                {
                    if (!keep.Lock(lockMessage))
                    {
                        throw new IOException("Cannot lock pack in " + finalPack);
                    }
                }
                catch (IOException)
                {
                    CleanupTemporaryFiles();
                    throw;
                }
            }

            if (!_dstPack.RenameTo(finalPack.ToString()))
            {
                CleanupTemporaryFiles();
                keep.Unlock();
                throw new IOException("Cannot move pack to " + finalPack);
            }

            if (!_dstIdx.RenameTo(finalIdx.ToString()))
            {
                CleanupTemporaryFiles();
                keep.Unlock();
                finalPack.Delete();
                //if (finalPack.Exists)
                // TODO: [caytchen]  finalPack.deleteOnExit();
                throw new IOException("Cannot move index to " + finalIdx);
            }

            try
            {
                _repo.OpenPack(finalPack, finalIdx);
            }
            catch (IOException)
            {
                keep.Unlock();
                finalPack.Delete();
                finalIdx.Delete();
                throw;
            }

            return(lockMessage != null ? keep : null);
        }