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