mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[vcs-log] add users index
This commit is contained in:
@@ -125,6 +125,15 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
public int getUserId(@NotNull VcsUser user) throws IOException {
|
||||
return myPersistentEnumerator.enumerate(user);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VcsUser getUserById(Integer userId) throws IOException {
|
||||
return myPersistentEnumerator.valueOf(userId);
|
||||
}
|
||||
|
||||
private class MyDescriptor implements KeyDescriptor<VcsUser> {
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, VcsUser value) throws IOException {
|
||||
|
||||
+34
-16
@@ -17,6 +17,8 @@ package com.intellij.vcs.log.data.index;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PathUtilRt;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
@@ -54,31 +56,47 @@ public class VcsLogFullDetailsIndex implements Disposable {
|
||||
Disposer.register(disposableParent, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TIntHashSet getCommitsWithAnyKey(@NotNull Set<Integer> keys) throws StorageException {
|
||||
TIntHashSet result = new TIntHashSet();
|
||||
|
||||
for (Integer key : keys) {
|
||||
iterateCommitIds(key, result::add);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TIntHashSet getCommitsWithAllKeys(@NotNull Set<Integer> keys) throws StorageException {
|
||||
TIntHashSet result = null;
|
||||
Ref<TIntHashSet> result = new Ref<>(null);
|
||||
|
||||
for (Integer key : keys) {
|
||||
TIntHashSet newResult = new TIntHashSet();
|
||||
ValueContainer<Void> data = myMapReduceIndex.getData(key);
|
||||
|
||||
ValueContainer.ValueIterator<Void> valueIt = data.getValueIterator();
|
||||
while (valueIt.hasNext()) {
|
||||
valueIt.next();
|
||||
ValueContainer.IntIterator inputIt = valueIt.getInputIdsIterator();
|
||||
while (inputIt.hasNext()) {
|
||||
int id = inputIt.next();
|
||||
if (result == null || result.contains(id)) {
|
||||
newResult.add(id);
|
||||
}
|
||||
iterateCommitIds(key, integer -> {
|
||||
if (result.get() == null || result.get().contains(integer)) {
|
||||
newResult.add(integer);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result = newResult;
|
||||
result.set(newResult);
|
||||
}
|
||||
|
||||
if (result == null) return new TIntHashSet();
|
||||
return result;
|
||||
if (result.get() == null) return new TIntHashSet();
|
||||
return result.get();
|
||||
}
|
||||
|
||||
private void iterateCommitIds(int key, @NotNull Consumer<Integer> consumer) throws StorageException {
|
||||
ValueContainer<Void> data = myMapReduceIndex.getData(key);
|
||||
|
||||
ValueContainer.ValueIterator<Void> valueIt = data.getValueIterator();
|
||||
while (valueIt.hasNext()) {
|
||||
valueIt.next();
|
||||
ValueContainer.IntIterator inputIt = valueIt.getInputIdsIterator();
|
||||
while (inputIt.hasNext()) {
|
||||
consumer.consume(inputIt.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(int commitId, @NotNull VcsFullCommitDetails details) throws IOException {
|
||||
|
||||
+87
-19
@@ -17,6 +17,7 @@ package com.intellij.vcs.log.data.index;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
@@ -27,6 +28,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -34,10 +36,16 @@ import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.PersistentHashMap;
|
||||
import com.intellij.util.io.PersistentMap;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.CommitDetailsGetter;
|
||||
import com.intellij.vcs.log.data.InMemoryMap;
|
||||
import com.intellij.vcs.log.data.TroveUtil;
|
||||
import com.intellij.vcs.log.data.VcsUserRegistryImpl;
|
||||
import com.intellij.vcs.log.ui.filter.VcsLogUserFilterImpl;
|
||||
import com.intellij.vcs.log.util.PersistentUtil;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntProcedure;
|
||||
@@ -59,9 +67,12 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
@NotNull private final Consumer<Exception> myFatalErrorsConsumer;
|
||||
@NotNull private final CommitDetailsGetter myDetailsGetter;
|
||||
@NotNull private final VcsLogStorage myHashMap;
|
||||
@NotNull private final VcsUserRegistryImpl myUserRegistry;
|
||||
@NotNull private final Set<VirtualFile> myRoots;
|
||||
|
||||
@NotNull private final PersistentMap<Integer, String> myMessagesIndex;
|
||||
@Nullable private final VcsLogMessagesTrigramIndex myTrigramIndex;
|
||||
@Nullable private final VcsLogUserIndex myUserIndex;
|
||||
|
||||
@NotNull private TIntHashSet myCommitsToIndex = new TIntHashSet();
|
||||
|
||||
@@ -75,28 +86,34 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
myProject = project;
|
||||
myDetailsGetter = detailsGetter;
|
||||
myFatalErrorsConsumer = fatalErrorsConsumer;
|
||||
myRoots = providers.keySet();
|
||||
|
||||
myUserRegistry = (VcsUserRegistryImpl)ServiceManager.getService(myProject, VcsUserRegistry.class);
|
||||
|
||||
String logId = PersistentUtil.calcLogId(myProject, providers);
|
||||
|
||||
myMessagesIndex = createIndex(EnumeratorStringDescriptor.INSTANCE, "messages", logId, 0);
|
||||
|
||||
VcsLogMessagesTrigramIndex trigramIndex;
|
||||
try {
|
||||
trigramIndex = new VcsLogMessagesTrigramIndex(logId, disposableParent);
|
||||
}
|
||||
catch (IOException e) {
|
||||
myFatalErrorsConsumer.consume(e);
|
||||
trigramIndex = null;
|
||||
}
|
||||
myTrigramIndex = trigramIndex;
|
||||
myMessagesIndex = createMap(EnumeratorStringDescriptor.INSTANCE, "messages", logId, 0);
|
||||
myTrigramIndex = createIndex(() -> new VcsLogMessagesTrigramIndex(logId, this));
|
||||
myUserIndex = createIndex(() -> new VcsLogUserIndex(logId, myUserRegistry, this));
|
||||
|
||||
Disposer.register(disposableParent, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <I extends VcsLogFullDetailsIndex> I createIndex(@NotNull ThrowableComputable<I, IOException> computable) {
|
||||
try {
|
||||
return computable.compute();
|
||||
}
|
||||
catch (IOException e) {
|
||||
myFatalErrorsConsumer.consume(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <V> PersistentMap<Integer, V> createIndex(@NotNull KeyDescriptor<V> descriptor,
|
||||
@NotNull String kind,
|
||||
@NotNull String logId, int version) {
|
||||
private <V> PersistentMap<Integer, V> createMap(@NotNull KeyDescriptor<V> descriptor,
|
||||
@NotNull String kind,
|
||||
@NotNull String logId, int version) {
|
||||
try {
|
||||
return PersistentUtil.createPersistentHashMap(descriptor, kind, logId, version);
|
||||
}
|
||||
@@ -141,10 +158,13 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
|
||||
myMessagesIndex.put(index, detail.getFullMessage());
|
||||
if (myTrigramIndex != null) myTrigramIndex.update(index, detail);
|
||||
if (myUserIndex != null) myUserIndex.update(index, detail);
|
||||
}
|
||||
myMessagesIndex.force();
|
||||
if (myTrigramIndex != null) myTrigramIndex.flush();
|
||||
} catch (IOException | StorageException e) {
|
||||
if (myUserIndex != null) myUserIndex.flush();
|
||||
}
|
||||
catch (IOException | StorageException e) {
|
||||
myFatalErrorsConsumer.consume(e);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +172,7 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
public boolean isIndexed(int commit) {
|
||||
try {
|
||||
return myMessagesIndex.get(commit) != null &&
|
||||
(myUserIndex == null || myUserIndex.isIndexed(commit)) &&
|
||||
(myTrigramIndex == null || myTrigramIndex.isIndexed(commit));
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -198,6 +219,19 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TIntHashSet filterUsers(@NotNull Set<VcsUser> users) {
|
||||
if (myUserIndex != null) {
|
||||
try {
|
||||
return myUserIndex.getCommitsForUsers(users);
|
||||
}
|
||||
catch (IOException | StorageException e) {
|
||||
myFatalErrorsConsumer.consume(e);
|
||||
}
|
||||
}
|
||||
return new TIntHashSet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TIntHashSet filterMessages(@NotNull String text) {
|
||||
if (myTrigramIndex != null) {
|
||||
@@ -239,7 +273,8 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
public boolean canFilter(@NotNull List<VcsLogDetailsFilter> filters) {
|
||||
if (filters.isEmpty()) return false;
|
||||
for (VcsLogDetailsFilter filter : filters) {
|
||||
if (!(filter instanceof VcsLogTextFilter)) {
|
||||
if (!((filter instanceof VcsLogTextFilter && myTrigramIndex != null) ||
|
||||
(filter instanceof VcsLogUserFilterImpl && myUserIndex != null))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -252,9 +287,42 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
|
||||
Set<Integer> result = ContainerUtil.newHashSet();
|
||||
|
||||
VcsLogTextFilter textFilter = ContainerUtil.findInstance(detailsFilters, VcsLogTextFilter.class);
|
||||
VcsLogUserFilterImpl userFilter = ContainerUtil.findInstance(detailsFilters, VcsLogUserFilterImpl.class);
|
||||
|
||||
TIntHashSet filteredByMessage;
|
||||
if (textFilter != null) {
|
||||
filterMessages(textFilter.getText()).forEach(value -> {
|
||||
result.add(value);
|
||||
filteredByMessage = filterMessages(textFilter.getText());
|
||||
}
|
||||
else {
|
||||
filteredByMessage = null;
|
||||
}
|
||||
|
||||
TIntHashSet filteredByUser;
|
||||
if (userFilter != null) {
|
||||
Set<VcsUser> users = ContainerUtil.newHashSet();
|
||||
for (VirtualFile root : myRoots) {
|
||||
users.addAll(userFilter.getUsers(root));
|
||||
}
|
||||
|
||||
filteredByUser = filterUsers(users);
|
||||
}
|
||||
else {
|
||||
filteredByUser = null;
|
||||
}
|
||||
|
||||
if (filteredByMessage == null) {
|
||||
if (filteredByUser != null) {
|
||||
filteredByUser.forEach(value -> {
|
||||
result.add(value);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
filteredByMessage.forEach(value -> {
|
||||
if (filteredByUser != null && filteredByUser.contains(value)) {
|
||||
result.add(value);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.vcs.log.data.index;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.DataIndexer;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import com.intellij.vcs.log.VcsUser;
|
||||
import com.intellij.vcs.log.data.VcsUserRegistryImpl;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class VcsLogUserIndex extends VcsLogFullDetailsIndex {
|
||||
private static final Logger LOG = Logger.getInstance(VcsLogUserIndex.class);
|
||||
private static final int VERSION = 0;
|
||||
@NotNull private final VcsUserRegistryImpl myUserRegistry;
|
||||
|
||||
public VcsLogUserIndex(@NotNull String logId,
|
||||
@NotNull VcsUserRegistryImpl userRegistry,
|
||||
@NotNull Disposable disposableParent) throws IOException {
|
||||
super(logId, "users", VERSION, new UserIndexer(userRegistry), disposableParent);
|
||||
myUserRegistry = userRegistry;
|
||||
}
|
||||
|
||||
public TIntHashSet getCommitsForUsers(@NotNull Set<VcsUser> users) throws IOException, StorageException {
|
||||
Set<Integer> ids = ContainerUtil.newHashSet();
|
||||
for (VcsUser user : users) {
|
||||
ids.add(myUserRegistry.getUserId(user));
|
||||
}
|
||||
return getCommitsWithAnyKey(ids);
|
||||
}
|
||||
|
||||
private static class UserIndexer implements DataIndexer<Integer, Void, VcsFullCommitDetails> {
|
||||
@NotNull private final VcsUserRegistryImpl myRegistry;
|
||||
|
||||
public UserIndexer(@NotNull VcsUserRegistryImpl registry) {
|
||||
myRegistry = registry;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<Integer, Void> map(@NotNull VcsFullCommitDetails inputData) {
|
||||
Map<Integer, Void> result = new THashMap<>();
|
||||
|
||||
try {
|
||||
result.put(myRegistry.getUserId(inputData.getAuthor()), null);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,15 @@ public class VcsLogUserFilterImpl implements VcsLogUserFilter {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<VcsUser> getUsers(@NotNull VirtualFile root) {
|
||||
Set<VcsUser> result = ContainerUtil.newHashSet();
|
||||
for (String user : myUsers) {
|
||||
result.addAll(getUsers(root, user));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<VcsUser> getUsers(@NotNull VirtualFile root, @NotNull String name) {
|
||||
Set<VcsUser> users = ContainerUtil.newHashSet();
|
||||
|
||||
Reference in New Issue
Block a user