cat-file: teach cat-file a '--literally' option
v7 cover cat-file: teach cat-file a '--literally' option
Changes made :
* Fixed the problem with packed types, which failed a few tests.
* Misspelled email.
Thanks for the suggestions and comments on version 6.
PATCH v7 1/4 sha1_file.c: support reading from a loose object of unknown type
Update sha1_loose_object_info() to optionally allow it to read from a loose object file of unknown/bogus type; as the function usually returns the type of the object it read in the form of enum for known types, add an optional "typename" field to receive the name of the type in textual form and a flag to indicate the reading of a loose object file of unknown/bogus type.
Add parse_sha1_header_extended() which acts as a wrapper around parse_sha1_header() allowing more information to be obtained.
Add unpack_sha1_header_to_strbuf() to unpack sha1 headers of unknown/corrupt objects which have a unknown sha1 header size to a strbuf structure. This was written by Junio C Hamano but tested by me.
--- cache.h | 2 ++ sha1_file.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 91 insertions(+), 22 deletions(-)
cache.h +2 -0
@@ -881,6 +881,7 @@ extern int is_ntfs_dotgit(const char *name);/* object replacement */ #define LOOKUP_REPLACE_OBJECT 1 +#define LOOKUP_LITERALLY 2extern void *read_sha1_file_extended (const unsigned char *sha1,enum object_type *type,unsigned long *size,unsigned flag);static inline void *read_sha1_file (const unsigned char *sha1,enum object_type *type,unsigned long *size) {
@@ -1349,6 +1350,7 @@ struct object_info {unsigned long *sizep;unsigned long *disk_sizep;unsigned char *delta_base_sha1; +struct strbuf *typename;/* Response */ enum {
sha1_file.c +89 -22
183 lines not on this page · raw message
Signature · 1 line
2.4.0.rc1.249.g9f2ee54
PATCH v7 1/4 sha1_file.c: support reading from a loose object of unknown type
Update sha1_loose_object_info() to optionally allow it to read from a loose object file of unknown/bogus type; as the function usually returns the type of the object it read in the form of enum for known types, add an optional "typename" field to receive the name of the type in textual form and a flag to indicate the reading of a loose object file of unknown/bogus type.
Add parse_sha1_header_extended() which acts as a wrapper around parse_sha1_header() allowing more information to be obtained.
Add unpack_sha1_header_to_strbuf() to unpack sha1 headers of unknown/corrupt objects which have a unknown sha1 header size to a strbuf structure. This was written by Junio C Hamano but tested by me.
--- cache.h | 2 ++ sha1_file.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 22 deletions(-)
cache.h +2 -0
@@ -881,6 +881,7 @@ extern int is_ntfs_dotgit(const char *name);/* object replacement */ #define LOOKUP_REPLACE_OBJECT 1 +#define LOOKUP_LITERALLY 2extern void *read_sha1_file_extended (const unsigned char *sha1,enum object_type *type,unsigned long *size,unsigned flag);static inline void *read_sha1_file (const unsigned char *sha1,enum object_type *type,unsigned long *size) {
@@ -1349,6 +1350,7 @@ struct object_info {unsigned long *sizep;unsigned long *disk_sizep;unsigned char *delta_base_sha1; +struct strbuf *typename;/* Response */ enum {
sha1_file.c +92 -22
192 lines not on this page · raw message
Signature · 1 line
2.4.0.rc1.249.g9f2ee54
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
Quoted 70 lines · Karthik Nayak
Update
sha1_loose_object_info()to optionally allow it to read from a loose object file of unknown/bogus type; as the function usually returns the type of the object it read in the form of enum for known types, add an optional "typename" field to receive the name of the type in textual form and a flag to indicate the reading of a loose object file of unknown/bogus type.Add
parse_sha1_header_extended()which acts as a wrapper aroundparse_sha1_header()allowing more information to be obtained.Add
unpack_sha1_header_to_strbuf()to unpack sha1 headers of unknown/corrupt objects which have a unknown sha1 header size to a strbuf structure. This was written by Junio C Hamano but tested by me.Helped-by Junio C Hamano <[email protected]>Helped-by Eric Sunshine <[email protected]>Signed-off-by Karthik Nayak <[email protected]>---
sha1_file.c +12
-9@@ -1614,27 +1642,24 @@ static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long s* too permissive for what we want to check. So do an anal * object header parse by hand. */ -int parse_sha1_header (const char *hdr,unsigned long *sizep) +int parse_sha1_header_extended (const char *hdr,struct object_info *oi, +unsigned int flags) { -char type[10 ]; -int i; +struct strbuf typename =STRBUF_INIT ;unsigned long size; +int type;/* * The type can be at most ten bytes (including the * terminating '\0' that we add), and is followed by * a space. */ - i =0 ;for (;;) {char c = *hdr++;if (c ==' ' )break ; - type[i++] = c; -if (i >=sizeof (type)) -return -1 ; +strbuf_addch (&typename, c); } - type[i] =0 ;/* * The length must follow immediately, and be in canonical @@ -1652,12 +1677,39 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep) size = size *10 + c; } } - *sizep = size; + + type =type_from_string_gently (typename.buf, typename.len,1 ); +if (oi->sizep) + *oi->sizep = size; +if (oi->typename) +strbuf_addbuf (oi->typename, &typename); +strbuf_release (&typename);/*
sha1_file.c int parse_sha1_header(const char *hdr, unsigned long *sizep) · line 1698
Quoted 10 lines
sha1_file.c +10
-0+* Set type to 0 if its an unknown object and +* we're obtaining the type using '--literally' +* option. +*/ +if ((flags &LOOKUP_LITERALLY ) && (type ==-1 )) + type =0 ; +else if (type ==-1 ) +die ("invalid object type" ); +if (oi->typep) + *oi->typep = type;
This unnecessary intermixing of 'type'/'typename' and 'size' processing makes the code more confusing than it ought to be. Why not do all the processing related to 'type'/'typename' before the processing of 'size'?
Quoted 18 lines
sha1_file.c +12
-1+/* * The length must be followed by a zero byte */ -return *hdr ?-1 :type_from_string (type); +return *hdr ?-1 : type; +} + +int parse_sha1_header (const char *hdr,unsigned long *sizep) +{ +struct object_info oi; + + oi.sizep = sizep; + oi.typename =NULL ; + oi.typep =NULL ; +return parse_sha1_header_extended (hdr, &oi,LOOKUP_REPLACE_OBJECT ); }static void *unpack_sha1_file (void *map,unsigned long mapsize,enum object_type *type,unsigned long *size,const unsigned char *sha1)
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
In reply to Karthik Nayaksha1_file.c int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, · line 2656
Quoted 9 lines · Karthik Nayak
sha1_file.c +2
-0@@ -2586,13 +2649,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, *(oi->disk_sizep) =0 ;if (oi->delta_base_sha1)hashclr (oi->delta_base_sha1); +if (oi->typename) +strbuf_addstr (oi->typename,typename (co->type)); oi->whence =OI_CACHED ;return 0 ; }
Just before the pre-context of this hunk, there is this bit:
if (oi->typep) *(oi->typep) = co->type;
which tells me that the callers of this function is allowed to pass a NULL in oi->typep when they are not interested in the type of the object.
sha1_file.c int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, · line 2685
Quoted 13 lines
sha1_file.c +3
-1if (!find_pack_entry (real, &e)) {/* Most likely it's a loose object. */ -if (!sha1_loose_object_info (real, oi)) { +if (!sha1_loose_object_info (real, oi, flags)) { oi->whence =OI_LOOSE ;return 0 ; }@@ -2616,6 +2681,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, oi->u.packed.is_delta = (rtype ==OBJ_REF_DELTA || rtype ==OBJ_OFS_DELTA ); } +if (oi->typename) +strbuf_addstr (oi->typename,typename (*oi->typep));
So, it makes me wonder what guarantee we have that this does not dereference a NULL here.
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
Quoted 21 lines · Junio C Hamano
sha1_file.c int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, · line 2656
Quoted 9 lines · Karthik Nayak
sha1_file.c +2
-0@@ -2586,13 +2649,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, *(oi->disk_sizep) =0 ;if (oi->delta_base_sha1)hashclr (oi->delta_base_sha1); +if (oi->typename) +strbuf_addstr (oi->typename,typename (co->type)); oi->whence =OI_CACHED ;return 0 ; }Just before the pre-context of this hunk, there is this bit:
if (oi->typep) *(oi->typep) = co->type;which tells me that the callers of this function is allowed to pass a NULL in
oi->typepwhen they are not interested in the type of the object.
Quoted 17 lines
sha1_file.c int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, · line 2685
Quoted 13 lines
sha1_file.c +3
-1if (!find_pack_entry (real, &e)) {/* Most likely it's a loose object. */ -if (!sha1_loose_object_info (real, oi)) { +if (!sha1_loose_object_info (real, oi, flags)) { oi->whence =OI_LOOSE ;return 0 ; }@@ -2616,6 +2681,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, oi->u.packed.is_delta = (rtype ==OBJ_REF_DELTA || rtype ==OBJ_OFS_DELTA ); } +if (oi->typename) +strbuf_addstr (oi->typename,typename (*oi->typep));So, it makes me wonder what guarantee we have that this does not dereference a NULL here.
As per my code, oi->typename is only pointing to something when oi->typep is ( As oi->typename is currently only used in cat-file.c).
But what you're saying also is true, there is no other guarantee, as a user may set oi->typename to point to a struct strbuf and leave out oi->typep.
if (oi->typename && oi->typep)
strbuf_addstr(oi->typename, typename(*oi->typep));
This should suffice. Do you want me to re-roll this?
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
Quoted 8 lines · karthik nayak
Quoted 3 lines
So, it makes me wonder what guarantee we have that this does not dereference a NULL here.
As per my code,
oi->typenameis only pointing to something whenoi->typepis ( Asoi->typenameis currently only used incat-file.c).
But what you're saying also is true, there is no other guarantee, as a user may setoi->typenameto point to a struct strbuf and leave outoi->typep.
Quoted 4 lines
if (
oi->typename&&oi->typep)strbuf_addstr(oi->typename, typename(*oi->typep));This should suffice. Do you want me to re-roll this?
I'd rather avoid the thinking along the lines of "at this moment, there happens to be only one caller that asks for typename and the caller also sets typep, so we will be safe as long as we make sure the caller passed typep before giving him typename back".
Somebody else may write new code that wants to learn the typename, forgets to set typep, calls into this codepath, and ends up scratching his head wondering why the typename string is returned to him. Surely the code may not crash at the new code you wrote, but you are not helping him.
If it semantically does not make sense to ask for the typename without asking for the type code, then we can and should make that as a new calling convention _all_ callers must follow.
In other words, I think it is better to have
if (oi->typename && !oi->typep)
die("BUG");somewhere near the beginning of the callchain that takes oi; that will ensure all callers understand the rule.
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
Quoted 20 lines · Junio C Hamano
Quoted 8 lines · karthik nayak
Quoted 3 lines
So, it makes me wonder what guarantee we have that this does not dereference a NULL here.
As per my code,
oi->typenameis only pointing to something whenoi->typepis ( Asoi->typenameis currently only used incat-file.c).
But what you're saying also is true, there is no other guarantee, as a user may setoi->typenameto point to a struct strbuf and leave outoi->typep.Quoted 4 lines
if (oi->typename && oi->typep) strbuf_addstr(oi->typename, typename(*oi->typep));This should suffice. Do you want me to re-roll this?
I'd rather avoid the thinking along the lines of "at this moment, there happens to be only one caller that asks for typename and the caller also sets typep, so we will be safe as long as we make sure the caller passed typep before giving him typename back".
Quoted 5 lines
Somebody else may write new code that wants to learn the typename, forgets to set typep, calls into this codepath, and ends up scratching his head wondering why the typename string is returned to him. Surely the code may not crash at the new code you wrote, but you are not helping him.
Yes! I do agree with you, If you read my previous reply, I did mention what you said about not having a guarantee that typep and typename are both set and another user might have a bug with this.
Quoted 5 lines
If it semantically does not make sense to ask for the typename without asking for the type code, then we can and should make that as a new calling convention _all_ callers must follow.
Quoted 8 lines
In other words, I think it is better to have
if (oi->typename && !oi->typep) die("BUG");somewhere near the beginning of the callchain that takes oi; that will ensure all callers understand the rule.
Yes! this is a better approach as it will enforce that typep must be set when typename is set.
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
Quoted 8 lines · karthik nayak
Quoted 6 lines · Junio C Hamano
If it semantically does not make sense to ask for the typename without asking for the type code, then we can and should make that as a new calling convention _all_ callers must follow.
In other words, I think it is better to have
Quoted 8 lines
Quoted 5 lines
if (oi->typename && !oi->typep) die("BUG");somewhere near the beginning of the callchain that takes oi; that will ensure all callers understand the rule.
Yes! this is a better approach as it will enforce that typep must be set when typename is set.
Not so fast ;-)
The key phrase in what I wrote above is "If it does not make sense", and I am not yet convinced if that is the case or not. If we are to change the calling convention for the callers, the reason why it does not make sense to ask only for typename but not typep must be explained in the log message.
And if it turns out that the answer to that question is "it is valid to ask only for typename", then it would be wrong to force everybody who wants to learn the stringified typename to supply typep. And in such a case it might be better to do something like this instead (on top of your patch I am responding to):
sha1_file.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
sha1_file.c +12 -0
@@ -2639,6 +2639,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,struct cached_object *co;struct pack_entry e;int rtype; +enum object_type real_type;const unsigned char *real =lookup_replace_object_extended (sha1, flags); co =find_cached_object (real);
@@ -2670,9 +2671,18 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,return -1 ; } +/* +* packed_object_info() does not follow the delta chain to +* find out the real type, unless it is given oi->typep. +*/ +if (oi->typename && !oi->typep) + oi->typep = &real_type; + rtype =packed_object_info (e.p, e.offset, oi);if (rtype <0 ) {mark_bad_packed_object (e.p, real); +if (oi->typep == &real_type) + oi->typep =NULL ;return sha1_object_info_extended (real, oi,0 ); }else if (in_delta_base_cache (e.p, e.offset)) { oi->whence =OI_DBCACHED ;
@@ -2686,6 +2696,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,if (oi->typename)strbuf_addstr (oi->typename,typename (*oi->typep)); +if (oi->typep == &real_type) + oi->typep =NULL ;return 0 ; }
Re: [PATCH v7 1/4] sha1_file.c: support reading from a loose object of unknown type
Quoted 69 lines · Junio C Hamano
Quoted 8 lines · karthik nayak
Quoted 6 lines · Junio C Hamano
If it semantically does not make sense to ask for the typename without asking for the type code, then we can and should make that as a new calling convention _all_ callers must follow.
In other words, I think it is better to have
Quoted 8 lines
Quoted 5 lines
if (oi->typename && !oi->typep) die("BUG");somewhere near the beginning of the callchain that takes oi; that will ensure all callers understand the rule.
Yes! this is a better approach as it will enforce that typep must be set when typename is set.
Not so fast ;-)
The key phrase in what I wrote above is "If it does not make sense", and I am not yet convinced if that is the case or not. If we are to change the calling convention for the callers, the reason why it does not make sense to ask only for typename but not typep must be explained in the log message.
And if it turns out that the answer to that question is "it is valid to ask only for typename", then it would be wrong to force everybody who wants to learn the stringified typename to supply typep. And in such a case it might be better to do something like this instead (on top of your patch I am responding to):
sha1_file.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)sha1_file.c +10
-0@@ -2639,6 +2639,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,struct cached_object *co;struct pack_entry e;int rtype; +enum object_type real_type;const unsigned char *real =lookup_replace_object_extended (sha1, flags); co =find_cached_object (real);@@ -2670,9 +2671,18 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,return -1 ; } +/* +* packed_object_info() does not follow the delta chain to +* find out the real type, unless it is given oi->typep. +*/ +if (oi->typename && !oi->typep) + oi->typep = &real_type; + rtype =packed_object_info (e.p, e.offset, oi);if (rtype <0 ) {mark_bad_packed_object (e.p, real); +if (oi->typep == &real_type) + oi->typep =NULL ;return sha1_object_info_extended (real, oi,0 ); }else if (in_delta_base_cache (e.p, e.offset)) { oi->whence =OI_DBCACHED ;
sha1_file.c int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, · line 2703
Quoted 8 lines
sha1_file.c +2
-0@@ -2686,6 +2696,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,if (oi->typename)strbuf_addstr (oi->typename,typename (*oi->typep)); +if (oi->typep == &real_type) + oi->typep =NULL ;return 0 ; }
Haha, If there is anything I love about code revisions its how you are subjected to so many different ways of thinking. I didn't think of what you said.
We could do this and support typename without typep being used. This could probably even eliminate the typep used by cat-file while getting the type of an object.
Will go through this again.
Thanks a lot.
PATCH v7 2/4 cat-file: teach cat-file a '--literally' option
In reply to karthik nayakCurrently 'git cat-file' throws an error while trying to print the type or size of a broken/corrupt object which is created using 'git hash-object --literally'. This is because these objects are usually of unknown types.
Teach git cat-file a '--literally' option where it prints the type or size of a broken/corrupt object without throwing an error.
Modify '-t' and '-s' options to call sha1_object_info_extended() directly to support the '--literally' option.
--- builtin/cat-file.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)
builtin/cat-file.c +29 -9
@@ -9,13 +9,20 @@#include "userdiff.h" #include "streaming.h" -static int cat_one_file (int opt,const char *exp_type,const char *obj_name) +static int cat_one_file (int opt,const char *exp_type,const char *obj_name, +int literally) {unsigned char sha1[20 ];enum object_type type;char *buf;unsigned long size;struct object_context obj_context; +struct object_info oi = {NULL }; +struct strbuf sb =STRBUF_INIT ; +unsigned flags =LOOKUP_REPLACE_OBJECT ; + +if (literally) + flags |=LOOKUP_LITERALLY ;if (get_sha1_with_context (obj_name,0 , sha1, &obj_context))die ("Not a valid object name %s" , obj_name);
@@ -23,16 +30,24 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) buf =NULL ;switch (opt) {case 't' : - type =sha1_object_info (sha1,NULL ); -if (type >0 ) { -printf ("%s\n" ,typename (type)); + oi.typep = &type; + oi.typename = &sb; +if (sha1_object_info_extended (sha1, &oi, flags) <0 ) +die ("git cat-file: could not get object info" ); +if (type >=0 && sb.len) { +printf ("%s\n" , sb.buf); +strbuf_release (&sb);return 0 ; }break ;case 's' : - type =sha1_object_info (sha1, &size); -if (type >0 ) { + oi.typep = &type; + oi.typename = &sb; + oi.sizep = &size; +if (sha1_object_info_extended (sha1, &oi, flags) <0 ) +die ("git cat-file: could not get object info" ); +if (type >=0 && sb.len) {printf ("%lu\n" , size);return 0 ; }
@@ -323,7 +338,7 @@ static int batch_objects(struct batch_options *opt) }static const char *const cat_file_usage[] = { -N_ ("git cat-file (-t | -s | -e | -p | <type> | --textconv) <object>" ), +N_ ("git cat-file (-t [--literally]|-s [--literally]|-e|-p|<type>|--textconv) <object>" ),N_ ("git cat-file (--batch | --batch-check) < <list-of-objects>" ),NULL };
@@ -359,6 +374,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)int opt =0 ;const char *exp_type =NULL , *obj_name =NULL ;struct batch_options batch = {0 }; +int literally =0 ;const struct option options[] = {OPT_GROUP (N_ ("<type> can be one of: blob, tree, commit, tag" )),
@@ -369,6 +385,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)OPT_SET_INT ('p' ,NULL , &opt,N_ ("pretty-print object's content" ),'p' ),OPT_SET_INT (0 ,"textconv" , &opt,N_ ("for blob objects, run textconv on object's content" ),'c' ), +OPT_BOOL (0 ,"literally" , &literally, +N_ ("get information about corrupt objects for debugging Git" )), { OPTION_CALLBACK, 0, "batch", &batch, "format",N_ ("show info and content of objects fed from the standard input" ), PARSE_OPT_OPTARG, batch_option_callback },
@@ -380,7 +398,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)git_config (git_cat_file_config,NULL ); -if (argc !=3 && argc !=2 ) +if (argc <2 || argc >4 )usage_with_options (cat_file_usage, options); argc =parse_options (argc, argv, prefix, options, cat_file_usage,0 );
@@ -405,5 +423,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)if (batch.enabled)return batch_objects (&batch); -return cat_one_file (opt, exp_type, obj_name); +if (literally && opt !='t' && opt !='s' ) +die ("git cat-file --literally: use with -s or -t" ); +return cat_one_file (opt, exp_type, obj_name, literally); }
Signature · 1 line
2.4.0.rc1.249.g9f2ee54
Quoted 4 lines · Karthik Nayak
Currently 'git cat-file' throws an error while trying to print the type or size of a broken/corrupt object which is created using 'git hash-object --literally'. This is because these objects are usually of unknown types.
This focus of this explanation is off-the-mark. The fact that such objects can be created by 'hash-object --literally' is tangental to the real purpose of the new 'cat-file --literally' option, which is that it can help with diagnosing broken/corrupt objects encountered in-the-wild.
Even mentioning 'hash-object --literally' here may be misleading and confusing since its purpose it to intentionally create broken objects for stress-testing git itself. I'd probably drop the reference altogether, but if you insist upon mentioning 'hash-object --literally', perhaps make it a very minor parenthetical comment at the end of the commit message saying that 'cat-file --literally' was inspired by its hash-object counterpart, or some such.
More below.
Quoted 38 lines
Teach git cat-file a '--literally' option where it prints the type or size of a broken/corrupt object without throwing an error.
Modify '-t' and '-s' options to call
sha1_object_info_extended()directly to support the '--literally' option.Helped-by Junio C Hamano <[email protected]>Helped-by Eric Sunshine <[email protected]>Signed-off-by Karthik Nayak <[email protected]>---
builtin/cat-file.c +8
-1@@ -9,13 +9,20 @@#include "userdiff.h" #include "streaming.h" -static int cat_one_file (int opt,const char *exp_type,const char *obj_name) +static int cat_one_file (int opt,const char *exp_type,const char *obj_name, +int literally) {unsigned char sha1[20 ];enum object_type type;char *buf;unsigned long size;struct object_context obj_context; +struct object_info oi = {NULL }; +struct strbuf sb =STRBUF_INIT ; +unsigned flags =LOOKUP_REPLACE_OBJECT ; + +if (literally) + flags |=LOOKUP_LITERALLY ;if (get_sha1_with_context (obj_name,0 , sha1, &obj_context))die ("Not a valid object name %s" , obj_name);
builtin/cat-file.c static int cat_one_file(int opt, const char *exp_type, const char *obj_name) · line 34
Quoted 8 lines
builtin/cat-file.c +2
-3@@ -23,16 +30,24 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) buf =NULL ;switch (opt) {case 't' : - type =sha1_object_info (sha1,NULL ); -if (type >0 ) { -printf ("%s\n" ,typename (type)); + oi.typep = &type; + oi.typename = &sb;
These two lines are common to the -t and -s cases. Would it make sense to instead move them to just after 'oi' and 'sb' are declared? However (see below)...
builtin/cat-file.c static int cat_one_file(int opt, const char *exp_type, const char *obj_name) · line 39
Quoted 5 lines
builtin/cat-file.c +5
-0+if (sha1_object_info_extended (sha1, &oi, flags) <0 ) +die ("git cat-file: could not get object info" ); +if (type >=0 && sb.len) { +printf ("%s\n" , sb.buf); +strbuf_release (&sb);
Here you release the strbuf...
builtin/cat-file.c static int cat_one_file(int opt, const char *exp_type, const char *obj_name) · line 46
Quoted 9 lines
builtin/cat-file.c +2
-2return 0 ; }break ;case 's' : - type =sha1_object_info (sha1, &size); -if (type >0 ) { + oi.typep = &type; + oi.typename = &sb;
Why do you need to collect 'typename' for the -s case? sha1_object_info_extended() promises that 'type' will be zero in the --literally case for unknown types, so checking 'sb.len' in the conditional below doesn't buy you anything, does it?
In fact, it's not even clear why you need to collect 'type' in the -s case? The return value of sha1_object_info_extended() already tells you whether or not the 'size' was retrieved successfully (--literally or not).
builtin/cat-file.c static int cat_one_file(int opt, const char *exp_type, const char *obj_name) · line 51
Quoted 5 lines
builtin/cat-file.c +4
-0+ oi.sizep = &size; +if (sha1_object_info_extended (sha1, &oi, flags) <0 ) +die ("git cat-file: could not get object info" ); +if (type >=0 && sb.len) {printf ("%lu\n" , size);
But here you do not release the strbuf.
builtin/cat-file.c int cmd_cat_file(int argc, const char **argv, const char *prefix) · line 389
Quoted 8 lines
builtin/cat-file.c +2
-0return 0 ; }@@ -369,6 +385,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)OPT_SET_INT ('p' ,NULL , &opt,N_ ("pretty-print object's content" ),'p' ),OPT_SET_INT (0 ,"textconv" , &opt,N_ ("for blob objects, run textconv on object's content" ),'c' ), +OPT_BOOL (0 ,"literally" , &literally, + N_("get information about corrupt objects for debugging Git")),
This option neither "gets information" nor is it for debugging Git. Rather, it's useful for diagnosing broken/corrupt objects in combination with other options. Perhaps rephrase something like this:
"allow -s and -t to work with broken/corrupt objects"
Quoted 3 lines
builtin/cat-file.c +0
-0{OPTION_CALLBACK ,0 ,"batch" , &batch,"format" ,N_ ("show info and content of objects fed from the standard input" ), PARSE_OPT_OPTARG, batch_option_callback },
PATCH v7 3/4 cat-file: add documentation for '--literally' option.
In reply to karthik nayak--- Documentation/git-cat-file.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
Documentation/git-cat-file.txt +5 -1
@@ -9,7 +9,7 @@ git-cat-file - Provide content or type and size information for repository objec SYNOPSIS -------- [verse] -'git cat-file' (-t | -s | -e | -p | <type> | --textconv ) <object> +'git cat-file' (-t [--literally]| -s [--literally]| -e | -p | <type> | --textconv ) <object> 'git cat-file' (--batch | --batch-check) < <list-of-objects> DESCRIPTION
@@ -69,6 +69,10 @@ OPTIONS not be combined with any other options or arguments. See the section `BATCH OUTPUT` below for details. +--literally:: + Print information of broken/corrupt objects of unknown type without + throwing an error. To be used combined with '-s' or '-t' option. + OUTPUT ------ If '-t' is specified, one of the <type>.
Signature · 1 line
2.4.0.rc1.249.g9f2ee54
Re: [PATCH v7 3/4] cat-file: add documentation for '--literally' option.
Quoted 16 lines · Karthik Nayak
Signed-off-by Karthik Nayak <[email protected]>---
Documentation/git-cat-file.txt +1
-1@@ -9,7 +9,7 @@ git-cat-file - Provide content or type and size information for repository objec SYNOPSIS -------- [verse] -'git cat-file' (-t | -s | -e | -p | <type> | --textconv ) <object> +'git cat-file' (-t [--literally]| -s [--literally]| -e | -p | <type> | --textconv ) <object> 'git cat-file' (--batch | --batch-check) < <list-of-objects> DESCRIPTION
Documentation/git-cat-file.txt OPTIONS · line 74
Quoted 6 lines
Documentation/git-cat-file.txt +3
-0@@ -69,6 +69,10 @@ OPTIONS not be combined with any other options or arguments. See the section `BATCH OUTPUT` below for details. +--literally:: + Print information of broken/corrupt objects of unknown type without + throwing an error. To be used combined with '-s' or '-t' option.
The way this is worded, it sounds as if the --literally option itself is printing some sort of additional information beyond what -s or -t outputs. In fact, it merely allows -s and -t to work with broken/corrupt objects. Perhaps rephrase something like this?
Allow -s or -t to query broken or corrupt objects of unknown type.
Quoted 6 lines
Documentation/git-cat-file.txt +0
-1OUTPUT ------ If '-t' is specified, one of the <type>. --2.4.0.rc1.249.g9f2ee54
PATCH v7 4/4 t1006: add tests for git cat-file --literally
In reply to karthik nayak--- t/t1006-cat-file.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
t/t1006-cat-file.sh +27 -0
@@ -47,6 +47,18 @@ $content" test_cmp expect actual ' + test_expect_success "Type of $type is correct using --literally" ' + echo $type >expect && + git cat-file -t --literally $sha1 >actual && + test_cmp expect actual + ' + + test_expect_success "Size of $type is correct using --literally" ' + echo $size >expect && + git cat-file -s --literally $sha1 >actual && + test_cmp expect actual + ' + test -z "$content" || test_expect_success "Content of $type is correct" ' maybe_remove_timestamp "$content" $no_ts >expect &&
@@ -296,4 +308,19 @@ test_expect_success '%(deltabase) reports packed delta bases' ' } ' +bogus_type="bogus" +bogus_sha1=$(git hash-object -t $bogus_type --literally -w --stdin </dev/null) + +test_expect_success "Type of broken object is correct" ' + echo $bogus_type >expect && + git cat-file -t --literally $bogus_sha1 >actual && + test_cmp expect actual +' + +test_expect_success "Size of broken object is correct" ' + echo "0" >expect && + git cat-file -s --literally $bogus_sha1 >actual && + test_cmp expect actual +' + test_done
Signature · 1 line
2.4.0.rc1.249.g9f2ee54
Re: [PATCH v7 4/4] t1006: add tests for git cat-file --literally
Quoted 30 lines · Karthik Nayak
Signed-off-by Karthik Nayak <[email protected]>---
t/t1006-cat-file.sh +13
-0@@ -47,6 +47,18 @@ $content" test_cmp expect actual ' + test_expect_success "Type of $type is correct using --literally" ' + echo $type >expect && + git cat-file -t --literally $sha1 >actual && + test_cmp expect actual + ' + + test_expect_success "Size of $type is correct using --literally" ' + echo $size >expect && + git cat-file -s --literally $sha1 >actual && + test_cmp expect actual + ' + test -z "$content" || test_expect_success "Content of $type is correct" ' maybe_remove_timestamp "$content" $no_ts >expect &&@@ -296,4 +308,19 @@ test_expect_success '%(deltabase) reports packed delta bases' ' } ' +bogus_type="bogus"
t/t1006-cat-file.sh test_expect_success '%(deltabase) reports packed delta bases' ' · line 321
Quoted 10 lines
t/t1006-cat-file.sh +10
-0+bogus_sha1=$(git hash-object -t $bogus_type --literally -w --stdin </dev/null) + +test_expect_success "Type of broken object is correct" ' + echo $bogus_type >expect && + git cat-file -t --literally $bogus_sha1 >actual && + test_cmp expect actual +' + +test_expect_success "Size of broken object is correct" ' + echo "0" >expect &&
Zero is such a common fallback value when things go wrong that it may not be the best choice for this test. Consequently, it might be better to create the bogus object with non-zero length. Take a look at how 'hello_length' and 'hello_sha1' are computed elsewhere in this script for inspiration.
Quoted 7 lines
t/t1006-cat-file.sh +4
-1+ git cat-file -s --literally $bogus_sha1 >actual && + test_cmp expect actual +' + test_done --2.4.0.rc1.249.g9f2ee54
Re: [PATCH v7 4/4] t1006: add tests for git cat-file --literally
Quoted 39 lines · Eric Sunshine
Quoted 38 lines · Karthik Nayak
Signed-off-by Karthik Nayak <[email protected]>---
t/t1006-cat-file.sh +21
-0@@ -47,6 +47,18 @@ $content" test_cmp expect actual ' + test_expect_success "Type of $type is correct using --literally" ' + echo $type >expect && + git cat-file -t --literally $sha1 >actual && + test_cmp expect actual + ' + + test_expect_success "Size of $type is correct using --literally" ' + echo $size >expect && + git cat-file -s --literally $sha1 >actual && + test_cmp expect actual + ' + test -z "$content" || test_expect_success "Content of $type is correct" ' maybe_remove_timestamp "$content" $no_ts >expect &&@@ -296,4 +308,19 @@ test_expect_success '%(deltabase) reports packed delta bases' ' } ' +bogus_type="bogus" +bogus_sha1=$(git hash-object -t $bogus_type --literally -w --stdin </dev/null) + +test_expect_success "Type of broken object is correct" ' + echo $bogus_type >expect && + git cat-file -t --literally $bogus_sha1 >actual && + test_cmp expect actual +' +
Quoted 8 lines
t/t1006-cat-file.sh test_expect_success '%(deltabase) reports packed delta bases' ' · line 321
Quoted 2 lines
t/t1006-cat-file.sh +2
-0+test_expect_success "Size of broken object is correct" ' + echo "0" >expect &&Zero is such a common fallback value when things go wrong that it may not be the best choice for this test. Consequently, it might be better to create the bogus object with non-zero length. Take a look at how '
hello_length' and 'hello_sha1' are computed elsewhere in this script for inspiration.
The first part of this patch contains tests which make use of 'hello_length' adn 'hello_sha1', but I get what you're saying, will look into it. Thanks.
Quoted 8 lines
Quoted 8 lines
t/t1006-cat-file.sh +4
-1+ git cat-file -s --literally $bogus_sha1 >actual && + test_cmp expect actual +' + test_done --2.4.0.rc1.249.g9f2ee54
Re: [PATCH v7 4/4] t1006: add tests for git cat-file --literally
Quoted 33 lines · karthik nayak
Quoted 23 lines · Eric Sunshine
Quoted 21 lines · Karthik Nayak
Signed-off-by Karthik Nayak <[email protected]>---
t/t1006-cat-file.sh +0
-0@@ -296,4 +308,19 @@ test_expect_success '%(deltabase) reports packeddelta bases' '
}'
t/t1006-cat-file.sh +2
-0+bogus_type="bogus" +bogus_sha1=$(git hash-object -t $bogus_type --literally -w --stdin<
/dev/null)t/t1006-cat-file.sh +7
-0+ +test_expect_success "Type of broken object is correct" ' + echo $bogus_type >expect && + git cat-file -t --literally $bogus_sha1 >actual && + test_cmp expect actual +' +Quoted 8 lines
t/t1006-cat-file.sh test_expect_success '%(deltabase) reports packed delta bases' ' · line 321
Quoted 2 lines
t/t1006-cat-file.sh +2
-0+test_expect_success "Size of broken object is correct" ' + echo "0" >expect &&Zero is such a common fallback value when things go wrong that it may not be the best choice for this test. Consequently, it might be better to create the bogus object with non-zero length. Take a look at how '
hello_length' and 'hello_sha1' are computed elsewhere in this script for inspiration.
Quoted 2 lines
The first part of this patch contains tests which make use of '
hello_length' adn 'hello_sha1', but I get what you're saying, will look into it. Thanks.
Just to be sure we're on the same page, I wasn't suggesting re-using 'hello_size' and 'hello_sha1', but merely to use that as an example of how to avoid hard-coding the length of your non-zero-length bogus object. So, something like this, perhaps:
bogus_content='bogus'
bogus_size=$(strlen "$bogus_content")
bogus_sha1=$(echo_without_newline "$bogus_content" |
git hash-object -t $bogus_type --literally -w --stdin)
...
test_expect_success "Size of broken object is correct" '
echo $bogus_size >expect &&
...Re: [PATCH v7 4/4] t1006: add tests for git cat-file --literally
Quoted 51 lines · Eric Sunshine
Quoted 2 lines · karthik nayak
Quoted 1 line · Eric Sunshine
On Sat, Apr 4, 2015 at 1:44 AM, Karthik Nayak
Quoted 8 lines
Quoted 8 lines
t/t1006-cat-file.sh test_expect_success '%(deltabase) reports
Quoted 7 lines · wrote:
Signed-off-by Karthik Nayak <[email protected]>---
t/t1006-cat-file.sh +0
-0@@ -296,4 +308,19 @@ test_expect_success '%(deltabase) reportspacked
Quoted 6 lines
Quoted 6 lines
t/t1006-cat-file.sh
Quoted 6 lines
delta bases' '
}'
t/t1006-cat-file.sh +2
-0+bogus_type="bogus" +bogus_sha1=$(git hash-object -t $bogus_type --literally -w--stdin
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
<
/dev/null)t/t1006-cat-file.sh +3
-0+ +test_expect_success "Type of broken object is correct" ' + echo $bogus_type >expect &&Quoted 8 lines
Quoted 8 lines
t/t1006-cat-file.sh test_expect_success '%(deltabase) reports packed delta bases' ' · line 321
Quoted 6 lines
t/t1006-cat-file.sh +6
-0+ git cat-file -t --literally $bogus_sha1 >actual && + test_cmp expect actual +' + +test_expect_success "Size of broken object is correct" ' + echo "0" >expect &&Zero is such a common fallback value when things go wrong that it
may
Quoted 1 line
Quoted 1 line
not be the best choice for this test. Consequently, it might be
better
Quoted 2 lines
Quoted 2 lines
to create the bogus object with non-zero length. Take a look at how '
hello_length' and 'hello_sha1' are computed elsewhere in thisscript
Quoted 3 lines
Quoted 1 line
for inspiration.
The first part of this patch contains tests which make use of
'
hello_length'Quoted 1 line
adn '
hello_sha1', but I get what you're saying, will look into it.Thanks.
Just to be sure we're on the same page, I wasn't suggesting re-using '
hello_size' and 'hello_sha1', but merely to use that as an example of how to avoid hard-coding the length of your non-zero-length bogus object. So, something like this, perhaps:
Quoted 8 lines
bogus_content='bogus'
bogus_size=$(strlen "$bogus_content")
bogus_sha1=$(echo_without_newline "$bogus_content" |
git hash-object -t $bogus_type --literally -w --stdin)
...
test_expect_success "Size of broken object is correct" '
echo $bogus_size >expect &&
...Yes, I had done exactly what you suggested here. Thanks