1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.internal.storage.dfs;
45
46 import static java.nio.charset.StandardCharsets.UTF_8;
47 import static org.eclipse.jgit.internal.storage.pack.PackExt.INDEX;
48 import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
49
50 import java.io.FileNotFoundException;
51 import java.io.IOException;
52
53 import org.eclipse.jgit.errors.CorruptPackIndexException;
54 import org.eclipse.jgit.errors.MissingObjectException;
55 import org.eclipse.jgit.internal.JGitText;
56 import org.eclipse.jgit.internal.fsck.FsckError;
57 import org.eclipse.jgit.internal.fsck.FsckError.CorruptIndex;
58 import org.eclipse.jgit.internal.fsck.FsckError.CorruptObject;
59 import org.eclipse.jgit.internal.fsck.FsckPackParser;
60 import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
61 import org.eclipse.jgit.internal.submodule.SubmoduleValidator;
62 import org.eclipse.jgit.internal.submodule.SubmoduleValidator.SubmoduleValidationException;
63 import org.eclipse.jgit.lib.AnyObjectId;
64 import org.eclipse.jgit.lib.Constants;
65 import org.eclipse.jgit.lib.GitmoduleEntry;
66 import org.eclipse.jgit.lib.NullProgressMonitor;
67 import org.eclipse.jgit.lib.ObjectChecker;
68 import org.eclipse.jgit.lib.ObjectId;
69 import org.eclipse.jgit.lib.ObjectLoader;
70 import org.eclipse.jgit.lib.ProgressMonitor;
71 import org.eclipse.jgit.lib.Ref;
72 import org.eclipse.jgit.revwalk.ObjectWalk;
73 import org.eclipse.jgit.revwalk.RevObject;
74
75
76
77
78 public class DfsFsck {
79 private final DfsRepository repo;
80 private final DfsObjDatabase objdb;
81 private ObjectCheckerr.html#ObjectChecker">ObjectChecker objChecker = new ObjectChecker();
82 private boolean connectivityOnly;
83
84
85
86
87
88
89
90 public DfsFsck(DfsRepository repository) {
91 repo = repository;
92 objdb = repo.getObjectDatabase();
93 }
94
95
96
97
98
99
100
101
102
103
104
105 public FsckError check(ProgressMonitor pm) throws IOException {
106 if (pm == null) {
107 pm = NullProgressMonitor.INSTANCE;
108 }
109
110 FsckError errors = new FsckError();
111 if (!connectivityOnly) {
112 objChecker.reset();
113 checkPacks(pm, errors);
114 }
115 checkConnectivity(pm, errors);
116 return errors;
117 }
118
119 private void checkPacks(ProgressMonitor pm, FsckError errors)
120 throws IOException, FileNotFoundException {
121 try (DfsReader ctx = objdb.newReader()) {
122 for (DfsPackFile pack : objdb.getPacks()) {
123 DfsPackDescription packDesc = pack.getPackDescription();
124 if (packDesc.getPackSource()
125 == PackSource.UNREACHABLE_GARBAGE) {
126 continue;
127 }
128 try (ReadableChannel rc = objdb.openFile(packDesc, PACK)) {
129 verifyPack(pm, errors, ctx, pack, rc);
130 } catch (MissingObjectException e) {
131 errors.getMissingObjects().add(e.getObjectId());
132 } catch (CorruptPackIndexException e) {
133 errors.getCorruptIndices().add(new CorruptIndex(
134 pack.getPackDescription().getFileName(INDEX),
135 e.getErrorType()));
136 }
137 }
138 }
139
140 checkGitModules(pm, errors);
141 }
142
143 private void verifyPack(ProgressMonitor pm, FsckError errors, DfsReader ctx,
144 DfsPackFile pack, ReadableChannel ch)
145 throws IOException, CorruptPackIndexException {
146 FsckPackParser fpp = new FsckPackParser(objdb, ch);
147 fpp.setObjectChecker(objChecker);
148 fpp.overwriteObjectCount(pack.getPackDescription().getObjectCount());
149 fpp.parse(pm);
150 errors.getCorruptObjects().addAll(fpp.getCorruptObjects());
151
152 fpp.verifyIndex(pack.getPackIndex(ctx));
153 }
154
155 private void checkGitModules(ProgressMonitor pm, FsckError errors)
156 throws IOException {
157 pm.beginTask(JGitText.get().validatingGitModules,
158 objChecker.getGitsubmodules().size());
159 for (GitmoduleEntry entry : objChecker.getGitsubmodules()) {
160 AnyObjectId blobId = entry.getBlobId();
161 ObjectLoader blob = objdb.open(blobId, Constants.OBJ_BLOB);
162
163 try {
164 SubmoduleValidator.assertValidGitModulesFile(
165 new String(blob.getBytes(), UTF_8));
166 } catch (SubmoduleValidationException e) {
167 CorruptObject co = new FsckError.CorruptObject(
168 blobId.toObjectId(), Constants.OBJ_BLOB,
169 e.getFsckMessageId());
170 errors.getCorruptObjects().add(co);
171 }
172 pm.update(1);
173 }
174 pm.endTask();
175 }
176
177 private void checkConnectivity(ProgressMonitor pm, FsckError errors)
178 throws IOException {
179 pm.beginTask(JGitText.get().countingObjects, ProgressMonitor.UNKNOWN);
180 try (ObjectWalklk/ObjectWalk.html#ObjectWalk">ObjectWalk ow = new ObjectWalk(repo)) {
181 for (Ref r : repo.getRefDatabase().getRefs()) {
182 ObjectId objectId = r.getObjectId();
183 if (objectId == null) {
184
185 continue;
186 }
187 RevObject tip;
188 try {
189 tip = ow.parseAny(objectId);
190 if (r.getLeaf().getName().startsWith(Constants.R_HEADS)
191 && tip.getType() != Constants.OBJ_COMMIT) {
192
193 errors.getNonCommitHeads().add(r.getLeaf().getName());
194 }
195 ow.markStart(tip);
196 } catch (MissingObjectException e) {
197 errors.getMissingObjects().add(e.getObjectId());
198 continue;
199 }
200 }
201 try {
202 ow.checkConnectivity();
203 } catch (MissingObjectException e) {
204 errors.getMissingObjects().add(e.getObjectId());
205 }
206 }
207 pm.endTask();
208 }
209
210
211
212
213
214
215
216
217
218
219
220 public void setObjectChecker(ObjectChecker objChecker) {
221 this.objChecker = objChecker;
222 }
223
224
225
226
227
228
229
230
231
232
233 public void setConnectivityOnly(boolean connectivityOnly) {
234 this.connectivityOnly = connectivityOnly;
235 }
236 }