hash-object: cleanup handling of command line options
authorGerrit Pape <pape@smarden.org>
Thu, 21 Feb 2008 10:06:47 +0000 (10:06 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 22 Feb 2008 17:32:49 +0000 (09:32 -0800)
git hash-object used to process the --stdin command line argument
before reading subsequent arguments.  This caused 'git hash-object
--stdin -w' to fail to actually write the object into the
database, while '-w --stdin' properly did.  Now git hash-object
first reads all arguments, and then processes them.

This regresses one insane use case.  git hash-object used to allow
multiple --stdin arguments on the command line:

   $ git hash-object --stdin --stdin
     foo
     ^D
     bar
     ^D

Now git hash-object errors out if --stdin is given more than once.

Reported by Josh Triplett through
 http://bugs.debian.org/464432

Signed-off-by: Gerrit Pape <pape@smarden.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
hash-object.c
t/t5303-hash-object.sh [new file with mode: 0755]

index 0a58f3f..61e7160 100644 (file)
@@ -41,6 +41,7 @@ int main(int argc, char **argv)
        const char *prefix = NULL;
        int prefix_length = -1;
        int no_more_flags = 0;
+       int hashstdin = 0;
 
        git_config(git_default_config);
 
@@ -65,13 +66,20 @@ int main(int argc, char **argv)
                        else if (!strcmp(argv[i], "--help"))
                                usage(hash_object_usage);
                        else if (!strcmp(argv[i], "--stdin")) {
-                               hash_stdin(type, write_object);
+                               if (hashstdin)
+                                       die("Multiple --stdin arguments are not supported");
+                               hashstdin = 1;
                        }
                        else
                                usage(hash_object_usage);
                }
                else {
                        const char *arg = argv[i];
+
+                       if (hashstdin) {
+                               hash_stdin(type, write_object);
+                               hashstdin = 0;
+                       }
                        if (0 <= prefix_length)
                                arg = prefix_filename(prefix, prefix_length,
                                                      arg);
@@ -79,5 +87,7 @@ int main(int argc, char **argv)
                        no_more_flags = 1;
                }
        }
+       if (hashstdin)
+               hash_stdin(type, write_object);
        return 0;
 }
diff --git a/t/t5303-hash-object.sh b/t/t5303-hash-object.sh
new file mode 100755 (executable)
index 0000000..543c078
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description=git-hash-object
+
+. ./test-lib.sh
+
+test_expect_success \
+    'git hash-object -w --stdin saves the object' \
+    'obname=$(echo foo | git hash-object -w --stdin) &&
+    obpath=$(echo $obname | sed -e "s/\(..\)/\1\//") &&
+    test -r .git/objects/"$obpath" &&
+    rm -f .git/objects/"$obpath"'
+    
+test_expect_success \
+    'git hash-object --stdin -w saves the object' \
+    'obname=$(echo foo | git hash-object --stdin -w) &&
+    obpath=$(echo $obname | sed -e "s/\(..\)/\1\//") &&
+    test -r .git/objects/"$obpath" &&
+    rm -f .git/objects/"$obpath"'    
+
+test_expect_success \
+    'git hash-object --stdin file1 <file0 first operates on file0, then file1' \
+    'echo foo > file1 &&
+    obname0=$(echo bar | git hash-object --stdin) &&
+    obname1=$(git hash-object file1) &&
+    obname0new=$(echo bar | git hash-object --stdin file1 | sed -n -e 1p) &&
+    obname1new=$(echo bar | git hash-object --stdin file1 | sed -n -e 2p) &&
+    test "$obname0" = "$obname0new" &&
+    test "$obname1" = "$obname1new"'
+
+test_expect_success \
+    'git hash-object refuses multiple --stdin arguments' \
+    '! git hash-object --stdin --stdin < file1'
+
+test_done