mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-07-04 03:39:14 +02:00
More flexible delete and query api (#1790)
Replaces the filter and delete by repository api's with a more flexible api, which allows to filter and delete by any id part.
This commit is contained in:
@@ -26,8 +26,6 @@ package sonia.scm.repository;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
@@ -109,7 +107,7 @@ class RepositoryIndexerTest {
|
||||
when(index.getDetails().getType()).then(ic -> String.class);
|
||||
indexer.createDeleteTask(heartOfGold).update(index);
|
||||
|
||||
verify(index.delete()).byRepository(heartOfGold);
|
||||
verify(index.delete().by(Repository.class, heartOfGold)).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -135,7 +133,8 @@ class RepositoryIndexerTest {
|
||||
|
||||
verify(searchEngine.forIndices().forResource(heartOfGold)).batch(captor.capture());
|
||||
captor.getValue().update(index);
|
||||
verify(index.delete()).byRepository(heartOfGold);
|
||||
|
||||
verify(index.delete().by(Repository.class, heartOfGold)).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.IndexWriterConfig;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.store.ByteBuffersDirectory;
|
||||
@@ -158,7 +159,24 @@ class LuceneIndexTest {
|
||||
}
|
||||
|
||||
try (LuceneIndex<Storable> index = createIndex(Storable.class)) {
|
||||
index.delete().byRepository("4212");
|
||||
index.delete().by(Repository.class, "4212").execute();
|
||||
}
|
||||
|
||||
assertHits("value", "content", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeleteByMultipleFields() throws IOException {
|
||||
Id<Storable> base = ONE.and(Repository.class, "4211");
|
||||
|
||||
try (LuceneIndex<Storable> index = createIndex(Storable.class)) {
|
||||
index.store(base.and(String.class, "1"), null, new Storable("content"));
|
||||
index.store(base.and(String.class, "2"), null, new Storable("content"));
|
||||
index.store(base.and(String.class, "2"), null, new Storable("content"));
|
||||
}
|
||||
|
||||
try (LuceneIndex<Storable> index = createIndex(Storable.class)) {
|
||||
index.delete().by(Repository.class, "4211").and(String.class, "2").execute();
|
||||
}
|
||||
|
||||
assertHits("value", "content", 1);
|
||||
@@ -233,11 +251,11 @@ class LuceneIndexTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowSearchEngineExceptionOnDeleteByRepository() throws IOException {
|
||||
when(writer.deleteDocuments(any(Term.class))).thenThrow(new IOException("failed to delete"));
|
||||
void shouldThrowSearchEngineExceptionOnDeleteBy() throws IOException {
|
||||
when(writer.deleteDocuments(any(Query.class))).thenThrow(new IOException("failed to delete"));
|
||||
|
||||
Index.Deleter<Storable> deleter = index.delete();
|
||||
assertThrows(SearchEngineException.class, () -> deleter.byRepository("42"));
|
||||
Index.DeleteBy deleter = index.delete().by(Repository.class, "42");
|
||||
assertThrows(SearchEngineException.class, deleter::execute);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -49,11 +49,13 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -277,16 +279,9 @@ class LuceneQueryBuilderTest {
|
||||
writer.addDocument(repositoryDoc("Awesome content three", "fgh"));
|
||||
}
|
||||
|
||||
QueryResult result;
|
||||
try (DirectoryReader reader = DirectoryReader.open(directory)) {
|
||||
SearchableTypeResolver resolver = new SearchableTypeResolver(Simple.class);
|
||||
LuceneSearchableType searchableType = resolver.resolve(Simple.class);
|
||||
when(opener.openForRead(searchableType, "default")).thenReturn(reader);
|
||||
LuceneQueryBuilder<Simple> builder = new LuceneQueryBuilder<>(
|
||||
opener, "default", searchableType, new StandardAnalyzer()
|
||||
);
|
||||
result = builder.repository("cde").execute("content:awesome");
|
||||
}
|
||||
QueryResult result = query(
|
||||
Simple.class, "content:awesome", builder -> builder.filter(Repository.class, "cde")
|
||||
);
|
||||
|
||||
assertThat(result.getTotalHits()).isOne();
|
||||
|
||||
@@ -297,6 +292,24 @@ class LuceneQueryBuilderTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFilterByIdParts() throws IOException {
|
||||
try (IndexWriter writer = writer()) {
|
||||
writer.addDocument(idPartsDoc("Awesome content one", "abc", "one"));
|
||||
writer.addDocument(idPartsDoc("Awesome content two", "abc", "two"));
|
||||
writer.addDocument(idPartsDoc("Awesome content three", "cde", "two"));
|
||||
}
|
||||
|
||||
QueryResult result = query(
|
||||
Simple.class, "content:awesome",
|
||||
builder -> builder.filter(Repository.class, "abc").filter(String.class, "two")
|
||||
);
|
||||
|
||||
List<Hit> hits = result.getHits();
|
||||
assertThat(hits).hasSize(1)
|
||||
.allSatisfy(hit -> assertValueField(hit, "content", "Awesome content two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnStringFields() throws IOException {
|
||||
try (IndexWriter writer = writer()) {
|
||||
@@ -549,6 +562,17 @@ class LuceneQueryBuilderTest {
|
||||
}
|
||||
|
||||
private <T> QueryResult query(Class<?> type, String queryString, Integer start, Integer limit) throws IOException {
|
||||
return query(type, queryString, builder -> {
|
||||
if (start != null) {
|
||||
builder.start(start);
|
||||
}
|
||||
if (limit != null) {
|
||||
builder.limit(limit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> QueryResult query(Class<T> type, String queryString, Consumer<LuceneQueryBuilder<T>> consumer) throws IOException {
|
||||
try (DirectoryReader reader = DirectoryReader.open(directory)) {
|
||||
SearchableTypeResolver resolver = new SearchableTypeResolver(type);
|
||||
LuceneSearchableType searchableType = resolver.resolve(type);
|
||||
@@ -557,12 +581,7 @@ class LuceneQueryBuilderTest {
|
||||
LuceneQueryBuilder<T> builder = new LuceneQueryBuilder<>(
|
||||
opener, "default", searchableType, new StandardAnalyzer()
|
||||
);
|
||||
if (start != null) {
|
||||
builder.start(start);
|
||||
}
|
||||
if (limit != null) {
|
||||
builder.limit(limit);
|
||||
}
|
||||
consumer.accept(builder);
|
||||
return builder.execute(queryString);
|
||||
}
|
||||
}
|
||||
@@ -576,14 +595,12 @@ class LuceneQueryBuilderTest {
|
||||
private Document simpleDoc(String content) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("content", content, Field.Store.YES));
|
||||
// document.add(new StringField(FieldNames.TYPE, "simple", Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
private Document permissionDoc(String content, String permission) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("content", content, Field.Store.YES));
|
||||
// document.add(new StringField(FieldNames.TYPE, "simple", Field.Store.YES));
|
||||
document.add(new StringField(FieldNames.PERMISSION, permission, Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
@@ -591,11 +608,18 @@ class LuceneQueryBuilderTest {
|
||||
private Document repositoryDoc(String content, String repository) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("content", content, Field.Store.YES));
|
||||
// document.add(new StringField(FieldNames.TYPE, "simple", Field.Store.YES));
|
||||
document.add(new StringField(FieldNames.REPOSITORY, repository, Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
private Document idPartsDoc(String content, String repository, String other) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("content", content, Field.Store.YES));
|
||||
document.add(new StringField(FieldNames.REPOSITORY, repository, Field.Store.YES));
|
||||
document.add(new StringField("_string", other, Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
private Document inetOrgPersonDoc(String firstName, String lastName, String displayName, String carLicense) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("firstName", firstName, Field.Store.YES));
|
||||
@@ -603,14 +627,12 @@ class LuceneQueryBuilderTest {
|
||||
document.add(new TextField("displayName", displayName, Field.Store.YES));
|
||||
document.add(new TextField("carLicense", carLicense, Field.Store.YES));
|
||||
document.add(new StringField(FieldNames.ID, lastName, Field.Store.YES));
|
||||
// document.add(new StringField(FieldNames.TYPE, "inetOrgPerson", Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
private Document personDoc(String lastName) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("lastName", lastName, Field.Store.YES));
|
||||
// document.add(new StringField(FieldNames.TYPE, "person", Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
@@ -623,14 +645,6 @@ class LuceneQueryBuilderTest {
|
||||
document.add(new StringField("boolValue", String.valueOf(boolValue), Field.Store.YES));
|
||||
document.add(new LongPoint("instantValue", instantValue.toEpochMilli()));
|
||||
document.add(new StoredField("instantValue", instantValue.toEpochMilli()));
|
||||
// document.add(new StringField(FieldNames.TYPE, "types", Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
private Document denyDoc(String value) {
|
||||
Document document = new Document();
|
||||
document.add(new TextField("value", value, Field.Store.YES));
|
||||
// document.add(new StringField(FieldNames.TYPE, "deny", Field.Store.YES));
|
||||
return document;
|
||||
}
|
||||
|
||||
@@ -679,11 +693,4 @@ class LuceneQueryBuilderTest {
|
||||
private String content;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@IndexedType(permission = "deny:4711")
|
||||
static class Deny {
|
||||
@Indexed(defaultQuery = true)
|
||||
private String value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user