@@ -1812,9 +1812,114 @@ static int packed_fsck_ref_header(struct fsck_options *o,
18121812 return 0 ;
18131813}
18141814
1815+ static int packed_fsck_ref_peeled_line (struct fsck_options * o ,
1816+ struct ref_store * ref_store ,
1817+ unsigned long line_number ,
1818+ const char * start , const char * eol )
1819+ {
1820+ struct strbuf packed_entry = STRBUF_INIT ;
1821+ struct fsck_ref_report report = { 0 };
1822+ struct object_id peeled ;
1823+ const char * p ;
1824+ int ret = 0 ;
1825+
1826+ /*
1827+ * Skip the '^' and parse the peeled oid.
1828+ */
1829+ start ++ ;
1830+ if (parse_oid_hex_algop (start , & peeled , & p , ref_store -> repo -> hash_algo )) {
1831+ strbuf_addf (& packed_entry , "packed-refs line %lu" , line_number );
1832+ report .path = packed_entry .buf ;
1833+
1834+ ret = fsck_report_ref (o , & report ,
1835+ FSCK_MSG_BAD_PACKED_REF_ENTRY ,
1836+ "'%.*s' has invalid peeled oid" ,
1837+ (int )(eol - start ), start );
1838+ goto cleanup ;
1839+ }
1840+
1841+ if (p != eol ) {
1842+ strbuf_addf (& packed_entry , "packed-refs line %lu" , line_number );
1843+ report .path = packed_entry .buf ;
1844+
1845+ ret = fsck_report_ref (o , & report ,
1846+ FSCK_MSG_BAD_PACKED_REF_ENTRY ,
1847+ "has trailing garbage after peeled oid '%.*s'" ,
1848+ (int )(eol - p ), p );
1849+ goto cleanup ;
1850+ }
1851+
1852+ cleanup :
1853+ strbuf_release (& packed_entry );
1854+ return ret ;
1855+ }
1856+
1857+ static int packed_fsck_ref_main_line (struct fsck_options * o ,
1858+ struct ref_store * ref_store ,
1859+ unsigned long line_number ,
1860+ struct strbuf * refname ,
1861+ const char * start , const char * eol )
1862+ {
1863+ struct strbuf packed_entry = STRBUF_INIT ;
1864+ struct fsck_ref_report report = { 0 };
1865+ struct object_id oid ;
1866+ const char * p ;
1867+ int ret = 0 ;
1868+
1869+ if (parse_oid_hex_algop (start , & oid , & p , ref_store -> repo -> hash_algo )) {
1870+ strbuf_addf (& packed_entry , "packed-refs line %lu" , line_number );
1871+ report .path = packed_entry .buf ;
1872+
1873+ ret = fsck_report_ref (o , & report ,
1874+ FSCK_MSG_BAD_PACKED_REF_ENTRY ,
1875+ "'%.*s' has invalid oid" ,
1876+ (int )(eol - start ), start );
1877+ goto cleanup ;
1878+ }
1879+
1880+ if (p == eol || !isspace (* p )) {
1881+ strbuf_addf (& packed_entry , "packed-refs line %lu" , line_number );
1882+ report .path = packed_entry .buf ;
1883+
1884+ ret = fsck_report_ref (o , & report ,
1885+ FSCK_MSG_BAD_PACKED_REF_ENTRY ,
1886+ "has no space after oid '%s' but with '%.*s'" ,
1887+ oid_to_hex (& oid ), (int )(eol - p ), p );
1888+ goto cleanup ;
1889+ }
1890+
1891+ p ++ ;
1892+ strbuf_reset (refname );
1893+ strbuf_add (refname , p , eol - p );
1894+ if (refname_contains_nul (refname )) {
1895+ strbuf_addf (& packed_entry , "packed-refs line %lu" , line_number );
1896+ report .path = packed_entry .buf ;
1897+
1898+ ret = fsck_report_ref (o , & report ,
1899+ FSCK_MSG_BAD_PACKED_REF_ENTRY ,
1900+ "refname '%s' contains NULL binaries" ,
1901+ refname -> buf );
1902+ }
1903+
1904+ if (check_refname_format (refname -> buf , 0 )) {
1905+ strbuf_addf (& packed_entry , "packed-refs line %lu" , line_number );
1906+ report .path = packed_entry .buf ;
1907+
1908+ ret = fsck_report_ref (o , & report ,
1909+ FSCK_MSG_BAD_REF_NAME ,
1910+ "has bad refname '%s'" , refname -> buf );
1911+ }
1912+
1913+ cleanup :
1914+ strbuf_release (& packed_entry );
1915+ return ret ;
1916+ }
1917+
18151918static int packed_fsck_ref_content (struct fsck_options * o ,
1919+ struct ref_store * ref_store ,
18161920 const char * start , const char * eof )
18171921{
1922+ struct strbuf refname = STRBUF_INIT ;
18181923 unsigned long line_number = 1 ;
18191924 const char * eol ;
18201925 int ret = 0 ;
@@ -1827,6 +1932,21 @@ static int packed_fsck_ref_content(struct fsck_options *o,
18271932 line_number ++ ;
18281933 }
18291934
1935+ while (start < eof ) {
1936+ ret |= packed_fsck_ref_next_line (o , line_number , start , eof , & eol );
1937+ ret |= packed_fsck_ref_main_line (o , ref_store , line_number , & refname , start , eol );
1938+ start = eol + 1 ;
1939+ line_number ++ ;
1940+ if (start < eof && * start == '^' ) {
1941+ ret |= packed_fsck_ref_next_line (o , line_number , start , eof , & eol );
1942+ ret |= packed_fsck_ref_peeled_line (o , ref_store , line_number ,
1943+ start , eol );
1944+ start = eol + 1 ;
1945+ line_number ++ ;
1946+ }
1947+ }
1948+
1949+ strbuf_release (& refname );
18301950 return ret ;
18311951}
18321952
@@ -1884,7 +2004,7 @@ static int packed_fsck(struct ref_store *ref_store,
18842004 goto cleanup ;
18852005 }
18862006
1887- ret = packed_fsck_ref_content (o , packed_ref_content .buf ,
2007+ ret = packed_fsck_ref_content (o , ref_store , packed_ref_content .buf ,
18882008 packed_ref_content .buf + packed_ref_content .len );
18892009
18902010cleanup :
0 commit comments