Merge branch 'jc/hash-object'
authorJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 21:23:59 +0000 (14:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 11 May 2015 21:23:59 +0000 (14:23 -0700)
"hash-object --literally" introduced in v2.2 was not prepared to
take a really long object type name.

* jc/hash-object:
write_sha1_file(): do not use a separate sha1[] array
t1007: add hash-object --literally tests
hash-object --literally: fix buffer overrun with extra-long object type
git-hash-object.txt: document --literally option

1  2 
builtin/hash-object.c
cache.h
sha1_file.c
t/t1007-hash-object.sh
Simple merge
diff --cc cache.h
Simple merge
diff --cc sha1_file.c
index 7634917e4ea934f6673d6d154420499660dbc1ab,5d320753c3eb57ab3c669e4fa945ba87c993fe6b..866021b2b10ff228a391d38342d7352b1ea779ff
@@@ -2989,27 -2945,8 +2989,26 @@@ static int write_loose_object(const uns
        return move_temp_to_file(tmp_file, filename);
  }
  
- int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
 +static int freshen_loose_object(const unsigned char *sha1)
 +{
 +      return check_and_freshen(sha1, 1);
 +}
 +
 +static int freshen_packed_object(const unsigned char *sha1)
 +{
 +      struct pack_entry e;
 +      if (!find_pack_entry(sha1, &e))
 +              return 0;
 +      if (e.p->freshened)
 +              return 1;
 +      if (!freshen_file(e.p->pack_name))
 +              return 0;
 +      e.p->freshened = 1;
 +      return 1;
 +}
 +
+ int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1)
  {
-       unsigned char sha1[20];
        char hdr[32];
        int hdrlen;
  
         * it out into .git/objects/??/?{38} file.
         */
        write_sha1_file_prepare(buf, len, type, sha1, hdr, &hdrlen);
-       if (returnsha1)
-               hashcpy(returnsha1, sha1);
 -      if (has_sha1_file(sha1))
 +      if (freshen_packed_object(sha1) || freshen_loose_object(sha1))
                return 0;
        return write_loose_object(sha1, hdr, hdrlen, buf, len, 0);
  }
  
 -      if (has_sha1_file(sha1))
+ int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type,
+                            unsigned char *sha1, unsigned flags)
+ {
+       char *header;
+       int hdrlen, status = 0;
+       /* type string, SP, %lu of the length plus NUL must fit this */
+       header = xmalloc(strlen(type) + 32);
+       write_sha1_file_prepare(buf, len, type, sha1, header, &hdrlen);
+       if (!(flags & HASH_WRITE_OBJECT))
+               goto cleanup;
++      if (freshen_packed_object(sha1) || freshen_loose_object(sha1))
+               goto cleanup;
+       status = write_loose_object(sha1, header, hdrlen, buf, len, 0);
+ cleanup:
+       free(header);
+       return status;
+ }
  int force_object_loose(const unsigned char *sha1, time_t mtime)
  {
        void *buf;
index ebb3a69c8cd68a51184f809357bb60cb7b35f928,7c3dcfb70ccb32314eb0a95edb0d2522936f48dd..7d2baa15bbd0bbbe8c12631ad2d24b77e90b8775
@@@ -201,12 -201,15 +201,23 @@@ test_expect_success 'corrupt tag' 
        test_must_fail git hash-object -t tag --stdin </dev/null
  '
  
 +test_expect_success 'hash-object complains about bogus type name' '
 +      test_must_fail git hash-object -t bogus --stdin </dev/null
 +'
 +
 +test_expect_success 'hash-object complains about truncated type name' '
 +      test_must_fail git hash-object -t bl --stdin </dev/null
 +'
 +
+ test_expect_success '--literally' '
+       t=1234567890 &&
+       echo example | git hash-object -t $t --literally --stdin
+ '
+ test_expect_success '--literally with extra-long type' '
+       t=12345678901234567890123456789012345678901234567890 &&
+       t="$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t" &&
+       echo example | git hash-object -t $t --literally --stdin
+ '
  test_done