Merge branch 'bc/repack'
authorJunio C Hamano <gitster@pobox.com>
Fri, 23 May 2008 23:06:01 +0000 (16:06 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 23 May 2008 23:06:01 +0000 (16:06 -0700)
* bc/repack:
Documentation/git-repack.txt: document new -A behaviour
let pack-objects do the writing of unreachable objects as loose objects
add a force_object_loose() function
builtin-gc.c: deprecate --prune, it now really has no effect
git-gc: always use -A when manually repacking
repack: modify behavior of -A option to leave unreferenced objects unpacked

Conflicts:

builtin-pack-objects.c

1  2 
Documentation/git-repack.txt
builtin-pack-objects.c
cache.h
git-repack.sh
index d14ab5154f6286d3b24e74b37b0a503d1270e381,906d3c7054a3481ac84478a15dfb2ce3384dcf33..f81a6607dec7bbe9c985106770ecae8b5f01f3c0
@@@ -8,7 -8,7 +8,7 @@@ git-repack - Pack unpacked objects in 
  
  SYNOPSIS
  --------
- 'git-repack' [-a] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
+ 'git-repack' [-a] [-A] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
  
  DESCRIPTION
  -----------
@@@ -37,6 -37,18 +37,18 @@@ OPTION
        leaves behind, but `git fsck --full` shows as
        dangling.
  
+ -A::
+       Same as `-a`, but any unreachable objects in a previous
+       pack become loose, unpacked objects, instead of being
+       left in the old pack.  Unreachable objects are never
+       intentionally added to a pack, even when repacking.
+       When used with '-d', this option
+       prevents unreachable objects from being immediately
+       deleted by way of being left in the old pack and then
+       removed.  Instead, the loose unreachable objects
+       will be pruned according to normal expiry rules
+       with the next linkgit:git-gc[1].
  -d::
        After packing, if the newly created packs make some
        existing packs redundant, remove the redundant packs.
        linkgit:git-pack-objects[1].
  
  -n::
 -        Do not update the server information with
 -        `git update-server-info`.
 +      Do not update the server information with
 +      `git update-server-info`.  This option skips
 +      updating local catalog files needed to publish
 +      this repository (or a direct copy of it)
 +      over HTTP or FTP.  See gitlink:git-update-server-info[1].
  
  --window=[N], --depth=[N]::
        These two options affect how the objects contained in the pack are
diff --combined builtin-pack-objects.c
index e20851e1c9c9ad517314794b7c8d4e3615afa9c5,5a10119fbd4f62c7a94c49c8d91c966f177331c1..f43eb67016ee719d34d2e2f4ae8d77e1ec74b396
@@@ -28,7 -28,8 +28,8 @@@ git-pack-objects [{ -q | --progress | -
        [--window=N] [--window-memory=N] [--depth=N] \n\
        [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
        [--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\
-       [--stdout | base-name] [--include-tag] [--keep-unreachable] \n\
+       [--stdout | base-name] [--include-tag] \n\
+       [--keep-unreachable | --unpack-unreachable] \n\
        [<ref-list | <object-list]";
  
  struct object_entry {
@@@ -43,7 -44,6 +44,7 @@@
                                             */
        void *delta_data;       /* cached delta (uncompressed) */
        unsigned long delta_size;       /* delta data size (uncompressed) */
 +      unsigned long z_delta_size;     /* delta data size (compressed) */
        unsigned int hash;      /* name hint hash */
        enum object_type type;
        enum object_type in_pack_type;  /* could be delta */
@@@ -66,8 -66,7 +67,8 @@@ static struct pack_idx_entry **written_
  static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
  
  static int non_empty;
 -static int no_reuse_delta, no_reuse_object, keep_unreachable, unpack_unreachable, include_tag;
 +static int reuse_delta = 1, reuse_object = 1;
- static int keep_unreachable, include_tag;
++static int keep_unreachable, unpack_unreachable, include_tag;
  static int local;
  static int incremental;
  static int allow_ofs_delta;
@@@ -104,53 -103,24 +105,53 @@@ static uint32_t written, written_delta
  static uint32_t reused, reused_delta;
  
  
 -static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
 +static void *get_delta(struct object_entry *entry)
  {
 -      unsigned long othersize, delta_size;
 +      unsigned long size, base_size, delta_size;
 +      void *buf, *base_buf, *delta_buf;
        enum object_type type;
 -      void *otherbuf = read_sha1_file(entry->delta->idx.sha1, &type, &othersize);
 -      void *delta_buf;
  
 -      if (!otherbuf)
 +      buf = read_sha1_file(entry->idx.sha1, &type, &size);
 +      if (!buf)
 +              die("unable to read %s", sha1_to_hex(entry->idx.sha1));
 +      base_buf = read_sha1_file(entry->delta->idx.sha1, &type, &base_size);
 +      if (!base_buf)
                die("unable to read %s", sha1_to_hex(entry->delta->idx.sha1));
 -        delta_buf = diff_delta(otherbuf, othersize,
 +      delta_buf = diff_delta(base_buf, base_size,
                               buf, size, &delta_size, 0);
 -        if (!delta_buf || delta_size != entry->delta_size)
 +      if (!delta_buf || delta_size != entry->delta_size)
                die("delta size changed");
 -        free(buf);
 -        free(otherbuf);
 +      free(buf);
 +      free(base_buf);
        return delta_buf;
  }
  
 +static unsigned long do_compress(void **pptr, unsigned long size)
 +{
 +      z_stream stream;
 +      void *in, *out;
 +      unsigned long maxsize;
 +
 +      memset(&stream, 0, sizeof(stream));
 +      deflateInit(&stream, pack_compression_level);
 +      maxsize = deflateBound(&stream, size);
 +
 +      in = *pptr;
 +      out = xmalloc(maxsize);
 +      *pptr = out;
 +
 +      stream.next_in = in;
 +      stream.avail_in = size;
 +      stream.next_out = out;
 +      stream.avail_out = maxsize;
 +      while (deflate(&stream, Z_FINISH) == Z_OK)
 +              ; /* nothing */
 +      deflateEnd(&stream);
 +
 +      free(in);
 +      return stream.total_out;
 +}
 +
  /*
   * The per-object header is a pretty dense thing, which is
   *  - first byte: low four bits are "size", then three bits of "type",
@@@ -253,42 -223,42 +254,42 @@@ static unsigned long write_object(struc
                                  struct object_entry *entry,
                                  off_t write_offset)
  {
 -      unsigned long size;
 -      enum object_type type;
 +      unsigned long size, limit, datalen;
        void *buf;
 -      unsigned char header[10];
 -      unsigned char dheader[10];
 +      unsigned char header[10], dheader[10];
        unsigned hdrlen;
 -      off_t datalen;
 -      enum object_type obj_type;
 -      int to_reuse = 0;
 -      /* write limit if limited packsize and not first object */
 -      unsigned long limit = pack_size_limit && nr_written ?
 -                              pack_size_limit - write_offset : 0;
 -                              /* no if no delta */
 -      int usable_delta =      !entry->delta ? 0 :
 -                              /* yes if unlimited packfile */
 -                              !pack_size_limit ? 1 :
 -                              /* no if base written to previous pack */
 -                              entry->delta->idx.offset == (off_t)-1 ? 0 :
 -                              /* otherwise double-check written to this
 -                               * pack,  like we do below
 -                               */
 -                              entry->delta->idx.offset ? 1 : 0;
 +      enum object_type type;
 +      int usable_delta, to_reuse;
  
        if (!pack_to_stdout)
                crc32_begin(f);
  
 -      obj_type = entry->type;
 -      if (no_reuse_object)
 +      type = entry->type;
 +
 +      /* write limit if limited packsize and not first object */
 +      limit = pack_size_limit && nr_written ?
 +                      pack_size_limit - write_offset : 0;
 +
 +      if (!entry->delta)
 +              usable_delta = 0;       /* no delta */
 +      else if (!pack_size_limit)
 +             usable_delta = 1;        /* unlimited packfile */
 +      else if (entry->delta->idx.offset == (off_t)-1)
 +              usable_delta = 0;       /* base was written to another pack */
 +      else if (entry->delta->idx.offset)
 +              usable_delta = 1;       /* base already exists in this pack */
 +      else
 +              usable_delta = 0;       /* base could end up in another pack */
 +
 +      if (!reuse_object)
                to_reuse = 0;   /* explicit */
        else if (!entry->in_pack)
                to_reuse = 0;   /* can't reuse what we don't have */
 -      else if (obj_type == OBJ_REF_DELTA || obj_type == OBJ_OFS_DELTA)
 +      else if (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA)
                                /* check_object() decided it for us ... */
                to_reuse = usable_delta;
                                /* ... but pack split may override that */
 -      else if (obj_type != entry->in_pack_type)
 +      else if (type != entry->in_pack_type)
                to_reuse = 0;   /* pack has delta which is unusable */
        else if (entry->delta)
                to_reuse = 0;   /* we want to pack afresh */
                                 */
  
        if (!to_reuse) {
 -              z_stream stream;
 -              unsigned long maxsize;
 -              void *out;
                if (!usable_delta) {
 -                      buf = read_sha1_file(entry->idx.sha1, &obj_type, &size);
 +                      buf = read_sha1_file(entry->idx.sha1, &type, &size);
                        if (!buf)
                                die("unable to read %s", sha1_to_hex(entry->idx.sha1));
 +                      /*
 +                       * make sure no cached delta data remains from a
 +                       * previous attempt before a pack split occured.
 +                       */
 +                      free(entry->delta_data);
 +                      entry->delta_data = NULL;
 +                      entry->z_delta_size = 0;
                } else if (entry->delta_data) {
                        size = entry->delta_size;
                        buf = entry->delta_data;
                        entry->delta_data = NULL;
 -                      obj_type = (allow_ofs_delta && entry->delta->idx.offset) ?
 +                      type = (allow_ofs_delta && entry->delta->idx.offset) ?
                                OBJ_OFS_DELTA : OBJ_REF_DELTA;
                } else {
 -                      buf = read_sha1_file(entry->idx.sha1, &type, &size);
 -                      if (!buf)
 -                              die("unable to read %s", sha1_to_hex(entry->idx.sha1));
 -                      buf = delta_against(buf, size, entry);
 +                      buf = get_delta(entry);
                        size = entry->delta_size;
 -                      obj_type = (allow_ofs_delta && entry->delta->idx.offset) ?
 +                      type = (allow_ofs_delta && entry->delta->idx.offset) ?
                                OBJ_OFS_DELTA : OBJ_REF_DELTA;
                }
 -              /* compress the data to store and put compressed length in datalen */
 -              memset(&stream, 0, sizeof(stream));
 -              deflateInit(&stream, pack_compression_level);
 -              maxsize = deflateBound(&stream, size);
 -              out = xmalloc(maxsize);
 -              /* Compress it */
 -              stream.next_in = buf;
 -              stream.avail_in = size;
 -              stream.next_out = out;
 -              stream.avail_out = maxsize;
 -              while (deflate(&stream, Z_FINISH) == Z_OK)
 -                      /* nothing */;
 -              deflateEnd(&stream);
 -              datalen = stream.total_out;
 +
 +              if (entry->z_delta_size)
 +                      datalen = entry->z_delta_size;
 +              else
 +                      datalen = do_compress(&buf, size);
  
                /*
                 * The object header is a byte of 'type' followed by zero or
                 * more bytes of length.
                 */
 -              hdrlen = encode_header(obj_type, size, header);
 +              hdrlen = encode_header(type, size, header);
  
 -              if (obj_type == OBJ_OFS_DELTA) {
 +              if (type == OBJ_OFS_DELTA) {
                        /*
                         * Deltas with relative base contain an additional
                         * encoding of the relative offset for the delta
                        while (ofs >>= 7)
                                dheader[--pos] = 128 | (--ofs & 127);
                        if (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit) {
 -                              free(out);
                                free(buf);
                                return 0;
                        }
                        sha1write(f, header, hdrlen);
                        sha1write(f, dheader + pos, sizeof(dheader) - pos);
                        hdrlen += sizeof(dheader) - pos;
 -              } else if (obj_type == OBJ_REF_DELTA) {
 +              } else if (type == OBJ_REF_DELTA) {
                        /*
                         * Deltas with a base reference contain
                         * an additional 20 bytes for the base sha1.
                         */
                        if (limit && hdrlen + 20 + datalen + 20 >= limit) {
 -                              free(out);
                                free(buf);
                                return 0;
                        }
                        hdrlen += 20;
                } else {
                        if (limit && hdrlen + datalen + 20 >= limit) {
 -                              free(out);
                                free(buf);
                                return 0;
                        }
                        sha1write(f, header, hdrlen);
                }
 -              sha1write(f, out, datalen);
 -              free(out);
 +              sha1write(f, buf, datalen);
                free(buf);
        }
        else {
                off_t offset;
  
                if (entry->delta) {
 -                      obj_type = (allow_ofs_delta && entry->delta->idx.offset) ?
 +                      type = (allow_ofs_delta && entry->delta->idx.offset) ?
                                OBJ_OFS_DELTA : OBJ_REF_DELTA;
                        reused_delta++;
                }
 -              hdrlen = encode_header(obj_type, entry->size, header);
 +              hdrlen = encode_header(type, entry->size, header);
                offset = entry->in_pack_offset;
                revidx = find_pack_revindex(p, offset);
                datalen = revidx[1].offset - offset;
                        die("bad packed object CRC for %s", sha1_to_hex(entry->idx.sha1));
                offset += entry->in_pack_header_size;
                datalen -= entry->in_pack_header_size;
 -              if (obj_type == OBJ_OFS_DELTA) {
 +              if (type == OBJ_OFS_DELTA) {
                        off_t ofs = entry->idx.offset - entry->delta->idx.offset;
                        unsigned pos = sizeof(dheader) - 1;
                        dheader[pos] = ofs & 127;
                        sha1write(f, header, hdrlen);
                        sha1write(f, dheader + pos, sizeof(dheader) - pos);
                        hdrlen += sizeof(dheader) - pos;
 -              } else if (obj_type == OBJ_REF_DELTA) {
 +              } else if (type == OBJ_REF_DELTA) {
                        if (limit && hdrlen + 20 + datalen + 20 >= limit)
                                return 0;
                        sha1write(f, header, hdrlen);
@@@ -471,10 -453,11 +472,10 @@@ static void write_pack_file(void
        struct sha1file *f;
        off_t offset, offset_one, last_obj_offset = 0;
        struct pack_header hdr;
 -      int do_progress = progress >> pack_to_stdout;
        uint32_t nr_remaining = nr_result;
        time_t last_mtime = 0;
  
 -      if (do_progress)
 +      if (progress > pack_to_stdout)
                progress_state = start_progress("Writing objects", nr_result);
        written_list = xmalloc(nr_objects * sizeof(*written_list));
  
@@@ -1040,7 -1023,7 +1041,7 @@@ static void check_object(struct object_
                        unuse_pack(&w_curs);
                        return;
                case OBJ_REF_DELTA:
 -                      if (!no_reuse_delta && !entry->preferred_base)
 +                      if (reuse_delta && !entry->preferred_base)
                                base_ref = use_pack(p, &w_curs,
                                                entry->in_pack_offset + used, NULL);
                        entry->in_pack_header_size = used + 20;
                                die("delta base offset out of bound for %s",
                                    sha1_to_hex(entry->idx.sha1));
                        ofs = entry->in_pack_offset - ofs;
 -                      if (!no_reuse_delta && !entry->preferred_base) {
 +                      if (reuse_delta && !entry->preferred_base) {
                                struct revindex_entry *revidx;
                                revidx = find_pack_revindex(p, ofs);
                                base_ref = nth_packed_object_sha1(p, revidx->nr);
@@@ -1251,7 -1234,7 +1252,7 @@@ static int try_delta(struct unpacked *t
         * We do not bother to try a delta that we discarded
         * on an earlier try, but only when reusing delta data.
         */
 -      if (!no_reuse_delta && trg_entry->in_pack &&
 +      if (reuse_delta && trg_entry->in_pack &&
            trg_entry->in_pack == src_entry->in_pack &&
            trg_entry->in_pack_type != OBJ_REF_DELTA &&
            trg_entry->in_pack_type != OBJ_OFS_DELTA)
@@@ -1459,34 -1442,11 +1460,34 @@@ static void find_deltas(struct object_e
                                best_base = other_idx;
                }
  
 +              /*
 +               * If we decided to cache the delta data, then it is best
 +               * to compress it right away.  First because we have to do
 +               * it anyway, and doing it here while we're threaded will
 +               * save a lot of time in the non threaded write phase,
 +               * as well as allow for caching more deltas within
 +               * the same cache size limit.
 +               * ...
 +               * But only if not writing to stdout, since in that case
 +               * the network is most likely throttling writes anyway,
 +               * and therefore it is best to go to the write phase ASAP
 +               * instead, as we can afford spending more time compressing
 +               * between writes at that moment.
 +               */
 +              if (entry->delta_data && !pack_to_stdout) {
 +                      entry->z_delta_size = do_compress(&entry->delta_data,
 +                                                        entry->delta_size);
 +                      cache_lock();
 +                      delta_cache_size -= entry->delta_size;
 +                      delta_cache_size += entry->z_delta_size;
 +                      cache_unlock();
 +              }
 +
                /* if we made n a delta, and if n is already at max
                 * depth, leaving it in the window is pointless.  we
                 * should evict it first.
                 */
 -              if (entry->delta && depth <= n->depth)
 +              if (entry->delta && max_depth <= n->depth)
                        continue;
  
                /*
@@@ -1729,7 -1689,7 +1730,7 @@@ static void prepare_pack(int window, in
  
                if (entry->delta)
                        /* This happens if we decided to reuse existing
 -                       * delta from a pack.  "!no_reuse_delta &&" is implied.
 +                       * delta from a pack.  "reuse_delta &&" is implied.
                         */
                        continue;
  
@@@ -1946,6 -1906,32 +1947,32 @@@ static void add_objects_in_unpacked_pac
        free(in_pack.array);
  }
  
+ static void loosen_unused_packed_objects(struct rev_info *revs)
+ {
+       struct packed_git *p;
+       uint32_t i;
+       const unsigned char *sha1;
+       for (p = packed_git; p; p = p->next) {
+               for (i = 0; i < revs->num_ignore_packed; i++) {
+                       if (matches_pack_name(p, revs->ignore_packed[i]))
+                               break;
+               }
+               if (revs->num_ignore_packed <= i)
+                       continue;
+               if (open_pack_index(p))
+                       die("cannot open pack index");
+               for (i = 0; i < p->num_objects; i++) {
+                       sha1 = nth_packed_object_sha1(p, i);
+                       if (!locate_object_entry(sha1))
+                               if (force_object_loose(sha1, p->mtime))
+                                       die("unable to force loose object");
+               }
+       }
+ }
  static void get_object_list(int ac, const char **av)
  {
        struct rev_info revs;
  
        if (keep_unreachable)
                add_objects_in_unpacked_packs(&revs);
+       if (unpack_unreachable)
+               loosen_unused_packed_objects(&revs);
  }
  
  static int adjust_perm(const char *path, mode_t mode)
@@@ -2091,11 -2079,11 +2120,11 @@@ int cmd_pack_objects(int argc, const ch
                        continue;
                }
                if (!strcmp("--no-reuse-delta", arg)) {
 -                      no_reuse_delta = 1;
 +                      reuse_delta = 0;
                        continue;
                }
                if (!strcmp("--no-reuse-object", arg)) {
 -                      no_reuse_object = no_reuse_delta = 1;
 +                      reuse_object = reuse_delta = 0;
                        continue;
                }
                if (!strcmp("--delta-base-offset", arg)) {
                        keep_unreachable = 1;
                        continue;
                }
+               if (!strcmp("--unpack-unreachable", arg)) {
+                       unpack_unreachable = 1;
+                       continue;
+               }
                if (!strcmp("--include-tag", arg)) {
                        include_tag = 1;
                        continue;
        if (!pack_to_stdout && thin)
                die("--thin cannot be used to build an indexable pack.");
  
+       if (keep_unreachable && unpack_unreachable)
+               die("--keep-unreachable and --unpack-unreachable are incompatible.");
  #ifdef THREADED_DELTA_SEARCH
        if (!delta_search_threads)      /* --threads=0 means autodetect */
                delta_search_threads = online_cpus();
diff --combined cache.h
index 0f89f1569a6b70766c2f2e04fcc6a5992df5db01,dcc7e988255174085e14f94393cd07c793929695..8db19cc253dda9b63401f7b55ffbc0d333e216a8
+++ b/cache.h
@@@ -133,7 -133,6 +133,7 @@@ struct cache_entry 
  #define CE_UPDATE    (0x10000)
  #define CE_REMOVE    (0x20000)
  #define CE_UPTODATE  (0x40000)
 +#define CE_ADDED     (0x80000)
  
  #define CE_HASHED    (0x100000)
  #define CE_UNHASHED  (0x200000)
@@@ -154,6 -153,20 +154,6 @@@ static inline void copy_cache_entry(str
        dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state;
  }
  
 -/*
 - * We don't actually *remove* it, we can just mark it invalid so that
 - * we won't find it in lookups.
 - *
 - * Not only would we have to search the lists (simple enough), but
 - * we'd also have to rehash other hash buckets in case this makes the
 - * hash bucket empty (common). So it's much better to just mark
 - * it.
 - */
 -static inline void remove_index_entry(struct cache_entry *ce)
 -{
 -      ce->ce_flags |= CE_UNHASHED;
 -}
 -
  static inline unsigned create_ce_flags(size_t len, unsigned stage)
  {
        if (len >= CE_NAMEMASK)
@@@ -228,23 -241,6 +228,23 @@@ struct index_state 
  
  extern struct index_state the_index;
  
 +/* Name hashing */
 +extern void add_name_hash(struct index_state *istate, struct cache_entry *ce);
 +/*
 + * We don't actually *remove* it, we can just mark it invalid so that
 + * we won't find it in lookups.
 + *
 + * Not only would we have to search the lists (simple enough), but
 + * we'd also have to rehash other hash buckets in case this makes the
 + * hash bucket empty (common). So it's much better to just mark
 + * it.
 + */
 +static inline void remove_name_hash(struct cache_entry *ce)
 +{
 +      ce->ce_flags |= CE_UNHASHED;
 +}
 +
 +
  #ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
  #define active_cache (the_index.cache)
  #define active_nr (the_index.cache_nr)
  #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))
  #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))
  #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))
 +#define add_to_cache(path, st, verbose) add_to_index(&the_index, (path), (st), (verbose))
  #define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))
  #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)
  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
 -#define cache_name_exists(name, namelen) index_name_exists(&the_index, (name), (namelen))
 +#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
  #endif
  
  enum object_type {
@@@ -356,7 -351,7 +356,7 @@@ extern int write_index(const struct ind
  extern int discard_index(struct index_state *);
  extern int unmerged_index(const struct index_state *);
  extern int verify_path(const char *path);
 -extern int index_name_exists(struct index_state *istate, const char *name, int namelen);
 +extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase);
  extern int index_name_pos(const struct index_state *, const char *name, int namelen);
  #define ADD_CACHE_OK_TO_ADD 1         /* Ok to add */
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
@@@ -366,7 -361,6 +366,7 @@@ extern int add_index_entry(struct index
  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
  extern int remove_index_entry_at(struct index_state *, int pos);
  extern int remove_file_from_index(struct index_state *, const char *path);
 +extern int add_to_index(struct index_state *, const char *path, struct stat *, int verbose);
  extern int add_file_to_index(struct index_state *, const char *path, int verbose);
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
@@@ -411,7 -405,6 +411,7 @@@ extern int delete_ref(const char *, con
  extern int trust_executable_bit;
  extern int quote_path_fully;
  extern int has_symlinks;
 +extern int ignore_case;
  extern int assume_unchanged;
  extern int prefer_symlink_refs;
  extern int log_all_ref_updates;
@@@ -441,15 -434,7 +441,15 @@@ enum branch_track 
        BRANCH_TRACK_EXPLICIT,
  };
  
 +enum rebase_setup_type {
 +      AUTOREBASE_NEVER = 0,
 +      AUTOREBASE_LOCAL,
 +      AUTOREBASE_REMOTE,
 +      AUTOREBASE_ALWAYS,
 +};
 +
  extern enum branch_track git_branch_track;
 +extern enum rebase_setup_type autorebase;
  
  #define GIT_REPO_VERSION 0
  extern int repository_format_version;
@@@ -521,6 -506,7 +521,7 @@@ extern void * read_sha1_file(const unsi
  extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1);
  extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
  extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
+ extern int force_object_loose(const unsigned char *sha1, time_t mtime);
  
  extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
  
@@@ -606,7 -592,7 +607,7 @@@ struct checkout 
  };
  
  extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 -extern int has_symlink_leading_path(const char *name, char *last_symlink);
 +extern int has_symlink_leading_path(int len, const char *name);
  
  extern struct alternate_object_database {
        struct alternate_object_database *next;
@@@ -735,7 -721,6 +736,7 @@@ extern int config_error_nonbool(const c
  #define MAX_GITNAME (1000)
  extern char git_default_email[MAX_GITNAME];
  extern char git_default_name[MAX_GITNAME];
 +extern int user_ident_explicitly_given;
  
  extern const char *git_commit_encoding;
  extern const char *git_log_output_encoding;
@@@ -782,13 -767,7 +783,13 @@@ extern int convert_to_git(const char *p
  extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);
  
  /* add */
 -void add_files_to_cache(int verbose, const char *prefix, const char **pathspec);
 +#define ADD_FILES_VERBOSE     01
 +#define ADD_FILES_IGNORE_ERRORS       02
 +/*
 + * return 0 if success, 1 - if addition of a file failed and
 + * ADD_FILES_IGNORE_ERRORS was specified in flags
 + */
 +int add_files_to_cache(const char *prefix, const char **pathspec, int flags);
  
  /* diff.c */
  extern int diff_auto_refresh_index;
diff --combined git-repack.sh
index 501519ab6897c2463c054e3f7310efc6721c432f,607f217b78997605b0cca7a9df8c9876022c41c4..10f735cff561c6606f5c2bd3f9feec1d6f6ae52e
@@@ -8,10 -8,9 +8,10 @@@ OPTIONS_SPEC="
  git-repack [options]
  --
  a               pack everything in a single pack
- A               same as -a, and keep unreachable objects too
+ A               same as -a, and turn unreachable objects loose
  d               remove redundant packs, and run git-prune-packed
  f               pass --no-reuse-delta to git-pack-objects
 +n               do not run git-update-server-info
  q,quiet         be quiet
  l               pass --local to git-pack-objects
   Packing constraints
@@@ -23,7 -22,7 +23,7 @@@ max-pack-size=  maximum size of each pa
  SUBDIRECTORY_OK='Yes'
  . git-sh-setup
  
- no_update_info= all_into_one= remove_redundant= keep_unreachable=
+ no_update_info= all_into_one= remove_redundant= unpack_unreachable=
  local= quiet= no_reuse= extra=
  while test $# != 0
  do
@@@ -31,7 -30,7 +31,7 @@@
        -n)     no_update_info=t ;;
        -a)     all_into_one=t ;;
        -A)     all_into_one=t
-               keep_unreachable=--keep-unreachable ;;
+               unpack_unreachable=--unpack-unreachable ;;
        -d)     remove_redundant=t ;;
        -q)     quiet=-q ;;
        -f)     no_reuse=--no-reuse-object ;;
@@@ -79,9 -78,9 +79,9 @@@ case ",$all_into_one," i
        if test -z "$args"
        then
                args='--unpacked --incremental'
-       elif test -n "$keep_unreachable"
+       elif test -n "$unpack_unreachable"
        then
-               args="$args $keep_unreachable"
+               args="$args $unpack_unreachable"
        fi
        ;;
  esac