@@ -804,11 +804,38 @@ static const char *parse_ref_line(char *line, unsigned char *sha1)
804804 return line ;
805805}
806806
807+ /*
808+ * Read f, which is a packed-refs file, into dir.
809+ *
810+ * A comment line of the form "# pack-refs with: " may contain zero or
811+ * more traits. We interpret the traits as follows:
812+ *
813+ * No traits:
814+ *
815+ * Probably no references are peeled. But if the file contains a
816+ * peeled value for a reference, we will use it.
817+ *
818+ * peeled:
819+ *
820+ * References under "refs/tags/", if they *can* be peeled, *are*
821+ * peeled in this file. References outside of "refs/tags/" are
822+ * probably not peeled even if they could have been, but if we find
823+ * a peeled value for such a reference we will use it.
824+ *
825+ * fully-peeled:
826+ *
827+ * All references in the file that can be peeled are peeled.
828+ * Inversely (and this is more important), any references in the
829+ * file for which no peeled value is recorded is not peelable. This
830+ * trait should typically be written alongside "peeled" for
831+ * compatibility with older clients, but we do not require it
832+ * (i.e., "peeled" is a no-op if "fully-peeled" is set).
833+ */
807834static void read_packed_refs (FILE * f , struct ref_dir * dir )
808835{
809836 struct ref_entry * last = NULL ;
810837 char refline [PATH_MAX ];
811- int flag = REF_ISPACKED ;
838+ enum { PEELED_NONE , PEELED_TAGS , PEELED_FULLY } peeled = PEELED_NONE ;
812839
813840 while (fgets (refline , sizeof (refline ), f )) {
814841 unsigned char sha1 [20 ];
@@ -817,24 +844,36 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
817844
818845 if (!strncmp (refline , header , sizeof (header )- 1 )) {
819846 const char * traits = refline + sizeof (header ) - 1 ;
820- if (strstr (traits , " peeled " ))
821- flag |= REF_KNOWS_PEELED ;
847+ if (strstr (traits , " fully-peeled " ))
848+ peeled = PEELED_FULLY ;
849+ else if (strstr (traits , " peeled " ))
850+ peeled = PEELED_TAGS ;
822851 /* perhaps other traits later as well */
823852 continue ;
824853 }
825854
826855 refname = parse_ref_line (refline , sha1 );
827856 if (refname ) {
828- last = create_ref_entry (refname , sha1 , flag , 1 );
857+ last = create_ref_entry (refname , sha1 , REF_ISPACKED , 1 );
858+ if (peeled == PEELED_FULLY ||
859+ (peeled == PEELED_TAGS && !prefixcmp (refname , "refs/tags/" )))
860+ last -> flag |= REF_KNOWS_PEELED ;
829861 add_ref (dir , last );
830862 continue ;
831863 }
832864 if (last &&
833865 refline [0 ] == '^' &&
834866 strlen (refline ) == 42 &&
835867 refline [41 ] == '\n' &&
836- !get_sha1_hex (refline + 1 , sha1 ))
868+ !get_sha1_hex (refline + 1 , sha1 )) {
837869 hashcpy (last -> u .value .peeled , sha1 );
870+ /*
871+ * Regardless of what the file header said,
872+ * we definitely know the value of *this*
873+ * reference:
874+ */
875+ last -> flag |= REF_KNOWS_PEELED ;
876+ }
838877 }
839878}
840879
0 commit comments