@@ -23,50 +23,102 @@ static void add_to_ref_list(const unsigned char *sha1, const char *name,
2323 list -> nr ++ ;
2424}
2525
26- /* returns an fd */
27- int read_bundle_header ( const char * path , struct bundle_header * header )
26+ /* Eventually this should go to strbuf.[ch] */
27+ static int strbuf_readline_fd ( struct strbuf * sb , int fd )
2828{
29- char buffer [1024 ];
30- int fd ;
31- long fpos ;
32- FILE * ffd = fopen (path , "rb" );
29+ strbuf_reset (sb );
30+
31+ while (1 ) {
32+ char ch ;
33+ ssize_t len = xread (fd , & ch , 1 );
34+ if (len < 0 )
35+ return -1 ;
36+ strbuf_addch (sb , ch );
37+ if (ch == '\n' )
38+ break ;
39+ }
40+ return 0 ;
41+ }
3342
34- if (!ffd )
35- return error ("could not open '%s'" , path );
36- if (!fgets (buffer , sizeof (buffer ), ffd ) ||
37- strcmp (buffer , bundle_signature )) {
38- fclose (ffd );
39- return error ("'%s' does not look like a v2 bundle file" , path );
43+ static int parse_bundle_header (int fd , struct bundle_header * header ,
44+ const char * report_path )
45+ {
46+ struct strbuf buf = STRBUF_INIT ;
47+ int status = 0 ;
48+
49+ /* The bundle header begins with the signature */
50+ if (strbuf_readline_fd (& buf , fd ) ||
51+ strcmp (buf .buf , bundle_signature )) {
52+ if (report_path )
53+ error ("'%s' does not look like a v2 bundle file" ,
54+ report_path );
55+ status = -1 ;
56+ goto abort ;
4057 }
41- while (fgets (buffer , sizeof (buffer ), ffd )
42- && buffer [0 ] != '\n' ) {
43- int is_prereq = buffer [0 ] == '-' ;
44- int offset = is_prereq ? 1 : 0 ;
45- int len = strlen (buffer );
58+
59+ /* The bundle header ends with an empty line */
60+ while (!strbuf_readline_fd (& buf , fd ) &&
61+ buf .len && buf .buf [0 ] != '\n' ) {
4662 unsigned char sha1 [20 ];
47- struct ref_list * list = is_prereq ? & header -> prerequisites
48- : & header -> references ;
49- char delim ;
50-
51- if (len && buffer [len - 1 ] == '\n' )
52- buffer [len - 1 ] = '\0' ;
53- if (get_sha1_hex (buffer + offset , sha1 )) {
54- warning ("unrecognized header: %s" , buffer );
55- continue ;
63+ int is_prereq = 0 ;
64+
65+ if (* buf .buf == '-' ) {
66+ is_prereq = 1 ;
67+ strbuf_remove (& buf , 0 , 1 );
68+ }
69+ strbuf_rtrim (& buf );
70+
71+ /*
72+ * Tip lines have object name, SP, and refname.
73+ * Prerequisites have object name that is optionally
74+ * followed by SP and subject line.
75+ */
76+ if (get_sha1_hex (buf .buf , sha1 ) ||
77+ (40 <= buf .len && !isspace (buf .buf [40 ])) ||
78+ (!is_prereq && buf .len <= 40 )) {
79+ if (report_path )
80+ error ("unrecognized header: %s%s (%d)" ,
81+ (is_prereq ? "-" : "" ), buf .buf , (int )buf .len );
82+ status = -1 ;
83+ break ;
84+ } else {
85+ if (is_prereq )
86+ add_to_ref_list (sha1 , "" , & header -> prerequisites );
87+ else
88+ add_to_ref_list (sha1 , buf .buf + 41 , & header -> references );
5689 }
57- delim = buffer [40 + offset ];
58- if (!isspace (delim ) && (delim != '\0' || !is_prereq ))
59- die ("invalid header: %s" , buffer );
60- add_to_ref_list (sha1 , isspace (delim ) ?
61- buffer + 41 + offset : "" , list );
6290 }
63- fpos = ftell (ffd );
64- fclose (ffd );
65- fd = open (path , O_RDONLY );
91+
92+ abort :
93+ if (status ) {
94+ close (fd );
95+ fd = -1 ;
96+ }
97+ strbuf_release (& buf );
98+ return fd ;
99+ }
100+
101+ int read_bundle_header (const char * path , struct bundle_header * header )
102+ {
103+ int fd = open (path , O_RDONLY );
104+
66105 if (fd < 0 )
67106 return error ("could not open '%s'" , path );
68- lseek (fd , fpos , SEEK_SET );
69- return fd ;
107+ return parse_bundle_header (fd , header , path );
108+ }
109+
110+ int is_bundle (const char * path , int quiet )
111+ {
112+ struct bundle_header header ;
113+ int fd = open (path , O_RDONLY );
114+
115+ if (fd < 0 )
116+ return 0 ;
117+ memset (& header , 0 , sizeof (header ));
118+ fd = parse_bundle_header (fd , & header , quiet ? NULL : path );
119+ if (fd >= 0 )
120+ close (fd );
121+ return (fd >= 0 );
70122}
71123
72124static int list_refs (struct ref_list * r , int argc , const char * * argv )
0 commit comments