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 ) \
67+ FUNC (GITIGNORE_SYMLINK , ERROR ) \
68+ FUNC (GITATTRIBUTES_SYMLINK , ERROR ) \
5469 /* warnings */ \
5570 FUNC (BAD_FILEMODE , WARN ) \
5671 FUNC (EMPTY_NAME , WARN ) \
@@ -561,10 +576,31 @@ static int fsck_tree(struct tree *item, struct fsck_options *options)
561576 has_empty_name |= !* name ;
562577 has_dot |= !strcmp (name , "." );
563578 has_dotdot |= !strcmp (name , ".." );
564- has_dotgit |= (!strcmp (name , ".git" ) ||
565- is_hfs_dotgit (name ) ||
566- is_ntfs_dotgit (name ));
579+ has_dotgit |= is_hfs_dotgit (name ) || is_ntfs_dotgit (name );
567580 has_zero_pad |= * (char * )desc .buffer == '0' ;
581+
582+ if (is_hfs_dotgitmodules (name ) || is_ntfs_dotgitmodules (name )) {
583+ if (!S_ISLNK (mode ))
584+ oidset_insert (& gitmodules_found , oid );
585+ else
586+ retval += report (options , & item -> object ,
587+ FSCK_MSG_GITMODULES_SYMLINK ,
588+ ".gitmodules is a symbolic link" );
589+ }
590+
591+ if (S_ISLNK (mode )) {
592+ if (is_hfs_dotgitignore (name ) ||
593+ is_ntfs_dotgitignore (name ))
594+ retval += report (options , & item -> object ,
595+ FSCK_MSG_GITIGNORE_SYMLINK ,
596+ ".gitignore is a symlink" );
597+ if (is_hfs_dotgitattributes (name ) ||
598+ is_ntfs_dotgitattributes (name ))
599+ retval += report (options , & item -> object ,
600+ FSCK_MSG_GITATTRIBUTES_SYMLINK ,
601+ ".gitattributes is a symlink" );
602+ }
603+
568604 if (update_tree_entry_gently (& desc )) {
569605 retval += report (options , & item -> object , FSCK_MSG_BAD_TREE , "cannot be parsed as a tree" );
570606 break ;
@@ -901,14 +937,74 @@ static int fsck_tag(struct tag *tag, const char *data,
901937 return fsck_tag_buffer (tag , data , size , options );
902938}
903939
940+ struct fsck_gitmodules_data {
941+ struct object * obj ;
942+ struct fsck_options * options ;
943+ int ret ;
944+ };
945+
946+ static int fsck_gitmodules_fn (const char * var , const char * value , void * vdata )
947+ {
948+ struct fsck_gitmodules_data * data = vdata ;
949+ const char * subsection , * key ;
950+ int subsection_len ;
951+ char * name ;
952+
953+ if (parse_config_key (var , "submodule" , & subsection , & subsection_len , & key ) < 0 ||
954+ !subsection )
955+ return 0 ;
956+
957+ name = xmemdupz (subsection , subsection_len );
958+ if (check_submodule_name (name ) < 0 )
959+ data -> ret |= report (data -> options , data -> obj ,
960+ FSCK_MSG_GITMODULES_NAME ,
961+ "disallowed submodule name: %s" ,
962+ name );
963+ free (name );
964+
965+ return 0 ;
966+ }
967+
968+ static int fsck_blob (struct blob * blob , const char * buf ,
969+ unsigned long size , struct fsck_options * options )
970+ {
971+ struct fsck_gitmodules_data data ;
972+
973+ if (!oidset_contains (& gitmodules_found , & blob -> object .oid ))
974+ return 0 ;
975+ oidset_insert (& gitmodules_done , & blob -> object .oid );
976+
977+ if (!buf ) {
978+ /*
979+ * A missing buffer here is a sign that the caller found the
980+ * blob too gigantic to load into memory. Let's just consider
981+ * that an error.
982+ */
983+ return report (options , & blob -> object ,
984+ FSCK_MSG_GITMODULES_PARSE ,
985+ ".gitmodules too large to parse" );
986+ }
987+
988+ data .obj = & blob -> object ;
989+ data .options = options ;
990+ data .ret = 0 ;
991+ if (git_config_from_mem (fsck_gitmodules_fn , CONFIG_ORIGIN_BLOB ,
992+ ".gitmodules" , buf , size , & data ))
993+ data .ret |= report (options , & blob -> object ,
994+ FSCK_MSG_GITMODULES_PARSE ,
995+ "could not parse gitmodules blob" );
996+
997+ return data .ret ;
998+ }
999+
9041000int fsck_object (struct object * obj , void * data , unsigned long size ,
9051001 struct fsck_options * options )
9061002{
9071003 if (!obj )
9081004 return report (options , obj , FSCK_MSG_BAD_OBJECT_SHA1 , "no valid object to fsck" );
9091005
9101006 if (obj -> type == OBJ_BLOB )
911- return 0 ;
1007+ return fsck_blob (( struct blob * ) obj , data , size , options ) ;
9121008 if (obj -> type == OBJ_TREE )
9131009 return fsck_tree ((struct tree * ) obj , options );
9141010 if (obj -> type == OBJ_COMMIT )
@@ -932,3 +1028,52 @@ int fsck_error_function(struct fsck_options *o,
9321028 error ("object %s: %s" , describe_object (o , obj ), message );
9331029 return 1 ;
9341030}
1031+
1032+ int fsck_finish (struct fsck_options * options )
1033+ {
1034+ int ret = 0 ;
1035+ struct oidset_iter iter ;
1036+ const struct object_id * oid ;
1037+
1038+ oidset_iter_init (& gitmodules_found , & iter );
1039+ while ((oid = oidset_iter_next (& iter ))) {
1040+ struct blob * blob ;
1041+ enum object_type type ;
1042+ unsigned long size ;
1043+ char * buf ;
1044+
1045+ if (oidset_contains (& gitmodules_done , oid ))
1046+ continue ;
1047+
1048+ blob = lookup_blob (oid );
1049+ if (!blob ) {
1050+ ret |= report (options , & blob -> object ,
1051+ FSCK_MSG_GITMODULES_BLOB ,
1052+ "non-blob found at .gitmodules" );
1053+ continue ;
1054+ }
1055+
1056+ buf = read_sha1_file (oid -> hash , & type , & size );
1057+ if (!buf ) {
1058+ if (is_promisor_object (& blob -> object .oid ))
1059+ continue ;
1060+ ret |= report (options , & blob -> object ,
1061+ FSCK_MSG_GITMODULES_MISSING ,
1062+ "unable to read .gitmodules blob" );
1063+ continue ;
1064+ }
1065+
1066+ if (type == OBJ_BLOB )
1067+ ret |= fsck_blob (blob , buf , size , options );
1068+ else
1069+ ret |= report (options , & blob -> object ,
1070+ FSCK_MSG_GITMODULES_BLOB ,
1071+ "non-blob found at .gitmodules" );
1072+ free (buf );
1073+ }
1074+
1075+
1076+ oidset_clear (& gitmodules_found );
1077+ oidset_clear (& gitmodules_done );
1078+ return ret ;
1079+ }
0 commit comments