Skip to content

Commit 5f001a1

Browse files
authored
handle empty Git repositories gracefully (#4608)
1 parent 926ed93 commit 5f001a1

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/history/GitRepository.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
/*
21-
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
21+
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
2222
* Portions Copyright (c) 2017, 2020, Chris Fraire <[email protected]>.
2323
* Portions Copyright (c) 2019, Krystof Tulinger <[email protected]>.
2424
* Portions Copyright (c) 2023, Ric Harris <[email protected]>.
@@ -36,6 +36,7 @@
3636
import java.util.List;
3737
import java.util.HashMap;
3838
import java.util.Map;
39+
import java.util.Objects;
3940
import java.util.Optional;
4041
import java.util.Scanner;
4142
import java.util.Set;
@@ -458,6 +459,11 @@ public int getPerPartesCount() {
458459
return MAX_CHANGESETS;
459460
}
460461

462+
private boolean isRepositoryEmpty() {
463+
File headsFile = Paths.get(getDirectoryName(), Constants.DOT_GIT, "refs", "heads").toFile();
464+
return headsFile.isDirectory() && (Objects.requireNonNull(headsFile.listFiles()).length == 0);
465+
}
466+
461467
@Override
462468
public void accept(String sinceRevision, Consumer<BoundaryChangesets.IdWithProgress> visitor, Progress progress)
463469
throws HistoryException {
@@ -473,7 +479,11 @@ public void accept(String sinceRevision, Consumer<BoundaryChangesets.IdWithProgr
473479
walk.markUninteresting(walk.lookupCommit(objId));
474480
}
475481
ObjectId objId = repository.resolve(Constants.HEAD);
476-
if (objId == null) {
482+
if (Objects.isNull(objId)) {
483+
if (isRepositoryEmpty()) {
484+
LOGGER.log(Level.FINEST, "ignoring empty repository {}", this);
485+
return;
486+
}
477487
throw new HistoryException("cannot resolve HEAD");
478488
}
479489
walk.markStart(walk.parseCommit(objId));
@@ -512,6 +522,11 @@ public void traverseHistory(File file, String sinceRevision, String tillRevision
512522
try (org.eclipse.jgit.lib.Repository repository = getJGitRepository(getDirectoryName());
513523
RevWalk walk = new RevWalk(repository)) {
514524

525+
if (Objects.isNull(repository.resolve(Constants.HEAD)) && isRepositoryEmpty()) {
526+
LOGGER.log(Level.FINEST, "ignoring empty repository {}", this);
527+
return;
528+
}
529+
515530
setupWalk(file, sinceRevision, tillRevision, repository, walk);
516531

517532
int num = 0;
@@ -544,17 +559,18 @@ public void traverseHistory(File file, String sinceRevision, String tillRevision
544559
}
545560

546561
private void setupWalk(File file, String sinceRevision, String tillRevision, Repository repository, RevWalk walk)
547-
throws IOException, ForbiddenSymlinkException {
562+
throws IOException, ForbiddenSymlinkException, HistoryException {
548563

549564
if (sinceRevision != null) {
550565
walk.markUninteresting(walk.lookupCommit(repository.resolve(sinceRevision)));
551566
}
552567

553-
if (tillRevision != null) {
554-
walk.markStart(walk.lookupCommit(repository.resolve(tillRevision)));
555-
} else {
556-
walk.markStart(walk.parseCommit(repository.resolve(Constants.HEAD)));
568+
final String revStr = Objects.requireNonNullElse(tillRevision, Constants.HEAD);
569+
ObjectId objectId = repository.resolve(revStr);
570+
if (Objects.isNull(objectId)) {
571+
throw new HistoryException("failed to lookup revision " + revStr);
557572
}
573+
walk.markStart(walk.lookupCommit(objectId));
558574

559575
String relativePath = RuntimeEnvironment.getInstance().getPathRelativeToSourceRoot(file);
560576
if (!getDirectoryNameRelative().equals(relativePath)) {

opengrok-indexer/src/test/java/org/opengrok/indexer/history/FileHistoryCacheTest.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
/*
21-
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
21+
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
2222
* Portions Copyright (c) 2018, 2020, Chris Fraire <[email protected]>.
2323
* Portions Copyright (c) 2020, 2023, Ric Harris <[email protected]>.
2424
*/
@@ -860,6 +860,25 @@ void testRenamedFileHistoryWithPerPartes(int maxCount) throws Exception {
860860
assertEquals(8, updatedHistory.getHistoryEntries().size());
861861
}
862862

863+
@Test
864+
void testHistoryCacheForEmptyGitRepository() throws Exception {
865+
File repositoryRoot = new File(repositories.getSourceRoot(), "emptyGit");
866+
assertTrue(repositoryRoot.mkdir());
867+
Git.init().setDirectory(repositoryRoot).call();
868+
869+
// Create untracked file.
870+
Path untrackedFile = repositoryRoot.toPath().resolve("untrackedFile");
871+
Files.createFile(untrackedFile);
872+
assertTrue(untrackedFile.toFile().exists());
873+
874+
Repository repository = RepositoryFactory.getRepository(repositoryRoot);
875+
assertNotNull(repository);
876+
History history = repository.getHistory(repositoryRoot);
877+
assertNotNull(history);
878+
assertTrue(history.getHistoryEntries().isEmpty());
879+
repository.createCache(cache, null);
880+
}
881+
863882
/**
864883
* Make sure produces correct history for a renamed and moved file in Subversion.
865884
*/

0 commit comments

Comments
 (0)