Merge branch 'ag/blame-encoding'
[gitweb.git] / index-pack.c
index a6e91fe3ba47e3b0837648180bb7d47acd3e7dc7..6f89bb9ac7f281434a9759956d8da23e6bc071db 100644 (file)
@@ -67,7 +67,7 @@ static struct progress *progress;
 static unsigned char input_buffer[4096];
 static unsigned int input_offset, input_len;
 static off_t consumed_bytes;
-static SHA_CTX input_ctx;
+static git_SHA_CTX input_ctx;
 static uint32_t input_crc32;
 static int input_fd, output_fd, pack_fd;
 
@@ -119,7 +119,7 @@ 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);
+               git_SHA1_Update(&input_ctx, input_buffer, input_offset);
                memmove(input_buffer, input_buffer + input_offset, input_len);
                input_offset = 0;
        }
@@ -172,7 +172,7 @@ static char *open_pack_file(char *pack_name)
                if (!pack_name) {
                        static char tmpfile[PATH_MAX];
                        snprintf(tmpfile, sizeof(tmpfile),
-                                "%s/tmp_pack_XXXXXX", get_object_directory());
+                                "%s/pack/tmp_pack_XXXXXX", get_object_directory());
                        output_fd = xmkstemp(tmpfile);
                        pack_name = xstrdup(tmpfile);
                } else
@@ -188,7 +188,7 @@ static char *open_pack_file(char *pack_name)
                output_fd = -1;
                pack_fd = input_fd;
        }
-       SHA1_Init(&input_ctx);
+       git_SHA1_Init(&input_ctx);
        return pack_name;
 }
 
@@ -365,8 +365,11 @@ static void *get_data_from_pack(struct object_entry *obj)
        data = src;
        do {
                ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
-               if (n <= 0)
+               if (n < 0)
                        die("cannot pread pack file: %s", strerror(errno));
+               if (!n)
+                       die("premature end of pack file, %lu bytes missing",
+                           len - rdy);
                rdy += n;
        } while (rdy < len);
        data = xmalloc(obj->size);
@@ -588,7 +591,7 @@ static void parse_pack_objects(unsigned char *sha1)
 
        /* Check pack integrity */
        flush();
-       SHA1_Final(sha1, &input_ctx);
+       git_SHA1_Final(sha1, &input_ctx);
        if (hashcmp(fill(20), sha1))
                die("pack is corrupted (SHA1 mismatch)");
        use(20);
@@ -704,6 +707,7 @@ static struct object_entry *append_obj_to_pack(struct sha1file *f,
        obj[1].idx.offset = obj[0].idx.offset + n;
        obj[1].idx.offset += write_compressed(f, buf, size);
        obj[0].idx.crc32 = crc32_end(f);
+       sha1flush(f);
        hashcpy(obj->idx.sha1, sha1);
        return obj;
 }
@@ -786,7 +790,6 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                err = close(output_fd);
                if (err)
                        die("error while closing pack file: %s", strerror(errno));
-               chmod(curr_pack_name, 0444);
        }
 
        if (keep_msg) {
@@ -820,8 +823,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
                if (move_temp_to_file(curr_pack_name, final_pack_name))
                        die("cannot store pack file");
        }
+       if (from_stdin)
+               chmod(final_pack_name, 0444);
 
-       chmod(curr_index_name, 0444);
        if (final_index_name != curr_index_name) {
                if (!final_index_name) {
                        snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
@@ -831,6 +835,7 @@ 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");
        }
+       chmod(final_index_name, 0444);
 
        if (!from_stdin) {
                printf("%s\n", sha1_to_hex(sha1));
@@ -875,10 +880,26 @@ int main(int argc, char **argv)
        char *index_name_buf = NULL, *keep_name_buf = NULL;
        struct pack_idx_entry **idx_objects;
        unsigned char pack_sha1[20];
-       int nongit = 0;
 
-       setup_git_directory_gently(&nongit);
-       git_config(git_index_pack_config, NULL);
+       /*
+        * We wish to read the repository's config file if any, and
+        * for that it is necessary to call setup_git_directory_gently().
+        * However if the cwd was inside .git/objects/pack/ then we need
+        * to go back there or all the pack name arguments will be wrong.
+        * And in that case we cannot rely on any prefix returned by
+        * setup_git_directory_gently() either.
+        */
+       {
+               char cwd[PATH_MAX+1];
+               int nongit;
+
+               if (!getcwd(cwd, sizeof(cwd)-1))
+                       die("Unable to get current working directory");
+               setup_git_directory_gently(&nongit);
+               git_config(git_index_pack_config, NULL);
+               if (chdir(cwd))
+                       die("Cannot come back to cwd");
+       }
 
        for (i = 1; i < argc; i++) {
                char *arg = argv[i];