summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-03-03 12:51:54 -0800
committerJunio C Hamano <gitster@pobox.com>2016-03-03 12:51:54 -0800
commit1ac36d297ef0cf4abe6883366e4504a6db68dfc0 (patch)
tree6b522345023ca8653e602919034ea13f95cafc17
parent851a1fced9141e3845c0321d25ad60443dc8268e (diff)
downloadgit-jc/index-pack-clone-bundle.tar.gz
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/git-index-pack.txt10
-rw-r--r--builtin/index-pack.c57
2 files changed, 62 insertions, 5 deletions
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index 7a4e055520..ade28126ab 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -9,7 +9,7 @@ git-index-pack - Build pack index file for an existing packed archive
SYNOPSIS
--------
[verse]
-'git index-pack' [-v] [-o <index-file>] <pack-file>
+'git index-pack' [-v] [-o <index-file>] [--clone-bundle] <pack-file>
'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
[<pack-file>]
@@ -35,6 +35,14 @@ OPTIONS
fails if the name of packed archive does not end
with .pack).
+--clone-bundle::
+ Write a split bundle file that uses the <pack-file> as its
+ data. The <pack-file> must not contain any broken links, or
+ the bundle file will not be written. The prerequisite list
+ of the resulting bundle will be empty. The reference list
+ of the resulting bundle points at tips of the history in the
+ <pack-file>.
+
--stdin::
When this flag is provided, the pack is read from stdin
instead and a copy is then written to <pack-file>. If
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index a5588a24d1..8fc04b04e7 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -13,7 +13,7 @@
#include "thread-utils.h"
static const char index_pack_usage[] =
-"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
+"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] [--clone-bundle] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
struct object_entry {
struct pack_idx_entry idx;
@@ -1373,9 +1373,40 @@ static void fix_unresolved_deltas(struct sha1file *f)
free(sorted_by_pos);
}
+static void write_bundle_file(const char *filename, unsigned char *sha1,
+ const char *packname)
+{
+ int fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600);
+ struct strbuf buf = STRBUF_INIT;
+ struct stat st;
+ int i;
+
+ if (stat(packname, &st))
+ die(_("cannot stat %s"), packname);
+
+ strbuf_addstr(&buf, "# v3 git bundle\n");
+ strbuf_addf(&buf, "size: %lu\n", (unsigned long) st.st_size);
+ strbuf_addf(&buf, "sha1: %s\n", sha1_to_hex(sha1));
+ strbuf_addf(&buf, "data: %s\n\n", packname);
+
+ for (i = 0; i < nr_objects; i++) {
+ struct object *o = lookup_object(objects[i].idx.sha1);
+ if (!o || (o->flags & FLAG_LINK))
+ continue;
+ strbuf_addf(&buf, "%s refs/objects/%s\n",
+ sha1_to_hex(o->oid.hash),
+ sha1_to_hex(o->oid.hash));
+ }
+ if (write_in_full(fd, buf.buf, buf.len) != buf.len)
+ die(_("cannot write bundle header for %s"), packname);
+ close(fd);
+ strbuf_release(&buf);
+}
+
static void final(const char *final_pack_name, const char *curr_pack_name,
const char *final_index_name, const char *curr_index_name,
const char *keep_name, const char *keep_msg,
+ const char *bundle_name, int foreign_nr,
unsigned char *sha1)
{
const char *report = "pack";
@@ -1457,6 +1488,13 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
input_offset += err;
}
}
+
+ if (bundle_name) {
+ if (foreign_nr)
+ warning(_("not writing bundle for an incomplete pack"));
+ else
+ write_bundle_file(bundle_name, sha1, final_pack_name);
+ }
}
static int git_index_pack_config(const char *k, const char *v, void *cb)
@@ -1612,12 +1650,14 @@ static const char *derive_filename(const char *pack_name, const char *suffix,
int cmd_index_pack(int argc, const char **argv, const char *prefix)
{
- int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
+ int i, fix_thin_pack = 0, verify = 0, stat_only = 0, clone_bundle = 0;
const char *curr_index;
const char *index_name = NULL, *pack_name = NULL;
const char *keep_name = NULL, *keep_msg = NULL;
- struct strbuf index_name_buf = STRBUF_INIT,
- keep_name_buf = STRBUF_INIT;
+ const char *bundle_name = NULL;
+ struct strbuf index_name_buf = STRBUF_INIT;
+ struct strbuf keep_name_buf = STRBUF_INIT;
+ struct strbuf bundle_name_buf = STRBUF_INIT;
struct pack_idx_entry **idx_objects;
struct pack_idx_option opts;
unsigned char pack_sha1[20];
@@ -1661,6 +1701,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
verify = 1;
show_stat = 1;
stat_only = 1;
+ } else if (!strcmp(arg, "--clone-bundle")) {
+ strict = 1;
+ clone_bundle = 1;
+ check_self_contained_and_connected = 1;
} else if (!strcmp(arg, "--keep")) {
keep_msg = "";
} else if (starts_with(arg, "--keep=")) {
@@ -1718,10 +1762,14 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
usage(index_pack_usage);
if (fix_thin_pack && !from_stdin)
die(_("--fix-thin cannot be used without --stdin"));
+ if (clone_bundle && from_stdin)
+ die(_("--clone-bundle cannot be used with --stdin"));
if (!index_name && pack_name)
index_name = derive_filename(pack_name, ".idx", &index_name_buf);
if (keep_msg && !keep_name && pack_name)
keep_name = derive_filename(pack_name, ".keep", &keep_name_buf);
+ if (clone_bundle)
+ bundle_name = derive_filename(pack_name, ".bndl", &bundle_name_buf);
if (verify) {
if (!index_name)
@@ -1768,6 +1816,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
final(pack_name, curr_pack,
index_name, curr_index,
keep_name, keep_msg,
+ bundle_name, foreign_nr,
pack_sha1);
else
close(input_fd);