Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

2008-12-06 Miguel de Icaza <miguel@novell.com>

	* Lib/UnpackedObjectCache.cs: Implement

	* Lib/Constants.cs: Add a handful of extra contants.

	* Lib/Codec.cs: Put here the coding/encoding routines that were
	originally in egit's lib/Constants.java class
  • Loading branch information...
commit 1f847bc3dee9a9c6a69a7885ccdd21dfcff64b3d 1 parent ba4711b
Miguel de Icaza authored
View
5 ChangeLog
@@ -1,5 +1,10 @@
2008-12-06 Miguel de Icaza <miguel@novell.com>
+ * Lib/Constants.cs: Add a handful of extra contants.
+
+ * Lib/Codec.cs: Put here the coding/encoding routines that were
+ originally in egit's lib/Constants.java class
+
* Lib/*: Align some API doc comments, add some API docs.
* Lib/RefDatabase.cs (Peel): Implement.
View
4 Exceptions/CorruptObjectException.cs
@@ -59,9 +59,7 @@ public class CorruptObjectException : IOException
public CorruptObjectException(ObjectId id, string message) : base(string.Format("Object {0} is corrupt: {1}",id,message)) { }
public CorruptObjectException(string message) : base(message) { }
public CorruptObjectException(ObjectId id, string message, Exception inner) : base(string.Format("Object {0} is corrupt: {1}", id, message), inner) { }
- protected CorruptObjectException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context)
+ protected CorruptObjectException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
}
View
3  Gitty.Lib.CSharp.csproj
@@ -58,7 +58,9 @@
<Compile Include="Lib\AnyObjectId.cs" />
<Compile Include="Lib\BinaryDelta.cs" />
<Compile Include="Lib\ByteWindow.cs" />
+ <Compile Include="Lib\Codec.cs" />
<Compile Include="Lib\Commit.cs" />
+ <Compile Include="Lib\Constants.cs" />
<Compile Include="Lib\CoreConfig.cs" />
<Compile Include="Lib\DeltaOfsPackedObjectLoader.cs" />
<Compile Include="Lib\DeltaPackedObjectLoader.cs" />
@@ -119,6 +121,7 @@
<Compile Include="Util\NestedDictionary.cs" />
<Compile Include="Util\Numbers.cs" />
<Compile Include="Util\PathUtil.cs" />
+ <Compile Include="Util\RawParseUtils.cs" />
<Compile Include="Util\WeakReference.cs" />
</ItemGroup>
<ItemGroup>
View
130 Lib/Codec.cs
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Kevin Thompson <kevin.thompson@theautomaters.com>
+ * Copyright (C) 2008, Novell, Inc <miguel@novell.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+using Gitty.Exceptions;
+using System;
+
+namespace Gitty.Lib
+{
+ internal static class Codec {
+
+ public static ObjectType DecodeTypeString (ObjectId id, byte [] typeString, byte endMark, ref int offset)
+ {
+ try {
+ switch (typeString [offset]){
+ case (byte) 'b':
+ if (typeString [offset + 1] != (byte) 'l' ||
+ typeString [offset + 2] != (byte) 'o' ||
+ typeString [offset + 3] != (byte) 'b' ||
+ typeString [offset + 4] != endMark)
+ break;
+ offset += 5;
+ return ObjectType.Blob;
+
+ case (byte) 'c':
+ if (typeString [offset + 1] != (byte) 'o' || typeString [offset + 2] != (byte) 'm' ||
+ typeString [offset + 3] != (byte) 'm' || typeString [offset + 4] != (byte) 'i' ||
+ typeString [offset + 5] != (byte) 't' || typeString [offset + 6] != endMark)
+ break;
+ offset += 7;
+ return ObjectType.Commit;
+
+ case (byte) 't':
+ switch (typeString [offset + 1]){
+ case (byte) 'a':
+ if (typeString [offset + 2] != (byte) 'g' || typeString [offset + 2] != endMark)
+ throw new CorruptObjectException (id, "invalid type");
+ offset += 4;
+ return ObjectType.Tag;
+
+ case (byte) 'r':
+ if (typeString [offset + 2] != (byte) 'e' || typeString [offset + 3] != (byte) 'e' || typeString [offset + 4] != endMark)
+ throw new CorruptObjectException (id, "invalid type");
+ offset += 5;
+ return ObjectType.Tree;
+
+ }
+ break;
+ }
+ } catch (IndexOutOfRangeException) {
+ }
+ throw new CorruptObjectException (id, "invalid type");
+ }
+
+ public static string TypeString (ObjectType objectType)
+ {
+ switch (objectType){
+ case ObjectType.Commit:
+ return Constants.TypeCommit;
+
+ case ObjectType.Tree:
+ return Constants.TypeTree;
+
+ case ObjectType.Blob:
+ return Constants.TypeBlob;
+
+ case ObjectType.Tag:
+ return Constants.TypeTag;
+
+ default:
+ throw new ArgumentException ("objectType", "Bad object type passed");
+ }
+ }
+
+ public static byte [] EncodedTypeString (ObjectType objectType)
+ {
+ switch (objectType){
+ case ObjectType.Commit:
+ return Constants.EncodedTypeCommit;
+
+ case ObjectType.Tree:
+ return Constants.EncodedTypeTree;
+
+ case ObjectType.Blob:
+ return Constants.EncodedTypeBlob;
+
+ case ObjectType.Tag:
+ return Constants.EncodedTypeTag;
+
+ default:
+ throw new ArgumentException ("objectType", "Bad object type passed");
+ }
+ }
+ }
+}
View
43 Lib/Constants.cs
@@ -42,7 +42,7 @@
namespace Gitty.Lib
{
- public sealed class Constants {
+ public static class Constants {
/// <summary>
/// Prefix for branch refs
/// </summary>
@@ -67,8 +67,39 @@ public sealed class Constants {
/// Annotated tags store a pointer to any other object, and an additional
/// message. It is most commonly used to record a stable release of the
/// project.
- /// </summary>
+ /// </remarks>
public static readonly string TypeTag = "tag";
+
+ /// <summary>
+ /// Text string that identifies an object as tree.
+ /// <summary>
+ /// <remarks>
+ /// Trees attach object ids (hashes) to names and file
+ /// modes. The normal use for a tree is to store a
+ /// version of a directory and its contents.
+ /// </remarks>
+ public static readonly string TypeTree = "tree";
+
+ /// <summary>
+ /// Text string that identifies an object as a blob
+ /// <summary>
+ /// <remarks>
+ /// Blobs store whole file revisions. They are used
+ /// for any user file, as well as for symlinks. Blobs
+ /// form the bulk of any project's storage space.
+ /// </remarks>
+ public static readonly string TypeBlob = "blob";
+
+ /// <summary>
+ /// Text string that identifies an object as a commit.
+ /// <summary>
+ /// <remarks>
+ /// Commits connect trees into a string of project
+ /// histories, where each commit is an assertion that
+ /// the best way to continue is to use this other tree
+ /// (set of files).
+ /// </remarks>
+ public static readonly string TypeCommit = "commit";
public static readonly Encoding Encoding = Encoding.UTF8;
@@ -81,5 +112,11 @@ public sealed class Constants {
public static readonly string HeadsSlash = HeadsPrefix + "/";
public static readonly string[] RefSearchPaths = { "", RefsSlash, TagsSlash, HeadsSlash, RemotesPrefix + "/" };
- }
+
+ public static readonly byte [] EncodedTypeCommit = new byte [] { (byte) 'c', (byte) 'o', (byte) 'm', (byte) 'm', (byte) 'i', (byte) 't' };
+ public static readonly byte [] EncodedTypeTree = new byte [] { (byte) 't', (byte) 'r', (byte) 'e', (byte) 'e' };
+ public static readonly byte [] EncodedTypeBlob = new byte [] { (byte) 'b', (byte) 'l', (byte) 'o', (byte) 'b' };
+ public static readonly byte [] EncodedTypeTag = new byte [] { (byte) 't', (byte) 'a', (byte) 'g' };
+
+ }
}
View
6 Lib/ObjectType.cs
@@ -50,8 +50,8 @@ public enum ObjectType
Blob = 3,
Tag = 4,
ObjectType5 = 5,
- OFSDelta = 6,
- RefDelta = 7,
- Unknown = 255
+ OffsetDelta = 6,
+ ReferenceDelta = 7,
+ Unknown = 255
}
}
View
4 Lib/PackFile.cs
@@ -307,7 +307,7 @@ private PackedObjectLoader Reader(WindowCursor curs, long objOffset)
case ObjectType.Blob:
case ObjectType.Tag:
return new WholePackedObjectLoader(curs, this, pos, objOffset, (ObjectType)typeCode, (int)dataSize);
- case ObjectType.OFSDelta:
+ case ObjectType.OffsetDelta:
pack.ReadFully(pos, ib, curs);
p = 0;
c = ib[p++] & 0xff;
@@ -320,7 +320,7 @@ private PackedObjectLoader Reader(WindowCursor curs, long objOffset)
ofs += (c & 127);
}
return new DeltaOfsPackedObjectLoader(curs, this, pos + p, objOffset, (int)dataSize, objOffset - ofs);
- case ObjectType.RefDelta:
+ case ObjectType.ReferenceDelta:
pack.ReadFully(pos, ib, curs);
return new DeltaRefPackedObjectLoader(curs, this, pos + ib.Length, objOffset, (int)dataSize, ObjectId.FromRaw(ib));
View
147 Lib/UnpackedObjectLoader.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2008, Kevin Thompson <kevin.thompson@theautomaters.com>
@@ -41,44 +41,147 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using ICSharpCode.SharpZipLib.Zip.Compression;
+using Gitty.Exceptions;
+using System.IO;
namespace Gitty.Lib
{
public class UnpackedObjectLoader : ObjectLoader
{
+ long objectSize;
+ byte [] bytes;
+ ObjectType objectType;
+
public UnpackedObjectLoader(Repository repo, ObjectId objectId)
+ : this (ReadCompressed (repo, objectId), objectId)
{
-
}
- public override ObjectType ObjectType
- {
- get { throw new NotImplementedException(); }
- }
+ public UnpackedObjectLoader (byte [] compressed) : this (compressed, null)
+ {
+ }
+
+ public UnpackedObjectLoader (byte [] compressed, ObjectId id)
+ {
+ Id = id;
+ // Try to determine if this is a legacy format loose object or
+ // a new style loose object. The legacy format was completely
+ // compressed with zlib so the first byte must be 0x78 (15-bit
+ // window size, deflated) and the first 16 bit word must be
+ // evenly divisible by 31. Otherwise its a new style loose
+ // object.
+ //
+ Inflater inflater = InflaterCache.GetInflater ();
+ try {
+ int fb = compressed [0] & 0xff;
+
+ if (fb == 0x78 && (((fb << 8) | compressed [1] & 0xff) % 31) == 0) {
+ inflater.SetInput (compressed);
+ byte[] hdr = new byte [64];
+ int avail = 0;
- public override long Size
- {
- get { throw new NotImplementedException(); }
- }
+ while (!inflater.IsFinished && avail < hdr.Length){
+ try {
+ avail += inflater.Inflate (hdr, avail, hdr.Length - avail);
+ } catch (Exception inn) {
+ throw new CorruptObjectException(id, "bad stream", inn);
+ }
+ }
+
+ if (avail < 5)
+ throw new CorruptObjectException(id, "no header");
- public override byte[] Bytes
- {
- get { throw new NotImplementedException(); }
+ int p = 0;
+ objectType = Codec.DecodeTypeString (id, hdr, (byte) ' ', ref p);
+ objectSize = RawParseUtils.ParseBase10 (hdr, ref p);
+ if (objectSize < 0)
+ throw new CorruptObjectException(id, "negative size");
+ if (hdr [p++] != 0)
+ throw new CorruptObjectException(id, "garbage after size");
+ bytes = new byte [objectSize];
+ if (p < avail)
+ Array.Copy (hdr, p, bytes, 0, avail - p);
+ Decompress (id, inflater, avail - p);
+ } else {
+ int p = 0;
+ int c = compressed [p++] & 0xff;
+ ObjectType typeCode = (ObjectType) ((c >> 4) & 7);
+ int size = c & 15;
+ int shift = 4;
+ while ((c & 0x80) != 0) {
+ c = compressed[p++] & 0xff;
+ size += (c & 0x7f) << shift;
+ shift += 7;
+ }
+
+ switch (typeCode) {
+ case ObjectType.Commit:
+ case ObjectType.Tree:
+ case ObjectType.Blob:
+ case ObjectType.Tag:
+ objectType = typeCode;
+ break;
+ default:
+ throw new CorruptObjectException(id, "invalid type");
+ }
+
+ objectSize = size;
+ bytes = new byte[objectSize];
+ inflater.SetInput (compressed, p, compressed.Length - p);
+ Decompress (id, inflater, 0);
+ }
+ } finally {
+ InflaterCache.Release(inflater);
+ }
+ }
+
+ void Decompress (ObjectId id, Inflater inf, int p)
+ {
+ try {
+ while (!inf.IsFinished){
+ p += inf.Inflate (bytes, p, (int) objectSize - p);
+ }
+ } catch (Exception e) {
+ throw new CorruptObjectException (id, "bad stream", e);
+ }
+ if (p != objectSize)
+ throw new CorruptObjectException (id, "Invalid Length");
+ }
+
+ static byte [] ReadCompressed (Repository db, ObjectId id)
+ {
+ byte [] compressed;
+
+ using (FileStream objStream = db.ToFile (id).OpenRead ()){
+ compressed = new byte [objStream.Length];
+ objStream.Read (compressed, 0, (int) objStream.Length);
+ }
+ return compressed;
+ }
+
+ public override ObjectType ObjectType {
+ get { return objectType; }
+ }
+
+ public override long Size {
+ get { return objectSize; }
+ }
+
+ public override byte[] Bytes {
+ get { return bytes; }
}
- public override byte[] CachedBytes
- {
- get { throw new NotImplementedException(); }
+ public override byte[] CachedBytes {
+ get { return bytes; }
}
- public override ObjectType RawType
- {
- get { throw new NotImplementedException(); }
+ public override ObjectType RawType {
+ get { return objectType; }
}
- public override long RawSize
- {
- get { throw new NotImplementedException(); }
+ public override long RawSize {
+ get { return objectSize; }
}
}
}
View
21 Lib/WindowCache.cs
@@ -46,9 +46,28 @@
namespace Gitty.Lib {
public class WindowCache {
+ const int KB = 1024;
+ const int MB = 1024 * 1024;
+
+ static int MaxByteCount = 10 * MB;
+ static int WindowSize = 8 * 1024;
+ static int WindowSizeShift = 13;
+ static ByteArrayWindow [] windows;
+
+ static WindowCache ()
+ {
+ windows = new ByteArrayWindow [MaxByteCount / WindowSize];
+ }
+
public static void Get (WindowCursor cursor, WindowedFile wp, long position)
{
- throw new NotImplementedException ();
+ Console.WriteLine ("Requesting to load from {0} at {1} from {2}", wp, position, Environment.StackTrace);
+
+ long id = (position >> WindowSizeShift);
+
+ wp.CacheOpen ();
+ wp.LoadWindow (cursor, (int) id, position, 8192);
+ Console.Error.WriteLine ("WindowCache.Get: This is incomplete and will likely fail");
}
public static void Purge (WindowedFile wp)
View
41 Lib/WindowedFile.cs
@@ -49,11 +49,11 @@ public class WindowedFile
{
FileInfo fPath;
FileStream fs;
-
+
public WindowedFile(FileInfo packFile)
{
fPath = packFile;
- Length = Int64.MaxValue;
+ Length = -1;
}
public ThreadStart OnOpen { get; set; }
@@ -69,6 +69,7 @@ public WindowedFile(FileInfo packFile)
internal void Close()
{
WindowCache.Purge (this);
+ Length = -1;
}
internal void ReadCompressed(long position, byte[] dstbuf, WindowCursor curs)
@@ -111,5 +112,41 @@ internal int Read (long position, byte[] dstbuf, WindowCursor curs)
{
return Read (position, dstbuf, 0, dstbuf.Length, curs);
}
+
+ internal void CacheOpen ()
+ {
+ fs = fPath.OpenRead ();
+ Length = fPath.Length;
+ try {
+ OnOpen ();
+ } catch {
+ CacheClose ();
+ throw;
+ }
+ }
+
+ void CacheClose ()
+ {
+ try {
+ fs.Close ();
+ } catch {}
+ fs = null;
+ Length = -1;
+ }
+
+ internal void LoadWindow (WindowCursor curs, int windowId, long pos, int windowSize)
+ {
+ byte [] b = new byte [windowSize];
+
+ fs.Position = pos;
+ fs.Read (b, 0, b.Length);
+ curs.Window = new ByteArrayWindow (this, pos, windowId, b);
+ curs.Handle = b;
+ }
+
+ public override string ToString ()
+ {
+ return "WindowedFile[" + Name + "]";
+ }
}
}
View
2  Makefile
@@ -14,6 +14,7 @@ SOURCES = \
Lib/AnyObjectId.cs \
Lib/BinaryDelta.cs \
Lib/ByteArrayWindow.cs \
+ Lib/Codec.cs \
Lib/Commit.cs \
Lib/Constants.cs \
Lib/CoreConfig.cs \
@@ -77,6 +78,7 @@ SOURCES = \
Util/NestedDictionary.cs \
Util/Numbers.cs \
Util/PathUtil.cs \
+ Util/RawParseUtils.cs \
Util/WeakReference.cs
all: Gitty.Lib.CSharp.dll test.exe
View
75 Util/RawParseUtils.cs
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+using System;
+namespace Gitty.Lib {
+
+ public static class RawParseUtils {
+
+ public static int ParseBase10 (byte [] b, ref int ptr)
+ {
+ int r = 0;
+ int sign = 1;
+
+ try {
+ int sz = b.Length;
+ while (ptr < sz && b [ptr] == ' ')
+ ptr++;
+
+ if (ptr >= sz)
+ return 0;
+
+ if (b [ptr] == '-'){
+ sign = -1;
+ ptr++;
+ } else if (b [ptr] == '+')
+ ptr++;
+
+ while (ptr < sz){
+ byte d = b [ptr];
+ if ((d < (byte) '0') | (d > (byte) '9'))
+ break;
+ r = r * 10 + (d - (byte) '0');
+ ptr++;
+ }
+ } catch (IndexOutOfRangeException) {
+ // Not a valid digit
+ }
+
+ return sign * r;
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.