88#include "pack.h"
99#include "cache-tree.h"
1010#include "tree-walk.h"
11+ #include "fsck.h"
1112#include "parse-options.h"
1213
1314#define REACHABLE 0x0001
@@ -63,13 +64,73 @@ static int objwarning(struct object *obj, const char *err, ...)
6364 return -1 ;
6465}
6566
67+ static int mark_object (struct object * obj , int type , void * data )
68+ {
69+ struct tree * tree = NULL ;
70+ struct object * parent = data ;
71+ int result ;
72+
73+ if (!obj ) {
74+ printf ("broken link from %7s %s\n" ,
75+ typename (parent -> type ), sha1_to_hex (parent -> sha1 ));
76+ printf ("broken link from %7s %s\n" ,
77+ (type == OBJ_ANY ? "unknown" : typename (type )), "unknown" );
78+ errors_found |= ERROR_REACHABLE ;
79+ return 1 ;
80+ }
81+
82+ if (type != OBJ_ANY && obj -> type != type )
83+ objerror (parent , "wrong object type in link" );
84+
85+ if (obj -> flags & REACHABLE )
86+ return 0 ;
87+ obj -> flags |= REACHABLE ;
88+ if (!obj -> parsed ) {
89+ if (parent && !has_sha1_file (obj -> sha1 )) {
90+ printf ("broken link from %7s %s\n" ,
91+ typename (parent -> type ), sha1_to_hex (parent -> sha1 ));
92+ printf (" to %7s %s\n" ,
93+ typename (obj -> type ), sha1_to_hex (obj -> sha1 ));
94+ errors_found |= ERROR_REACHABLE ;
95+ }
96+ return 1 ;
97+ }
98+
99+ if (obj -> type == OBJ_TREE ) {
100+ obj -> parsed = 0 ;
101+ tree = (struct tree * )obj ;
102+ if (parse_tree (tree ) < 0 )
103+ return 1 ; /* error already displayed */
104+ }
105+ result = fsck_walk (obj , mark_object , obj );
106+ if (tree ) {
107+ free (tree -> buffer );
108+ tree -> buffer = NULL ;
109+ }
110+ if (result < 0 )
111+ result = 1 ;
112+
113+ return result ;
114+ }
115+
116+ static void mark_object_reachable (struct object * obj )
117+ {
118+ mark_object (obj , OBJ_ANY , 0 );
119+ }
120+
121+ static int mark_used (struct object * obj , int type , void * data )
122+ {
123+ if (!obj )
124+ return 1 ;
125+ obj -> used = 1 ;
126+ return 0 ;
127+ }
128+
66129/*
67130 * Check a single reachable object
68131 */
69132static void check_reachable_object (struct object * obj )
70133{
71- const struct object_refs * refs ;
72-
73134 /*
74135 * We obviously want the object to be parsed,
75136 * except if it was in a pack-file and we didn't
@@ -82,25 +143,6 @@ static void check_reachable_object(struct object *obj)
82143 errors_found |= ERROR_REACHABLE ;
83144 return ;
84145 }
85-
86- /*
87- * Check that everything that we try to reference is also good.
88- */
89- refs = lookup_object_refs (obj );
90- if (refs ) {
91- unsigned j ;
92- for (j = 0 ; j < refs -> count ; j ++ ) {
93- struct object * ref = refs -> ref [j ];
94- if (ref -> parsed ||
95- (has_sha1_file (ref -> sha1 )))
96- continue ;
97- printf ("broken link from %7s %s\n" ,
98- typename (obj -> type ), sha1_to_hex (obj -> sha1 ));
99- printf (" to %7s %s\n" ,
100- typename (ref -> type ), sha1_to_hex (ref -> sha1 ));
101- errors_found |= ERROR_REACHABLE ;
102- }
103- }
104146}
105147
106148/*
@@ -414,6 +456,8 @@ static int fsck_sha1(const unsigned char *sha1)
414456 if (obj -> flags & SEEN )
415457 return 0 ;
416458 obj -> flags |= SEEN ;
459+ if (fsck_walk (obj , mark_used , 0 ))
460+ objerror (obj , "broken links" );
417461 if (obj -> type == OBJ_BLOB )
418462 return 0 ;
419463 if (obj -> type == OBJ_TREE )
@@ -538,13 +582,13 @@ static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
538582 obj = lookup_object (osha1 );
539583 if (obj ) {
540584 obj -> used = 1 ;
541- mark_reachable (obj , REACHABLE );
585+ mark_object_reachable (obj );
542586 }
543587 }
544588 obj = lookup_object (nsha1 );
545589 if (obj ) {
546590 obj -> used = 1 ;
547- mark_reachable (obj , REACHABLE );
591+ mark_object_reachable (obj );
548592 }
549593 return 0 ;
550594}
@@ -574,7 +618,7 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int f
574618 error ("%s: not a commit" , refname );
575619 default_refs ++ ;
576620 obj -> used = 1 ;
577- mark_reachable (obj , REACHABLE );
621+ mark_object_reachable (obj );
578622
579623 return 0 ;
580624}
@@ -660,7 +704,7 @@ static int fsck_cache_tree(struct cache_tree *it)
660704 sha1_to_hex (it -> sha1 ));
661705 return 1 ;
662706 }
663- mark_reachable (obj , REACHABLE );
707+ mark_object_reachable (obj );
664708 obj -> used = 1 ;
665709 if (obj -> type != OBJ_TREE )
666710 err |= objerror (obj , "non-tree in cache-tree" );
@@ -693,7 +737,6 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
693737{
694738 int i , heads ;
695739
696- track_object_refs = 1 ;
697740 errors_found = 0 ;
698741
699742 argc = parse_options (argc , argv , fsck_opts , fsck_usage , 0 );
@@ -741,7 +784,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
741784 continue ;
742785
743786 obj -> used = 1 ;
744- mark_reachable (obj , REACHABLE );
787+ mark_object_reachable (obj );
745788 heads ++ ;
746789 continue ;
747790 }
@@ -773,7 +816,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
773816 continue ;
774817 obj = & blob -> object ;
775818 obj -> used = 1 ;
776- mark_reachable (obj , REACHABLE );
819+ mark_object_reachable (obj );
777820 }
778821 if (active_cache_tree )
779822 fsck_cache_tree (active_cache_tree );
0 commit comments