summaryrefslogtreecommitdiff
path: root/src/odb.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-07-09 15:05:14 +0200
committerVicent Marti <tanoku@gmail.com>2011-07-09 15:05:14 +0200
commitc52736fa5226141754918cabf55c22be9c2aee1b (patch)
tree97b9d36ba49045c53ab12a6529b7c6260065498b /src/odb.c
parent3b2a423c3fb9e434c427b819d3281ae9e277091d (diff)
downloadlibgit2-c52736fa5226141754918cabf55c22be9c2aee1b.tar.gz
status: Cleanup
The `hashfile` function has been moved to ODB, next to `git_odb_hash`. Global state has been removed from the dirent call in `status.c`, because global state is killing the rainforest and causing global warming.
Diffstat (limited to 'src/odb.c')
-rw-r--r--src/odb.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/src/odb.c b/src/odb.c
index caa4e1bef..52546e7c7 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -46,10 +46,10 @@ typedef struct
int is_alternate;
} backend_internal;
-static int format_object_header(char *hdr, size_t n, git_rawobj *obj)
+static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type)
{
- const char *type_str = git_object_type2string(obj->type);
- int len = snprintf(hdr, n, "%s %"PRIuZ, type_str, obj->len);
+ const char *type_str = git_object_type2string(obj_type);
+ int len = snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len);
assert(len > 0); /* otherwise snprintf() is broken */
assert(((size_t) len) < n); /* otherwise the caller is broken! */
@@ -72,7 +72,7 @@ int git_odb__hash_obj(git_oid *id, char *hdr, size_t n, int *len, git_rawobj *ob
if (!obj->data && obj->len != 0)
return git__throw(GIT_ERROR, "Failed to hash object. No data given");
- if ((hdrlen = format_object_header(hdr, n, obj)) < 0)
+ if ((hdrlen = format_object_header(hdr, n, obj->len, obj->type)) < 0)
return git__rethrow(hdrlen, "Failed to hash object");
*len = hdrlen;
@@ -134,6 +134,52 @@ void git_odb_object_close(git_odb_object *object)
git_cached_obj_decref((git_cached_obj *)object, &free_odb_object);
}
+int git_odb_hashfile(git_oid *out, const char *path, git_otype type)
+{
+ int fd, hdr_len;
+ char hdr[64], buffer[2048];
+ git_off_t size;
+ git_hash_ctx *ctx;
+
+ if ((fd = p_open(path, O_RDONLY)) < 0)
+ return git__throw(GIT_ENOTFOUND, "Could not open '%s'", path);
+
+ if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) {
+ p_close(fd);
+ return git__throw(GIT_EOSERR, "'%s' appears to be corrupted", path);
+ }
+
+ hdr_len = format_object_header(hdr, sizeof(hdr), size, type);
+ if (hdr_len < 0)
+ return git__throw(GIT_ERROR, "Failed to format blob header. Length is out of bounds");
+
+ ctx = git_hash_new_ctx();
+
+ git_hash_update(ctx, hdr, hdr_len);
+
+ while (size > 0) {
+ ssize_t read_len;
+
+ read_len = read(fd, buffer, sizeof(buffer));
+
+ if (read_len < 0) {
+ p_close(fd);
+ git_hash_free_ctx(ctx);
+ return git__throw(GIT_EOSERR, "Can't read full file '%s'", path);
+ }
+
+ git_hash_update(ctx, buffer, read_len);
+ size -= read_len;
+ }
+
+ p_close(fd);
+
+ git_hash_final(out, ctx);
+ git_hash_free_ctx(ctx);
+
+ return GIT_SUCCESS;
+}
+
int git_odb_hash(git_oid *id, const void *data, size_t len, git_otype type)
{
char hdr[64];