1010#include "utf8.h"
1111#include "sha1-array.h"
1212#include "decorate.h"
13+ #include "oidset.h"
14+ #include "packfile.h"
15+ #include "submodule-config.h"
16+ #include "config.h"
17+
18+ static struct oidset gitmodules_found = OIDSET_INIT ;
19+ static struct oidset gitmodules_done = OIDSET_INIT ;
1320
1421#define FSCK_FATAL -1
1522#define FSCK_INFO -2
4451 FUNC (MISSING_TAG_ENTRY , ERROR ) \
4552 FUNC (MISSING_TAG_OBJECT , ERROR ) \
4653 FUNC (MISSING_TREE , ERROR ) \
54+ FUNC (MISSING_TREE_OBJECT , ERROR ) \
4755 FUNC (MISSING_TYPE , ERROR ) \
4856 FUNC (MISSING_TYPE_ENTRY , ERROR ) \
4957 FUNC (MULTIPLE_AUTHORS , ERROR ) \
5058 FUNC (TAG_OBJECT_NOT_TAG , ERROR ) \
5159 FUNC (TREE_NOT_SORTED , ERROR ) \
5260 FUNC (UNKNOWN_TYPE , ERROR ) \
5361 FUNC (ZERO_PADDED_DATE , ERROR ) \
62+ FUNC (GITMODULES_MISSING , ERROR ) \
63+ FUNC (GITMODULES_BLOB , ERROR ) \
64+ FUNC (GITMODULES_PARSE , ERROR ) \
65+ FUNC (GITMODULES_NAME , ERROR ) \
66+ FUNC (GITMODULES_SYMLINK , ERROR ) \
5467 /* warnings */ \
5568 FUNC (BAD_FILEMODE , WARN ) \
5669 FUNC (EMPTY_NAME , WARN ) \
@@ -561,10 +574,18 @@ static int fsck_tree(struct tree *item, struct fsck_options *options)
561574 has_empty_name |= !* name ;
562575 has_dot |= !strcmp (name , "." );
563576 has_dotdot |= !strcmp (name , ".." );
564- has_dotgit |= (!strcmp (name , ".git" ) ||
565- is_hfs_dotgit (name ) ||
566- is_ntfs_dotgit (name ));
577+ has_dotgit |= is_hfs_dotgit (name ) || is_ntfs_dotgit (name );
567578 has_zero_pad |= * (char * )desc .buffer == '0' ;
579+
580+ if (is_hfs_dotgitmodules (name ) || is_ntfs_dotgitmodules (name )) {
581+ if (!S_ISLNK (mode ))
582+ oidset_insert (& gitmodules_found , oid );
583+ else
584+ retval += report (options , & item -> object ,
585+ FSCK_MSG_GITMODULES_SYMLINK ,
586+ ".gitmodules is a symbolic link" );
587+ }
588+
568589 if (update_tree_entry_gently (& desc )) {
569590 retval += report (options , & item -> object , FSCK_MSG_BAD_TREE , "cannot be parsed as a tree" );
570591 break ;
@@ -901,14 +922,74 @@ static int fsck_tag(struct tag *tag, const char *data,
901922 return fsck_tag_buffer (tag , data , size , options );
902923}
903924
925+ struct fsck_gitmodules_data {
926+ struct object * obj ;
927+ struct fsck_options * options ;
928+ int ret ;
929+ };
930+
931+ static int fsck_gitmodules_fn (const char * var , const char * value , void * vdata )
932+ {
933+ struct fsck_gitmodules_data * data = vdata ;
934+ const char * subsection , * key ;
935+ int subsection_len ;
936+ char * name ;
937+
938+ if (parse_config_key (var , "submodule" , & subsection , & subsection_len , & key ) < 0 ||
939+ !subsection )
940+ return 0 ;
941+
942+ name = xmemdupz (subsection , subsection_len );
943+ if (check_submodule_name (name ) < 0 )
944+ data -> ret |= report (data -> options , data -> obj ,
945+ FSCK_MSG_GITMODULES_NAME ,
946+ "disallowed submodule name: %s" ,
947+ name );
948+ free (name );
949+
950+ return 0 ;
951+ }
952+
953+ static int fsck_blob (struct blob * blob , const char * buf ,
954+ unsigned long size , struct fsck_options * options )
955+ {
956+ struct fsck_gitmodules_data data ;
957+
958+ if (!oidset_contains (& gitmodules_found , & blob -> object .oid ))
959+ return 0 ;
960+ oidset_insert (& gitmodules_done , & blob -> object .oid );
961+
962+ if (!buf ) {
963+ /*
964+ * A missing buffer here is a sign that the caller found the
965+ * blob too gigantic to load into memory. Let's just consider
966+ * that an error.
967+ */
968+ return report (options , & blob -> object ,
969+ FSCK_MSG_GITMODULES_PARSE ,
970+ ".gitmodules too large to parse" );
971+ }
972+
973+ data .obj = & blob -> object ;
974+ data .options = options ;
975+ data .ret = 0 ;
976+ if (git_config_from_mem (fsck_gitmodules_fn , CONFIG_ORIGIN_BLOB ,
977+ ".gitmodules" , buf , size , & data ))
978+ data .ret |= report (options , & blob -> object ,
979+ FSCK_MSG_GITMODULES_PARSE ,
980+ "could not parse gitmodules blob" );
981+
982+ return data .ret ;
983+ }
984+
904985int fsck_object (struct object * obj , void * data , unsigned long size ,
905986 struct fsck_options * options )
906987{
907988 if (!obj )
908989 return report (options , obj , FSCK_MSG_BAD_OBJECT_SHA1 , "no valid object to fsck" );
909990
910991 if (obj -> type == OBJ_BLOB )
911- return 0 ;
992+ return fsck_blob (( struct blob * ) obj , data , size , options ) ;
912993 if (obj -> type == OBJ_TREE )
913994 return fsck_tree ((struct tree * ) obj , options );
914995 if (obj -> type == OBJ_COMMIT )
@@ -932,3 +1013,52 @@ int fsck_error_function(struct fsck_options *o,
9321013 error ("object %s: %s" , describe_object (o , obj ), message );
9331014 return 1 ;
9341015}
1016+
1017+ int fsck_finish (struct fsck_options * options )
1018+ {
1019+ int ret = 0 ;
1020+ struct oidset_iter iter ;
1021+ const struct object_id * oid ;
1022+
1023+ oidset_iter_init (& gitmodules_found , & iter );
1024+ while ((oid = oidset_iter_next (& iter ))) {
1025+ struct blob * blob ;
1026+ enum object_type type ;
1027+ unsigned long size ;
1028+ char * buf ;
1029+
1030+ if (oidset_contains (& gitmodules_done , oid ))
1031+ continue ;
1032+
1033+ blob = lookup_blob (oid );
1034+ if (!blob ) {
1035+ ret |= report (options , & blob -> object ,
1036+ FSCK_MSG_GITMODULES_BLOB ,
1037+ "non-blob found at .gitmodules" );
1038+ continue ;
1039+ }
1040+
1041+ buf = read_sha1_file (oid -> hash , & type , & size );
1042+ if (!buf ) {
1043+ if (is_promisor_object (& blob -> object .oid ))
1044+ continue ;
1045+ ret |= report (options , & blob -> object ,
1046+ FSCK_MSG_GITMODULES_MISSING ,
1047+ "unable to read .gitmodules blob" );
1048+ continue ;
1049+ }
1050+
1051+ if (type == OBJ_BLOB )
1052+ ret |= fsck_blob (blob , buf , size , options );
1053+ else
1054+ ret |= report (options , & blob -> object ,
1055+ FSCK_MSG_GITMODULES_BLOB ,
1056+ "non-blob found at .gitmodules" );
1057+ free (buf );
1058+ }
1059+
1060+
1061+ oidset_clear (& gitmodules_found );
1062+ oidset_clear (& gitmodules_done );
1063+ return ret ;
1064+ }
0 commit comments