2011-12-02 35 views
5

Tengo un problema muy simple pero molesto, y no puedo encontrar la respuesta en Internet. Espero que puedas señalarme, lo que he hecho mal.Decodificación de objetos GIT/"La longitud del bloque no coincide con su complemento" error

Estoy intentando decodificar objetos del repositorio de Git. De acuerdo con ProGit, el nombre del archivo y su contenido se han desinflado durante la confirmación.

Estoy usando C# para leer el objeto indicado por SHA1 en una secuencia, inflarlo y convertirlo en una matriz de bytes. Aquí está el código:

using System.IO.Compression; 

static internal byte[] GetObjectBySha(string storagePath, string sha) 
{ 
    string filePath = Path.Combine(storagePath, "objects", sha.Substring(0, 2), sha.Substring(2, 38)); 
    byte[] fileContent = null; 

    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (DeflateStream gs = new DeflateStream(fs, CompressionMode.Decompress)) 
      { 
       gs.CopyTo(ms); 
      } 

      fileContent = ms.ToArray(); 
     } 
    } 

    return fileContent; 
} 

Cuando gs.CopyTo(ms); se alcanza el tiempo de ejecución de error se produce: Longitud de bloque no coincide con su complemento.

¿Por qué?

En cuanto al contenido del archivo que estoy tratando de leer ... Es binario y fue creado por el ejecutable git. El nombre del archivo original es testfile.txt, su contenido es Sample text. SHA1 es 51d0be227ecdc0039698122a1513421ce35c1dbe.

¡Cualquier idea sería muy apreciada!

Respuesta

7

DeflateStream y zlib son dos cosas diferentes como se explica en this answer:

No hay ZlibStream en la biblioteca de clases base de .NET - nada que produce o consume ZLIB

Así que lo que la necesidad es un consumidor ZLIB. La biblioteca DotNetZip proporciona uno:

static internal byte[] GetObjectBySha(string storagePath, string sha) 
{ 
    string filePath = Path.Combine(storagePath, "objects", sha.Substring(0, 2), sha.Substring(2, 38)); 
    byte[] compressed = File.ReadAllBytes(filePath); 
    return Ionic.Zlib.ZlibStream.UncompressBuffer(compressed); 
} 
+0

¡Gracias, esto fue realmente útil! – shytikov

2

ZLib es Deflate con un encabezado adicional de dos bytes, un opcional "diccionario" y una suma de comprobación de cuatro bytes al final. Dependiendo de su aplicación, por ejemplo, si sabe que no va a haber un diccionario, puede salirse con la tarea cortando los primeros dos bytes y los últimos cuatro bytes de los datos antes de ejecutarlo a través de DeflateStream. Es una solución sucia, pero podría salvarte de tener que traer una dependencia externa.

Cuestiones relacionadas