Skip to content

Commit c790eb7

Browse files
Vladimir Kotalidodeclare
authored andcommitted
Lift most of Oracle's PR #1846 on symlink bug, with assertion fix
Chris Fraire <[email protected]> fixed the assertion.
1 parent 1a0291e commit c790eb7

File tree

6 files changed

+184
-16
lines changed

6 files changed

+184
-16
lines changed

src/org/opensolaris/opengrok/history/FileHistoryCache.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,11 @@ public boolean hasCacheForDirectory(File directory, Repository repository)
631631
return dir.exists();
632632
}
633633

634+
@Override
635+
public boolean hasCacheForFile(File file) throws HistoryException {
636+
return getCachedFile(file).exists();
637+
}
638+
634639
public String getRepositoryHistDataDirname(Repository repository) {
635640
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
636641
String repoDirBasename;
@@ -645,7 +650,7 @@ public String getRepositoryHistDataDirname(Repository repository) {
645650
}
646651

647652
return env.getDataRootPath() + File.separatorChar
648-
+ this.historyCacheDirName
653+
+ FileHistoryCache.historyCacheDirName
649654
+ repoDirBasename;
650655
}
651656

src/org/opensolaris/opengrok/history/HistoryCache.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ void store(History history, Repository repository)
9494
boolean hasCacheForDirectory(File directory, Repository repository)
9595
throws HistoryException;
9696

97+
/**
98+
* Check if the specified file is present in the cache.
99+
* @param file the file to check
100+
* @return {@code true} if the file is in the cache, {@code false}
101+
* otherwise
102+
*/
103+
boolean hasCacheForFile(File file) throws HistoryException;
104+
97105
/**
98106
* Get the revision identifier for the latest cached revision in a
99107
* repository.

src/org/opensolaris/opengrok/history/HistoryGuru.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,23 @@ public boolean hasHistory(File file) {
295295
|| !repo.isRemote());
296296
}
297297

298+
/**
299+
* Does the history cache contain entry for this directory ?
300+
* @param file
301+
* @return true if there is cache, false otherwise
302+
*/
303+
public boolean hasCacheForFile(File file) {
304+
if (!useCache()) {
305+
return false;
306+
}
307+
308+
try {
309+
return historyCache.hasCacheForFile(file);
310+
} catch (HistoryException ex) {
311+
return false;
312+
}
313+
}
314+
298315
/**
299316
* Check if we can annotate the specified file.
300317
*
@@ -392,7 +409,6 @@ private Collection<RepositoryInfo> addRepositories(File[] files,
392409
}
393410
}
394411
} else {
395-
repository.setDirectoryName(path);
396412
if (RuntimeEnvironment.getInstance().isVerbose()) {
397413
LOGGER.log(Level.CONFIG, "Adding <{0}> repository: <{1}>",
398414
new Object[]{repository.getClass().getName(), path});
@@ -812,14 +828,7 @@ public void ensureHistoryCacheExists(File file) throws HistoryException {
812828
}
813829

814830
protected Repository getRepository(File path) {
815-
File file;
816-
817-
try {
818-
file = path.getCanonicalFile();
819-
} catch (IOException e) {
820-
LOGGER.log(Level.WARNING, "Failed to get canonical path for " + path, e);
821-
return null;
822-
}
831+
File file = path;
823832

824833
while (file != null) {
825834
Repository r = repositories.get(file.getAbsolutePath());

test/org/opensolaris/opengrok/configuration/RuntimeEnvironmentTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@
3131
import java.io.StringWriter;
3232
import java.net.InetSocketAddress;
3333
import java.net.SocketAddress;
34+
import java.nio.file.Files;
35+
import java.nio.file.Paths;
3436
import java.util.ArrayList;
37+
import java.util.Arrays;
3538
import java.util.Date;
39+
import java.util.HashSet;
3640
import java.util.List;
3741
import java.util.Map;
3842
import java.util.TreeMap;
@@ -61,6 +65,8 @@
6165
import static org.junit.Assert.assertSame;
6266
import static org.junit.Assert.assertTrue;
6367
import static org.junit.Assert.fail;
68+
import org.opensolaris.opengrok.util.FileUtilities;
69+
import org.opensolaris.opengrok.util.IOUtils;
6470

6571
/**
6672
* Test the RuntimeEnvironment class
@@ -1062,4 +1068,55 @@ public void testLoadNullStatistics() throws IOException, ParseException {
10621068
public void testLoadNullStatisticsFile() throws IOException, ParseException {
10631069
RuntimeEnvironment.getInstance().loadStatistics((File) null);
10641070
}
1071+
1072+
/**
1073+
* Verify that getPathRelativeToSourceRoot() returns path relative to
1074+
* source root for both directories and symbolic links.
1075+
* @throws java.io.IOException
1076+
*/
1077+
@Test
1078+
public void testGetPathRelativeToSourceRoot() throws IOException {
1079+
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
1080+
1081+
// Create and set source root.
1082+
File sourceRoot = FileUtilities.createTemporaryDirectory("src");
1083+
assertTrue(sourceRoot.exists());
1084+
assertTrue(sourceRoot.isDirectory());
1085+
env.setSourceRoot(sourceRoot.getPath());
1086+
1087+
// Create directory underneath source root and check.
1088+
String filename = "foo";
1089+
File file = new File(env.getSourceRootFile(), filename);
1090+
file.createNewFile();
1091+
assertTrue(file.exists());
1092+
assertEquals(File.separator + filename,
1093+
env.getPathRelativeToSourceRoot(file));
1094+
1095+
// Create symlink underneath source root.
1096+
String symlinkName = "symlink";
1097+
File realDir = FileUtilities.createTemporaryDirectory("realdir");
1098+
File symlink = new File(sourceRoot, symlinkName);
1099+
Files.createSymbolicLink(
1100+
Paths.get(symlink.getPath()),
1101+
Paths.get(realDir.getPath()));
1102+
assertTrue(symlink.exists());
1103+
env.setAllowedSymlinks(new HashSet<>());
1104+
IOException exexp = null;
1105+
try {
1106+
env.getPathRelativeToSourceRoot(symlink);
1107+
} catch (IOException e) {
1108+
exexp = e;
1109+
}
1110+
assertTrue("getPathRelativeToSourceRoot() should have thrown " +
1111+
"IOexception for symlink that is not allowed", exexp != null);
1112+
1113+
// Allow the symlink and retest.
1114+
env.setAllowedSymlinks(new HashSet<>(Arrays.asList(symlink.getPath())));
1115+
assertEquals(File.separator + symlinkName,
1116+
env.getPathRelativeToSourceRoot(symlink));
1117+
1118+
// cleanup
1119+
IOUtils.removeRecursive(sourceRoot.toPath());
1120+
IOUtils.removeRecursive(realDir.toPath());
1121+
}
10651122
}

test/org/opensolaris/opengrok/history/MercurialRepositoryTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,16 @@ public void testGetHistoryPartial() throws Exception {
161161
/**
162162
* Run Mercurial command.
163163
*
164-
* @param command hg command to run
165164
* @param reposRoot directory of the repository root
166-
* @param arg argument to use for the command
165+
* @param args {@code hg} command arguments
167166
*/
168167
static public void runHgCommand(File reposRoot, String ... args) {
169168
List<String> cmdargs = new ArrayList<>();
170169
MercurialRepository repo = new MercurialRepository();
170+
171171
cmdargs.add(repo.getRepoCommand());
172-
for (String arg: args) {
173-
cmdargs.add(arg);
174-
}
172+
cmdargs.addAll(Arrays.asList(args));
173+
175174
Executor exec = new Executor(cmdargs, reposRoot);
176175
int exitCode = exec.exec();
177176
if (exitCode != 0) {

test/org/opensolaris/opengrok/index/IndexerRepoTest.java

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,36 @@
2222
*/
2323
package org.opensolaris.opengrok.index;
2424

25+
import java.io.File;
2526
import static org.junit.Assert.assertEquals;
2627

2728
import java.io.IOException;
29+
import java.nio.file.Files;
30+
import java.nio.file.Path;
31+
import java.nio.file.Paths;
32+
import java.util.ArrayList;
33+
import java.util.Arrays;
34+
import java.util.HashMap;
35+
import java.util.HashSet;
36+
import java.util.List;
37+
import java.util.Map;
2838

2939
import org.junit.After;
3040
import org.junit.Before;
3141
import org.junit.Test;
42+
import org.opensolaris.opengrok.condition.ConditionalRun;
43+
import org.opensolaris.opengrok.condition.RepositoryInstalled;
44+
import org.opensolaris.opengrok.configuration.Project;
3245
import org.opensolaris.opengrok.configuration.RuntimeEnvironment;
3346
import org.opensolaris.opengrok.history.HistoryGuru;
47+
import org.opensolaris.opengrok.history.MercurialRepositoryTest;
48+
import org.opensolaris.opengrok.history.RepositoryInfo;
49+
import org.opensolaris.opengrok.util.FileUtilities;
3450
import org.opensolaris.opengrok.util.TestRepository;
51+
import org.opensolaris.opengrok.util.IOUtils;
3552

3653
/**
37-
* Test cleanup of renamed thread pool after indexing.
54+
* Test indexer w.r.t. repositories.
3855
*
3956
* @author Vladimir Kotal
4057
*/
@@ -73,6 +90,76 @@ private void checkNumberOfThreads() {
7390
}
7491
}
7592

93+
/**
94+
* Test that symlinked directories from source root get their relative
95+
* path set correctly in RepositoryInfo objects.
96+
* @throws org.opensolaris.opengrok.index.IndexerException
97+
* @throws java.io.IOException
98+
*/
99+
@ConditionalRun(condition = RepositoryInstalled.MercurialInstalled.class)
100+
@Test
101+
public void testSymlinks() throws IndexerException, IOException {
102+
103+
final String symlink = "symlink";
104+
RuntimeEnvironment env = RuntimeEnvironment.getInstance();
105+
106+
// Set source root to pristine directory so that there is only one
107+
// repository to deal with (which makes this faster and easier to write)
108+
// and clone the mercurial repository outside of the source root.
109+
File realSource = FileUtilities.createTemporaryDirectory("real");
110+
File sourceRoot = FileUtilities.createTemporaryDirectory("src");
111+
MercurialRepositoryTest.runHgCommand(sourceRoot,
112+
"clone", repository.getSourceRoot() + File.separator + "mercurial",
113+
realSource.getPath());
114+
115+
// Create symlink from source root to the real repository.
116+
String symlinkPath = sourceRoot.toString() + File.separator + symlink;
117+
Files.createSymbolicLink(Paths.get(symlinkPath), Paths.get(realSource.getPath()));
118+
119+
env.setSourceRoot(sourceRoot.toString());
120+
env.setDataRoot(repository.getDataRoot());
121+
// Need to have history cache enabled in order to perform scan of repositories.
122+
env.setHistoryEnabled(true);
123+
// Normally the Indexer would add the symlink automatically.
124+
env.setAllowedSymlinks(new HashSet<String>(Arrays.asList(symlinkPath)));
125+
126+
// Do a rescan of the projects, and only that (we don't care about
127+
// the other aspects of indexing in this test case).
128+
Indexer.getInstance().prepareIndexer(
129+
env,
130+
true, // search for repositories
131+
true, // scan and add projects
132+
null, // no default project
133+
false, // don't list files
134+
false, // don't create dictionary
135+
null, // subFiles - not needed since we don't list files
136+
null, // repositories - not needed when not refreshing history
137+
new ArrayList<>(), // don't zap cache
138+
false); // don't list repos
139+
140+
// Check the respository paths.
141+
List<RepositoryInfo> repos = env.getRepositories();
142+
assertEquals(repos.size(), 1);
143+
RepositoryInfo repo = repos.get(0);
144+
assertEquals("/" + symlink, repo.getDirectoryNameRelative());
145+
assertEquals(sourceRoot.toString() + File.separator + "symlink",
146+
repo.getDirectoryName());
147+
148+
// Check that history exists for a file in the repository.
149+
File repoRoot = new File(env.getSourceRootFile(), symlink);
150+
File fileInRepo = new File(repoRoot, "main.c");
151+
assertTrue(fileInRepo.exists());
152+
assertTrue(HistoryGuru.getInstance().hasHistory(fileInRepo));
153+
assertTrue(HistoryGuru.getInstance().hasCacheForFile(fileInRepo));
154+
155+
// cleanup
156+
IOUtils.removeRecursive(realSource.toPath());
157+
IOUtils.removeRecursive(sourceRoot.toPath());
158+
}
159+
160+
/**
161+
* Test cleanup of renamed thread pool after indexing with -H.
162+
*/
76163
@Test
77164
public void testMainWithH() throws IOException {
78165
System.out.println("Generate index by using command line options with -H");
@@ -88,6 +175,9 @@ public void testMainWithH() throws IOException {
88175
}
89176
}
90177

178+
/**
179+
* Test cleanup of renamed thread pool after indexing without -H.
180+
*/
91181
@Test
92182
public void testMainWithoutH() throws IOException {
93183
System.out.println("Generate index by using command line options without -H");

0 commit comments

Comments
 (0)