Git's object store and packing are optimized for
* Expensive repo to repo bandwidth; and
* Small-ish files
This justifies extensive use of compression.
In a multi-developer *office* with inter-repository
transfers occurring over a 100Mb+ LAN, there is less
reason to compress files and slow down response times.
Response times suffer even more when large files are involved.
However, *off-line* pack compression may still be
desirable to reduce storage space.
Consequently, for such a usage pattern it is useful
to specify different compression levels for loose
objects and packs. This patch implements a config
variable pack.compression in addition to the existing
core.compression, meant to be used for repacking.
It also adds --compression=N to pack-objects,
meant for push/pull/fetch, if different, or if different
on a per-repository basis.
** THIS PATCH IS UNTESTED AND MEANT FOR DISCUSSION. **
git-repack.sh might also need to be modified,
and how to pass --compression=N during push/pull/fetch
has not been investigated.
This applies on top of the git-repack --max-pack-size patchset.
Signed-off-by: Dana L. How <danahow@gmail.com>
---
builtin-pack-objects.c | 56 ++++++++++++++++++++++++++++++++++++------------
1 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 69fec34..b663c15 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -70,6 +70,7 @@ static uint32_t pack_size_limit;
static int pack_to_stdout;
static int num_preferred_base;
static struct progress progress_state;
+static int pack_compression_level, pack_compression_seen;
/*
* The object names in objects array are hashed with this hashtable,
@@ -414,6 +415,16 @@ static unsigned long write_object(struct sha1file *f,
/* 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->offset == (off_t)-1 ? 0 :
+ /* otherwise double-check written to this
+ * pack, like we do below
+ */
+ entry->delta->offset ? 1 : 0;
if (!pack_to_stdout)
crc32_begin(f);
@@ -423,8 +434,7 @@ static unsigned long write_object(struct sha1file *f,
to_reuse = 0; /* can't reuse what we don't have */
else if (obj_type == OBJ_REF_DELTA || obj_type == OBJ_OFS_DELTA)
/* check_object() decided it for us ... */
- to_reuse = !pack_size_limit ||
- (entry->delta->offset && entry->delta->offset != (off_t)-1);
+ to_reuse = usable_delta;
/* ... but pack split may override that */
else if (obj_type != entry->in_pack_type)
to_reuse = 0; /* pack has delta which is unusable */
@@ -435,6 +445,10 @@ static unsigned long write_object(struct sha1file *f,
* 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 (!entry->in_pack && !entry->delta) {
unsigned char *map;
unsigned long mapsize;
@@ -462,16 +476,6 @@ static unsigned long write_object(struct sha1file *f,
z_stream stream;
unsigned long maxsize;
void *out;
- /* 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->offset == (off_t)-1 ? 0 :
- /* otherwise double-check written to this
- * pack, like we do below
- */
- entry->delta->offset ? 1 : 0;
buf = read_sha1_file(entry->sha1, &type, &size);
if (!buf)
die("unable to read %s", sha1_to_hex(entry->sha1));
@@ -493,7 +497,7 @@ static unsigned long write_object(struct sha1file *f,
}
/* compress the data to store and put compressed length in datalen */
memset(&stream, 0, sizeof(stream));
- deflateInit(&stream, zlib_compression_level);
+ deflateInit(&stream, pack_compression_level);
maxsize = deflateBound(&stream, size);
out = xmalloc(maxsize);
/* Compress it */
@@ -606,7 +610,7 @@ static unsigned long write_object(struct sha1file *f,
unuse_pack(&w_curs);
reused++;
}
- if (entry->delta)
+ if (usable_delta)
written_delta++;
written++;
if (!pack_to_stdout)
@@ -1622,6 +1626,16 @@ static int git_pack_config(const char *k, const char *v)
window = 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);
}
@@ -1732,6 +1746,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
rp_ac = 2;
git_config(git_pack_config);
+ if (!pack_compression_seen)
+ pack_compression_level = zlib_compression_level;
progress = isatty(2);
for (i = 1; i < argc; i++) {
@@ -1759,6 +1775,18 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
usage(pack_usage);
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);
--
1.5.2.rc0.787.g0014
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
| David Miller | Slow DOWN, please!!! |
| Greg KH | Re: Linux 2.6.21 |
| Andrew Morton | Re: 2.6.23-rc6-mm1 |
| Bryan Woods | Stardom SATA HSM violation |
git: | |
| Kyle Moffett | Using GIT to store /etc (Or: How to make GIT store all file permission bits) |
| Tony Stubbs | git svn rebase - could not detach HEAD |
| Ken Pratt | pack operation is thrashing my server |
| Karl | Re: Git checkout preserve timestamp? |
| Richard Stallman | Real men don't attack straw men |
| GVG GVG | ssh_exchange_identification: Connection closed by remote host |
| new_guy | Longest Uptime? |
| Steve B | Intel Atom and D945GCLF2 |
| Peter Schuller | Re: When will ZFS become stable? |
| Sam Fourman Jr. | amd64 NVIDIA support in FreeBSD 7 |
| Justin Hibbits | Re: [ANNOUNCEMENT] Wiki for discussing P35/IHC9(R)/SATA issues set up |
| Dan Davis | Atheros AR928x |
| VPN's on NetBSD | 2 hours ago | NetBSD |
| Why does uClinux 2.6.18 bootup block SuperIO UART IRQs that BIOS configured | 3 hours ago | Linux kernel |
| USB statistics | 4 hours ago | Linux kernel |
| Block Sub System query | 9 hours ago | Linux kernel |
| kernel module to intercept socket creation | 10 hours ago | Linux kernel |
| Image size changing during each build | 10 hours ago | Linux kernel |
| Soft lock bug | 15 hours ago | Linux kernel |
| sysctl - dynamic registration problem | 21 hours ago | Linux kernel |
| Question on swap as ramdisk partition | 23 hours ago | Linux kernel |
| serial driver xmit problem | 1 day ago | Linux kernel |
