@NotNull private Set<VcsRef> readBranches(@NotNull GitRepository repository) { StopWatch sw = StopWatch.start("readBranches in " + repository.getRoot().getName()); VirtualFile root = repository.getRoot(); repository.update(); Collection<GitLocalBranch> localBranches = repository.getBranches().getLocalBranches(); Collection<GitRemoteBranch> remoteBranches = repository.getBranches().getRemoteBranches(); Set<VcsRef> refs = new THashSet<VcsRef>(localBranches.size() + remoteBranches.size()); for (GitLocalBranch localBranch : localBranches) { refs.add( myVcsObjectsFactory.createRef( localBranch.getHash(), localBranch.getName(), GitRefManager.LOCAL_BRANCH, root)); } for (GitRemoteBranch remoteBranch : remoteBranches) { refs.add( myVcsObjectsFactory.createRef( remoteBranch.getHash(), remoteBranch.getNameForLocalOperations(), GitRefManager.REMOTE_BRANCH, root)); } String currentRevision = repository.getCurrentRevision(); if (currentRevision != null) { // null => fresh repository refs.add( myVcsObjectsFactory.createRef( HashImpl.build(currentRevision), "HEAD", GitRefManager.HEAD, root)); } sw.report(); return refs; }
@NotNull private Set<String> readCurrentTagNames(@NotNull VirtualFile root) throws VcsException { StopWatch sw = StopWatch.start("reading tags in " + root.getName()); Set<String> tags = newHashSet(); GitTag.listAsStrings(myProject, root, tags, null); sw.report(); return tags; }
@NotNull private DetailedLogData loadSomeCommitsOnTaggedBranches( @NotNull VirtualFile root, int commitCount, @NotNull Collection<String> unmatchedTags) throws VcsException { StopWatch sw = StopWatch.start("loading commits on tagged branch in " + root.getName()); List<String> params = new ArrayList<String>(); params.add("--max-count=" + commitCount); params.addAll(unmatchedTags); sw.report(); return GitHistoryUtils.loadMetadata(myProject, root, true, ArrayUtil.toStringArray(params)); }
private static void validateDataAndReportError( @NotNull final VirtualFile root, @NotNull final Set<VcsRef> allRefs, @NotNull final List<VcsCommitMetadata> sortedCommits, @NotNull final DetailedLogData firstBlockSyncData, @NotNull final Set<VcsRef> manuallyReadBranches, @Nullable final Set<String> currentTagNames, @Nullable final DetailedLogData commitsFromTags) { StopWatch sw = StopWatch.start("validating data in " + root.getName()); final Set<Hash> refs = ContainerUtil.map2Set( allRefs, new Function<VcsRef, Hash>() { @Override public Hash fun(VcsRef ref) { return ref.getCommitHash(); } }); PermanentGraphImpl.newInstance( sortedCommits, new GraphColorManager<Hash>() { @Override public int getColorOfBranch(@NotNull Hash headCommit) { return 0; } @Override public int getColorOfFragment(@NotNull Hash headCommit, int magicIndex) { return 0; } @Override public int compareHeads(@NotNull Hash head1, @NotNull Hash head2) { if (!refs.contains(head1) || !refs.contains(head2)) { LOG.error( "GitLogProvider returned inconsistent data", new Attachment( "error-details.txt", printErrorDetails( root, allRefs, sortedCommits, firstBlockSyncData, manuallyReadBranches, currentTagNames, commitsFromTags))); } return 0; } }, refs); sw.report(); }
private void readCurrentUser() { StopWatch sw = StopWatch.start("readCurrentUser"); for (Map.Entry<VirtualFile, VcsLogProvider> entry : myLogProviders.entrySet()) { VirtualFile root = entry.getKey(); try { VcsUser me = entry.getValue().getCurrentUser(root); if (me != null) { myCurrentUser.put(root, me); } else { LOG.info("Username not configured for root " + root); } } catch (VcsException e) { LOG.warn("Couldn't read the username from root " + root, e); } } sw.report(); }
public void initialize() { final StopWatch initSw = StopWatch.start("initialize"); myDataLoaderQueue.clear(); runInBackground( new ThrowableConsumer<ProgressIndicator, VcsException>() { @Override public void consume(ProgressIndicator indicator) throws VcsException { resetState(); readCurrentUser(); DataPack dataPack = myRefresher.readFirstBlock(); myDataPackUpdateHandler.consume(dataPack); initSw.report(); } }, "Loading History..."); }
@NotNull @Override public DetailedLogData readFirstBlock( @NotNull VirtualFile root, @NotNull Requirements requirements) throws VcsException { if (!isRepositoryReady(root)) { return LogDataImpl.empty(); } GitRepository repository = ObjectUtils.assertNotNull(myRepositoryManager.getRepositoryForRoot(root)); // need to query more to sort them manually; this doesn't affect performance: it is equal for // -1000 and -2000 int commitCount = requirements.getCommitCount() * 2; String[] params = new String[] {"HEAD", "--branches", "--remotes", "--max-count=" + commitCount}; // NB: not specifying --tags, because it introduces great slowdown if there are many tags, // but makes sense only if there are heads without branch or HEAD labels (rare case). Such cases // are partially handled below. boolean refresh = requirements instanceof VcsLogProviderRequirementsEx && ((VcsLogProviderRequirementsEx) requirements).isRefresh(); DetailedLogData data = GitHistoryUtils.loadMetadata(myProject, root, true, params); Set<VcsRef> safeRefs = data.getRefs(); Set<VcsRef> allRefs = new OpenTHashSet<VcsRef>(safeRefs, DONT_CONSIDER_SHA); Set<VcsRef> branches = readBranches(repository); addNewElements(allRefs, branches); Collection<VcsCommitMetadata> allDetails; Set<String> currentTagNames = null; DetailedLogData commitsFromTags = null; if (!refresh) { allDetails = data.getCommits(); } else { // on refresh: get new tags, which point to commits not from the first block; then get // history, walking down just from these tags // on init: just ignore such tagged-only branches. The price for speed-up. VcsLogProviderRequirementsEx rex = (VcsLogProviderRequirementsEx) requirements; currentTagNames = readCurrentTagNames(root); addOldStillExistingTags(allRefs, currentTagNames, rex.getPreviousRefs()); allDetails = newHashSet(data.getCommits()); Set<String> previousTags = newHashSet(ContainerUtil.mapNotNull(rex.getPreviousRefs(), GET_TAG_NAME)); Set<String> safeTags = newHashSet(ContainerUtil.mapNotNull(safeRefs, GET_TAG_NAME)); Set<String> newUnmatchedTags = remove(currentTagNames, previousTags, safeTags); if (!newUnmatchedTags.isEmpty()) { commitsFromTags = loadSomeCommitsOnTaggedBranches(root, commitCount, newUnmatchedTags); addNewElements(allDetails, commitsFromTags.getCommits()); addNewElements(allRefs, commitsFromTags.getRefs()); } } StopWatch sw = StopWatch.start("sorting commits in " + root.getName()); List<VcsCommitMetadata> sortedCommits = VcsLogSorter.sortByDateTopoOrder(allDetails); sortedCommits = sortedCommits.subList(0, Math.min(sortedCommits.size(), requirements.getCommitCount())); sw.report(); if (LOG.isDebugEnabled()) { validateDataAndReportError( root, allRefs, sortedCommits, data, branches, currentTagNames, commitsFromTags); } return new LogDataImpl(allRefs, sortedCommits); }