Code

Merge branch 'jc/test-clone' into jc/clone
[git.git] / index-pack.c
index 866a0540560c085cd9feadb277b5b5e1e7891310..6d6c92bf14803923f4c98678ae682aef4d41d3ab 100644 (file)
@@ -10,7 +10,7 @@
 #include <signal.h>
 
 static const char index_pack_usage[] =
-"git-index-pack [-v] [-o <index-file>] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
+"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
 
 struct object_entry
 {
@@ -90,13 +90,13 @@ static SHA_CTX input_ctx;
 static int input_fd, output_fd, mmap_fd;
 
 /* Discard current buffer used content. */
-static void flush()
+static void flush(void)
 {
        if (input_offset) {
                if (output_fd >= 0)
                        write_or_die(output_fd, input_buffer, input_offset);
                SHA1_Update(&input_ctx, input_buffer, input_offset);
-               memcpy(input_buffer, input_buffer + input_offset, input_len);
+               memmove(input_buffer, input_buffer + input_offset, input_len);
                input_offset = 0;
        }
 }
@@ -754,8 +754,10 @@ static const char *write_index_file(const char *index_name, unsigned char *sha1)
 
 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,
                  unsigned char *sha1)
 {
+       char *report = "pack";
        char name[PATH_MAX];
        int err;
 
@@ -766,17 +768,26 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                if (err)
                        die("error while closing pack file: %s", strerror(errno));
                chmod(curr_pack_name, 0444);
+       }
 
-               /*
-                * Let's just mimic git-unpack-objects here and write
-                * the last part of the buffer to stdout.
-                */
-               while (input_len) {
-                       err = xwrite(1, input_buffer + input_offset, input_len);
-                       if (err <= 0)
-                               break;
-                       input_len -= err;
-                       input_offset += err;
+       if (keep_msg) {
+               int keep_fd, keep_msg_len = strlen(keep_msg);
+               if (!keep_name) {
+                       snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
+                                get_object_directory(), sha1_to_hex(sha1));
+                       keep_name = name;
+               }
+               keep_fd = open(keep_name, O_RDWR|O_CREAT|O_EXCL, 0600);
+               if (keep_fd < 0) {
+                       if (errno != EEXIST)
+                               die("cannot write keep file");
+               } else {
+                       if (keep_msg_len > 0) {
+                               write_or_die(keep_fd, keep_msg, keep_msg_len);
+                               write_or_die(keep_fd, "\n", 1);
+                       }
+                       close(keep_fd);
+                       report = "keep";
                }
        }
 
@@ -800,6 +811,27 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                if (move_temp_to_file(curr_index_name, final_index_name))
                        die("cannot store index file");
        }
+
+       if (!from_stdin) {
+               printf("%s\n", sha1_to_hex(sha1));
+       } else {
+               char buf[48];
+               int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
+                                  report, sha1_to_hex(sha1));
+               xwrite(1, buf, len);
+
+               /*
+                * Let's just mimic git-unpack-objects here and write
+                * the last part of the input buffer to stdout.
+                */
+               while (input_len) {
+                       err = xwrite(1, input_buffer + input_offset, input_len);
+                       if (err <= 0)
+                               break;
+                       input_len -= err;
+                       input_offset += err;
+               }
+       }
 }
 
 int main(int argc, char **argv)
@@ -807,7 +839,8 @@ int main(int argc, char **argv)
        int i, fix_thin_pack = 0;
        const char *curr_pack, *pack_name = NULL;
        const char *curr_index, *index_name = NULL;
-       char *index_name_buf = NULL;
+       const char *keep_name = NULL, *keep_msg = NULL;
+       char *index_name_buf = NULL, *keep_name_buf = NULL;
        unsigned char sha1[20];
 
        for (i = 1; i < argc; i++) {
@@ -818,6 +851,23 @@ int main(int argc, char **argv)
                                from_stdin = 1;
                        } else if (!strcmp(arg, "--fix-thin")) {
                                fix_thin_pack = 1;
+                       } else if (!strcmp(arg, "--keep")) {
+                               keep_msg = "";
+                       } else if (!strncmp(arg, "--keep=", 7)) {
+                               keep_msg = arg + 7;
+                       } else if (!strncmp(arg, "--pack_header=", 14)) {
+                               struct pack_header *hdr;
+                               char *c;
+
+                               hdr = (struct pack_header *)input_buffer;
+                               hdr->hdr_signature = htonl(PACK_SIGNATURE);
+                               hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
+                               if (*c != ',')
+                                       die("bad %s", arg);
+                               hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
+                               if (*c)
+                                       die("bad %s", arg);
+                               input_len = sizeof(*hdr);
                        } else if (!strcmp(arg, "-v")) {
                                verbose = 1;
                        } else if (!strcmp(arg, "-o")) {
@@ -848,6 +898,16 @@ int main(int argc, char **argv)
                strcpy(index_name_buf + len - 5, ".idx");
                index_name = index_name_buf;
        }
+       if (keep_msg && !keep_name && pack_name) {
+               int len = strlen(pack_name);
+               if (!has_extension(pack_name, ".pack"))
+                       die("packfile name '%s' does not end with '.pack'",
+                           pack_name);
+               keep_name_buf = xmalloc(len);
+               memcpy(keep_name_buf, pack_name, len - 5);
+               strcpy(keep_name_buf + len - 5, ".keep");
+               keep_name = keep_name_buf;
+       }
 
        curr_pack = open_pack_file(pack_name);
        parse_pack_header();
@@ -880,12 +940,13 @@ int main(int argc, char **argv)
        }
        free(deltas);
        curr_index = write_index_file(index_name, sha1);
-       final(pack_name, curr_pack, index_name, curr_index, sha1);
+       final(pack_name, curr_pack,
+               index_name, curr_index,
+               keep_name, keep_msg,
+               sha1);
        free(objects);
        free(index_name_buf);
-
-       if (!from_stdin)
-               printf("%s\n", sha1_to_hex(sha1));
+       free(keep_name_buf);
 
        return 0;
 }