private async Task ExecuteAsync( VsrModule module, IReadOnlyList <IGitRef> refs, IObserver <GitRevision> subject, RefFilterOptions refFilterOptions, string branchFilter, string revisionFilter, string pathFilter, [CanBeNull] Func <GitRevision, bool> revisionPredicate) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var token = _cancellationTokenSequence.Next(); var revisionCount = 0; await TaskScheduler.Default; token.ThrowIfCancellationRequested(); var branchName = module.IsValidVersionrWorkingDir() ? module.GetSelectedBranch() : ""; token.ThrowIfCancellationRequested(); UpdateSelectedRef(module, refs, branchName); var refsByObjectId = refs.ToLookup(head => head.ObjectId); token.ThrowIfCancellationRequested(); var arguments = BuildArguments(refFilterOptions, branchFilter, revisionFilter, pathFilter); #if TRACE var sw = Stopwatch.StartNew(); #endif var versions = module.GetLog(1000); // TODO: VSR - limit is in revisionFilter variable foreach (var version in versions) { token.ThrowIfCancellationRequested(); var revision = new GitRevision(new ObjectId(version.ID)) { ParentIds = version.Parent.HasValue ? new[] { new ObjectId(version.Parent.Value) } : null, TreeGuid = null, // TODO: VSR Author = version.Author, AuthorEmail = version.Email, AuthorDate = version.Timestamp, // TODO: VSR Committer = version.Author, // TODO: VSR CommitterEmail = version.Email, // TODO: VSR CommitDate = version.Timestamp, MessageEncoding = null, // TODO: VSR Subject = version.Message, Body = version.Message, // TODO: VSR Name = version.ShortName, // TODO: VSR HasMultiLineMessage = false, // TODO: VSR - !ReferenceEquals(Subject, Body), HasNotes = false }; if (revisionPredicate == null || revisionPredicate(revision)) { // The full commit message body is used initially in InMemFilter, after which it isn't // strictly needed and can be re-populated asynchronously. // // We keep full multiline message bodies within the last six months. // Commits earlier than that have their properties set to null and the // memory will be GCd. if (DateTime.Now - revision.AuthorDate > TimeSpan.FromDays(30 * 6)) { revision.Body = null; } // Look up any refs associated with this revision revision.Refs = refsByObjectId[revision.ObjectId].AsReadOnlyList(); revisionCount++; subject.OnNext(revision); } } // This property is relatively expensive to call for every revision, so // cache it for the duration of the loop. var logOutputEncoding = module.LogOutputEncoding; if (!token.IsCancellationRequested) { subject.OnCompleted(); } }