"refs/heads/master");
}
+ private ObjectId insertGitModules(String contents) throws IOException {
+ ObjectId blobId = ins.insert(Constants.OBJ_BLOB,
+ Constants.encode(contents));
+
+ byte[] blobIdBytes = new byte[OBJECT_ID_LENGTH];
+ blobId.copyRawTo(blobIdBytes, 0);
+ byte[] data = concat(encodeASCII("100644 .gitmodules\0"), blobIdBytes);
+ ins.insert(Constants.OBJ_TREE, data);
+ ins.flush();
+
+ return blobId;
+ }
+
+ @Test
+ public void testInvalidGitModules() throws Exception {
+ String fakeGitmodules = new StringBuilder()
+ .append("[submodule \"test\"]\n")
+ .append(" path = xlib\n")
+ .append(" url = https://example.com/repo/xlib.git\n\n")
+ .append("[submodule \"test2\"]\n")
+ .append(" path = zlib\n")
+ .append(" url = -upayload.sh\n")
+ .toString();
+
+ ObjectId blobId = insertGitModules(fakeGitmodules);
+
+ DfsFsck fsck = new DfsFsck(repo);
+ FsckError errors = fsck.check(null);
+ assertEquals(errors.getCorruptObjects().size(), 1);
+
+ CorruptObject error = errors.getCorruptObjects().iterator().next();
+ assertEquals(error.getId(), blobId);
+ assertEquals(error.getType(), Constants.OBJ_BLOB);
+ assertEquals(error.getErrorType(), ErrorType.GITMODULES_URL);
+ }
+
+
+ @Test
+ public void testValidGitModules() throws Exception {
+ String fakeGitmodules = new StringBuilder()
+ .append("[submodule \"test\"]\n")
+ .append(" path = xlib\n")
+ .append(" url = https://example.com/repo/xlib.git\n\n")
+ .append("[submodule \"test2\"]\n")
+ .append(" path = zlib\n")
+ .append(" url = ok/path\n")
+ .toString();
+
+ insertGitModules(fakeGitmodules);
+
+ DfsFsck fsck = new DfsFsck(repo);
+ FsckError errors = fsck.check(null);
+ assertEquals(errors.getCorruptObjects().size(), 0);
+ }
+
}
uriNotFoundWithMessage={0} not found: {1}
URINotSupported=URI not supported: {0}
userConfigFileInvalid=User config file {0} invalid {1}
+validatingGitModules=Validating .gitmodules files
walkFailure=Walk failure.
wantNotValid=want {0} not valid
weeksAgo={0} weeks ago
/***/ public String uriNotFoundWithMessage;
/***/ public String URINotSupported;
/***/ public String userConfigFileInvalid;
+ /***/ public String validatingGitModules;
/***/ public String walkFailure;
/***/ public String wantNotValid;
/***/ public String weeksAgo;
package org.eclipse.jgit.internal.storage.dfs;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.internal.storage.pack.PackExt.INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.fsck.FsckError;
import org.eclipse.jgit.internal.fsck.FsckError.CorruptIndex;
+import org.eclipse.jgit.internal.fsck.FsckError.CorruptObject;
import org.eclipse.jgit.internal.fsck.FsckPackParser;
import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
+import org.eclipse.jgit.internal.submodule.SubmoduleValidator;
+import org.eclipse.jgit.internal.submodule.SubmoduleValidator.SubmoduleValidationException;
+import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitmoduleEntry;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectChecker;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.ObjectWalk;
FsckError errors = new FsckError();
if (!connectivityOnly) {
+ objChecker.reset();
checkPacks(pm, errors);
}
checkConnectivity(pm, errors);
}
}
}
+
+ checkGitModules(pm, errors);
}
private void verifyPack(ProgressMonitor pm, FsckError errors, DfsReader ctx,
fpp.verifyIndex(pack.getPackIndex(ctx));
}
+ private void checkGitModules(ProgressMonitor pm, FsckError errors)
+ throws IOException {
+ pm.beginTask(JGitText.get().validatingGitModules,
+ objChecker.getGitsubmodules().size());
+ for (GitmoduleEntry entry : objChecker.getGitsubmodules()) {
+ AnyObjectId blobId = entry.getBlobId();
+ ObjectLoader blob = objdb.open(blobId, Constants.OBJ_BLOB);
+
+ try {
+ SubmoduleValidator.assertValidGitModulesFile(
+ new String(blob.getBytes(), UTF_8));
+ } catch (SubmoduleValidationException e) {
+ CorruptObject co = new FsckError.CorruptObject(
+ blobId.toObjectId(), Constants.OBJ_BLOB,
+ e.getFsckMessageId());
+ errors.getCorruptObjects().add(co);
+ }
+ pm.update(1);
+ }
+ pm.endTask();
+ }
+
private void checkConnectivity(ProgressMonitor pm, FsckError errors)
throws IOException {
pm.beginTask(JGitText.get().countingObjects, ProgressMonitor.UNKNOWN);
* Use a customized object checker instead of the default one. Caller can
* specify a skip list to ignore some errors.
*
+ * It will be reset at the start of each {{@link #check(ProgressMonitor)}
+ * call.
+ *
* @param objChecker
* A customized object checker.
*/
* the caller can provide both of these validations on its own.
* <p>
* Instances of this class are not thread safe, but they may be reused to
- * perform multiple object validations.
+ * perform multiple object validations, calling {@link #reset()} between them to
+ * clear the internal state (e.g. {@link #getGitsubmodules()})
*/
public class ObjectChecker {
/** Header "tree " */
public List<GitmoduleEntry> getGitsubmodules() {
return gitsubmodules;
}
+
+ /**
+ * Reset the invocation-specific state from this instance. Specifically this
+ * clears the list of .gitmodules files encountered (see
+ * {@link #getGitsubmodules()})
+ *
+ * Configurations like errors to filter, skip lists or the specified O.S.
+ * (set via {@link #setSafeForMacOS(boolean)} or
+ * {@link #setSafeForWindows(boolean)}) are NOT cleared.
+ *
+ * @since 5.2
+ */
+ public void reset() {
+ gitsubmodules.clear();
+ }
}