aboutsummaryrefslogtreecommitdiffstats
path: root/sha1_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'sha1_file.c')
-rw-r--r--sha1_file.c158
1 files changed, 124 insertions, 34 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 8ae6cb6285..831d9e7343 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -24,11 +24,11 @@
#include "bulk-checkin.h"
#include "streaming.h"
#include "dir.h"
-#include "mru.h"
#include "list.h"
#include "mergesort.h"
#include "quote.h"
#include "packfile.h"
+#include "fetch-object.h"
const unsigned char null_sha1[GIT_MAX_RAWSZ];
const struct object_id null_oid;
@@ -39,6 +39,64 @@ const struct object_id empty_blob_oid = {
EMPTY_BLOB_SHA1_BIN_LITERAL
};
+static void git_hash_sha1_init(void *ctx)
+{
+ git_SHA1_Init((git_SHA_CTX *)ctx);
+}
+
+static void git_hash_sha1_update(void *ctx, const void *data, size_t len)
+{
+ git_SHA1_Update((git_SHA_CTX *)ctx, data, len);
+}
+
+static void git_hash_sha1_final(unsigned char *hash, void *ctx)
+{
+ git_SHA1_Final(hash, (git_SHA_CTX *)ctx);
+}
+
+static void git_hash_unknown_init(void *ctx)
+{
+ die("trying to init unknown hash");
+}
+
+static void git_hash_unknown_update(void *ctx, const void *data, size_t len)
+{
+ die("trying to update unknown hash");
+}
+
+static void git_hash_unknown_final(unsigned char *hash, void *ctx)
+{
+ die("trying to finalize unknown hash");
+}
+
+const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
+ {
+ NULL,
+ 0x00000000,
+ 0,
+ 0,
+ 0,
+ git_hash_unknown_init,
+ git_hash_unknown_update,
+ git_hash_unknown_final,
+ NULL,
+ NULL,
+ },
+ {
+ "sha-1",
+ /* "sha1", big-endian */
+ 0x73686131,
+ sizeof(git_SHA_CTX),
+ GIT_SHA1_RAWSZ,
+ GIT_SHA1_HEXSZ,
+ git_hash_sha1_init,
+ git_hash_sha1_update,
+ git_hash_sha1_final,
+ &empty_tree_oid,
+ &empty_blob_oid,
+ },
+};
+
/*
* This is meant to hold a *small* number of objects that you would
* want read_sha1_file() to be able to return, but yet you do not want
@@ -75,14 +133,14 @@ static struct cached_object *find_cached_object(const unsigned char *sha1)
}
-static enum safe_crlf get_safe_crlf(unsigned flags)
+static int get_conv_flags(unsigned flags)
{
if (flags & HASH_RENORMALIZE)
- return SAFE_CRLF_RENORMALIZE;
+ return CONV_EOL_RENORMALIZE;
else if (flags & HASH_WRITE_OBJECT)
- return safe_crlf;
+ return global_conv_flags_eol;
else
- return SAFE_CRLF_FALSE;
+ return 0;
}
@@ -263,15 +321,11 @@ static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
}
}
-const char *sha1_file_name(const unsigned char *sha1)
+void sha1_file_name(struct strbuf *buf, const unsigned char *sha1)
{
- static struct strbuf buf = STRBUF_INIT;
-
- strbuf_reset(&buf);
- strbuf_addf(&buf, "%s/", get_object_directory());
-
- fill_sha1_path(&buf, sha1);
- return buf.buf;
+ strbuf_addstr(buf, get_object_directory());
+ strbuf_addch(buf, '/');
+ fill_sha1_path(buf, sha1);
}
struct strbuf *alt_scratch_buf(struct alternate_object_database *alt)
@@ -652,7 +706,12 @@ int check_and_freshen_file(const char *fn, int freshen)
static int check_and_freshen_local(const unsigned char *sha1, int freshen)
{
- return check_and_freshen_file(sha1_file_name(sha1), freshen);
+ static struct strbuf buf = STRBUF_INIT;
+
+ strbuf_reset(&buf);
+ sha1_file_name(&buf, sha1);
+
+ return check_and_freshen_file(buf.buf, freshen);
}
static int check_and_freshen_nonlocal(const unsigned char *sha1, int freshen)
@@ -808,8 +867,12 @@ static int stat_sha1_file(const unsigned char *sha1, struct stat *st,
const char **path)
{
struct alternate_object_database *alt;
+ static struct strbuf buf = STRBUF_INIT;
+
+ strbuf_reset(&buf);
+ sha1_file_name(&buf, sha1);
+ *path = buf.buf;
- *path = sha1_file_name(sha1);
if (!lstat(*path, st))
return 0;
@@ -833,8 +896,12 @@ static int open_sha1_file(const unsigned char *sha1, const char **path)
int fd;
struct alternate_object_database *alt;
int most_interesting_errno;
+ static struct strbuf buf = STRBUF_INIT;
+
+ strbuf_reset(&buf);
+ sha1_file_name(&buf, sha1);
+ *path = buf.buf;
- *path = sha1_file_name(sha1);
fd = git_open(*path);
if (fd >= 0)
return fd;
@@ -1155,6 +1222,8 @@ static int sha1_loose_object_info(const unsigned char *sha1,
return (status < 0) ? status : 0;
}
+int fetch_if_missing = 1;
+
int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
{
static struct object_info blank_oi = OBJECT_INFO_INIT;
@@ -1163,6 +1232,10 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
const unsigned char *real = (flags & OBJECT_INFO_LOOKUP_REPLACE) ?
lookup_replace_object(sha1) :
sha1;
+ int already_retried = 0;
+
+ if (is_null_sha1(real))
+ return -1;
if (!oi)
oi = &blank_oi;
@@ -1187,19 +1260,32 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
}
}
- if (!find_pack_entry(real, &e)) {
+ while (1) {
+ if (find_pack_entry(real, &e))
+ break;
+
/* Most likely it's a loose object. */
if (!sha1_loose_object_info(real, oi, flags))
return 0;
/* Not a loose object; someone else may have just packed it. */
- if (flags & OBJECT_INFO_QUICK) {
- return -1;
- } else {
- reprepare_packed_git();
- if (!find_pack_entry(real, &e))
- return -1;
+ reprepare_packed_git();
+ if (find_pack_entry(real, &e))
+ break;
+
+ /* Check if it is a missing object */
+ if (fetch_if_missing && repository_format_partial_clone &&
+ !already_retried) {
+ /*
+ * TODO Investigate haveing fetch_object() return
+ * TODO error/success and stopping the music here.
+ */
+ fetch_object(repository_format_partial_clone, real);
+ already_retried = 1;
+ continue;
}
+
+ return -1;
}
if (oi == &blank_oi)
@@ -1208,7 +1294,6 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
* information below, so return early.
*/
return 0;
-
rtype = packed_object_info(e.p, e.offset, oi);
if (rtype < 0) {
mark_bad_packed_object(e.p, real);
@@ -1496,9 +1581,12 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
git_SHA_CTX c;
unsigned char parano_sha1[20];
static struct strbuf tmp_file = STRBUF_INIT;
- const char *filename = sha1_file_name(sha1);
+ static struct strbuf filename = STRBUF_INIT;
+
+ strbuf_reset(&filename);
+ sha1_file_name(&filename, sha1);
- fd = create_tmpfile(&tmp_file, filename);
+ fd = create_tmpfile(&tmp_file, filename.buf);
if (fd < 0) {
if (errno == EACCES)
return error("insufficient permission for adding an object to repository database %s", get_object_directory());
@@ -1551,7 +1639,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
warning_errno("failed utime() on %s", tmp_file.buf);
}
- return finalize_object_file(tmp_file.buf, filename);
+ return finalize_object_file(tmp_file.buf, filename.buf);
}
static int freshen_loose_object(const unsigned char *sha1)
@@ -1691,7 +1779,7 @@ static int index_mem(struct object_id *oid, void *buf, size_t size,
if ((type == OBJ_BLOB) && path) {
struct strbuf nbuf = STRBUF_INIT;
if (convert_to_git(&the_index, path, buf, size, &nbuf,
- get_safe_crlf(flags))) {
+ get_conv_flags(flags))) {
buf = strbuf_detach(&nbuf, &size);
re_allocated = 1;
}
@@ -1725,7 +1813,7 @@ static int index_stream_convert_blob(struct object_id *oid, int fd,
assert(would_convert_to_git_filter_fd(path));
convert_to_git_filter_fd(&the_index, path, fd, &sbuf,
- get_safe_crlf(flags));
+ get_conv_flags(flags));
if (write_object)
ret = write_sha1_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB),
@@ -1903,7 +1991,6 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
origlen = path->len;
strbuf_complete(path, '/');
strbuf_addf(path, "%02x", subdir_nr);
- baselen = path->len;
dir = opendir(path->buf);
if (!dir) {
@@ -1914,15 +2001,18 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
}
oid.hash[0] = subdir_nr;
+ strbuf_addch(path, '/');
+ baselen = path->len;
while ((de = readdir(dir))) {
+ size_t namelen;
if (is_dot_or_dotdot(de->d_name))
continue;
+ namelen = strlen(de->d_name);
strbuf_setlen(path, baselen);
- strbuf_addf(path, "/%s", de->d_name);
-
- if (strlen(de->d_name) == GIT_SHA1_HEXSZ - 2 &&
+ strbuf_add(path, de->d_name, namelen);
+ if (namelen == GIT_SHA1_HEXSZ - 2 &&
!hex_to_bytes(oid.hash + 1, de->d_name,
GIT_SHA1_RAWSZ - 1)) {
if (obj_cb) {
@@ -1941,7 +2031,7 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
}
closedir(dir);
- strbuf_setlen(path, baselen);
+ strbuf_setlen(path, baselen - 1);
if (!r && subdir_cb)
r = subdir_cb(subdir_nr, path->buf, data);