From 3fca07a6b586a196a4f3bf80089a66c1d96df4bb Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Tue, 18 Mar 2025 19:14:48 +0100 Subject: [PATCH 1/8] avoid global isHistoryEnabled() checks in favor of per repository check fixes #4063 --- .../indexer/analysis/AnalyzerGuru.java | 4 +- .../indexer/configuration/Configuration.java | 37 +--------------- .../opengrok/indexer/history/HistoryGuru.java | 13 ++++-- .../indexer/history/LatestRevisionUtil.java | 7 ++- .../org/opengrok/indexer/index/Indexer.java | 43 ++++++++++++++++--- .../history/FileAnnotationCacheTest.java | 4 +- .../indexer/history/HistoryGuruTest.java | 1 + .../history/MercurialRepositoryTest.java | 7 +++ .../index/IndexerVsDeletedDocumentsTest.java | 9 +++- .../api/v1/controller/ProjectsController.java | 12 +++--- opengrok-web/src/main/webapp/help.jsp | 8 +--- opengrok-web/src/main/webapp/list.jsp | 4 +- opengrok-web/src/main/webapp/menu.jspf | 8 +--- opengrok-web/src/main/webapp/minisearch.jspf | 18 ++++---- .../opengrok/web/DirectoryListingTest.java | 9 +++- .../java/org/opengrok/web/PageConfigTest.java | 7 ++- 16 files changed, 104 insertions(+), 87 deletions(-) diff --git a/opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/AnalyzerGuru.java b/opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/AnalyzerGuru.java index c64675bd5a6..a8396f7fe92 100644 --- a/opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/AnalyzerGuru.java +++ b/opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/AnalyzerGuru.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * Portions Copyright (c) 2017, 2021, Chris Fraire . */ package org.opengrok.indexer.analysis; @@ -596,7 +596,7 @@ public void populateDocument(Document doc, File file, String path, AbstractAnaly doc.add(new SortedDocValuesField(QueryBuilder.FULLPATH, new BytesRef(file.getAbsolutePath()))); - if (RuntimeEnvironment.getInstance().isHistoryEnabled()) { + if (HistoryGuru.getInstance().repositorySupportsHistory(file)) { populateDocumentHistory(doc, file); } doc.add(new Field(QueryBuilder.DATE, date, string_ft_stored_nanalyzed_norms)); diff --git a/opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java b/opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java index 11ecca956f5..fd327af16f6 100644 --- a/opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java +++ b/opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * Portions Copyright (c) 2017, 2020, Chris Fraire . * Portions Copyright (c) 2020, Aleksandr Kirillov . */ @@ -580,7 +580,7 @@ public Configuration() { setHandleHistoryOfRenamedFiles(false); setHistoryBasedReindex(true); setHistoryCache(true); - setHistoryEnabled(true); + setHistoryEnabled(false); setHitsPerPage(25); setIgnoredNames(new IgnoredNames()); setIncludedNames(new Filter()); @@ -1610,37 +1610,4 @@ public ConfigurationException(String message) { super(message); } } - - /** - * Check if configuration is populated and self-consistent. - * @throws ConfigurationException on error - */ - public void checkConfiguration() throws ConfigurationException { - - if (getSourceRoot() == null) { - throw new ConfigurationException("Source root is not specified."); - } - - if (getDataRoot() == null) { - throw new ConfigurationException("Data root is not specified."); - } - - if (!new File(getSourceRoot()).canRead()) { - throw new ConfigurationException("Source root directory '" + getSourceRoot() + "' must be readable."); - } - - if (!new File(getDataRoot()).canWrite()) { - throw new ConfigurationException("Data root directory '" + getDataRoot() + "' must be writable."); - } - - if (!isHistoryEnabled() && isHistoryBasedReindex()) { - LOGGER.log(Level.INFO, "History based reindex is on, however history is off. " + - "History has to be enabled for history based reindex."); - } - - if (!isHistoryCache() && isHistoryBasedReindex()) { - LOGGER.log(Level.INFO, "History based reindex is on, however history cache is off. " + - "History cache has to be enabled for history based reindex."); - } - } } diff --git a/opengrok-indexer/src/main/java/org/opengrok/indexer/history/HistoryGuru.java b/opengrok-indexer/src/main/java/org/opengrok/indexer/history/HistoryGuru.java index 683b180c856..ae5a1875e64 100644 --- a/opengrok-indexer/src/main/java/org/opengrok/indexer/history/HistoryGuru.java +++ b/opengrok-indexer/src/main/java/org/opengrok/indexer/history/HistoryGuru.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * Portions Copyright (c) 2017, 2020, Chris Fraire . */ package org.opengrok.indexer.history; @@ -54,7 +54,6 @@ import org.opengrok.indexer.analysis.AnalyzerFactory; import org.opengrok.indexer.analysis.AnalyzerGuru; import org.opengrok.indexer.configuration.CommandTimeoutType; -import org.opengrok.indexer.configuration.Configuration; import org.opengrok.indexer.configuration.Configuration.RemoteSCM; import org.opengrok.indexer.configuration.OpenGrokThreadFactory; import org.opengrok.indexer.configuration.PathAccepter; @@ -630,6 +629,14 @@ public boolean hasHistory(File file) { } } + return repositorySupportsHistory(file); + } + + /** + * @param file file object + * @return whether related {@link Repository} and settings allow for history retrieval + */ + public boolean repositorySupportsHistory(File file) { Repository repo = getRepository(file); if (repo == null) { LOGGER.finest(() -> String.format("cannot find repository for '%s' to check history presence", @@ -642,7 +649,7 @@ public boolean hasHistory(File file) { } // This should return true for Annotate view. - Configuration.RemoteSCM globalRemoteSupport = env.getRemoteScmSupported(); + RemoteSCM globalRemoteSupport = env.getRemoteScmSupported(); boolean remoteSupported = ((globalRemoteSupport == RemoteSCM.ON) || (globalRemoteSupport == RemoteSCM.UIONLY) || (globalRemoteSupport == RemoteSCM.DIRBASED) diff --git a/opengrok-indexer/src/main/java/org/opengrok/indexer/history/LatestRevisionUtil.java b/opengrok-indexer/src/main/java/org/opengrok/indexer/history/LatestRevisionUtil.java index f2ed898474c..7b7e2e66f45 100644 --- a/opengrok-indexer/src/main/java/org/opengrok/indexer/history/LatestRevisionUtil.java +++ b/opengrok-indexer/src/main/java/org/opengrok/indexer/history/LatestRevisionUtil.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. */ package org.opengrok.indexer.history; @@ -26,7 +26,6 @@ import org.apache.lucene.document.Document; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; -import org.opengrok.indexer.configuration.RuntimeEnvironment; import org.opengrok.indexer.index.IndexDatabase; import org.opengrok.indexer.logger.LoggerFactory; import org.opengrok.indexer.search.QueryBuilder; @@ -52,11 +51,11 @@ private LatestRevisionUtil() { /** * @param file file object corresponding to a file under source root - * @return last revision string for {@code file} or null + * @return last revision string for {@code file} or {@code null} */ @Nullable public static String getLatestRevision(File file) { - if (!RuntimeEnvironment.getInstance().isHistoryEnabled()) { + if (!HistoryGuru.getInstance().repositorySupportsHistory(file)) { return null; } diff --git a/opengrok-indexer/src/main/java/org/opengrok/indexer/index/Indexer.java b/opengrok-indexer/src/main/java/org/opengrok/indexer/index/Indexer.java index ccbdc0d03fa..804e459b254 100644 --- a/opengrok-indexer/src/main/java/org/opengrok/indexer/index/Indexer.java +++ b/opengrok-indexer/src/main/java/org/opengrok/indexer/index/Indexer.java @@ -209,8 +209,6 @@ public static int runMain(String[] argv) { exitWithHelp(); } - checkConfiguration(); - if (awaitProfiler) { pauseToAwaitProfiler(); } @@ -278,6 +276,8 @@ public static int runMain(String[] argv) { } } + checkConfiguration(cfg); + // Set updated configuration in RuntimeEnvironment. This is called so that the tunables set // via command line options are available. env.setConfiguration(cfg, subFilePaths, CommandTimeoutType.INDEXER); @@ -494,11 +494,44 @@ private static void checkIndexAndExit(Set subFileArgs) { System.exit(0); } + /** + * Check if configuration is populated and self-consistent. + * @throws Configuration.ConfigurationException on error + */ + public static void checkConfigurationValues(Configuration cfg) throws Configuration.ConfigurationException { + + if (cfg.getSourceRoot() == null) { + throw new Configuration.ConfigurationException("Source root is not specified."); + } + + if (cfg.getDataRoot() == null) { + throw new Configuration.ConfigurationException("Data root is not specified."); + } + + if (!new File(cfg.getSourceRoot()).canRead()) { + throw new Configuration.ConfigurationException("Source root directory '" + cfg.getSourceRoot() + "' must be readable."); + } + + if (!new File(cfg.getDataRoot()).canWrite()) { + throw new Configuration.ConfigurationException("Data root directory '" + cfg.getDataRoot() + "' must be writable."); + } + + if (!cfg.isHistoryEnabled() && cfg.isHistoryBasedReindex()) { + LOGGER.log(Level.INFO, "History based reindex is on, however history is off. " + + "History has to be enabled for history based reindex."); + } + + if (!cfg.isHistoryCache() && cfg.isHistoryBasedReindex()) { + LOGGER.log(Level.INFO, "History based reindex is on, however history cache is off. " + + "History cache has to be enabled for history based reindex."); + } + } + /** * This is supposed to be run after {@link #parseOptions(String[])}. * It will exit the program if there is some serious configuration (meaning {@link #cfg}) discrepancy. */ - private static void checkConfiguration() { + private static void checkConfiguration(Configuration cfg) { if (bareConfig && (env.getConfigURI() == null || env.getConfigURI().isEmpty())) { die("Missing webappURI setting"); } @@ -513,7 +546,7 @@ private static void checkConfiguration() { } try { - cfg.checkConfiguration(); + checkConfigurationValues(cfg); } catch (Configuration.ConfigurationException e) { die(e.getMessage()); } @@ -1026,8 +1059,6 @@ public static String[] parseOptions(String[] argv) throws ParseException { cfg = new Configuration(); } - cfg.setHistoryEnabled(false); // force user to turn on history capture - argv = optParser.parse(argv); return argv; diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/history/FileAnnotationCacheTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/history/FileAnnotationCacheTest.java index 7da38f19f92..13d1fe0a062 100644 --- a/opengrok-indexer/src/test/java/org/opengrok/indexer/history/FileAnnotationCacheTest.java +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/history/FileAnnotationCacheTest.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. */ package org.opengrok.indexer.history; @@ -61,6 +61,8 @@ void setUp() throws Exception { repositories = new TestRepository(); repositories.create(getClass().getResource("/repositories")); + env.setHistoryEnabled(true); + // This needs to be set before the call to env.setRepositories() below as it instantiates HistoryGuru. env.setAnnotationCacheEnabled(true); diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/history/HistoryGuruTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/history/HistoryGuruTest.java index 6d0adb16b71..cd78582194e 100644 --- a/opengrok-indexer/src/test/java/org/opengrok/indexer/history/HistoryGuruTest.java +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/history/HistoryGuruTest.java @@ -90,6 +90,7 @@ class HistoryGuruTest { @BeforeAll static void setUpClass() throws Exception { env = RuntimeEnvironment.getInstance(); + env.setHistoryEnabled(true); env.setAnnotationCacheEnabled(true); savedNestingMaximum = env.getNestingMaximum(); diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/history/MercurialRepositoryTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/history/MercurialRepositoryTest.java index f82e544826d..40c4ad02fc5 100644 --- a/opengrok-indexer/src/test/java/org/opengrok/indexer/history/MercurialRepositoryTest.java +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/history/MercurialRepositoryTest.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -108,6 +109,12 @@ private void setUpTestRepository() throws IOException, URISyntaxException { repositoryRoot = new File(repository.getSourceRoot(), "mercurial"); } + @BeforeAll + static void setUpClass() throws Exception { + RuntimeEnvironment env = RuntimeEnvironment.getInstance(); + env.setHistoryEnabled(true); + } + @BeforeEach void setup() throws IOException, URISyntaxException { setUpTestRepository(); diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/IndexerVsDeletedDocumentsTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/IndexerVsDeletedDocumentsTest.java index e0810f6ad54..cc81c443fe0 100644 --- a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/IndexerVsDeletedDocumentsTest.java +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/IndexerVsDeletedDocumentsTest.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ package org.opengrok.indexer.index; @@ -36,6 +36,7 @@ import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -81,6 +82,12 @@ class IndexerVsDeletedDocumentsTest { RuntimeEnvironment env = RuntimeEnvironment.getInstance(); + @BeforeAll + static void setUpClass() { + RuntimeEnvironment env = RuntimeEnvironment.getInstance(); + env.setHistoryEnabled(true); + } + private static String getRandomString(int numChars) { Random random = new Random(); final StringBuilder sb = new StringBuilder(); diff --git a/opengrok-web/src/main/java/org/opengrok/web/api/v1/controller/ProjectsController.java b/opengrok-web/src/main/java/org/opengrok/web/api/v1/controller/ProjectsController.java index a323c3b1713..4e578d440f7 100644 --- a/opengrok-web/src/main/java/org/opengrok/web/api/v1/controller/ProjectsController.java +++ b/opengrok-web/src/main/java/org/opengrok/web/api/v1/controller/ProjectsController.java @@ -18,7 +18,7 @@ */ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * Portions Copyright (c) 2020, Chris Fraire . */ package org.opengrok.web.api.v1.controller; @@ -113,7 +113,7 @@ private void addProjectWorkHorse(String projectName) { if (!env.getProjects().containsKey(projectName)) { Project project = new Project(projectName, "/" + projectName); - if (env.isHistoryEnabled()) { + if (project.isHistoryEnabled()) { // Add repositories in this project. List repos = getRepositoriesInDir(projDir); @@ -130,7 +130,7 @@ private void addProjectWorkHorse(String projectName) { Project project = env.getProjects().get(projectName); Map> map = env.getProjectRepositoriesMap(); - if (env.isHistoryEnabled()) { + if (project.isHistoryEnabled()) { // Refresh the list of repositories of this project. // This is the goal of this action: if an existing project // is re-added, this means its list of repositories has changed. @@ -202,7 +202,7 @@ private void deleteProjectWorkHorse(Project project) { group.getProjects().remove(project); } - if (env.isHistoryEnabled()) { + if (project.isHistoryEnabled()) { // Now remove the repositories associated with this project. List repos = env.getProjectRepositoriesMap().get(project); if (repos != null) { @@ -302,11 +302,11 @@ private Project getProjectFromName(String projectNameParam) { public Response deleteHistoryCache(@Context HttpServletRequest request, @PathParam("project") String projectNameParam) { - if (!env.isHistoryEnabled()) { + Project project = getProjectFromName(projectNameParam); + if (!project.isHistoryEnabled()) { return Response.status(Response.Status.NO_CONTENT).build(); } - Project project = getProjectFromName(projectNameParam); List repos = env.getProjectRepositoriesMap().get(project); if (repos == null || repos.isEmpty()) { LOGGER.log(Level.INFO, NO_REPO_LOG_MSG, project.getName()); diff --git a/opengrok-web/src/main/webapp/help.jsp b/opengrok-web/src/main/webapp/help.jsp index 557feebb833..add38b83188 100644 --- a/opengrok-web/src/main/webapp/help.jsp +++ b/opengrok-web/src/main/webapp/help.jsp @@ -16,7 +16,7 @@ information: Portions Copyright [yyyy] [name of copyright owner] CDDL HEADER END -Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. Portions Copyright 2011 Jens Elkner. Portions Copyright (c) 2018, 2020, Chris Fraire . Portions Copyright (c) 2022, Krystof Tulinger . @@ -184,14 +184,8 @@ A Query is a series of clauses. A clause may be prefixed by:
path
path of the source file (no need to use dividers, or if, then use "/" - Windows users, "\" is an escape key in Lucene query syntax!
Please don't use "\", or replace it with "/").
Also note that if you want just exact path, enclose it in "", e.g. "src/mypath", otherwise dividers will be removed and you get more hits.
- <% - if (PageConfig.get(request).getEnv().isHistoryEnabled()) { - %>
hist
History log comments.
- <% - } - %>
type
Type of analyzer used to scope down to certain file types (e.g. just C sources).
Current mappings: <%=SearchHelper.getFileTypeDescriptions().toString()%>
diff --git a/opengrok-web/src/main/webapp/list.jsp b/opengrok-web/src/main/webapp/list.jsp index 3002b6ef453..be8ac04f2e4 100644 --- a/opengrok-web/src/main/webapp/list.jsp +++ b/opengrok-web/src/main/webapp/list.jsp @@ -16,7 +16,7 @@ information: Portions Copyright [yyyy] [name of copyright owner] CDDL HEADER END -Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. Portions Copyright 2011 Jens Elkner. Portions Copyright (c) 2017-2020, Chris Fraire . @@ -62,7 +62,7 @@ org.opengrok.web.DirectoryListing" cfg.checkSourceRootExistence(); String rev = cfg.getRequestedRevision(); - if (!cfg.isDir() && rev.length() == 0) { + if (!cfg.isDir() && rev.isEmpty()) { /* * Get the latest revision and redirect so that the revision number * appears in the URL. diff --git a/opengrok-web/src/main/webapp/menu.jspf b/opengrok-web/src/main/webapp/menu.jspf index edea73bd4ee..91b278ba69d 100644 --- a/opengrok-web/src/main/webapp/menu.jspf +++ b/opengrok-web/src/main/webapp/menu.jspf @@ -16,7 +16,7 @@ information: Portions Copyright [yyyy] [name of copyright owner] CDDL HEADER END -Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. Portions Copyright 2011 Jens Elkner. Portions Copyright (c) 2020, Chris Fraire . @@ -177,9 +177,6 @@ document.domReady.push(function() { domReadyMenu(); }); id="<%= QueryParameters.PATH_SEARCH_PARAM %>" type="text" value="<%= Util.formQuoteEscape(queryParams.getPath()) %>"/> - <% - if (cfg.getEnv().isHistoryEnabled()) { - %> @@ -188,9 +185,6 @@ document.domReady.push(function() { domReadyMenu(); }); id="<%= QueryParameters.HIST_SEARCH_PARAM %>" type="text" value="<%= Util.formQuoteEscape(queryParams.getHist()) %>"/> - <% - } - %> From 1ea12850ecac2e7956a285951e5255da893b29fe Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 19 Mar 2025 16:16:52 +0100 Subject: [PATCH 6/8] add test for populateDocument() vs history override --- .../opengrok/indexer/index/IndexDatabase.java | 7 +- .../index/AnalyzerGuruDocumentTest.java | 115 ++++++++++++++++++ 2 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java diff --git a/opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexDatabase.java b/opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexDatabase.java index 8242fe20b44..b9eca106406 100644 --- a/opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexDatabase.java +++ b/opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexDatabase.java @@ -1283,10 +1283,9 @@ private static void createAnnotationCache(File file, Document doc) { } } - private AbstractAnalyzer getAnalyzerFor(File file, String path) - throws IOException { - try (InputStream in = new BufferedInputStream( - new FileInputStream(file))) { + @VisibleForTesting + static AbstractAnalyzer getAnalyzerFor(File file, String path) throws IOException { + try (InputStream in = new BufferedInputStream(new FileInputStream(file))) { return AnalyzerGuru.getAnalyzer(in, path); } } diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java new file mode 100644 index 00000000000..bd61e6ae767 --- /dev/null +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java @@ -0,0 +1,115 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * See LICENSE.txt included in this distribution for the specific + * language governing permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at LICENSE.txt. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + */ +package org.opengrok.indexer.index; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.TextField; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.opengrok.indexer.analysis.AbstractAnalyzer; +import org.opengrok.indexer.analysis.AnalyzerGuru; +import org.opengrok.indexer.configuration.CommandTimeoutType; +import org.opengrok.indexer.configuration.RuntimeEnvironment; +import org.opengrok.indexer.history.HistoryGuru; +import org.opengrok.indexer.history.Repository; +import org.opengrok.indexer.history.RepositoryFactory; +import org.opengrok.indexer.search.QueryBuilder; +import org.opengrok.indexer.util.NullWriter; +import org.opengrok.indexer.util.TestRepository; + +import java.io.File; +import java.io.Writer; +import java.net.URL; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.verify; + +class AnalyzerGuruDocumentTest { + private RuntimeEnvironment env; + + private static TestRepository repository; + + @BeforeEach + void setUpClass() throws Exception { + env = RuntimeEnvironment.getInstance(); + + repository = new TestRepository(); + URL resourceURL = HistoryGuru.class.getResource("/repositories"); + assertNotNull(resourceURL); + repository.create(resourceURL); + + env.setSourceRoot(repository.getSourceRoot()); + env.setDataRoot(repository.getDataRoot()); + env.setHistoryEnabled(true); + env.setProjectsEnabled(true); + RepositoryFactory.initializeIgnoredNames(env); + + // Restore the project and repository information. + env.setProjects(new HashMap<>()); + HistoryGuru.getInstance().removeRepositories(List.of("/git")); + env.setRepositories(repository.getSourceRoot()); + HistoryGuru.getInstance().invalidateRepositories(env.getRepositories(), CommandTimeoutType.INDEXER); + env.generateProjectRepositoriesMap(); + } + + @AfterEach + void tearDownClass() throws Exception { + env.releaseIndexSearchers(); + repository.destroy(); + } + + /** + * {@link AnalyzerGuru#populateDocument(Document, File, String, AbstractAnalyzer, Writer)} should populate + * the history of the document only if the repository related to the file allows for it. + */ + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void testPopulateDocumentHistory(boolean historyEnabled) throws Exception { + AnalyzerGuru analyzerGuru = new AnalyzerGuru(); + Document doc = Mockito.mock(Document.class); + Path filePath = Path.of(env.getSourceRootPath(), "git", "main.c"); + File file = filePath.toFile(); + assertTrue(file.exists()); + HistoryGuru histGuru = HistoryGuru.getInstance(); + Repository fileRepository = histGuru.getRepository(file); + assertNotNull(fileRepository); + fileRepository.setHistoryEnabled(historyEnabled); + String relativePath = env.getPathRelativeToSourceRoot(file); + analyzerGuru.populateDocument(doc, file, relativePath, + IndexDatabase.getAnalyzerFor(file, relativePath), new NullWriter()); + ArgumentCaptor argument = ArgumentCaptor.forClass(TextField.class); + verify(doc, atLeast(1)).add(argument.capture()); + assertEquals(historyEnabled, + argument.getAllValues().stream().anyMatch(e -> e.name().equals(QueryBuilder.HIST))); + } +} From ed6c1594f7217b38699d89306e9c0dbcc8c219c4 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 19 Mar 2025 16:20:54 +0100 Subject: [PATCH 7/8] cleanup --- .../org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java index bd61e6ae767..6c636a62a36 100644 --- a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java @@ -76,7 +76,6 @@ void setUpClass() throws Exception { // Restore the project and repository information. env.setProjects(new HashMap<>()); - HistoryGuru.getInstance().removeRepositories(List.of("/git")); env.setRepositories(repository.getSourceRoot()); HistoryGuru.getInstance().invalidateRepositories(env.getRepositories(), CommandTimeoutType.INDEXER); env.generateProjectRepositoriesMap(); @@ -84,7 +83,6 @@ void setUpClass() throws Exception { @AfterEach void tearDownClass() throws Exception { - env.releaseIndexSearchers(); repository.destroy(); } From 9dd6d5681ca99c00299ebf143e08cde619f1d746 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 19 Mar 2025 16:21:32 +0100 Subject: [PATCH 8/8] rename --- .../index/AnalyzerGuruDocumentTest.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java index 6c636a62a36..8accff69b41 100644 --- a/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java +++ b/opengrok-indexer/src/test/java/org/opengrok/indexer/index/AnalyzerGuruDocumentTest.java @@ -46,7 +46,6 @@ import java.net.URL; import java.nio.file.Path; import java.util.HashMap; -import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -57,33 +56,33 @@ class AnalyzerGuruDocumentTest { private RuntimeEnvironment env; - private static TestRepository repository; + private static TestRepository testRepository; @BeforeEach void setUpClass() throws Exception { env = RuntimeEnvironment.getInstance(); - repository = new TestRepository(); + testRepository = new TestRepository(); URL resourceURL = HistoryGuru.class.getResource("/repositories"); assertNotNull(resourceURL); - repository.create(resourceURL); + testRepository.create(resourceURL); - env.setSourceRoot(repository.getSourceRoot()); - env.setDataRoot(repository.getDataRoot()); + env.setSourceRoot(testRepository.getSourceRoot()); + env.setDataRoot(testRepository.getDataRoot()); env.setHistoryEnabled(true); env.setProjectsEnabled(true); RepositoryFactory.initializeIgnoredNames(env); // Restore the project and repository information. env.setProjects(new HashMap<>()); - env.setRepositories(repository.getSourceRoot()); + env.setRepositories(testRepository.getSourceRoot()); HistoryGuru.getInstance().invalidateRepositories(env.getRepositories(), CommandTimeoutType.INDEXER); env.generateProjectRepositoriesMap(); } @AfterEach void tearDownClass() throws Exception { - repository.destroy(); + testRepository.destroy(); } /** @@ -99,9 +98,9 @@ void testPopulateDocumentHistory(boolean historyEnabled) throws Exception { File file = filePath.toFile(); assertTrue(file.exists()); HistoryGuru histGuru = HistoryGuru.getInstance(); - Repository fileRepository = histGuru.getRepository(file); - assertNotNull(fileRepository); - fileRepository.setHistoryEnabled(historyEnabled); + Repository repository = histGuru.getRepository(file); + assertNotNull(repository); + repository.setHistoryEnabled(historyEnabled); String relativePath = env.getPathRelativeToSourceRoot(file); analyzerGuru.populateDocument(doc, file, relativePath, IndexDatabase.getAnalyzerFor(file, relativePath), new NullWriter());