From b64a98460682366d7533ea251d26026b85bb39cb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 11 Sep 2014 12:19:54 -0700 Subject: [PATCH 1/3] hash-object: reduce file-scope statics Most of the knobs that affect helper functions called from cmd_hash_object() were passed to them as parameters already, and the only effect of having them as file-scope statics was to make the reader wonder if the parameters are hiding the file-scope global values by accident. Adjust their initialisation and make them function-local variables. The only exception was no_filters hash_stdin_paths() peeked from the file-scope global, which was converted to a parameter to the helper function. Signed-off-by: Junio C Hamano --- builtin/hash-object.c | 52 +++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index d7fcf4c13c..40008e256f 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -36,9 +36,7 @@ static void hash_object(const char *path, const char *type, int write_object, hash_fd(fd, type, write_object, vpath); } -static int no_filters; - -static void hash_stdin_paths(const char *type, int write_objects) +static void hash_stdin_paths(const char *type, int write_objects, int no_filters) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; @@ -50,42 +48,38 @@ static void hash_stdin_paths(const char *type, int write_objects) strbuf_swap(&buf, &nbuf); } hash_object(buf.buf, type, write_objects, - no_filters ? NULL : buf.buf); + no_filters ? NULL : buf.buf); } strbuf_release(&buf); strbuf_release(&nbuf); } -static const char * const hash_object_usage[] = { - N_("git hash-object [-t ] [-w] [--path=|--no-filters] [--stdin] [--] ..."), - N_("git hash-object --stdin-paths < "), - NULL -}; - -static const char *type; -static int write_object; -static int hashstdin; -static int stdin_paths; -static const char *vpath; - -static const struct option hash_object_options[] = { - OPT_STRING('t', NULL, &type, N_("type"), N_("object type")), - OPT_BOOL('w', NULL, &write_object, N_("write the object into the object database")), - OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")), - OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")), - OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")), - OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")), - OPT_END() -}; - int cmd_hash_object(int argc, const char **argv, const char *prefix) { + static const char * const hash_object_usage[] = { + N_("git hash-object [-t ] [-w] [--path=|--no-filters] [--stdin] [--] ..."), + N_("git hash-object --stdin-paths < "), + NULL + }; + const char *type = blob_type; + int hashstdin = 0; + int stdin_paths = 0; + int write_object = 0; + int no_filters = 0; + const char *vpath = NULL; + const struct option hash_object_options[] = { + OPT_STRING('t', NULL, &type, N_("type"), N_("object type")), + OPT_BOOL('w', NULL, &write_object, N_("write the object into the object database")), + OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")), + OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")), + OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")), + OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")), + OPT_END() + }; int i; int prefix_length = -1; const char *errstr = NULL; - type = blob_type; - argc = parse_options(argc, argv, NULL, hash_object_options, hash_object_usage, 0); @@ -131,7 +125,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) } if (stdin_paths) - hash_stdin_paths(type, write_object); + hash_stdin_paths(type, write_object, no_filters); return 0; } From 17b787f6031d72619e4e2982ea84f47fe161cb30 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 11 Sep 2014 12:44:05 -0700 Subject: [PATCH 2/3] hash-object: pass 'write_object' as a flag Instead of forcing callers of lower level functions write (write_object ? HASH_WRITE_OBJECT : 0), prepare the flag to be passed down in the callchain from the command line parser. Signed-off-by: Junio C Hamano --- builtin/hash-object.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 40008e256f..1fb07ee085 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -10,33 +10,31 @@ #include "parse-options.h" #include "exec_cmd.h" -static void hash_fd(int fd, const char *type, int write_object, const char *path) +static void hash_fd(int fd, const char *type, const char *path, unsigned flags) { struct stat st; unsigned char sha1[20]; - unsigned flags = (HASH_FORMAT_CHECK | - (write_object ? HASH_WRITE_OBJECT : 0)); if (fstat(fd, &st) < 0 || index_fd(sha1, fd, &st, type_from_string(type), path, flags)) - die(write_object + die((flags & HASH_WRITE_OBJECT) ? "Unable to add %s to database" : "Unable to hash %s", path); printf("%s\n", sha1_to_hex(sha1)); maybe_flush_or_die(stdout, "hash to stdout"); } -static void hash_object(const char *path, const char *type, int write_object, - const char *vpath) +static void hash_object(const char *path, const char *type, const char *vpath, + unsigned flags) { int fd; fd = open(path, O_RDONLY); if (fd < 0) die_errno("Cannot open '%s'", path); - hash_fd(fd, type, write_object, vpath); + hash_fd(fd, type, vpath, flags); } -static void hash_stdin_paths(const char *type, int write_objects, int no_filters) +static void hash_stdin_paths(const char *type, int no_filters, unsigned flags) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; @@ -47,8 +45,7 @@ static void hash_stdin_paths(const char *type, int write_objects, int no_filters die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } - hash_object(buf.buf, type, write_objects, - no_filters ? NULL : buf.buf); + hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags); } strbuf_release(&buf); strbuf_release(&nbuf); @@ -64,12 +61,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) const char *type = blob_type; int hashstdin = 0; int stdin_paths = 0; - int write_object = 0; int no_filters = 0; + unsigned flags = HASH_FORMAT_CHECK; const char *vpath = NULL; const struct option hash_object_options[] = { OPT_STRING('t', NULL, &type, N_("type"), N_("object type")), - OPT_BOOL('w', NULL, &write_object, N_("write the object into the object database")), + OPT_BIT('w', NULL, &flags, N_("write the object into the object database"), + HASH_WRITE_OBJECT), OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")), OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")), OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")), @@ -83,7 +81,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, NULL, hash_object_options, hash_object_usage, 0); - if (write_object) { + if (flags & HASH_WRITE_OBJECT) { prefix = setup_git_directory(); prefix_length = prefix ? strlen(prefix) : 0; if (vpath && prefix) @@ -113,19 +111,19 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) } if (hashstdin) - hash_fd(0, type, write_object, vpath); + hash_fd(0, type, vpath, flags); for (i = 0 ; i < argc; i++) { const char *arg = argv[i]; if (0 <= prefix_length) arg = prefix_filename(prefix, prefix_length, arg); - hash_object(arg, type, write_object, - no_filters ? NULL : vpath ? vpath : arg); + hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg, + flags); } if (stdin_paths) - hash_stdin_paths(type, write_object, no_filters); + hash_stdin_paths(type, no_filters, flags); return 0; } From 5ba9a93b39bef057be54ecf7933386a582981625 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 11 Sep 2014 13:14:51 -0700 Subject: [PATCH 3/3] hash-object: add --literally option This allows "hash-object --stdin" to just hash any garbage into a "loose object" that may not pass the standard object parsing check or fsck, so that different kind of corrupt objects we may encounter in the field can be imitated in our test suite. That would in turn allow us to test features that catch these corrupt objects. Note that "cat-file" may need to learn "--literally" option to allow us peek into a truly broken object. Signed-off-by: Junio C Hamano --- builtin/hash-object.c | 45 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 1fb07ee085..6158363318 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -10,13 +10,36 @@ #include "parse-options.h" #include "exec_cmd.h" -static void hash_fd(int fd, const char *type, const char *path, unsigned flags) +/* + * This is to create corrupt objects for debugging and as such it + * needs to bypass the data conversion performed by, and the type + * limitation imposed by, index_fd() and its callees. + */ +static int hash_literally(unsigned char *sha1, int fd, const char *type, unsigned flags) +{ + struct strbuf buf = STRBUF_INIT; + int ret; + + if (strbuf_read(&buf, fd, 4096) < 0) + ret = -1; + else if (flags & HASH_WRITE_OBJECT) + ret = write_sha1_file(buf.buf, buf.len, type, sha1); + else + ret = hash_sha1_file(buf.buf, buf.len, type, sha1); + strbuf_release(&buf); + return ret; +} + +static void hash_fd(int fd, const char *type, const char *path, unsigned flags, + int literally) { struct stat st; unsigned char sha1[20]; if (fstat(fd, &st) < 0 || - index_fd(sha1, fd, &st, type_from_string(type), path, flags)) + (literally + ? hash_literally(sha1, fd, type, flags) + : index_fd(sha1, fd, &st, type_from_string(type), path, flags))) die((flags & HASH_WRITE_OBJECT) ? "Unable to add %s to database" : "Unable to hash %s", path); @@ -25,16 +48,17 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags) } static void hash_object(const char *path, const char *type, const char *vpath, - unsigned flags) + unsigned flags, int literally) { int fd; fd = open(path, O_RDONLY); if (fd < 0) die_errno("Cannot open '%s'", path); - hash_fd(fd, type, vpath, flags); + hash_fd(fd, type, vpath, flags, literally); } -static void hash_stdin_paths(const char *type, int no_filters, unsigned flags) +static void hash_stdin_paths(const char *type, int no_filters, unsigned flags, + int literally) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; @@ -45,7 +69,8 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags) die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } - hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags); + hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags, + literally); } strbuf_release(&buf); strbuf_release(&nbuf); @@ -62,6 +87,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) int hashstdin = 0; int stdin_paths = 0; int no_filters = 0; + int literally = 0; unsigned flags = HASH_FORMAT_CHECK; const char *vpath = NULL; const struct option hash_object_options[] = { @@ -71,6 +97,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")), OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")), OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")), + OPT_BOOL( 0, "literally", &literally, N_("just hash any random garbage to create corrupt objects for debugging Git")), OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")), OPT_END() }; @@ -111,7 +138,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) } if (hashstdin) - hash_fd(0, type, vpath, flags); + hash_fd(0, type, vpath, flags, literally); for (i = 0 ; i < argc; i++) { const char *arg = argv[i]; @@ -119,11 +146,11 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) if (0 <= prefix_length) arg = prefix_filename(prefix, prefix_length, arg); hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg, - flags); + flags, literally); } if (stdin_paths) - hash_stdin_paths(type, no_filters, flags); + hash_stdin_paths(type, no_filters, flags, literally); return 0; }