Merge fighting fsck-cache updates from Junio
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 28 Jun 2005 22:20:10 +0000 (15:20 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 28 Jun 2005 22:20:10 +0000 (15:20 -0700)
It's just easier to let git help out with the merge than it is to try to
fix up the diffs.

1  2 
sha1_file.c

diff --combined sha1_file.c
@@@ -10,7 -10,6 +10,7 @@@
  #include <dirent.h>
  #include "cache.h"
  #include "delta.h"
 +#include "pack.h"
  
  #ifndef O_NOATIME
  #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
@@@ -185,10 -184,7 +185,7 @@@ char *sha1_file_name(const unsigned cha
        return base;
  }
  
- static struct alternate_object_database {
-       char *base;
-       char *name;
- } *alt_odb;
+ struct alternate_object_database *alt_odb;
  
  /*
   * Prepare alternate object database registry.
   * pointed by base fields of the array elements with one xmalloc();
   * the string pool immediately follows the array.
   */
static void prepare_alt_odb(void)
+ void prepare_alt_odb(void)
  {
        int pass, totlen, i;
        const char *cp, *last;
        char *op = NULL;
        const char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
  
+       if (alt_odb)
+               return;
        /* The first pass counts how large an area to allocate to
         * hold the entire alt_odb structure, including array of
         * structs and path buffers for them.  The second pass fills
@@@ -259,8 -257,7 +258,7 @@@ static char *find_sha1_file(const unsig
  
        if (!stat(name, st))
                return name;
-       if (!alt_odb)
-               prepare_alt_odb();
+       prepare_alt_odb();
        for (i = 0; (name = alt_odb[i].name) != NULL; i++) {
                fill_sha1_path(name, sha1);
                if (!stat(alt_odb[i].base, st))
  #define PACK_MAX_SZ (1<<26)
  static int pack_used_ctr;
  static unsigned long pack_mapped;
- static struct packed_git {
-       struct packed_git *next;
-       unsigned long index_size;
-       unsigned long pack_size;
-       unsigned int *index_base;
-       void *pack_base;
-       unsigned int pack_last_used;
-       char pack_name[0]; /* something like ".git/objects/pack/xxxxx.pack" */
- } *packed_git;
+ struct packed_git *packed_git;
  
  struct pack_entry {
        unsigned int offset;
@@@ -396,7 -385,6 +386,7 @@@ static struct packed_git *add_packed_gi
        p->pack_size = st.st_size;
        p->index_base = idx_map;
        p->next = NULL;
 +      p->pack_base = NULL;
        p->pack_last_used = 0;
        return p;
  }
@@@ -431,7 -419,7 +421,7 @@@ static void prepare_packed_git_one(cha
        }
  }
  
static void prepare_packed_git(void)
+ void prepare_packed_git(void)
  {
        int i;
        static int run_once = 0;
                return;
  
        prepare_packed_git_one(get_object_directory());
-       if (!alt_odb)
-               prepare_alt_odb();
+       prepare_alt_odb();
        for (i = 0; alt_odb[i].base != NULL; i++) {
                alt_odb[i].name[0] = 0;
                prepare_packed_git_one(alt_odb[i].base);
@@@ -667,60 -654,37 +656,60 @@@ static int packed_delta_info(unsigned c
        return 0;
  }
  
 +static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
 +      enum object_type *type, unsigned long *sizep)
 +{
 +      unsigned char *pack, c;
 +      unsigned long size;
 +
 +      if (offset >= p->pack_size)
 +              die("object offset outside of pack file");
 +
 +      pack =  p->pack_base + offset;
 +      c = *pack++;
 +      offset++;
 +      *type = (c >> 4) & 7;
 +      size = c & 15;
 +      while (c & 0x80) {
 +              if (offset >= p->pack_size)
 +                      die("object offset outside of pack file");
 +              c = *pack++;
 +              offset++;
 +              size = (size << 7) | (c & 0x7f);
 +      }
 +      *sizep = size;
 +      return offset;
 +}
 +
  static int packed_object_info(struct pack_entry *entry,
                              char *type, unsigned long *sizep)
  {
        struct packed_git *p = entry->p;
        unsigned long offset, size, left;
        unsigned char *pack;
 -
 -      offset = entry->offset;
 -      if (p->pack_size - 5 < offset)
 -              die("object offset outside of pack file");
 +      enum object_type kind;
  
        if (use_packed_git(p))
                die("cannot map packed file");
  
 +      offset = unpack_object_header(p, entry->offset, &kind, &size);
        pack = p->pack_base + offset;
 -      size = (pack[1] << 24) + (pack[2] << 16) + (pack[3] << 8) + pack[4];
 -      left = p->pack_size - offset - 5;
 -      switch (*pack) {
 -      case 'D':
 -              return packed_delta_info(pack+5, size, left, type, sizep);
 +      left = p->pack_size - offset;
 +
 +      switch (kind) {
 +      case OBJ_DELTA:
 +              return packed_delta_info(pack, size, left, type, sizep);
                break;
 -      case 'C':
 +      case OBJ_COMMIT:
                strcpy(type, "commit");
                break;
 -      case 'T':
 +      case OBJ_TREE:
                strcpy(type, "tree");
                break;
 -      case 'B':
 +      case OBJ_BLOB:
                strcpy(type, "blob");
                break;
 -      case 'G':
 +      case OBJ_TAG:
                strcpy(type, "tag");
                break;
        default:
@@@ -812,36 -776,55 +801,52 @@@ static void *unpack_entry(struct pack_e
        struct packed_git *p = entry->p;
        unsigned long offset, size, left;
        unsigned char *pack;
 -
 -      offset = entry->offset;
 -      if (p->pack_size - 5 < offset)
 -              die("object offset outside of pack file");
 +      enum object_type kind;
  
        if (use_packed_git(p))
                die("cannot map packed file");
  
 +      offset = unpack_object_header(p, entry->offset, &kind, &size);
        pack = p->pack_base + offset;
 -      size = (pack[1] << 24) + (pack[2] << 16) + (pack[3] << 8) + pack[4];
 -      left = p->pack_size - offset - 5;
 -      switch (*pack) {
 -      case 'D':
 -              return unpack_delta_entry(pack+5, size, left, type, sizep);
 -      case 'C':
 +      left = p->pack_size - offset;
 +      switch (kind) {
 +      case OBJ_DELTA:
 +              return unpack_delta_entry(pack, size, left, type, sizep);
 +      case OBJ_COMMIT:
                strcpy(type, "commit");
                break;
 -      case 'T':
 +      case OBJ_TREE:
                strcpy(type, "tree");
                break;
 -      case 'B':
 +      case OBJ_BLOB:
                strcpy(type, "blob");
                break;
 -      case 'G':
 +      case OBJ_TAG:
                strcpy(type, "tag");
                break;
        default:
                die("corrupted pack file");
        }
        *sizep = size;
 -      return unpack_non_delta_entry(pack+5, size, left);
 +      return unpack_non_delta_entry(pack, size, left);
  }
  
+ int num_packed_objects(const struct packed_git *p)
+ {
+       /* See check_packed_git_idx and pack-objects.c */
+       return (p->index_size - 20 - 20 - 4*256) / 24;
+ }
+ int nth_packed_object_sha1(const struct packed_git *p, int n,
+                          unsigned char* sha1)
+ {
+       void *index = p->index_base + 256;
+       if (n < 0 || num_packed_objects(p) <= n)
+               return -1;
+       memcpy(sha1, (index + 24 * n + 4), 20);
+       return 0;
+ }
  static int find_pack_entry_1(const unsigned char *sha1,
                             struct pack_entry *e, struct packed_git *p)
  {