From 2e03db322ea93cac67275bdd584a67b559ed185a Mon Sep 17 00:00:00 2001 From: Luca Milanesio Date: Thu, 22 Dec 2016 00:42:56 +0000 Subject: [PATCH 01/11] Bump to Lucene 5.5.2 --- .classpath | 14 +++---- build.moxie | 2 +- gitblit.iml | 42 +++++++++---------- .../com/gitblit/service/LuceneService.java | 22 +++++----- .../com/gitblit/tickets/TicketIndexer.java | 30 ++++++------- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/.classpath b/.classpath index 3dac2010b..42756d8be 100644 --- a/.classpath +++ b/.classpath @@ -21,13 +21,13 @@ - - - - - - - + + + + + + + diff --git a/build.moxie b/build.moxie index eb05e2c81..9e5da7095 100644 --- a/build.moxie +++ b/build.moxie @@ -106,7 +106,7 @@ properties: { jetty.version : 9.2.13.v20150730 slf4j.version : 1.7.12 wicket.version : 1.4.22 - lucene.version : 4.10.4 + lucene.version : 5.5.2 jgit.version : 4.1.1.201511131810-r groovy.version : 2.4.4 bouncycastle.version : 1.52 diff --git a/gitblit.iml b/gitblit.iml index 038c4f4d1..aefea941f 100644 --- a/gitblit.iml +++ b/gitblit.iml @@ -180,79 +180,79 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/main/java/com/gitblit/service/LuceneService.java b/src/main/java/com/gitblit/service/LuceneService.java index 097a39b2f..59b1ff248 100644 --- a/src/main/java/com/gitblit/service/LuceneService.java +++ b/src/main/java/com/gitblit/service/LuceneService.java @@ -267,7 +267,7 @@ public synchronized void close() { // close all writers for (String writer : writers.keySet()) { try { - writers.get(writer).close(true); + writers.get(writer).close(); } catch (Throwable t) { logger.error("Failed to close Lucene writer for " + writer, t); } @@ -722,8 +722,8 @@ public boolean deleteBlob(String repositoryName, String branch, String path) thr String q = MessageFormat.format(pattern, SearchObjectType.blob.name(), branch, path); BooleanQuery query = new BooleanQuery(); - StandardAnalyzer analyzer = new StandardAnalyzer(LUCENE_VERSION); - QueryParser qp = new QueryParser(LUCENE_VERSION, FIELD_SUMMARY, analyzer); + StandardAnalyzer analyzer = new StandardAnalyzer(); + QueryParser qp = new QueryParser(FIELD_SUMMARY, analyzer); query.add(qp.parse(q), Occur.MUST); IndexWriter writer = getIndexWriter(repositoryName); @@ -968,14 +968,14 @@ private IndexWriter getIndexWriter(String repository) throws IOException { IndexWriter indexWriter = writers.get(repository); File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repository), FS.DETECTED); File indexFolder = new File(repositoryFolder, LUCENE_DIR); - Directory directory = FSDirectory.open(indexFolder); + Directory directory = FSDirectory.open(indexFolder.toPath()); if (indexWriter == null) { if (!indexFolder.exists()) { indexFolder.mkdirs(); } - StandardAnalyzer analyzer = new StandardAnalyzer(LUCENE_VERSION); - IndexWriterConfig config = new IndexWriterConfig(LUCENE_VERSION, analyzer); + StandardAnalyzer analyzer = new StandardAnalyzer(); + IndexWriterConfig config = new IndexWriterConfig(analyzer); config.setOpenMode(OpenMode.CREATE_OR_APPEND); indexWriter = new IndexWriter(directory, config); writers.put(repository, indexWriter); @@ -1028,16 +1028,16 @@ public List search(String text, int page, int pageSize, String... return null; } Set results = new LinkedHashSet(); - StandardAnalyzer analyzer = new StandardAnalyzer(LUCENE_VERSION); + StandardAnalyzer analyzer = new StandardAnalyzer(); try { // default search checks summary and content BooleanQuery query = new BooleanQuery(); QueryParser qp; - qp = new QueryParser(LUCENE_VERSION, FIELD_SUMMARY, analyzer); + qp = new QueryParser(FIELD_SUMMARY, analyzer); qp.setAllowLeadingWildcard(true); query.add(qp.parse(text), Occur.SHOULD); - qp = new QueryParser(LUCENE_VERSION, FIELD_CONTENT, analyzer); + qp = new QueryParser(FIELD_CONTENT, analyzer); qp.setAllowLeadingWildcard(true); query.add(qp.parse(text), Occur.SHOULD); @@ -1060,7 +1060,7 @@ public List search(String text, int page, int pageSize, String... Query rewrittenQuery = searcher.rewrite(query); logger.debug(rewrittenQuery.toString()); - TopScoreDocCollector collector = TopScoreDocCollector.create(5000, true); + TopScoreDocCollector collector = TopScoreDocCollector.create(5000); searcher.search(rewrittenQuery, collector); int offset = Math.max(0, (page - 1) * pageSize); ScoreDoc[] hits = collector.topDocs(offset, pageSize).scoreDocs; @@ -1225,7 +1225,7 @@ float duration() { */ private class MultiSourceReader extends MultiReader { - MultiSourceReader(IndexReader [] readers) { + MultiSourceReader(IndexReader [] readers) throws IOException { super(readers, false); } diff --git a/src/main/java/com/gitblit/tickets/TicketIndexer.java b/src/main/java/com/gitblit/tickets/TicketIndexer.java index e2d53af7b..02af25ef1 100644 --- a/src/main/java/com/gitblit/tickets/TicketIndexer.java +++ b/src/main/java/com/gitblit/tickets/TicketIndexer.java @@ -167,7 +167,7 @@ public static Lucene fromString(String value) { private final Logger log = LoggerFactory.getLogger(getClass()); - private final Version luceneVersion = Version.LUCENE_46; + private final Version luceneVersion = Version.LUCENE_5_5_2; private final File luceneDir; @@ -201,8 +201,8 @@ public void deleteAll() { public boolean deleteAll(RepositoryModel repository) { try { IndexWriter writer = getWriter(); - StandardAnalyzer analyzer = new StandardAnalyzer(luceneVersion); - QueryParser qp = new QueryParser(luceneVersion, Lucene.rid.name(), analyzer); + StandardAnalyzer analyzer = new StandardAnalyzer(); + QueryParser qp = new QueryParser(Lucene.rid.name(), analyzer); BooleanQuery query = new BooleanQuery(); query.add(qp.parse(repository.getRID()), Occur.MUST); @@ -287,8 +287,8 @@ public boolean delete(TicketModel ticket) { * @return true, if deleted, false if no record was deleted */ private boolean delete(String repository, long ticketId, IndexWriter writer) throws Exception { - StandardAnalyzer analyzer = new StandardAnalyzer(luceneVersion); - QueryParser qp = new QueryParser(luceneVersion, Lucene.did.name(), analyzer); + StandardAnalyzer analyzer = new StandardAnalyzer(); + QueryParser qp = new QueryParser(Lucene.did.name(), analyzer); BooleanQuery query = new BooleanQuery(); query.add(qp.parse(StringUtils.getSHA1(repository + ticketId)), Occur.MUST); @@ -331,21 +331,21 @@ public List searchFor(RepositoryModel repository, String text, int return Collections.emptyList(); } Set results = new LinkedHashSet(); - StandardAnalyzer analyzer = new StandardAnalyzer(luceneVersion); + StandardAnalyzer analyzer = new StandardAnalyzer(); try { // search the title, description and content BooleanQuery query = new BooleanQuery(); QueryParser qp; - qp = new QueryParser(luceneVersion, Lucene.title.name(), analyzer); + qp = new QueryParser(Lucene.title.name(), analyzer); qp.setAllowLeadingWildcard(true); query.add(qp.parse(text), Occur.SHOULD); - qp = new QueryParser(luceneVersion, Lucene.body.name(), analyzer); + qp = new QueryParser(Lucene.body.name(), analyzer); qp.setAllowLeadingWildcard(true); query.add(qp.parse(text), Occur.SHOULD); - qp = new QueryParser(luceneVersion, Lucene.content.name(), analyzer); + qp = new QueryParser(Lucene.content.name(), analyzer); qp.setAllowLeadingWildcard(true); query.add(qp.parse(text), Occur.SHOULD); @@ -354,7 +354,7 @@ public List searchFor(RepositoryModel repository, String text, int log.debug(rewrittenQuery.toString()); - TopScoreDocCollector collector = TopScoreDocCollector.create(5000, true); + TopScoreDocCollector collector = TopScoreDocCollector.create(5000); searcher.search(rewrittenQuery, collector); int offset = Math.max(0, (page - 1) * pageSize); ScoreDoc[] hits = collector.topDocs(offset, pageSize).scoreDocs; @@ -392,9 +392,9 @@ public List queryFor(String queryText, int page, int pageSize, Stri } Set results = new LinkedHashSet(); - StandardAnalyzer analyzer = new StandardAnalyzer(luceneVersion); + StandardAnalyzer analyzer = new StandardAnalyzer(); try { - QueryParser qp = new QueryParser(luceneVersion, Lucene.content.name(), analyzer); + QueryParser qp = new QueryParser(Lucene.content.name(), analyzer); Query query = qp.parse(queryText); IndexSearcher searcher = getSearcher(); @@ -443,14 +443,14 @@ public List queryFor(String queryText, int page, int pageSize, Stri private IndexWriter getWriter() throws IOException { if (writer == null) { - Directory directory = FSDirectory.open(luceneDir); + Directory directory = FSDirectory.open(luceneDir.toPath()); if (!luceneDir.exists()) { luceneDir.mkdirs(); } - StandardAnalyzer analyzer = new StandardAnalyzer(luceneVersion); - IndexWriterConfig config = new IndexWriterConfig(luceneVersion, analyzer); + StandardAnalyzer analyzer = new StandardAnalyzer(); + IndexWriterConfig config = new IndexWriterConfig(analyzer); config.setOpenMode(OpenMode.CREATE_OR_APPEND); writer = new IndexWriter(directory, config); } From 9795ce49e134db7026a856671c8cc7e9dc82e5f8 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Mon, 2 Jan 2017 16:59:44 +0100 Subject: [PATCH 02/11] Exclude Lucene transitive dependencies. Exclude Lucene dependencies `lucene-spatial` and `lucene-join`. They were added during the update but are not needed. This patch excludes them explicitly so that they do not show up in the generated IDE files and `ext` directory. --- .classpath | 2 +- build.moxie | 4 ++-- gitblit.iml | 24 ++++++++++++------------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.classpath b/.classpath index 42756d8be..42cbfbc87 100644 --- a/.classpath +++ b/.classpath @@ -24,8 +24,8 @@ - + diff --git a/build.moxie b/build.moxie index 9e5da7095..f21241d1b 100644 --- a/build.moxie +++ b/build.moxie @@ -146,9 +146,9 @@ dependencies: - compile 'org.apache.wicket:wicket-extensions:${wicket.version}' :war !org.mockito - compile 'org.apache.lucene:lucene-core:${lucene.version}' :war :fedclient - compile 'org.apache.lucene:lucene-analyzers-common:${lucene.version}' :war :fedclient -- compile 'org.apache.lucene:lucene-highlighter:${lucene.version}' :war :fedclient +- compile 'org.apache.lucene:lucene-highlighter:${lucene.version}' :war :fedclient !org.apache.lucene:lucene-join - compile 'org.apache.lucene:lucene-memory:${lucene.version}' :war :fedclient -- compile 'org.apache.lucene:lucene-queryparser:${lucene.version}' :war :fedclient +- compile 'org.apache.lucene:lucene-queryparser:${lucene.version}' :war :fedclient !org.apache.lucene:lucene-spatial - compile 'org.pegdown:pegdown:1.5.0' :war - compile 'org.fusesource.wikitext:wikitext-core:${wikitext.version}' :war - compile 'org.fusesource.wikitext:twiki-core:${wikitext.version}' :war diff --git a/gitblit.iml b/gitblit.iml index aefea941f..1f4aa2483 100644 --- a/gitblit.iml +++ b/gitblit.iml @@ -213,46 +213,46 @@ - + - + - + - + - + - + - + - + - + - + - + - + From 065583353751a976d578d08e2d4525fdc1ee042a Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Mon, 9 Jan 2017 14:43:46 +0100 Subject: [PATCH 03/11] Add library `lucene-backward-codecs` to migrate indices. To be able to read and migrate Lucene indices from old (4.x) formats to new (5.x) ones, add the `lucene-backward-codecs` library to the project. It is added to the `ext` directory and therefore to the classpath. According to the Lucene documentation, having it in the classpath can affect performance. But right now the `ext` directory is the only one available and even for a separate tool for offline migration the library would be needed. --- .classpath | 1 + build.moxie | 1 + gitblit.iml | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/.classpath b/.classpath index 42cbfbc87..5d96d16d3 100644 --- a/.classpath +++ b/.classpath @@ -22,6 +22,7 @@ + diff --git a/build.moxie b/build.moxie index f21241d1b..2748eab2c 100644 --- a/build.moxie +++ b/build.moxie @@ -145,6 +145,7 @@ dependencies: - compile 'org.apache.wicket:wicket-auth-roles:${wicket.version}' :war !org.mockito - compile 'org.apache.wicket:wicket-extensions:${wicket.version}' :war !org.mockito - compile 'org.apache.lucene:lucene-core:${lucene.version}' :war :fedclient +- compile 'org.apache.lucene:lucene-backward-codecs:${lucene.version}' :war :fedclient - compile 'org.apache.lucene:lucene-analyzers-common:${lucene.version}' :war :fedclient - compile 'org.apache.lucene:lucene-highlighter:${lucene.version}' :war :fedclient !org.apache.lucene:lucene-join - compile 'org.apache.lucene:lucene-memory:${lucene.version}' :war :fedclient diff --git a/gitblit.iml b/gitblit.iml index 1f4aa2483..25a4447de 100644 --- a/gitblit.iml +++ b/gitblit.iml @@ -190,6 +190,17 @@ + + + + + + + + + + + From 9c2ddffa83353d608a24b5fdd0164a4a18d75916 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sun, 15 Jan 2017 00:11:16 +0100 Subject: [PATCH 04/11] Remove obsolete Lucene version constants. --- src/main/java/com/gitblit/service/LuceneService.java | 3 --- src/main/java/com/gitblit/tickets/TicketIndexer.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/main/java/com/gitblit/service/LuceneService.java b/src/main/java/com/gitblit/service/LuceneService.java index 59b1ff248..f22cb5a57 100644 --- a/src/main/java/com/gitblit/service/LuceneService.java +++ b/src/main/java/com/gitblit/service/LuceneService.java @@ -65,7 +65,6 @@ import org.apache.lucene.search.highlight.SimpleSpanFragmenter; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; -import org.apache.lucene.util.Version; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; @@ -125,8 +124,6 @@ public class LuceneService implements Runnable { private static final String CONF_ALIAS = "aliases"; private static final String CONF_BRANCH = "branches"; - private static final Version LUCENE_VERSION = Version.LUCENE_4_10_0; - private final Logger logger = LoggerFactory.getLogger(LuceneService.class); private final IStoredSettings storedSettings; diff --git a/src/main/java/com/gitblit/tickets/TicketIndexer.java b/src/main/java/com/gitblit/tickets/TicketIndexer.java index 02af25ef1..652323a4c 100644 --- a/src/main/java/com/gitblit/tickets/TicketIndexer.java +++ b/src/main/java/com/gitblit/tickets/TicketIndexer.java @@ -49,7 +49,6 @@ import org.apache.lucene.search.TopScoreDocCollector; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; -import org.apache.lucene.util.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -167,8 +166,6 @@ public static Lucene fromString(String value) { private final Logger log = LoggerFactory.getLogger(getClass()); - private final Version luceneVersion = Version.LUCENE_5_5_2; - private final File luceneDir; private IndexWriter writer; From 8130906c48dcd4886bb8b28a6c1055489b499140 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sat, 21 Jan 2017 18:05:53 +0100 Subject: [PATCH 05/11] Update link target to Lucene 5.5 query syntax, moving the link to the page. Update the link target to the query parser syntax page of the 5.5 version. Refactor the `LuceneSearchPage` to use an `ExternalLink` for the link to the lucene page, so that the link target is kept and updated in the Java code. Move the link out of the language files. This was way too cumbersome to update the link target (which is probably why no one ever did). The query help text is changed to contain a variable: `gb.queryHelp = here be some ${querySyntax} help`, which is replaced by Wicket with a link. The link text is a new lange file property: `gb.querySyntax`. --- .../gitblit/wicket/GitBlitWebApp.properties | 3 +- .../wicket/GitBlitWebApp_cs.properties | 3 +- .../wicket/GitBlitWebApp_de.properties | 3 +- .../wicket/GitBlitWebApp_es.properties | 3 +- .../wicket/GitBlitWebApp_fr.properties | 3 +- .../wicket/GitBlitWebApp_it.properties | 3 +- .../wicket/GitBlitWebApp_ja.properties | 3 +- .../wicket/GitBlitWebApp_ko.properties | 211 +++++++++--------- .../wicket/GitBlitWebApp_nl.properties | 3 +- .../wicket/GitBlitWebApp_no.properties | 3 +- .../wicket/GitBlitWebApp_pl.properties | 3 +- .../wicket/GitBlitWebApp_pt_BR.properties | 3 +- .../wicket/GitBlitWebApp_zh_CN.properties | 3 +- .../wicket/GitBlitWebApp_zh_TW.properties | 3 +- .../wicket/pages/LuceneSearchPage.html | 4 +- .../wicket/pages/LuceneSearchPage.java | 4 + 16 files changed, 139 insertions(+), 119 deletions(-) diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 66101f4db..c46bd63dd 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -218,7 +218,8 @@ gb.pages = pages gb.workingCopy = working copy gb.workingCopyWarning = this repository has a working copy and can not receive pushes gb.query = query -gb.queryHelp = Standard query syntax is supported.

Please see Lucene Query Parser Syntax for details. +gb.queryHelp = Standard query syntax is supported.

Please see ${querySyntax} for details. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = results {0} - {1} ({2} hits) gb.noHits = no hits gb.authored = authored diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_cs.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_cs.properties index dc159ea57..45eb428fb 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_cs.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_cs.properties @@ -773,7 +773,8 @@ gb.transportPreferenceDescription=Vyberte transport, kter\u00fd preferujete pro gb.sortHighestSeverity=nejvy\u0161\u0161\u00ed z\u00e1va\u017enost gb.diffFileDiffTooLarge=Rozd\u00edl je p\u0159\u00edli\u0161 velk\u00fd gb.missingIntegrationBranchMore=C\u00edlov\u00e1 integra\u010dn\u00ed v\u011btev v repozit\u00e1\u0159i neexistuje! -gb.queryHelp=Standardn\u00ed syntaxe dotaz\u016f je podporov\u00e1na.

Pod\u00edvejte se pros\u00edm na Lucene Query Parser Syntax pro detaily. +gb.queryHelp=Standardn\u00ed syntaxe dotaz\u016f je podporov\u00e1na.

Pod\u00edvejte se pros\u00edm na ${querySyntax} pro detaily. +gb.querySyntax=Lucene Query Parser Syntax gb.diffTruncated=Diff o\u0159iznut po p\u0159edchoz\u00edm souboru gb.blame=blame gb.imgdiffSubtract=Od\u010d\u00edtat (\u010dern\u00e1 = stejn\u00e9l) diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_de.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_de.properties index eca3fd2a7..9599f7eb5 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_de.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_de.properties @@ -218,7 +218,8 @@ gb.pages = Seiten gb.workingCopy = Arbeitskopie gb.workingCopyWarning = Dieses Repository besitzt eine Arbeitskopie und kann keine Pushes empfangen gb.query = Abfrage -gb.queryHelp = Standard Abfragesyntax wird unterst\u00fctzt.

Unter Lucene Query Parser Syntax finden Sie weitere Details. +gb.queryHelp = Standard Abfragesyntax wird unterst\u00fctzt.

Unter ${querySyntax} finden Sie weitere Details. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = Ergebnisse {0} - {1} ({2} Treffer) gb.noHits = Keine Treffer gb.authored = ist Autor von diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_es.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_es.properties index 791b286ee..fa08485a4 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_es.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_es.properties @@ -218,7 +218,8 @@ gb.pages = P\u00E1ginas gb.workingCopy = Copia de trabajo gb.workingCopyWarning = Este repositorio tiene una copia de trabajo y no se le puede empujar gb.query = Consulta -gb.queryHelp = Se admite la sintaxis de consulta est\u00E1ndar.

Por favor, lee el: Analizador sint\u00E1ctico de consultas de Lucene para m\u00E1s detalles. +gb.queryHelp = Se admite la sintaxis de consulta est\u00E1ndar.

Por favor, lee el: ${querySyntax} para m\u00E1s detalles. +gb.querySyntax = Analizador sint\u00E1ctico de consultas de Lucene gb.queryResults = Resultados {0} - {1} ({2} coincidencias) gb.noHits = Sin coincidencias gb.authored = Autor diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties index d479b3d66..3e7571201 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_fr.properties @@ -218,7 +218,8 @@ gb.pages = pages gb.workingCopy = d\u00e9p\u00f4t de travail gb.workingCopyWarning = ce d\u00e9p\u00f4t poss\u00e8de un d\u00e9p\u00f4t de travail et ne peut donc pas recevoir de pushes gb.query = recherche -gb.queryHelp = La syntaxe Lucene standard est support\u00e9e.

Se r\u00e9f\u00e9rer \u00e0 la Syntaxe de recherche Lucene pour plus de d\u00e9tails. +gb.queryHelp = La syntaxe Lucene standard est support\u00e9e.

Se r\u00e9f\u00e9rer \u00e0 la ${querySyntax} pour plus de d\u00e9tails. +gb.querySyntax = Syntaxe de recherche Lucene gb.queryResults = r\u00e9sultats {0} - {1} ({2} hits) gb.noHits = aucun r\u00e9sultats gb.authored = authored diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_it.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_it.properties index 7230ec836..970496bb1 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_it.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_it.properties @@ -218,7 +218,8 @@ gb.pages = pagine gb.workingCopy = copia di lavoro gb.workingCopyWarning = questo repository è una copia di lavoro a non ammette push gb.query = interrogazione -gb.queryHelp = La sintassi standard è supportata.

Si vedi Lucene Query Parser Syntax per ulteriori dettagli. +gb.queryHelp = La sintassi standard è supportata.

Si vedi ${querySyntax} per ulteriori dettagli. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = risultati {0} - {1} ({2} corrispondenze) gb.noHits = nessuna corrispondenza gb.authored = creato da diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_ja.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_ja.properties index c8a2449fb..36e21a7fc 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_ja.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_ja.properties @@ -217,7 +217,8 @@ gb.pages = \u30da\u30fc\u30b8 gb.workingCopy = \u4f5c\u696d\u30b3\u30d4\u30fc gb.workingCopyWarning = \u3053\u306e\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u306f\u4f5c\u696d\u30b3\u30d4\u30fc\u304c\u3042\u308b\u305f\u3081 push \u3067\u304d\u307e\u305b\u3093 gb.query = \u30af\u30a8\u30ea\u30fc -gb.queryHelp = \u6a19\u6e96\u7684\u306a\u30af\u30a8\u30ea\u30fc\u66f8\u5f0f\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059\u3002

\u8a73\u7d30\u306f Lucene Query Parser Syntax \u3092\u53c2\u7167\u3057\u3066\u4e0b\u3055\u3044\u3002 +gb.queryHelp = \u6a19\u6e96\u7684\u306a\u30af\u30a8\u30ea\u30fc\u66f8\u5f0f\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059\u3002

\u8a73\u7d30\u306f ${querySyntax} \u3092\u53c2\u7167\u3057\u3066\u4e0b\u3055\u3044\u3002 +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = \u691c\u7d22\u7d50\u679c {0} - {1} ({2} \u30d2\u30c3\u30c8) gb.noHits = \u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 gb.authored = authored diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_ko.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_ko.properties index 031ff8dbd..b4a675ce8 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_ko.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_ko.properties @@ -180,110 +180,111 @@ gb.free = \uD504\uB9AC gb.version = \uBC84\uC804 gb.releaseDate = \uB9B4\uB9AC\uC988 \uB0A0\uC9DC gb.date = date -gb.activity = \uC561\uD2F0\uBE44\uD2F0 -gb.subscribe = \uAD6C\uB3C5 -gb.branch = \uBE0C\uB79C\uCE58 -gb.maxHits = \uB9E5\uC2A4\uD788\uD2B8 -gb.recentActivity = \uCD5C\uADFC \uC561\uD2F0\uBE44\uD2F0 -gb.recentActivityStats = \uC9C0\uB09C {0}\uC77C / \uC791\uC131\uC790 {2}\uBA85\uC774 {1}\uAC1C \uCEE4\uBC0B\uD568 -gb.recentActivityNone = \uC9C0\uB09C {0}\uC77C / \uC5C6\uC74C -gb.dailyActivity = \uC77C\uC77C \uC561\uD2F0\uBE44\uD2F0 -gb.activeRepositories = \uC0AC\uC6A9\uC911\uC778 \uC800\uC7A5\uC18C -gb.activeAuthors = \uC0AC\uC6A9\uC911\uC778 \uC791\uC131\uC790 -gb.commits = \uCEE4\uBC0B -gb.teams = \uD300 -gb.teamName = \uD300 \uC774\uB984 -gb.teamMembers = \uD300 \uBA64\uBC84 -gb.teamMemberships = \uD300 \uB9F4\uBC84\uC27D -gb.newTeam = \uC0C8\uB85C\uC6B4 \uD300 -gb.permittedTeams = \uD5C8\uC6A9\uB41C \uD300 -gb.emptyRepository = \uBE48 \uC800\uC7A5\uC18C -gb.repositoryUrl = \uC800\uC7A5\uC18C url -gb.mailingLists = \uBA54\uC77C\uB9C1 \uB9AC\uC2A4\uD2B8 -gb.preReceiveScripts = pre-receive \uC2A4\uD06C\uB9BD\uD2B8 -gb.postReceiveScripts = post-receive \uC2A4\uD06C\uB9BD\uD2B8 -gb.hookScripts = \uD6C4\uD06C \uC2A4\uD06C\uB9BD\uD2B8 -gb.customFields = \uC0AC\uC6A9\uC790 \uD544\uB4DC -gb.customFieldsDescription = \uADF8\uB8E8\uBE44 \uD6C5\uC5D0 \uC0AC\uC6A9\uC790 \uD544\uB4DC \uC0AC\uC6A9 \uAC00\uB2A5 -gb.accessPermissions = \uC811\uC18D \uAD8C\uD55C -gb.filters = \uD544\uD130 -gb.generalDescription = \uC77C\uBC18 \uC124\uC815 -gb.accessPermissionsDescription = \uC720\uC800\uC640 \uD300\uC73C\uB85C \uC811\uC18D\uAD8C\uD55C \uBD80\uC5EC -gb.accessPermissionsForUserDescription = \uD300\uC744 \uC9C0\uC815\uD558\uAC70\uB098 \uC811\uC18D \uAD8C\uD55C\uC744 \uC9C0\uC815\uD560 \uC800\uC7A5\uC18C \uC120\uD0DD -gb.accessPermissionsForTeamDescription = \uD300 \uB9F4\uBC84\uB97C \uC120\uD0DD\uD558\uACE0, \uC811\uC18D \uAD8C\uD55C\uC744 \uC9C0\uC815\uD560 \uC800\uC7A5\uC18C \uC120\uD0DD -gb.federationRepositoryDescription = \uC774 \uC800\uC7A5\uC18C\uB97C \uB2E4\uB978 Gitblit \uC11C\uBC84\uC640 \uACF5\uC720 -gb.hookScriptsDescription = \uC774 Gitblit \uC11C\uBC84\uC5D0 \uD478\uC2DC\uB418\uBA74 \uADF8\uB8E8\uBE44(Groovy) \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uC2E4\uD589 -gb.reset = \uB9AC\uC14B -gb.pages = \uD398\uC774\uC9C0 -gb.workingCopy = \uC6CC\uD0B9 \uCE74\uD53C -gb.workingCopyWarning = \uC774 \uC800\uC7A5\uC18C\uB294 \uC6CC\uD0B9\uCE74\uD53C\uB97C \uAC00\uC9C0\uACE0 \uC788\uACE0 \uD478\uC2DC\uB97C \uBC1B\uC744 \uC218 \uC5C6\uC74C -gb.query = \uCFFC\uB9AC -gb.queryHelp = \uD45C\uC900 \uCFFC\uB9AC \uBB38\uBC95\uC744 \uC9C0\uC6D0.

\uC790\uC138\uD55C \uAC83\uC744 \uC6D0\uD55C\uB2E4\uBA74 \uB8E8\uC2E0 \uCFFC\uB9AC \uD30C\uC11C \uBB38\uBC95 \uC744 \uBC29\uBB38\uD574 \uC8FC\uC138\uC694. -gb.queryResults = \uAC80\uC0C9\uACB0\uACFC {0} - {1} ({2}\uAC1C \uAC80\uC0C9\uB428) -gb.noHits = \uAC80\uC0C9 \uACB0\uACFC \uC5C6\uC74C -gb.authored = \uAC00 \uC791\uC131\uD568. -gb.committed = \uCEE4\uBC0B\uB428 -gb.indexedBranches = \uC778\uB371\uC2F1\uD560 \uBE0C\uB79C\uCE58 -gb.indexedBranchesDescription = \uB8E8\uC2E0 \uC778\uB371\uC2A4\uC5D0 \uD3EC\uD568\uD560 \uBE0C\uB79C\uCE58 \uC120\uD0DD -gb.noIndexedRepositoriesWarning = \uC800\uC7A5\uC18C\uAC00 \uB8E8\uC2E0 \uC778\uB371\uC2F1\uC5D0 \uC124\uC815\uB418\uC9C0 \uC54A\uC74C -gb.undefinedQueryWarning = \uCFFC\uB9AC \uC9C0\uC815\uB418\uC9C0 \uC54A\uC74C! -gb.noSelectedRepositoriesWarning = \uD558\uB098 \uB610\uB294 \uADF8 \uC774\uC0C1\uC758 \uC800\uC7A5\uC18C\uB97C \uC120\uD0DD\uD558\uC138\uC694! -gb.luceneDisabled = \uB8E8\uC2E0 \uC778\uB371\uC2F1 \uC911\uC9C0\uB428 -gb.failedtoRead = \uC77C\uAE30 \uC2E4\uD328 -gb.isNotValidFile = \uC720\uD6A8\uD55C \uD30C\uC77C\uC774 \uC544\uB2D8 -gb.failedToReadMessage = {0}\uC5D0\uC11C \uB514\uD3F4\uD2B8 \uBA54\uC2DC\uC9C0 \uC77C\uAE30 \uC2E4\uD328! -gb.passwordsDoNotMatch = \uD328\uC2A4\uC6CC\uB4DC\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC544\uC694! -gb.passwordTooShort = \uD328\uC2A4\uC6CC\uB4DC\uAC00 \uB108\uBB34 \uC9E7\uC544\uC694. \uC801\uC5B4\uB3C4 {0} \uAC1C \uBB38\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4. -gb.passwordChanged = \uD328\uC2A4\uC6CC\uB4DC\uAC00 \uBCC0\uACBD \uC131\uACF5. -gb.passwordChangeAborted = \uD328\uC2A4\uC6CC\uB4DC \uBCC0\uACBD \uCDE8\uC18C\uB428. -gb.pleaseSetRepositoryName = \uC800\uC7A5\uC18C \uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694! -gb.illegalLeadingSlash = \uC800\uC7A5\uC18C \uC774\uB984 \uB610\uB294 \uD3F4\uB354\uB294 (/) \uB85C \uC2DC\uC791\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. -gb.illegalRelativeSlash = \uC0C1\uB300 \uACBD\uB85C \uC9C0\uC815 (../) \uC740 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.. -gb.illegalCharacterRepositoryName = \uBB38\uC790 ''{0}'' \uC800\uC7A5\uC18C \uC774\uB984\uC5D0 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC5B4\uC694! -gb.selectAccessRestriction = \uC811\uC18D \uAD8C\uD55C\uC744 \uC120\uD0DD\uD558\uC138\uC694! -gb.selectFederationStrategy = \uD398\uB354\uB808\uC774\uC158 \uC815\uCC45\uC744 \uC120\uD0DD\uD558\uC138\uC694! -gb.pleaseSetTeamName = \uD300\uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694! -gb.teamNameUnavailable = ''{0}'' \uD300\uC740 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC5B4\uC694. -gb.teamMustSpecifyRepository = \uD300\uC740 \uC801\uC5B4\uB3C4 \uD558\uB098\uC758 \uC800\uC7A5\uC18C\uB97C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4. -gb.teamCreated = \uC0C8\uB85C\uC6B4 \uD300 ''{0}'' \uC0DD\uC131 \uC644\uB8CC. -gb.pleaseSetUsername = \uC720\uC800\uB124\uC784\uC744 \uC785\uB825\uD558\uC138\uC694! -gb.usernameUnavailable = ''{0}'' \uC720\uC800\uB124\uC784\uC740 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC5B4\uC694. -gb.combinedMd5Rename = Gitblit \uC740 combined-md5 \uD574\uC2F1 \uD328\uC2A4\uC6CC\uB4DC\uB85C \uC124\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uACC4\uC815 \uC774\uB984 \uBCC0\uACBD \uC2DC \uC0C8 \uD328\uC2A4\uC6CC\uB4DC\uB97C \uC785\uB825\uD574\uC57C \uD569\uB2C8\uB2E4. -gb.userCreated = \uC0C8\uB85C\uC6B4 \uC720\uC800 ''{0}'' \uC0DD\uC131 \uC644\uB8CC. -gb.couldNotFindFederationRegistration = \uD398\uB354\uB808\uC774\uC158 \uB4F1\uB85D\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4! -gb.failedToFindGravatarProfile = {0} \uC758 Gravatar \uD504\uB85C\uD30C\uC77C \uCC3E\uAE30 \uC2E4\uD328 -gb.branchStats = {2} \uC548\uC5D0 {0} \uCEE4\uBC0B {1} \uD0DC\uADF8 -gb.repositoryNotSpecified = \uC800\uC7A5\uC18C\uAC00 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC74C! -gb.repositoryNotSpecifiedFor = {0} \uB97C \uC704\uD55C \uC800\uC7A5\uC18C\uAC00 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC74C! -gb.canNotLoadRepository = \uC800\uC7A5\uC18C\uB97C \uBD88\uB7EC\uC62C \uC218 \uC5C6\uC74C -gb.commitIsNull = \uB110 \uCEE4\uBC0B -gb.unauthorizedAccessForRepository = \uC800\uC7A5\uC18C\uC5D0 \uC811\uADFC \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC74C -gb.failedToFindCommit = \uCEE4\uBC0B\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC74C \"{0}\" in {1} for {2} \uD398\uC774\uC9C0! -gb.couldNotFindFederationProposal = \uD398\uB354\uB808\uC774\uC158 \uC81C\uC548\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4! -gb.invalidUsernameOrPassword = \uC798\uBABB\uB41C \uC720\uC800\uB124\uC784 \uB610\uB294 \uD328\uC2A4\uC6CC\uB4DC! -gb.OneProposalToReview = \uAC80\uD1A0\uB97C \uAE30\uB2E4\uB9AC\uACE0 \uC788\uB294 1\uAC1C\uC758 \uD398\uB354\uB808\uC774\uC158 \uC81C\uC548\uC774 \uC788\uC2B5\uB2C8\uB2E4. -gb.nFederationProposalsToReview = \uAC80\uD1A0\uB97C \uAE30\uB2E4\uB9AC\uACE0 \uC788\uB294 {0} \uAC1C\uC758 \uD398\uB354\uB808\uC774\uC158 \uC81C\uC548\uC774 \uC788\uC2B5\uB2C8\uB2E4. -gb.couldNotFindTag = \uD0DC\uADF8 {0} \uB97C(\uC744) \uCC3E\uC744 \uC218 \uC5C6\uC74C -gb.couldNotCreateFederationProposal = \uD398\uB354\uB808\uC774\uC158 \uC81C\uC548 \uC0DD\uC131 \uC2E4\uD328! -gb.pleaseSetGitblitUrl = Gitblit url \uC744 \uC785\uB825\uD558\uC138\uC694! -gb.pleaseSetDestinationUrl = \uB2F9\uC2E0\uC758 \uC81C\uC548\uC5D0 \uB300\uD55C \uB300\uC0C1 url \uC744 \uC785\uB825\uD558\uC138\uC694! -gb.proposalReceived = {0} \uC758 \uC81C\uC548 \uC131\uACF5\uC801 \uC218\uC2E0 -gb.noGitblitFound = \uC8C4\uC1A1\uD569\uB2C8\uB2E4, Gitblit \uC778\uC2A4\uD134\uC2A4 {1} \uC5D0\uC11C {0} \uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. -gb.noProposals = \uC8C4\uC1A1\uD569\uB2C8\uB2E4, \uC774\uBC88\uC5D0\uB294 {0} \uC758 \uC81C\uC548\uC744 \uC218\uC6A9\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. -gb.noFederation = \uC8C4\uC1A1\uD569\uB2C8\uB2E4, {0} \uC5D0\uB294 \uD398\uB354\uB808\uC774\uC158 \uC124\uC815\uB41C Gitblit \uC778\uC2A4\uD134\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. -gb.proposalFailed = \uC8C4\uC1A1\uD569\uB2C8\uB2E4, {0} \uC5D0\uB294 \uC81C\uC548 \uB370\uC774\uD130\uB97C \uBC1B\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. -gb.proposalError = \uC8C4\uC1A1\uD569\uB2C8\uB2E4, {0} \uC5D0 \uB300\uD55C \uC624\uB958 \uBC1C\uC0DD \uBCF4\uACE0 -gb.failedToSendProposal = \uC81C\uC548 \uBCF4\uB0B4\uAE30 \uC2E4\uD328! -gb.userServiceDoesNotPermitAddUser = {0} \uC0C8\uB85C\uC6B4 \uC720\uC800\uB97C \uCD94\uAC00\uD560 \uC218 \uC5C6\uC74C! -gb.userServiceDoesNotPermitPasswordChanges = {0} \uD328\uC2A4\uC6CC\uB4DC\uB97C \uBCC0\uACBD\uD560 \uC218 \uC5C6\uC74C! -gb.displayName = \uD45C\uC2DC\uB418\uB294 \uC774\uB984 -gb.emailAddress = \uC774\uBA54\uC77C \uC8FC\uC18C -gb.errorAdminLoginRequired = \uAD00\uB9AC\uB97C \uC704\uD574\uC11C\uB294 \uB85C\uADF8\uC778\uC774 \uD544\uC694 -gb.errorOnlyAdminMayCreateRepository = \uAD00\uB9AC\uC790\uB9CC \uC800\uC7A5\uC18C\uB97C \uB9CC\uB4E4\uC218 \uC788\uC74C -gb.errorOnlyAdminOrOwnerMayEditRepository = \uAD00\uB9AC\uC790\uC640 \uC18C\uC720\uC790\uB9CC \uC800\uC7A5\uC18C\uB97C \uC218\uC815\uD560 \uC218 \uC788\uC74C -gb.errorAdministrationDisabled = \uAD00\uB9AC\uAE30\uB2A5 \uBE44\uD65C\uC131\uD654\uB428 -gb.lastNDays = {0} \uC77C\uC804 -gb.completeGravatarProfile = Gravatar.com \uC5D0 \uD504\uB85C\uD30C\uC77C \uC0DD\uC131\uB428 +gb.activity = \uc561\ud2f0\ube44\ud2f0 +gb.subscribe = \uad6c\ub3c5 +gb.branch = \ube0c\ub79c\uce58 +gb.maxHits = \ub9e5\uc2a4\ud788\ud2b8 +gb.recentActivity = \ucd5c\uadfc \uc561\ud2f0\ube44\ud2f0 +gb.recentActivityStats = \uc9c0\ub09c {0}\uc77c / \uc791\uc131\uc790 {2}\uba85\uc774 {1}\uac1c \ucee4\ubc0b\ud568 +gb.recentActivityNone = \uc9c0\ub09c {0}\uc77c / \uc5c6\uc74c +gb.dailyActivity = \uc77c\uc77c \uc561\ud2f0\ube44\ud2f0 +gb.activeRepositories = \uc0ac\uc6a9\uc911\uc778 \uc800\uc7a5\uc18c +gb.activeAuthors = \uc0ac\uc6a9\uc911\uc778 \uc791\uc131\uc790 +gb.commits = \ucee4\ubc0b +gb.teams = \ud300 +gb.teamName = \ud300 \uc774\ub984 +gb.teamMembers = \ud300 \uba64\ubc84 +gb.teamMemberships = \ud300 \ub9f4\ubc84\uc27d +gb.newTeam = \uc0c8\ub85c\uc6b4 \ud300 +gb.permittedTeams = \ud5c8\uc6a9\ub41c \ud300 +gb.emptyRepository = \ube48 \uc800\uc7a5\uc18c +gb.repositoryUrl = \uc800\uc7a5\uc18c url +gb.mailingLists = \uba54\uc77c\ub9c1 \ub9ac\uc2a4\ud2b8 +gb.preReceiveScripts = pre-receive \uc2a4\ud06c\ub9bd\ud2b8 +gb.postReceiveScripts = post-receive \uc2a4\ud06c\ub9bd\ud2b8 +gb.hookScripts = \ud6c4\ud06c \uc2a4\ud06c\ub9bd\ud2b8 +gb.customFields = \uc0ac\uc6a9\uc790 \ud544\ub4dc +gb.customFieldsDescription = \uadf8\ub8e8\ube44 \ud6c5\uc5d0 \uc0ac\uc6a9\uc790 \ud544\ub4dc \uc0ac\uc6a9 \uac00\ub2a5 +gb.accessPermissions = \uc811\uc18d \uad8c\ud55c +gb.filters = \ud544\ud130 +gb.generalDescription = \uc77c\ubc18 \uc124\uc815 +gb.accessPermissionsDescription = \uc720\uc800\uc640 \ud300\uc73c\ub85c \uc811\uc18d\uad8c\ud55c \ubd80\uc5ec +gb.accessPermissionsForUserDescription = \ud300\uc744 \uc9c0\uc815\ud558\uac70\ub098 \uc811\uc18d \uad8c\ud55c\uc744 \uc9c0\uc815\ud560 \uc800\uc7a5\uc18c \uc120\ud0dd +gb.accessPermissionsForTeamDescription = \ud300 \ub9f4\ubc84\ub97c \uc120\ud0dd\ud558\uace0, \uc811\uc18d \uad8c\ud55c\uc744 \uc9c0\uc815\ud560 \uc800\uc7a5\uc18c \uc120\ud0dd +gb.federationRepositoryDescription = \uc774 \uc800\uc7a5\uc18c\ub97c \ub2e4\ub978 Gitblit \uc11c\ubc84\uc640 \uacf5\uc720 +gb.hookScriptsDescription = \uc774 Gitblit \uc11c\ubc84\uc5d0 \ud478\uc2dc\ub418\uba74 \uadf8\ub8e8\ube44(Groovy) \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc2e4\ud589 +gb.reset = \ub9ac\uc14b +gb.pages = \ud398\uc774\uc9c0 +gb.workingCopy = \uc6cc\ud0b9 \uce74\ud53c +gb.workingCopyWarning = \uc774 \uc800\uc7a5\uc18c\ub294 \uc6cc\ud0b9\uce74\ud53c\ub97c \uac00\uc9c0\uace0 \uc788\uace0 \ud478\uc2dc\ub97c \ubc1b\uc744 \uc218 \uc5c6\uc74c +gb.query = \ucffc\ub9ac +gb.queryHelp = \ud45c\uc900 \ucffc\ub9ac \ubb38\ubc95\uc744 \uc9c0\uc6d0.

\uc790\uc138\ud55c \uac83\uc744 \uc6d0\ud55c\ub2e4\uba74 ${querySyntax} \uc744 \ubc29\ubb38\ud574 \uc8fc\uc138\uc694. +gb.querySyntax = \ub8e8\uc2e0 \ucffc\ub9ac \ud30c\uc11c \ubb38\ubc95 +gb.queryResults = \uac80\uc0c9\uacb0\uacfc {0} - {1} ({2}\uac1c \uac80\uc0c9\ub428) +gb.noHits = \uac80\uc0c9 \uacb0\uacfc \uc5c6\uc74c +gb.authored = \uac00 \uc791\uc131\ud568. +gb.committed = \ucee4\ubc0b\ub428 +gb.indexedBranches = \uc778\ub371\uc2f1\ud560 \ube0c\ub79c\uce58 +gb.indexedBranchesDescription = \ub8e8\uc2e0 \uc778\ub371\uc2a4\uc5d0 \ud3ec\ud568\ud560 \ube0c\ub79c\uce58 \uc120\ud0dd +gb.noIndexedRepositoriesWarning = \uc800\uc7a5\uc18c\uac00 \ub8e8\uc2e0 \uc778\ub371\uc2f1\uc5d0 \uc124\uc815\ub418\uc9c0 \uc54a\uc74c +gb.undefinedQueryWarning = \ucffc\ub9ac \uc9c0\uc815\ub418\uc9c0 \uc54a\uc74c! +gb.noSelectedRepositoriesWarning = \ud558\ub098 \ub610\ub294 \uadf8 \uc774\uc0c1\uc758 \uc800\uc7a5\uc18c\ub97c \uc120\ud0dd\ud558\uc138\uc694! +gb.luceneDisabled = \ub8e8\uc2e0 \uc778\ub371\uc2f1 \uc911\uc9c0\ub428 +gb.failedtoRead = \uc77c\uae30 \uc2e4\ud328 +gb.isNotValidFile = \uc720\ud6a8\ud55c \ud30c\uc77c\uc774 \uc544\ub2d8 +gb.failedToReadMessage = {0}\uc5d0\uc11c \ub514\ud3f4\ud2b8 \uba54\uc2dc\uc9c0 \uc77c\uae30 \uc2e4\ud328! +gb.passwordsDoNotMatch = \ud328\uc2a4\uc6cc\ub4dc\uac00 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc694! +gb.passwordTooShort = \ud328\uc2a4\uc6cc\ub4dc\uac00 \ub108\ubb34 \uc9e7\uc544\uc694. \uc801\uc5b4\ub3c4 {0} \uac1c \ubb38\uc790\uc5ec\uc57c \ud569\ub2c8\ub2e4. +gb.passwordChanged = \ud328\uc2a4\uc6cc\ub4dc\uac00 \ubcc0\uacbd \uc131\uacf5. +gb.passwordChangeAborted = \ud328\uc2a4\uc6cc\ub4dc \ubcc0\uacbd \ucde8\uc18c\ub428. +gb.pleaseSetRepositoryName = \uc800\uc7a5\uc18c \uc774\ub984\uc744 \uc785\ub825\ud558\uc138\uc694! +gb.illegalLeadingSlash = \uc800\uc7a5\uc18c \uc774\ub984 \ub610\ub294 \ud3f4\ub354\ub294 (/) \ub85c \uc2dc\uc791\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +gb.illegalRelativeSlash = \uc0c1\ub300 \uacbd\ub85c \uc9c0\uc815 (../) \uc740 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.. +gb.illegalCharacterRepositoryName = \ubb38\uc790 ''{0}'' \uc800\uc7a5\uc18c \uc774\ub984\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5b4\uc694! +gb.selectAccessRestriction = \uc811\uc18d \uad8c\ud55c\uc744 \uc120\ud0dd\ud558\uc138\uc694! +gb.selectFederationStrategy = \ud398\ub354\ub808\uc774\uc158 \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uc138\uc694! +gb.pleaseSetTeamName = \ud300\uc774\ub984\uc744 \uc785\ub825\ud558\uc138\uc694! +gb.teamNameUnavailable = ''{0}'' \ud300\uc740 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5b4\uc694. +gb.teamMustSpecifyRepository = \ud300\uc740 \uc801\uc5b4\ub3c4 \ud558\ub098\uc758 \uc800\uc7a5\uc18c\ub97c \uc9c0\uc815\ud574\uc57c \ud569\ub2c8\ub2e4. +gb.teamCreated = \uc0c8\ub85c\uc6b4 \ud300 ''{0}'' \uc0dd\uc131 \uc644\ub8cc. +gb.pleaseSetUsername = \uc720\uc800\ub124\uc784\uc744 \uc785\ub825\ud558\uc138\uc694! +gb.usernameUnavailable = ''{0}'' \uc720\uc800\ub124\uc784\uc740 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5b4\uc694. +gb.combinedMd5Rename = Gitblit \uc740 combined-md5 \ud574\uc2f1 \ud328\uc2a4\uc6cc\ub4dc\ub85c \uc124\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uacc4\uc815 \uc774\ub984 \ubcc0\uacbd \uc2dc \uc0c8 \ud328\uc2a4\uc6cc\ub4dc\ub97c \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +gb.userCreated = \uc0c8\ub85c\uc6b4 \uc720\uc800 ''{0}'' \uc0dd\uc131 \uc644\ub8cc. +gb.couldNotFindFederationRegistration = \ud398\ub354\ub808\uc774\uc158 \ub4f1\ub85d\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4! +gb.failedToFindGravatarProfile = {0} \uc758 Gravatar \ud504\ub85c\ud30c\uc77c \ucc3e\uae30 \uc2e4\ud328 +gb.branchStats = {2} \uc548\uc5d0 {0} \ucee4\ubc0b {1} \ud0dc\uadf8 +gb.repositoryNotSpecified = \uc800\uc7a5\uc18c\uac00 \uc9c0\uc815\ub418\uc9c0 \uc54a\uc74c! +gb.repositoryNotSpecifiedFor = {0} \ub97c \uc704\ud55c \uc800\uc7a5\uc18c\uac00 \uc9c0\uc815\ub418\uc9c0 \uc54a\uc74c! +gb.canNotLoadRepository = \uc800\uc7a5\uc18c\ub97c \ubd88\ub7ec\uc62c \uc218 \uc5c6\uc74c +gb.commitIsNull = \ub110 \ucee4\ubc0b +gb.unauthorizedAccessForRepository = \uc800\uc7a5\uc18c\uc5d0 \uc811\uadfc \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc74c +gb.failedToFindCommit = \ucee4\ubc0b\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc74c \"{0}\" in {1} for {2} \ud398\uc774\uc9c0! +gb.couldNotFindFederationProposal = \ud398\ub354\ub808\uc774\uc158 \uc81c\uc548\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4! +gb.invalidUsernameOrPassword = \uc798\ubabb\ub41c \uc720\uc800\ub124\uc784 \ub610\ub294 \ud328\uc2a4\uc6cc\ub4dc! +gb.OneProposalToReview = \uac80\ud1a0\ub97c \uae30\ub2e4\ub9ac\uace0 \uc788\ub294 1\uac1c\uc758 \ud398\ub354\ub808\uc774\uc158 \uc81c\uc548\uc774 \uc788\uc2b5\ub2c8\ub2e4. +gb.nFederationProposalsToReview = \uac80\ud1a0\ub97c \uae30\ub2e4\ub9ac\uace0 \uc788\ub294 {0} \uac1c\uc758 \ud398\ub354\ub808\uc774\uc158 \uc81c\uc548\uc774 \uc788\uc2b5\ub2c8\ub2e4. +gb.couldNotFindTag = \ud0dc\uadf8 {0} \ub97c(\uc744) \ucc3e\uc744 \uc218 \uc5c6\uc74c +gb.couldNotCreateFederationProposal = \ud398\ub354\ub808\uc774\uc158 \uc81c\uc548 \uc0dd\uc131 \uc2e4\ud328! +gb.pleaseSetGitblitUrl = Gitblit url \uc744 \uc785\ub825\ud558\uc138\uc694! +gb.pleaseSetDestinationUrl = \ub2f9\uc2e0\uc758 \uc81c\uc548\uc5d0 \ub300\ud55c \ub300\uc0c1 url \uc744 \uc785\ub825\ud558\uc138\uc694! +gb.proposalReceived = {0} \uc758 \uc81c\uc548 \uc131\uacf5\uc801 \uc218\uc2e0 +gb.noGitblitFound = \uc8c4\uc1a1\ud569\ub2c8\ub2e4, Gitblit \uc778\uc2a4\ud134\uc2a4 {1} \uc5d0\uc11c {0} \ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +gb.noProposals = \uc8c4\uc1a1\ud569\ub2c8\ub2e4, \uc774\ubc88\uc5d0\ub294 {0} \uc758 \uc81c\uc548\uc744 \uc218\uc6a9\ud558\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +gb.noFederation = \uc8c4\uc1a1\ud569\ub2c8\ub2e4, {0} \uc5d0\ub294 \ud398\ub354\ub808\uc774\uc158 \uc124\uc815\ub41c Gitblit \uc778\uc2a4\ud134\uc2a4\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. +gb.proposalFailed = \uc8c4\uc1a1\ud569\ub2c8\ub2e4, {0} \uc5d0\ub294 \uc81c\uc548 \ub370\uc774\ud130\ub97c \ubc1b\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +gb.proposalError = \uc8c4\uc1a1\ud569\ub2c8\ub2e4, {0} \uc5d0 \ub300\ud55c \uc624\ub958 \ubc1c\uc0dd \ubcf4\uace0 +gb.failedToSendProposal = \uc81c\uc548 \ubcf4\ub0b4\uae30 \uc2e4\ud328! +gb.userServiceDoesNotPermitAddUser = {0} \uc0c8\ub85c\uc6b4 \uc720\uc800\ub97c \ucd94\uac00\ud560 \uc218 \uc5c6\uc74c! +gb.userServiceDoesNotPermitPasswordChanges = {0} \ud328\uc2a4\uc6cc\ub4dc\ub97c \ubcc0\uacbd\ud560 \uc218 \uc5c6\uc74c! +gb.displayName = \ud45c\uc2dc\ub418\ub294 \uc774\ub984 +gb.emailAddress = \uc774\uba54\uc77c \uc8fc\uc18c +gb.errorAdminLoginRequired = \uad00\ub9ac\ub97c \uc704\ud574\uc11c\ub294 \ub85c\uadf8\uc778\uc774 \ud544\uc694 +gb.errorOnlyAdminMayCreateRepository = \uad00\ub9ac\uc790\ub9cc \uc800\uc7a5\uc18c\ub97c \ub9cc\ub4e4\uc218 \uc788\uc74c +gb.errorOnlyAdminOrOwnerMayEditRepository = \uad00\ub9ac\uc790\uc640 \uc18c\uc720\uc790\ub9cc \uc800\uc7a5\uc18c\ub97c \uc218\uc815\ud560 \uc218 \uc788\uc74c +gb.errorAdministrationDisabled = \uad00\ub9ac\uae30\ub2a5 \ube44\ud65c\uc131\ud654\ub428 +gb.lastNDays = {0} \uc77c\uc804 +gb.completeGravatarProfile = Gravatar.com \uc5d0 \ud504\ub85c\ud30c\uc77c \uc0dd\uc131\ub428 gb.none = none gb.line = \uB77C\uC778 gb.content = \uB0B4\uC6A9 @@ -782,4 +783,4 @@ gb.deletePatchset = {0} \uD328\uCE58\uC14B \uC0AD\uC81C gb.deletePatchsetSuccess = {0} \uD328\uCE58\uC14B\uC774 \uC0AD\uC81C\uB418\uC5C8\uC5B4\uC694. gb.deletePatchsetFailure = {0} \uD328\uCE58\uC14B \uC0AD\uC81C \uC624\uB958. gb.referencedByCommit = \uCEE4\uBC0B\uC5D0 \uCC38\uC870\uB428. -gb.referencedByTicket = \uD2F0\uCF13\uC5D0 \uCC38\uC870\uB428. \ No newline at end of file +gb.referencedByTicket = \uD2F0\uCF13\uC5D0 \uCC38\uC870\uB428. diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties index f71d67d74..41656e8a9 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_nl.properties @@ -218,7 +218,8 @@ gb.pages = paginas gb.workingCopy = werkkopie gb.workingCopyWarning = deze repositorie heeft een werkkopie en kan geen pushes ontvangen gb.query = query -gb.queryHelp = Standaard query syntax wordt ondersteund.

Zie aub Lucene Query Parser Syntax voor informatie. +gb.queryHelp = Standaard query syntax wordt ondersteund.

Zie aub ${querySyntax} voor informatie. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = resultaten {0} - {1} ({2} hits) gb.noHits = geen hits gb.authored = geschreven diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_no.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_no.properties index efc13a1ea..a02a30f33 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_no.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_no.properties @@ -218,7 +218,8 @@ gb.pages = sider gb.workingCopy = arbeidskopi gb.workingCopyWarning = dette repositoriet har en arbeidskopi, og kan ikke pushes til. gb.query = sp\u00F8rring -gb.queryHelp = Standard lucene sp\u00F8rringssyntaks st\u00F8ttes.

Se Lucene Query Parser Syntax for mer info. +gb.queryHelp = Standard lucene sp\u00F8rringssyntaks st\u00F8ttes.

Se ${querySyntax} for mer info. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = resultater {0} - {1} ({2} treff) gb.noHits = ingen treff gb.authored = forfattet diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties index b00d1ff8c..fee4b9759 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_pl.properties @@ -217,7 +217,8 @@ gb.pages = Strony gb.workingCopy = Kopia robocza gb.workingCopyWarning = To repozytorium ma kopi\u0119 robocz\u0105 i nie mo\u017Ce otrzymywa\u0107 zmian gb.query = Szukaj -gb.queryHelp = Standardowa sk\u0142adnia wyszukiwa\u0144 jest wspierana.

Na stronie Lucene Query Parser Syntax dost\u0119pne s\u0105 dalsze szczeg\u00F3\u0142y. +gb.queryHelp = Standardowa sk\u0142adnia wyszukiwa\u0144 jest wspierana.

Na stronie ${querySyntax} dost\u0119pne s\u0105 dalsze szczeg\u00F3\u0142y. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = Wyniki {0} - {1} ({2} wynik\u00F3w) gb.noHits = Brak wynik\u00F3w gb.authored = utworzy\u0142 diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties index 4d2ea553e..b573792f8 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties @@ -217,7 +217,8 @@ gb.pages = p gb.workingCopy = working copy gb.workingCopyWarning = este repositório tem uma working copy e não pode receber pushes gb.query = query -gb.queryHelp = Standard query syntax é suportada.

Por favor veja Lucene Query Parser Syntax para mais detalhes. +gb.queryHelp = Standard query syntax é suportada.

Por favor veja ${querySyntax} para mais detalhes. +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = resultados {0} - {1} ({2} hits) gb.noHits = sem hits gb.authored = foi autor de diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties index b5e4f658c..c82e12fa6 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties @@ -218,7 +218,8 @@ gb.pages = \u9875\u9762 gb.workingCopy = \u5de5\u4f5c\u526f\u672c gb.workingCopyWarning = \u6b64\u7248\u672c\u5e93\u5b58\u5728\u4e00\u4efd\u5de5\u4f5c\u526f\u672c\uff0c\u65e0\u6cd5\u8fdb\u884c\u63a8\u9001 gb.query = \u67e5\u8be2 -gb.queryHelp = \u652f\u6301\u6807\u51c6\u67e5\u8be2\u683c\u5f0f.

\u8bf7\u67e5\u770b Lucene \u67e5\u8be2\u5904\u7406\u5668\u683c\u5f0f \u4ee5\u83b7\u53d6\u8be6\u7ec6\u5185\u5bb9\u3002 +gb.queryHelp = \u652f\u6301\u6807\u51c6\u67e5\u8be2\u683c\u5f0f.

\u8bf7\u67e5\u770b ${querySyntax} \u4ee5\u83b7\u53d6\u8be6\u7ec6\u5185\u5bb9\u3002 +gb.querySyntax = Lucene \u67e5\u8be2\u5904\u7406\u5668\u683c\u5f0f gb.queryResults = \u7ed3\u679c {0} - {1} ({2} \u6b21\u547d\u4e2d) gb.noHits = \u672a\u547d\u4e2d gb.authored = authored diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties index 157dd5660..631064694 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp_zh_TW.properties @@ -219,7 +219,8 @@ gb.pages = \u6587\u4ef6 gb.workingCopy = \u66ab\u5b58\u8907\u672c gb.workingCopyWarning = \u8a72\u7248\u672c\u5eab\u4ecd\u6709\u66ab\u5b58\u8907\u672c,\u56e0\u6b64\u7121\u6cd5\u63a5\u53d7\u63a8\u9001(push) gb.query = \u67e5\u8a62 -gb.queryHelp = \u652f\u63f4\u6a19\u6e96\u67e5\u8a62\u8a9e\u6cd5.

\u8a73\u60c5\u8acb\u53c3\u8003 Lucene Query Parser Syntax +gb.queryHelp = \u652f\u63f4\u6a19\u6e96\u67e5\u8a62\u8a9e\u6cd5.

\u8a73\u60c5\u8acb\u53c3\u8003 ${querySyntax} +gb.querySyntax = Lucene Query Parser Syntax gb.queryResults = \u7d50\u679c {0} - {1} ({2} \u67e5\u8a62) gb.noHits = \u7121\u9ede\u64ca gb.authored = \u6388\u6b0a diff --git a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.html b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.html index d62b7b224..a386f425c 100644 --- a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.html +++ b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.html @@ -52,7 +52,9 @@

- + + +
diff --git a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java index 1d81061e5..a97d37a8e 100644 --- a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java +++ b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java @@ -27,6 +27,7 @@ import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.ListMultipleChoice; import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; @@ -50,6 +51,8 @@ public class LuceneSearchPage extends RootPage { + private final static String LUCENE_QUERY_SYNTAX_LINK = "https://lucene.apache.org/core/5_5_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description"; + public LuceneSearchPage() { super(); setup(null); @@ -167,6 +170,7 @@ public void onSubmit() { form.add(selections.setEnabled(luceneEnabled)); form.add(new TextField("query", queryModel).setEnabled(luceneEnabled)); form.add(new CheckBox("allrepos", allreposModel)); + form.add(new ExternalLink("querySyntax", LUCENE_QUERY_SYNTAX_LINK)); add(form.setEnabled(luceneEnabled)); // execute search From 71e24e22cca3f85996b8a0d1951311b4592f2213 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sat, 21 Jan 2017 19:09:18 +0100 Subject: [PATCH 06/11] Replace deprecated BooleanQuery constructor with builder. Also replace deprecated `search` method with the one without a filter argument, since the filter isn't used anyhow. --- .../com/gitblit/service/LuceneService.java | 10 +++++----- .../com/gitblit/tickets/TicketIndexer.java | 18 ++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/gitblit/service/LuceneService.java b/src/main/java/com/gitblit/service/LuceneService.java index f22cb5a57..9b97ad5b3 100644 --- a/src/main/java/com/gitblit/service/LuceneService.java +++ b/src/main/java/com/gitblit/service/LuceneService.java @@ -718,10 +718,9 @@ public boolean deleteBlob(String repositoryName, String branch, String path) thr String pattern = MessageFormat.format("{0}:'{'0} AND {1}:\"'{'1'}'\" AND {2}:\"'{'2'}'\"", FIELD_OBJECT_TYPE, FIELD_BRANCH, FIELD_PATH); String q = MessageFormat.format(pattern, SearchObjectType.blob.name(), branch, path); - BooleanQuery query = new BooleanQuery(); StandardAnalyzer analyzer = new StandardAnalyzer(); QueryParser qp = new QueryParser(FIELD_SUMMARY, analyzer); - query.add(qp.parse(q), Occur.MUST); + BooleanQuery query = new BooleanQuery.Builder().add(qp.parse(q), Occur.MUST).build(); IndexWriter writer = getIndexWriter(repositoryName); int numDocsBefore = writer.numDocs(); @@ -1028,15 +1027,15 @@ public List search(String text, int page, int pageSize, String... StandardAnalyzer analyzer = new StandardAnalyzer(); try { // default search checks summary and content - BooleanQuery query = new BooleanQuery(); + BooleanQuery.Builder bldr = new BooleanQuery.Builder(); QueryParser qp; qp = new QueryParser(FIELD_SUMMARY, analyzer); qp.setAllowLeadingWildcard(true); - query.add(qp.parse(text), Occur.SHOULD); + bldr.add(qp.parse(text), Occur.SHOULD); qp = new QueryParser(FIELD_CONTENT, analyzer); qp.setAllowLeadingWildcard(true); - query.add(qp.parse(text), Occur.SHOULD); + bldr.add(qp.parse(text), Occur.SHOULD); IndexSearcher searcher; if (repositories.length == 1) { @@ -1054,6 +1053,7 @@ public List search(String text, int page, int pageSize, String... searcher = new IndexSearcher(reader); } + BooleanQuery query = bldr.build(); Query rewrittenQuery = searcher.rewrite(query); logger.debug(rewrittenQuery.toString()); diff --git a/src/main/java/com/gitblit/tickets/TicketIndexer.java b/src/main/java/com/gitblit/tickets/TicketIndexer.java index 652323a4c..b765cc660 100644 --- a/src/main/java/com/gitblit/tickets/TicketIndexer.java +++ b/src/main/java/com/gitblit/tickets/TicketIndexer.java @@ -200,8 +200,7 @@ public boolean deleteAll(RepositoryModel repository) { IndexWriter writer = getWriter(); StandardAnalyzer analyzer = new StandardAnalyzer(); QueryParser qp = new QueryParser(Lucene.rid.name(), analyzer); - BooleanQuery query = new BooleanQuery(); - query.add(qp.parse(repository.getRID()), Occur.MUST); + BooleanQuery query = new BooleanQuery.Builder().add(qp.parse(repository.getRID()), Occur.MUST).build(); int numDocsBefore = writer.numDocs(); writer.deleteDocuments(query); @@ -286,8 +285,7 @@ public boolean delete(TicketModel ticket) { private boolean delete(String repository, long ticketId, IndexWriter writer) throws Exception { StandardAnalyzer analyzer = new StandardAnalyzer(); QueryParser qp = new QueryParser(Lucene.did.name(), analyzer); - BooleanQuery query = new BooleanQuery(); - query.add(qp.parse(StringUtils.getSHA1(repository + ticketId)), Occur.MUST); + BooleanQuery query = new BooleanQuery.Builder().add(qp.parse(StringUtils.getSHA1(repository + ticketId)), Occur.MUST).build(); int numDocsBefore = writer.numDocs(); writer.deleteDocuments(query); @@ -331,23 +329,23 @@ public List searchFor(RepositoryModel repository, String text, int StandardAnalyzer analyzer = new StandardAnalyzer(); try { // search the title, description and content - BooleanQuery query = new BooleanQuery(); + BooleanQuery.Builder bldr = new BooleanQuery.Builder(); QueryParser qp; qp = new QueryParser(Lucene.title.name(), analyzer); qp.setAllowLeadingWildcard(true); - query.add(qp.parse(text), Occur.SHOULD); + bldr.add(qp.parse(text), Occur.SHOULD); qp = new QueryParser(Lucene.body.name(), analyzer); qp.setAllowLeadingWildcard(true); - query.add(qp.parse(text), Occur.SHOULD); + bldr.add(qp.parse(text), Occur.SHOULD); qp = new QueryParser(Lucene.content.name(), analyzer); qp.setAllowLeadingWildcard(true); - query.add(qp.parse(text), Occur.SHOULD); + bldr.add(qp.parse(text), Occur.SHOULD); IndexSearcher searcher = getSearcher(); - Query rewrittenQuery = searcher.rewrite(query); + Query rewrittenQuery = searcher.rewrite(bldr.build()); log.debug(rewrittenQuery.toString()); @@ -406,7 +404,7 @@ public List queryFor(String queryText, int page, int pageSize, Stri sort = new Sort(Lucene.fromString(sortBy).asSortField(desc)); } int maxSize = 5000; - TopFieldDocs docs = searcher.search(rewrittenQuery, null, maxSize, sort, false, false); + TopFieldDocs docs = searcher.search(rewrittenQuery, maxSize, sort, false, false); int size = (pageSize <= 0) ? maxSize : pageSize; int offset = Math.max(0, (page - 1) * size); ScoreDoc[] hits = subset(docs.scoreDocs, offset, size); From bf1b35aac29b6c0d5e918f00d99a0632e4925b51 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sun, 26 Feb 2017 18:44:02 +0100 Subject: [PATCH 07/11] Add DocValues to support sorting of ticket index fields. In order to support sorting, Lucene 5 needs DocValue fields in an index. So in order to make the ticket index work, i.e. show any tickets on the tickets page, the ticket index needs to be changed, adding a DocValues field. The DocValuesFields are implemented for the current index, which does not use multiple values for a field. Should at any time in the future an existing numeric field get multiple values stored in a document, then the index needs to know that and use SortedNumeric DocValues and SortFields instead. --- src/main/java/com/gitblit/tickets/TicketIndexer.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/gitblit/tickets/TicketIndexer.java b/src/main/java/com/gitblit/tickets/TicketIndexer.java index b765cc660..8aab74ba7 100644 --- a/src/main/java/com/gitblit/tickets/TicketIndexer.java +++ b/src/main/java/com/gitblit/tickets/TicketIndexer.java @@ -31,6 +31,8 @@ import org.apache.lucene.document.Field.Store; import org.apache.lucene.document.IntField; import org.apache.lucene.document.LongField; +import org.apache.lucene.document.NumericDocValuesField; +import org.apache.lucene.document.SortedDocValuesField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexWriter; @@ -49,6 +51,7 @@ import org.apache.lucene.search.TopScoreDocCollector; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; +import org.apache.lucene.util.BytesRef; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -549,14 +552,17 @@ private void toDocField(Document doc, Lucene lucene, Date value) { return; } doc.add(new LongField(lucene.name(), value.getTime(), Store.YES)); + doc.add(new NumericDocValuesField(lucene.name(), value.getTime())); } private void toDocField(Document doc, Lucene lucene, long value) { doc.add(new LongField(lucene.name(), value, Store.YES)); + doc.add(new NumericDocValuesField(lucene.name(), value)); } private void toDocField(Document doc, Lucene lucene, int value) { doc.add(new IntField(lucene.name(), value, Store.YES)); + doc.add(new NumericDocValuesField(lucene.name(), value)); } private void toDocField(Document doc, Lucene lucene, String value) { @@ -564,6 +570,7 @@ private void toDocField(Document doc, Lucene lucene, String value) { return; } doc.add(new org.apache.lucene.document.Field(lucene.name(), value, TextField.TYPE_STORED)); + doc.add(new SortedDocValuesField(lucene.name(), new BytesRef(value))); } /** From 71a27ddc781e0c2a684f747c794f8948c65cbf5c Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sun, 5 Mar 2017 16:45:44 +0100 Subject: [PATCH 08/11] Introduce an index version for the ticket index In order to be able to update the index definition, the ticket index is assigned a version number, 2. This way the definiton can be updated and compatability with existing index files can be checked. The actual index is stored in a directory of name `indexVersion_codecVersion`. This wayit is veriy easy to check if an index of a certain version exists on the filesystem. It allows to have multiple indexes of different versions present, so that a downgrade of the software is possible without having to reindex again. Of coure, this is only possible if no new tickets were created since these would be missing in the old index. A new class `LuceneIndexStore` is introduced, which abstracts away the versioned index directory. The idea is, that this provides one place to keep the Lucene codec version and to allow to code compatibility rules into this class, so that older indices can still be used if they are compatible. --- .../com/gitblit/tickets/TicketIndexer.java | 18 +- .../com/gitblit/utils/LuceneIndexStore.java | 98 +++++++ .../gitblit/utils/LuceneIndexStoreTest.java | 245 ++++++++++++++++++ 3 files changed, 352 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/gitblit/utils/LuceneIndexStore.java create mode 100644 src/test/java/com/gitblit/utils/LuceneIndexStoreTest.java diff --git a/src/main/java/com/gitblit/tickets/TicketIndexer.java b/src/main/java/com/gitblit/tickets/TicketIndexer.java index 8aab74ba7..bc08fc889 100644 --- a/src/main/java/com/gitblit/tickets/TicketIndexer.java +++ b/src/main/java/com/gitblit/tickets/TicketIndexer.java @@ -62,7 +62,7 @@ import com.gitblit.models.TicketModel.Attachment; import com.gitblit.models.TicketModel.Patchset; import com.gitblit.models.TicketModel.Status; -import com.gitblit.utils.FileUtils; +import com.gitblit.utils.LuceneIndexStore; import com.gitblit.utils.StringUtils; /** @@ -110,6 +110,8 @@ public static enum Lucene { priority(Type.INT), severity(Type.INT); + final static int INDEX_VERSION = 2; + final Type fieldType; Lucene(Type fieldType) { @@ -169,14 +171,15 @@ public static Lucene fromString(String value) { private final Logger log = LoggerFactory.getLogger(getClass()); - private final File luceneDir; + private final LuceneIndexStore indexStore; private IndexWriter writer; private IndexSearcher searcher; public TicketIndexer(IRuntimeManager runtimeManager) { - this.luceneDir = runtimeManager.getFileOrFolder(Keys.tickets.indexFolder, "${baseFolder}/tickets/lucene"); + File luceneDir = runtimeManager.getFileOrFolder(Keys.tickets.indexFolder, "${baseFolder}/tickets/lucene"); + this.indexStore = new LuceneIndexStore(luceneDir, Lucene.INDEX_VERSION); } /** @@ -192,7 +195,7 @@ public void close() { */ public void deleteAll() { close(); - FileUtils.delete(luceneDir); + indexStore.delete(); } /** @@ -441,12 +444,9 @@ public List queryFor(String queryText, int page, int pageSize, Stri private IndexWriter getWriter() throws IOException { if (writer == null) { - Directory directory = FSDirectory.open(luceneDir.toPath()); - - if (!luceneDir.exists()) { - luceneDir.mkdirs(); - } + indexStore.create(); + Directory directory = FSDirectory.open(indexStore.getPath()); StandardAnalyzer analyzer = new StandardAnalyzer(); IndexWriterConfig config = new IndexWriterConfig(analyzer); config.setOpenMode(OpenMode.CREATE_OR_APPEND); diff --git a/src/main/java/com/gitblit/utils/LuceneIndexStore.java b/src/main/java/com/gitblit/utils/LuceneIndexStore.java new file mode 100644 index 000000000..0ccfd2e8c --- /dev/null +++ b/src/main/java/com/gitblit/utils/LuceneIndexStore.java @@ -0,0 +1,98 @@ +/* + * Copyright 2017 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitblit.utils; + +import java.io.File; +import java.nio.file.Path; + +/** + * @author Florian Zschocke + * + * @since 1.9.0 + */ +public class LuceneIndexStore +{ + + public static final int LUCENE_CODEC_VERSION = 54; + + protected File indexFolder; + + /** + * Constructor for a base folder that contains the version specific index folders + * and an index version. + * + * @param luceneFolder + * Path to the base folder for the Lucene indices, i.e. the common "lucene" directory. + * @param indexVersion + * Version of the index definition + */ + public LuceneIndexStore(File luceneFolder, int indexVersion) + { + this.indexFolder = new File(luceneFolder, indexVersion + "_" + LUCENE_CODEC_VERSION); + } + + + + /** + * Create the Lucene index directory for this index version and Lucene codec version + */ + public void create() + { + if (! indexFolder.exists()) { + indexFolder.mkdirs(); + } + } + + + /** + * Delete the Lucene index directory for this index version and Lucene codec version + * + * @return True if the directory could successfully be deleted. + */ + public boolean delete() + { + if (indexFolder.exists()) { + return FileUtils.delete(indexFolder); + } + return true; + } + + + + /** + * @return The Path to the index folder + */ + public Path getPath() + { + return indexFolder.toPath(); + } + + + + /** + * Check if an index of the respective version, or compatible, already exists. + * + * @return True if an index exists, False otherwise + */ + public boolean hasIndex() + { + return indexFolder.exists() && + indexFolder.isDirectory() && + (indexFolder.list().length > 1); + } + +} diff --git a/src/test/java/com/gitblit/utils/LuceneIndexStoreTest.java b/src/test/java/com/gitblit/utils/LuceneIndexStoreTest.java new file mode 100644 index 000000000..4d66c5dc7 --- /dev/null +++ b/src/test/java/com/gitblit/utils/LuceneIndexStoreTest.java @@ -0,0 +1,245 @@ +/* + * Copyright 2017 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitblit.utils; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + + +/** + * @author Florian Zschocke + * + */ +public class LuceneIndexStoreTest +{ + + private final int LUCENE_VERSION = LuceneIndexStore.LUCENE_CODEC_VERSION; + + @Rule + public TemporaryFolder baseFolder = new TemporaryFolder(); + + private String getIndexDir(int version) + { + return version + "_" + LUCENE_VERSION; + } + + + + @Test + public void testCreate() + { + int version = 0; + File luceneFolder = new File(baseFolder.getRoot(), "tickets/lucene"); + assertFalse("Precondition failure: directory exists already", luceneFolder.exists()); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + li.create(); + + File luceneDir = new File(luceneFolder, getIndexDir(version)); + assertTrue(luceneDir.exists()); + } + + @Test + public void testCreateIndexDir() + { + int version = 111222; + File luceneFolder = null; + try { + luceneFolder = baseFolder.newFolder("tickets", "lucene"); + } + catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: directory does not exist", luceneFolder.exists()); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + li.create(); + + File luceneDir = new File(luceneFolder, getIndexDir(version)); + assertTrue(luceneDir.exists()); + assertTrue(luceneDir.isDirectory()); + + // Make sure nothing else was created. + assertEquals(0, luceneDir.list().length); + assertEquals(1, luceneDir.getParentFile().list().length); + assertEquals(1, luceneDir.getParentFile().getParentFile().list().length); + } + + @Test + public void testCreateIfNecessary() + { + int version = 1; + File luceneFolder = new File(baseFolder.getRoot(), "tickets/lucene"); + File luceneDir = null; + try { + luceneDir = baseFolder.newFolder("tickets", "lucene", getIndexDir(version)); + } + catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: directory does not exist", luceneDir.exists()); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + li.create(); + + assertTrue(luceneDir.exists()); + assertTrue(luceneDir.isDirectory()); + + // Make sure nothing else was created. + assertEquals(0, luceneDir.list().length); + assertEquals(1, luceneDir.getParentFile().list().length); + assertEquals(1, luceneDir.getParentFile().getParentFile().list().length); + } + + @Test + public void testDelete() + { + int version = 111222333; + File luceneFolder = new File(baseFolder.getRoot(), "repo1/lucene"); + File luceneDir = null; + try { + luceneDir = baseFolder.newFolder("repo1", "lucene", getIndexDir(version)); + } + catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: index directory does not exist", luceneDir.exists()); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + assertTrue(li.delete()); + + assertFalse(luceneDir.exists()); + assertTrue(luceneFolder.exists()); + } + + @Test + public void testDeleteNotExist() + { + int version = 0; + + File luceneFolder = null; + try { + luceneFolder = baseFolder.newFolder("repo1", "lucene"); + } + catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + File luceneDir = new File(luceneFolder, getIndexDir(version)); + assertFalse("Precondition failure: index directory exists already", luceneDir.exists()); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + assertTrue(li.delete()); + + assertFalse(luceneDir.exists()); + assertTrue(luceneFolder.exists()); + } + + @Test + public void testDeleteWithFiles() + { + int version = 111222333; + + File luceneFolder = new File(baseFolder.getRoot(), "tickets/lucene"); + File luceneDir = null; + + File otherDir = new File(baseFolder.getRoot(), "tickets/lucene/" + version + "_10"); + File dbFile = null; + try { + luceneDir = baseFolder.newFolder("tickets", "lucene", getIndexDir(version)); + File file = new File(luceneDir, "_file1"); + file.createNewFile(); + file = new File(luceneDir, "_file2.db"); + file.createNewFile(); + file = new File(luceneDir, "conf.conf"); + file.createNewFile(); + + otherDir.mkdirs(); + dbFile = new File(otherDir, "_file2.db"); + dbFile.createNewFile(); + file = new File(otherDir, "conf.conf"); + file.createNewFile(); + } + catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: index directory does not exist", luceneDir.exists()); + assertTrue("Precondition failure: other index directory does not exist", otherDir.exists()); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + li.delete(); + + assertFalse(luceneDir.exists()); + assertTrue(luceneFolder.exists()); + assertTrue(otherDir.exists()); + assertTrue(dbFile.exists()); + } + + + + + @Test + public void testGetPath() throws IOException + { + int version = 2; + File luceneFolder = baseFolder.newFolder("tickets", "lucene"); + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + Path dir = li.getPath(); + File luceneDir = new File(luceneFolder, getIndexDir(version)); + assertEquals(luceneDir.toPath(), dir); + } + + + + @Test + public void testHasIndex() throws IOException + { + int version = 0; + File luceneFolder = new File(baseFolder.getRoot(), "ticktock/lucene"); + + LuceneIndexStore li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + baseFolder.newFolder("ticktock"); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + baseFolder.newFolder("ticktock", "lucene"); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + File luceneDir = baseFolder.newFolder("ticktock", "lucene", getIndexDir(version)); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + new File(luceneDir, "write.lock").createNewFile(); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + new File(luceneDir, "segments_1").createNewFile(); + li = new LuceneIndexStore(luceneFolder, version); + assertTrue(li.hasIndex()); + + } + +} From f44f45a15e10a87bcb62a6a3a1bb0f7cbc282478 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sun, 5 Mar 2017 17:11:50 +0100 Subject: [PATCH 09/11] Use versioned index directories for repository indices. Change from the index version of a repository index being stored in a config file to also using index directories with the version in the name. For that, `LuceneRepoIndexStore` is added, which adds the fixed `lucene` part to the path. It also gives out the location of the `lucene.conf` file, which is now stored in the index directory. This way it is automatically deleted when the directory is deleted. I believe that it should also provide means to store branch aliases and tips, i.e. hide the config file completely. But this isn't implemented with this commit, the `LuceneService` is still aware that a config file is used. --- .../gitblit/service/LuceneRepoIndexStore.java | 55 ++++ .../com/gitblit/service/LuceneService.java | 65 ++--- .../service/LuceneRepoIndexStoreTest.java | 267 ++++++++++++++++++ 3 files changed, 339 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/gitblit/service/LuceneRepoIndexStore.java create mode 100644 src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java diff --git a/src/main/java/com/gitblit/service/LuceneRepoIndexStore.java b/src/main/java/com/gitblit/service/LuceneRepoIndexStore.java new file mode 100644 index 000000000..ff7d08853 --- /dev/null +++ b/src/main/java/com/gitblit/service/LuceneRepoIndexStore.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitblit.service; + +import java.io.File; + +import com.gitblit.utils.LuceneIndexStore; + +/** + * @author Florian Zschocke + * + * @since 1.9.0 + */ +class LuceneRepoIndexStore extends LuceneIndexStore +{ + + private static final String LUCENE_DIR = "lucene"; + private static final String CONF_FILE = "gb_lucene.conf"; + + + /** + * @param repositoryFolder + * The directory of the repository for this index + * @param indexVersion + * Version of the index definition + */ + public LuceneRepoIndexStore(File repositoryFolder, int indexVersion) { + super(new File(repositoryFolder, LUCENE_DIR), indexVersion); + } + + + /** + * Get the index config File. + * + * @return The index config File + */ + public File getConfigFile() { + return new File(this.indexFolder, CONF_FILE); + } + +} diff --git a/src/main/java/com/gitblit/service/LuceneService.java b/src/main/java/com/gitblit/service/LuceneService.java index 9b97ad5b3..906a0b5e6 100644 --- a/src/main/java/com/gitblit/service/LuceneService.java +++ b/src/main/java/com/gitblit/service/LuceneService.java @@ -117,10 +117,6 @@ public class LuceneService implements Runnable { private static final String FIELD_DATE = "date"; private static final String FIELD_TAG = "tag"; - private static final String CONF_FILE = "lucene.conf"; - private static final String LUCENE_DIR = "lucene"; - private static final String CONF_INDEX = "index"; - private static final String CONF_VERSION = "version"; private static final String CONF_ALIAS = "aliases"; private static final String CONF_BRANCH = "branches"; @@ -290,26 +286,13 @@ public synchronized void close() { * @return true, if successful */ public boolean deleteIndex(String repositoryName) { - try { - // close any open writer/searcher - close(repositoryName); - - // delete the index folder - File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repositoryName), FS.DETECTED); - File luceneIndex = new File(repositoryFolder, LUCENE_DIR); - if (luceneIndex.exists()) { - org.eclipse.jgit.util.FileUtils.delete(luceneIndex, - org.eclipse.jgit.util.FileUtils.RECURSIVE); - } - // delete the config file - File luceneConfig = new File(repositoryFolder, CONF_FILE); - if (luceneConfig.exists()) { - luceneConfig.delete(); - } - return true; - } catch (IOException e) { - throw new RuntimeException(e); - } + // close any open writer/searcher + close(repositoryName); + + // delete the index folder + File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repositoryName), FS.DETECTED); + LuceneRepoIndexStore luceneIndex = new LuceneRepoIndexStore(repositoryFolder, INDEX_VERSION); + return luceneIndex.delete(); } /** @@ -383,29 +366,20 @@ private String getBranchKey(String branchName) { * @return a config object */ private FileBasedConfig getConfig(Repository repository) { - File file = new File(repository.getDirectory(), CONF_FILE); - FileBasedConfig config = new FileBasedConfig(file, FS.detect()); + LuceneRepoIndexStore luceneIndex = new LuceneRepoIndexStore(repository.getDirectory(), INDEX_VERSION); + FileBasedConfig config = new FileBasedConfig(luceneIndex.getConfigFile(), FS.detect()); return config; } /** - * Reads the Lucene config file for the repository to check the index - * version. If the index version is different, then rebuild the repository - * index. + * Checks if an index exists for the repository, that is compatible with + * INDEX_VERSION and the Lucene version. * * @param repository - * @return true of the on-disk index format is different than INDEX_VERSION + * @return true if no index is found for the repository, false otherwise. */ private boolean shouldReindex(Repository repository) { - try { - FileBasedConfig config = getConfig(repository); - config.load(); - int indexVersion = config.getInt(CONF_INDEX, CONF_VERSION, 0); - // reindex if versions do not match - return indexVersion != INDEX_VERSION; - } catch (Throwable t) { - } - return true; + return ! (new LuceneRepoIndexStore(repository.getDirectory(), INDEX_VERSION).hasIndex()); } @@ -615,7 +589,6 @@ public int compare(RefModel ref1, RefModel ref2) { reader.close(); // commit all changes and reset the searcher - config.setInt(CONF_INDEX, null, CONF_VERSION, INDEX_VERSION); config.save(); writer.commit(); resetIndexSearcher(model.name); @@ -844,7 +817,6 @@ public int compare(RefModel ref1, RefModel ref2) { } // update the config - config.setInt(CONF_INDEX, null, CONF_VERSION, INDEX_VERSION); config.setString(CONF_ALIAS, null, keyName, branchName); config.setString(CONF_BRANCH, null, keyName, branch.getObjectId().getName()); config.save(); @@ -962,14 +934,11 @@ private IndexSearcher getIndexSearcher(String repository) throws IOException { */ private IndexWriter getIndexWriter(String repository) throws IOException { IndexWriter indexWriter = writers.get(repository); - File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repository), FS.DETECTED); - File indexFolder = new File(repositoryFolder, LUCENE_DIR); - Directory directory = FSDirectory.open(indexFolder.toPath()); - if (indexWriter == null) { - if (!indexFolder.exists()) { - indexFolder.mkdirs(); - } + File repositoryFolder = FileKey.resolve(new File(repositoriesFolder, repository), FS.DETECTED); + LuceneRepoIndexStore indexStore = new LuceneRepoIndexStore(repositoryFolder, INDEX_VERSION); + indexStore.create(); + Directory directory = FSDirectory.open(indexStore.getPath()); StandardAnalyzer analyzer = new StandardAnalyzer(); IndexWriterConfig config = new IndexWriterConfig(analyzer); config.setOpenMode(OpenMode.CREATE_OR_APPEND); diff --git a/src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java b/src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java new file mode 100644 index 000000000..baac3516a --- /dev/null +++ b/src/test/java/com/gitblit/service/LuceneRepoIndexStoreTest.java @@ -0,0 +1,267 @@ +/* + * Copyright 2017 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gitblit.service; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import com.gitblit.utils.LuceneIndexStore; + +/** + * @author Florian Zschocke + * + */ +public class LuceneRepoIndexStoreTest +{ + + private static final int LUCENE_VERSION = LuceneIndexStore.LUCENE_CODEC_VERSION; + private static final String LUCENE_DIR = "lucene"; + + + @Rule + public TemporaryFolder baseFolder = new TemporaryFolder(); + + + private String getIndexDir(int version) + { + return version + "_" + LUCENE_VERSION; + } + + + private String getLuceneIndexDir(int version) + { + return LUCENE_DIR + "/" + version + "_" + LUCENE_VERSION; + } + + + @Test + public void testGetConfigFile() throws IOException + { + int version = 1; + File repositoryFolder = baseFolder.getRoot(); + LuceneRepoIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + File confFile= li.getConfigFile(); + File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version) + "/gb_lucene.conf"); + assertEquals(luceneDir, confFile); + } + + + @Test + public void testCreate() + { + int version = 0; + File repositoryFolder = baseFolder.getRoot(); + File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version)); + assertFalse("Precondition failure: directory exists already", new File(repositoryFolder, LUCENE_DIR).exists()); + assertFalse("Precondition failure: directory exists already", luceneDir.exists()); + + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + li.create(); + + assertTrue(luceneDir.exists()); + assertTrue(luceneDir.isDirectory()); + } + + @Test + public void testCreateIndexDir() + { + int version = 7777; + File repositoryFolder = baseFolder.getRoot(); + try { + baseFolder.newFolder(LUCENE_DIR); + } catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version)); + + assertTrue("Precondition failure: directory does not exist", new File(repositoryFolder, LUCENE_DIR).exists()); + assertFalse("Precondition failure: directory exists already", luceneDir.exists()); + + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + li.create(); + + assertTrue(luceneDir.exists()); + assertTrue(luceneDir.isDirectory()); + + // Make sure nothing else was created. + assertEquals(0, luceneDir.list().length); + assertEquals(1, luceneDir.getParentFile().list().length); + } + + @Test + public void testCreateIfNecessary() + { + int version = 7777888; + File repositoryFolder = baseFolder.getRoot(); + File luceneDir = null; + try { + luceneDir = baseFolder.newFolder(LUCENE_DIR, getIndexDir(version)); + } catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: directory does not exist", new File(repositoryFolder, LUCENE_DIR).exists()); + assertTrue("Precondition failure: directory does not exist", luceneDir.exists()); + + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + li.create(); + + assertTrue(luceneDir.exists()); + assertTrue(luceneDir.isDirectory()); + + // Make sure nothing else was created. + assertEquals(0, luceneDir.list().length); + assertEquals(1, luceneDir.getParentFile().list().length); + } + + + @Test + public void testDelete() + { + int version = 111222333; + + File repositoryFolder = baseFolder.getRoot(); + File luceneDir = null; + try { + luceneDir = baseFolder.newFolder(LUCENE_DIR, getIndexDir(version)); + } catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: directory does not exist", luceneDir.exists()); + + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + assertTrue(li.delete()); + + assertFalse(luceneDir.exists()); + assertTrue(new File(repositoryFolder, LUCENE_DIR).exists()); + } + + + @Test + public void testDeleteNotExist() + { + int version = 0; + + File repositoryFolder = baseFolder.getRoot(); + try { + baseFolder.newFolder(LUCENE_DIR); + } catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version)); + assertTrue("Precondition failure: directory does not exist", new File(repositoryFolder, LUCENE_DIR).exists()); + assertFalse("Precondition failure: directory does exist", luceneDir.exists()); + + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + assertTrue(li.delete()); + + assertFalse(luceneDir.exists()); + assertTrue(new File(repositoryFolder, LUCENE_DIR).exists()); + } + + + @Test + public void testDeleteWithFiles() + { + int version = 5; + + File repositoryFolder = baseFolder.getRoot(); + File luceneFolder = new File(baseFolder.getRoot(), LUCENE_DIR); + File luceneDir = null; + + File otherDir = new File(luceneFolder, version + "_10"); + File dbFile = null; + try { + luceneDir = baseFolder.newFolder(LUCENE_DIR, getIndexDir(version)); + File file = new File(luceneDir, "_file1"); + file.createNewFile(); + file = new File(luceneDir, "_file2.db"); + file.createNewFile(); + file = new File(luceneDir, "conf.conf"); + file.createNewFile(); + + otherDir.mkdirs(); + dbFile = new File(otherDir, "_file2.db"); + dbFile.createNewFile(); + file = new File(otherDir, "conf.conf"); + file.createNewFile(); + } + catch (IOException e) { + fail("Failed in setup of folder: " + e); + } + assertTrue("Precondition failure: index directory does not exist", luceneDir.exists()); + assertTrue("Precondition failure: other index directory does not exist", otherDir.exists()); + + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + li.delete(); + + assertFalse(luceneDir.exists()); + assertTrue(luceneFolder.exists()); + assertTrue(otherDir.exists()); + assertTrue(dbFile.exists()); + } + + + + @Test + public void testGetPath() throws IOException + { + int version = 7; + File repositoryFolder = baseFolder.getRoot(); + LuceneIndexStore li = new LuceneRepoIndexStore(repositoryFolder, version); + Path dir = li.getPath(); + File luceneDir = new File(repositoryFolder, getLuceneIndexDir(version)); + assertEquals(luceneDir.toPath(), dir); + } + + + @Test + public void testHasIndex() throws IOException + { + int version = 0; + File luceneFolder = new File(baseFolder.getRoot(), "lucene"); + + LuceneIndexStore li = new LuceneRepoIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + baseFolder.newFolder("lucene"); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + File luceneDir = baseFolder.newFolder("lucene", getIndexDir(version)); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + new File(luceneDir, "write.lock").createNewFile(); + li = new LuceneIndexStore(luceneFolder, version); + assertFalse(li.hasIndex()); + + new File(luceneDir, "segments_1").createNewFile(); + li = new LuceneIndexStore(luceneFolder, version); + System.out.println("Check " + luceneDir); + assertTrue(li.hasIndex()); + + } + + +} From 197ddd27c8a6d304c9ba20e8ef9af9daef5f3083 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Mon, 9 Jan 2017 14:43:46 +0100 Subject: [PATCH 10/11] Revert "Add library `lucene-backward-codecs` to migrate indices." This reverts commit 662fb9012fb6897c9b05c939232919797e665f38. --- .classpath | 1 - build.moxie | 1 - gitblit.iml | 11 ----------- 3 files changed, 13 deletions(-) diff --git a/.classpath b/.classpath index 5d96d16d3..42cbfbc87 100644 --- a/.classpath +++ b/.classpath @@ -22,7 +22,6 @@ - diff --git a/build.moxie b/build.moxie index 2748eab2c..f21241d1b 100644 --- a/build.moxie +++ b/build.moxie @@ -145,7 +145,6 @@ dependencies: - compile 'org.apache.wicket:wicket-auth-roles:${wicket.version}' :war !org.mockito - compile 'org.apache.wicket:wicket-extensions:${wicket.version}' :war !org.mockito - compile 'org.apache.lucene:lucene-core:${lucene.version}' :war :fedclient -- compile 'org.apache.lucene:lucene-backward-codecs:${lucene.version}' :war :fedclient - compile 'org.apache.lucene:lucene-analyzers-common:${lucene.version}' :war :fedclient - compile 'org.apache.lucene:lucene-highlighter:${lucene.version}' :war :fedclient !org.apache.lucene:lucene-join - compile 'org.apache.lucene:lucene-memory:${lucene.version}' :war :fedclient diff --git a/gitblit.iml b/gitblit.iml index 25a4447de..1f4aa2483 100644 --- a/gitblit.iml +++ b/gitblit.iml @@ -190,17 +190,6 @@
- - - - - - - - - - - From 63dbdfda13daa78a26f1c2e77b0a4bfd5a35df8d Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sun, 5 Mar 2017 20:12:48 +0100 Subject: [PATCH 11/11] Reindex tickets on server start if no index exists Check if tickets need to be reindexed when the server starts. This is the case if no ticket index exists. In that case the ticket index is built. This is done during the start of the `ITicketService`. For this the interface of `ITicketService` needed to change. The `start` method was defined abstract and the specific ticket services had to implement it. None does any real starting stuff in it. The `start` method is now final. It calls a new abstract method `onStart` which the specific ticket services need to implement. In the existing implementations I just changed `start` to `onStart`. --- .../gitblit/tickets/BranchTicketService.java | 3 +- .../gitblit/tickets/FileTicketService.java | 3 +- .../com/gitblit/tickets/ITicketService.java | 43 ++++++++++++++++--- .../gitblit/tickets/NullTicketService.java | 3 +- .../gitblit/tickets/RedisTicketService.java | 3 +- .../com/gitblit/tickets/TicketIndexer.java | 14 +++++- .../com/gitblit/utils/LuceneIndexStore.java | 2 +- .../tests/BranchTicketServiceTest.java | 2 +- .../gitblit/tests/FileTicketServiceTest.java | 2 +- .../gitblit/tests/RedisTicketServiceTest.java | 2 +- .../java/com/gitblit/tests/UITicketTest.java | 2 +- 11 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/gitblit/tickets/BranchTicketService.java b/src/main/java/com/gitblit/tickets/BranchTicketService.java index 7bef435aa..8430c546b 100644 --- a/src/main/java/com/gitblit/tickets/BranchTicketService.java +++ b/src/main/java/com/gitblit/tickets/BranchTicketService.java @@ -110,9 +110,8 @@ public BranchTicketService( } @Override - public BranchTicketService start() { + public void onStart() { log.info("{} started", getClass().getSimpleName()); - return this; } @Override diff --git a/src/main/java/com/gitblit/tickets/FileTicketService.java b/src/main/java/com/gitblit/tickets/FileTicketService.java index 1e82f0de1..05670468a 100644 --- a/src/main/java/com/gitblit/tickets/FileTicketService.java +++ b/src/main/java/com/gitblit/tickets/FileTicketService.java @@ -80,9 +80,8 @@ public FileTicketService( } @Override - public FileTicketService start() { + public void onStart() { log.info("{} started", getClass().getSimpleName()); - return this; } @Override diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java index 20b6505b4..3252a603f 100644 --- a/src/main/java/com/gitblit/tickets/ITicketService.java +++ b/src/main/java/com/gitblit/tickets/ITicketService.java @@ -181,7 +181,24 @@ public ITicketService( * @since 1.4.0 */ @Override - public abstract ITicketService start(); + public final ITicketService start() { + onStart(); + if (shouldReindex()) { + log.info("Re-indexing all tickets..."); +// long startTime = System.currentTimeMillis(); + reindex(); +// float duration = (System.currentTimeMillis() - startTime) / 1000f; +// log.info("Built Lucene index over all tickets in {} secs", duration); + } + return this; + } + + /** + * Start the specific ticket service implementation. + * + * @since 1.9.0 + */ + public abstract void onStart(); /** * Stop the service. @@ -196,6 +213,12 @@ public final ITicketService stop() { return this; } + /** + * Closes any open resources used by this service. + * @since 1.4.0 + */ + protected abstract void close(); + /** * Creates a ticket notifier. The ticket notifier is not thread-safe! * @since 1.4.0 @@ -273,12 +296,6 @@ public boolean hasTickets(RepositoryModel repository) { return indexer.hasTickets(repository); } - /** - * Closes any open resources used by this service. - * @since 1.4.0 - */ - protected abstract void close(); - /** * Reset all caches in the service. * @since 1.4.0 @@ -1343,6 +1360,18 @@ public List queryFor(String query, int page, int pageSize, String s return indexer.queryFor(query, page, pageSize, sortBy, descending); } + + /** + * Checks tickets should get re-indexed. + * + * @return true if tickets should get re-indexed, false otherwise. + */ + private boolean shouldReindex() + { + return indexer.shouldReindex(); + } + + /** * Destroys an existing index and reindexes all tickets. * This operation may be expensive and time-consuming. diff --git a/src/main/java/com/gitblit/tickets/NullTicketService.java b/src/main/java/com/gitblit/tickets/NullTicketService.java index 3947b945e..050c69905 100644 --- a/src/main/java/com/gitblit/tickets/NullTicketService.java +++ b/src/main/java/com/gitblit/tickets/NullTicketService.java @@ -61,9 +61,8 @@ public boolean isReady() { } @Override - public NullTicketService start() { + public void onStart() { log.info("{} started", getClass().getSimpleName()); - return this; } @Override diff --git a/src/main/java/com/gitblit/tickets/RedisTicketService.java b/src/main/java/com/gitblit/tickets/RedisTicketService.java index 0f9ad174e..4e632317f 100644 --- a/src/main/java/com/gitblit/tickets/RedisTicketService.java +++ b/src/main/java/com/gitblit/tickets/RedisTicketService.java @@ -83,12 +83,11 @@ public RedisTicketService( } @Override - public RedisTicketService start() { + public void onStart() { log.info("{} started", getClass().getSimpleName()); if (!isReady()) { log.warn("{} is not ready!", getClass().getSimpleName()); } - return this; } @Override diff --git a/src/main/java/com/gitblit/tickets/TicketIndexer.java b/src/main/java/com/gitblit/tickets/TicketIndexer.java index bc08fc889..7c1644872 100644 --- a/src/main/java/com/gitblit/tickets/TicketIndexer.java +++ b/src/main/java/com/gitblit/tickets/TicketIndexer.java @@ -226,6 +226,18 @@ public boolean deleteAll(RepositoryModel repository) { return false; } + /** + * Checks if a tickets index exists, that is compatible with Lucene.INDEX_VERSION + * and the Lucene codec version. + * + * @return true if no tickets index is found, false otherwise. + * + * @since 1.9.0 + */ + boolean shouldReindex() { + return ! this.indexStore.hasIndex(); + } + /** * Bulk Add/Update tickets in the Lucene index * @@ -665,4 +677,4 @@ private int unpackInt(Document doc, Lucene lucene) { int i = Integer.parseInt(val); return i; } -} \ No newline at end of file +} diff --git a/src/main/java/com/gitblit/utils/LuceneIndexStore.java b/src/main/java/com/gitblit/utils/LuceneIndexStore.java index 0ccfd2e8c..c05e2019b 100644 --- a/src/main/java/com/gitblit/utils/LuceneIndexStore.java +++ b/src/main/java/com/gitblit/utils/LuceneIndexStore.java @@ -92,7 +92,7 @@ public boolean hasIndex() { return indexFolder.exists() && indexFolder.isDirectory() && - (indexFolder.list().length > 1); + (indexFolder.list().length > 1); // Must have more than 'write.lock' } } diff --git a/src/test/java/com/gitblit/tests/BranchTicketServiceTest.java b/src/test/java/com/gitblit/tests/BranchTicketServiceTest.java index 0a5de1961..0e9d88746 100644 --- a/src/test/java/com/gitblit/tests/BranchTicketServiceTest.java +++ b/src/test/java/com/gitblit/tests/BranchTicketServiceTest.java @@ -59,7 +59,7 @@ protected ITicketService getService(boolean deleteAll) throws Exception { IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); - BranchTicketService service = new BranchTicketService( + BranchTicketService service = (BranchTicketService) new BranchTicketService( runtimeManager, pluginManager, notificationManager, diff --git a/src/test/java/com/gitblit/tests/FileTicketServiceTest.java b/src/test/java/com/gitblit/tests/FileTicketServiceTest.java index 1fb2eed96..c4a63c410 100644 --- a/src/test/java/com/gitblit/tests/FileTicketServiceTest.java +++ b/src/test/java/com/gitblit/tests/FileTicketServiceTest.java @@ -58,7 +58,7 @@ protected ITicketService getService(boolean deleteAll) throws Exception { IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); - FileTicketService service = new FileTicketService( + FileTicketService service = (FileTicketService) new FileTicketService( runtimeManager, pluginManager, notificationManager, diff --git a/src/test/java/com/gitblit/tests/RedisTicketServiceTest.java b/src/test/java/com/gitblit/tests/RedisTicketServiceTest.java index 48011ade2..5f3cb94fc 100644 --- a/src/test/java/com/gitblit/tests/RedisTicketServiceTest.java +++ b/src/test/java/com/gitblit/tests/RedisTicketServiceTest.java @@ -66,7 +66,7 @@ protected ITicketService getService(boolean deleteAll) throws Exception { IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); - RedisTicketService service = new RedisTicketService( + RedisTicketService service = (RedisTicketService) new RedisTicketService( runtimeManager, pluginManager, notificationManager, diff --git a/src/test/java/com/gitblit/tests/UITicketTest.java b/src/test/java/com/gitblit/tests/UITicketTest.java index 54aa1e1e7..e89c32fcf 100644 --- a/src/test/java/com/gitblit/tests/UITicketTest.java +++ b/src/test/java/com/gitblit/tests/UITicketTest.java @@ -83,7 +83,7 @@ protected ITicketService getService(boolean deleteAll) throws Exception { IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); - BranchTicketService service = new BranchTicketService( + BranchTicketService service = (BranchTicketService) new BranchTicketService( runtimeManager, pluginManager, notificationManager,