Merge branch 'dh/pack'
authorJunio C Hamano <junkio@cox.net>
Sun, 20 May 2007 09:19:19 +0000 (02:19 -0700)
committerJunio C Hamano <junkio@cox.net>
Sun, 20 May 2007 09:19:19 +0000 (02:19 -0700)
* dh/pack:
Custom compression levels for objects and packs

1  2 
Documentation/config.txt
builtin-pack-objects.c
cache.h
config.c
environment.c
diff --combined Documentation/config.txt
index b8d48d1013c46fd46d0da13f80552971a5f58644,382a31bb4f87d416dd0a176d41145f1a32746cf6..ee1c35e8eb952967980884d521d12a76622f38f4
@@@ -204,11 -204,30 +204,17 @@@ core.warnAmbiguousRefs:
        and might match multiple refs in the .git/refs/ tree. True by default.
  
  core.compression::
+       An integer -1..9, indicating a default compression level.
+       -1 is the zlib default. 0 means no compression,
+       and 1..9 are various speed/size tradeoffs, 9 being slowest.
+ core.loosecompression::
        An integer -1..9, indicating the compression level for objects that
-       are not in a pack file. -1 is the zlib and git default. 0 means no
+       are not in a pack file. -1 is the zlib default. 0 means no
        compression, and 1..9 are various speed/size tradeoffs, 9 being
-       slowest.
+       slowest.  If not set,  defaults to core.compression.  If that is
+       not set,  defaults to 0 (best speed).
  
 -core.legacyheaders::
 -      A boolean which
 -      changes the format of loose objects so that they are more
 -      efficient to pack and to send out of the repository over git
 -      native protocol, since v1.4.2.  However, loose objects
 -      written in the new format cannot be read by git older than
 -      that version; people fetching from your repository using
 -      older versions of git over dumb transports (e.g. http)
 -      will also be affected.
 -+
 -To let git use the new loose object format, you have to
 -set core.legacyheaders to false.
 -
  core.packedGitWindowSize::
        Number of bytes of a pack file to map into memory in a
        single mapping operation.  Larger window sizes may allow
@@@ -371,11 -390,6 +377,11 @@@ format.suffix:
        `.patch`. Use this variable to change that suffix (make sure to
        include the dot if you want it).
  
 +gc.aggressiveWindow::
 +      The window size parameter used in the delta compression
 +      algorithm used by 'git gc --aggressive'.  This defaults
 +      to 10.
 +
  gc.packrefs::
        `git gc` does not run `git pack-refs` in a bare repository by
        default so that older dumb-transport clients can still fetch
@@@ -542,6 -556,13 +548,13 @@@ pack.depth:
        The maximum delta depth used by gitlink:git-pack-objects[1] when no
        maximum depth is given on the command line. Defaults to 50.
  
+ pack.compression::
+       An integer -1..9, indicating the compression level for objects
+       in a pack file. -1 is the zlib default. 0 means no
+       compression, and 1..9 are various speed/size tradeoffs, 9 being
+       slowest.  If not set,  defaults to core.compression.  If that is
+       not set,  defaults to -1.
  pull.octopus::
        The default merge strategy to use when pulling multiple branches
        at once.
diff --combined builtin-pack-objects.c
index 5fa98132fe665bf511be77b926d8bc976ed64613,5c468aa50aa0a591676e0c83ca2de1790e937c87..d165f10288558d55fee5e8a7ae88ac9fccfbc3d7
@@@ -68,6 -68,8 +68,8 @@@ static int depth = 50
  static int pack_to_stdout;
  static int num_preferred_base;
  static struct progress progress_state;
+ static int pack_compression_level = Z_DEFAULT_COMPRESSION;
+ static int pack_compression_seen;
  
  /*
   * The object names in objects array are hashed with this hashtable,
@@@ -346,6 -348,56 +348,6 @@@ static void copy_pack_data(struct sha1f
        }
  }
  
 -static int check_loose_inflate(unsigned char *data, unsigned long len, unsigned long expect)
 -{
 -      z_stream stream;
 -      unsigned char fakebuf[4096];
 -      int st;
 -
 -      memset(&stream, 0, sizeof(stream));
 -      stream.next_in = data;
 -      stream.avail_in = len;
 -      stream.next_out = fakebuf;
 -      stream.avail_out = sizeof(fakebuf);
 -      inflateInit(&stream);
 -
 -      while (1) {
 -              st = inflate(&stream, Z_FINISH);
 -              if (st == Z_STREAM_END || st == Z_OK) {
 -                      st = (stream.total_out == expect &&
 -                            stream.total_in == len) ? 0 : -1;
 -                      break;
 -              }
 -              if (st != Z_BUF_ERROR) {
 -                      st = -1;
 -                      break;
 -              }
 -              stream.next_out = fakebuf;
 -              stream.avail_out = sizeof(fakebuf);
 -      }
 -      inflateEnd(&stream);
 -      return st;
 -}
 -
 -static int revalidate_loose_object(struct object_entry *entry,
 -                                 unsigned char *map,
 -                                 unsigned long mapsize)
 -{
 -      /* we already know this is a loose object with new type header. */
 -      enum object_type type;
 -      unsigned long size, used;
 -
 -      if (pack_to_stdout)
 -              return 0;
 -
 -      used = unpack_object_header_gently(map, mapsize, &type, &size);
 -      if (!used)
 -              return -1;
 -      map += used;
 -      mapsize -= used;
 -      return check_loose_inflate(map, mapsize, size);
 -}
 -
  static unsigned long write_object(struct sha1file *f,
                                  struct object_entry *entry)
  {
                                 * and we do not need to deltify it.
                                 */
  
 -      /* differing core & pack compression when loose object -> must recompress */
 -      if (!entry->in_pack && pack_compression_level != zlib_compression_level)
 -              to_reuse = 0;
 -      else if (!no_reuse_object && !entry->in_pack && !entry->delta) {
 -              unsigned char *map;
 -              unsigned long mapsize;
 -              map = map_sha1_file(entry->sha1, &mapsize);
 -              if (map && !legacy_loose_object(map)) {
 -                      /* We can copy straight into the pack file */
 -                      if (revalidate_loose_object(entry, map, mapsize))
 -                              die("corrupt loose object %s",
 -                                  sha1_to_hex(entry->sha1));
 -                      sha1write(f, map, mapsize);
 -                      munmap(map, mapsize);
 -                      written++;
 -                      reused++;
 -                      return mapsize;
 -              }
 -              if (map)
 -                      munmap(map, mapsize);
 -      }
 -
        if (!to_reuse) {
                buf = read_sha1_file(entry->sha1, &type, &size);
                if (!buf)
                        sha1write(f, entry->delta->sha1, 20);
                        hdrlen += 20;
                }
-               datalen = sha1write_compressed(f, buf, size);
+               datalen = sha1write_compressed(f, buf, size, pack_compression_level);
                free(buf);
        }
        else {
@@@ -1427,6 -1501,16 +1429,16 @@@ static int git_pack_config(const char *
                depth = git_config_int(k, v);
                return 0;
        }
+       if (!strcmp(k, "pack.compression")) {
+               int level = git_config_int(k, v);
+               if (level == -1)
+                       level = Z_DEFAULT_COMPRESSION;
+               else if (level < 0 || level > Z_BEST_COMPRESSION)
+                       die("bad pack compression level %d", level);
+               pack_compression_level = level;
+               pack_compression_seen = 1;
+               return 0;
+       }
        return git_default_config(k, v);
  }
  
@@@ -1538,6 -1622,8 +1550,8 @@@ int cmd_pack_objects(int argc, const ch
        rp_ac = 2;
  
        git_config(git_pack_config);
+       if (!pack_compression_seen && core_compression_seen)
+               pack_compression_level = core_compression_level;
  
        progress = isatty(2);
        for (i = 1; i < argc; i++) {
                        incremental = 1;
                        continue;
                }
+               if (!prefixcmp(arg, "--compression=")) {
+                       char *end;
+                       int level = strtoul(arg+14, &end, 0);
+                       if (!arg[14] || *end)
+                               usage(pack_usage);
+                       if (level == -1)
+                               level = Z_DEFAULT_COMPRESSION;
+                       else if (level < 0 || level > Z_BEST_COMPRESSION)
+                               die("bad pack compression level %d", level);
+                       pack_compression_level = level;
+                       continue;
+               }
                if (!prefixcmp(arg, "--window=")) {
                        char *end;
                        window = strtoul(arg+9, &end, 0);
diff --combined cache.h
index f98ccd0e20e6a4d0970db125814135df10e26e73,2b3f359b21df82ac3353a5e1b61cf01baffa2d3a..65b4685c1fedf4fd7da1b5f4ab3c4ba9645331e3
+++ b/cache.h
@@@ -273,6 -273,7 +273,6 @@@ extern void rollback_lock_file(struct l
  extern int delete_ref(const char *, const unsigned char *sha1);
  
  /* Environment bits from configuration mechanism */
 -extern int use_legacy_headers;
  extern int trust_executable_bit;
  extern int has_symlinks;
  extern int assume_unchanged;
@@@ -282,6 -283,8 +282,8 @@@ extern int warn_ambiguous_refs
  extern int shared_repository;
  extern const char *apply_default_whitespace;
  extern int zlib_compression_level;
+ extern int core_compression_level;
+ extern int core_compression_seen;
  extern size_t packed_git_window_size;
  extern size_t packed_git_limit;
  extern size_t delta_base_cache_limit;
@@@ -353,6 -356,7 +355,6 @@@ extern int move_temp_to_file(const cha
  extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
  extern int has_sha1_file(const unsigned char *sha1);
  extern void *map_sha1_file(const unsigned char *sha1, unsigned long *);
 -extern int legacy_loose_object(unsigned char *);
  
  extern int has_pack_file(const unsigned char *sha1);
  extern int has_pack_index(const unsigned char *sha1);
@@@ -408,7 -412,6 +410,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 struct alternate_object_database {
        struct alternate_object_database *next;
@@@ -461,8 -464,7 +463,8 @@@ struct ref 
  #define REF_HEADS     (1u << 1)
  #define REF_TAGS      (1u << 2)
  
 -extern pid_t git_connect(int fd[2], char *url, const char *prog);
 +#define CONNECT_VERBOSE       (1u << 0)
 +extern pid_t git_connect(int fd[2], char *url, const char *prog, int flags);
  extern int finish_connect(pid_t pid);
  extern int path_match(const char *path, int nr, char **match);
  extern int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
@@@ -547,7 -549,6 +549,7 @@@ extern void trace_argv_printf(const cha
  /* convert.c */
  extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep);
  extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep);
 +extern void *convert_sha1_file(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size);
  
  /* match-trees.c */
  void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int);
diff --combined config.c
index 521ebef3819bff1705d652684780434d6ab3fca7,5627ed6a7946ffd9c8dac419d32c9e77dc000587..0614c2b29fa93b66065ec6bc20712d38193aec89
+++ b/config.c
@@@ -12,6 -12,8 +12,8 @@@
  static FILE *config_file;
  static const char *config_file_name;
  static int config_linenr;
+ static int zlib_compression_seen;
  static int get_next_char(void)
  {
        int c;
@@@ -299,13 -301,32 +301,27 @@@ int git_default_config(const char *var
                return 0;
        }
  
-       if (!strcmp(var, "core.compression")) {
 -      if (!strcmp(var, "core.legacyheaders")) {
 -              use_legacy_headers = git_config_bool(var, value);
 -              return 0;
 -      }
 -
+       if (!strcmp(var, "core.loosecompression")) {
                int level = git_config_int(var, value);
                if (level == -1)
                        level = Z_DEFAULT_COMPRESSION;
                else if (level < 0 || level > Z_BEST_COMPRESSION)
                        die("bad zlib compression level %d", level);
                zlib_compression_level = level;
+               zlib_compression_seen = 1;
+               return 0;
+       }
+       if (!strcmp(var, "core.compression")) {
+               int level = git_config_int(var, value);
+               if (level == -1)
+                       level = Z_DEFAULT_COMPRESSION;
+               else if (level < 0 || level > Z_BEST_COMPRESSION)
+                       die("bad zlib compression level %d", level);
+               core_compression_level = level;
+               core_compression_seen = 1;
+               if (!zlib_compression_seen)
+                       zlib_compression_level = level;
                return 0;
        }
  
@@@ -446,9 -467,6 +462,9 @@@ static int matches(const char* key, con
  
  static int store_aux(const char* key, const char* value)
  {
 +      const char *ep;
 +      size_t section_len;
 +
        switch (store.state) {
        case KEY_SEEN:
                if (matches(key, value)) {
                }
                break;
        case SECTION_SEEN:
 -              if (strncmp(key, store.key, store.baselen+1)) {
 +              /*
 +               * What we are looking for is in store.key (both
 +               * section and var), and its section part is baselen
 +               * long.  We found key (again, both section and var).
 +               * We would want to know if this key is in the same
 +               * section as what we are looking for.  We already
 +               * know we are in the same section as what should
 +               * hold store.key.
 +               */
 +              ep = strrchr(key, '.');
 +              section_len = ep - key;
 +
 +              if ((section_len != store.baselen) ||
 +                  memcmp(key, store.key, section_len+1)) {
                        store.state = SECTION_END_SEEN;
                        break;
 -              } else
 -                      /* do not increment matches: this is no match */
 -                      store.offset[store.seen] = ftell(config_file);
 +              }
 +
 +              /*
 +               * Do not increment matches: this is no match, but we
 +               * just made sure we are in the desired section.
 +               */
 +              store.offset[store.seen] = ftell(config_file);
                /* fallthru */
        case SECTION_END_SEEN:
        case START:
diff --combined environment.c
index 54e3abae98db6606702b597bb3bf47c27d027232,b7aeb1a4936c095dccd2c1f4ac1f91dc2ef139e4..9d3e5eb72fea51eb30a201151aeffe1dfbb549d3
@@@ -11,6 -11,7 +11,6 @@@
  
  char git_default_email[MAX_GITNAME];
  char git_default_name[MAX_GITNAME];
 -int use_legacy_headers = 1;
  int trust_executable_bit = 1;
  int has_symlinks = 1;
  int assume_unchanged;
@@@ -23,7 -24,9 +23,9 @@@ const char *git_commit_encoding
  const char *git_log_output_encoding;
  int shared_repository = PERM_UMASK;
  const char *apply_default_whitespace;
- int zlib_compression_level = Z_DEFAULT_COMPRESSION;
+ int zlib_compression_level = Z_BEST_SPEED;
+ int core_compression_level;
+ int core_compression_seen;
  size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
  size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
  size_t delta_base_cache_limit = 16 * 1024 * 1024;