private void LoadChangesetList(bool refresh = false) { if (_changesetLoadingTaskActive) { if (!refresh) { return; } } _changesetLoadingTaskActive = true; Repository.Instance.BackgroundTaskManager.Start( Constants.Tasks.LoadChangesetListKey, refresh ? ChangesetsRefreshing : ChangesetsLoading, (task) => { var results = new List <ChangesetListElement>(); task.TrackProgress.ProgressInfo = "Loading changesets ..."; lock (_changesetLock) { int count = 0; foreach (var changeset in _changesets) { task.TrackProgress.ProgressInfo = string.Format("Loading changesets ({0} done) ...", ++count); var source = FindChangeset(changeset, MergeSource); var target = FindChangeset(changeset, MergeTarget); var changesetListElement = new ChangesetListElement() { Changeset = TfsItemCache.UpdateChangesetFromCache(new TfsChangesetWrapper(changeset)), CanBeMerged = (target == null), SourceExists = (source != null), SourceCheckinDate = (source != null) ? source.Changeset.CreationDate : DateTime.MinValue, SourceCheckinId = (source != null) ? source.Changeset.ChangesetId : 0, TargetExists = (target != null), TargetCheckinDate = (target != null) ? new DateTime?(target.Changeset.CreationDate) : null, TargetCheckinId = (target != null) ? target.Changeset.ChangesetId : 0 }; DetermineWarningStatus(changesetListElement); results.Add(changesetListElement); } } Repository.Instance.BackgroundTaskManager.Post( () => { _changesetLoadingTaskActive = false; _changesetList = results; RaisePropertyChanged("ChangesetList"); return(true); }); }); }
private void AutoMerge() { try { var confirm = new MessageBoxViewModel("vMerge: AutoMerge all changesets", "All changesets will be merged silently as long as no conflict arises. Are you really sure to proceed?", MessageBoxViewModel.MessageBoxButtons.None); var goOn = new MessageBoxViewModel.MessageBoxButton("Merge silently"); var cancel = new MessageBoxViewModel.MessageBoxButton("Cancel"); confirm.ConfirmButtons.Add(goOn); confirm.ConfirmButtons.Add(cancel); Repository.Instance.ViewManager.ShowModal(confirm); if (goOn.IsChecked) { ChangesetListElement conflictingChangeset = null; Repository.Instance.BackgroundTaskManager.RunWithCancelDialog( (progressParams) => { progressParams.TrackProgress.MaxProgress = ChangesetList.Where(item => item.CanBeMerged).Count(); foreach (var changeset in ChangesetList.Where(item => item.CanBeMerged).OrderBy(item => item.SourceCheckinId)) { progressParams.TrackProgress.Increment(); progressParams.CancellationToken.ThrowIfCancellationRequested(); var copy = progressParams.CloneWithoutIncrements(); if (!PerformMerge(changeset, copy)) { SimpleLogger.Log(SimpleLogLevel.Info, "Merge conflict in: " + changeset.SourceCheckinId + " " + changeset.SourceComment); conflictingChangeset = changeset; break; } } }, "Merging changesets ..."); if (conflictingChangeset != null) { var comment = conflictingChangeset.SourceComment; if (comment.Length > 80) { comment = comment.Substring(0, 77) + "..."; } var cancelled = new MessageBoxViewModel("vMerge: AutoMerge all changesets", String.Format("AutoMerge has stopped due to a conflict caused by changeset #{0} (comment: \"{1}\").\r\nPlease merge the remaining changesets manually.", conflictingChangeset.SourceCheckinId, comment), MessageBoxViewModel.MessageBoxButtons.OK); Repository.Instance.ViewManager.ShowModal(cancelled); } LoadAllAssociatedChangesetsIncludingMerges(true); } } catch (Exception ex) { SimpleLogger.Log(ex, true, false); } }
private void DetermineWarningStatus(ChangesetListElement changesetListElement) { if (changesetListElement.TargetCheckinId != 0) { return; } if (changesetListElement.SourceCheckinId == 0) { changesetListElement.HasWarning = true; changesetListElement.WarningText = "This changeset has not yet been merged to the selected source branch."; changesetListElement.CanBeMerged = false; return; } TfsChangesetWrapper sourceCS = TfsItemCache.GetChangesetFromCache(changesetListElement.SourceCheckinId); bool anyChangeNotInFilter = PathFilter == null ? false : sourceCS.TfsChangeset.GetAllChanges() .Any(change => !change.Change.Item.ServerItem.StartsWith(PathFilter)); bool allChangesNotInFilter = PathFilter == null ? false : sourceCS.TfsChangeset.GetAllChanges() .All(change => !change.Change.Item.ServerItem.StartsWith(PathFilter)); if (anyChangeNotInFilter || allChangesNotInFilter) { changesetListElement.HasWarning = true; if (allChangesNotInFilter) { changesetListElement.WarningText = "No change in this changeset is part of the merge due to the path filter selection."; changesetListElement.CanBeMerged = false; } else if (anyChangeNotInFilter) { changesetListElement.WarningText = "Some changes in this changeset are not part of the merge due to the path filter selection."; } } }
bool PerformMerge(ChangesetListElement item, TrackProgressParameters externalProgress = null) { bool returnValue = false; if (item == null) { return(false); } var tempWorkspace = Repository.Instance.TfsBridgeProvider.GetTemporaryWorkspace(MergeSource, MergeTarget); var mergeChangeset = TfsItemCache.GetChangesetFromCache(item.SourceCheckinId).TfsChangeset; bool finished = Repository.Instance.BackgroundTaskManager.RunWithCancelDialog( (progressParams) => { tempWorkspace.Merge( MergeTarget, PathFilter, new ITfsChangeset[] { mergeChangeset }.AsEnumerable(), progressParams.TrackProgress); }, String.Format("Merging changeset #{0} ...", item.SourceCheckinId), externalProgress); if (!finished) { tempWorkspace.UndoAllPendingChanges(); return(false); } var checkInSummary = new CheckInSummaryViewModel(); tempWorkspace.RefreshConflicts(); checkInSummary.Changes = tempWorkspace.PendingChanges .Select( change => new CheckInSummaryViewModel.PendingChangeWithConflict( change, tempWorkspace.Conflicts.Where(conflict => conflict.ServerPath == change.ServerPath).FirstOrDefault())) .ToList(); while (tempWorkspace.Conflicts.Count != 0) { int oldConflictsCount = tempWorkspace.Conflicts.Count; Repository.Instance.TfsUIInteractionProvider.ResolveConflictsPerTF(tempWorkspace.MappedFolder); tempWorkspace.RefreshConflicts(); if (tempWorkspace.Conflicts.Count == oldConflictsCount) { MessageBoxViewModel mbvm = new MessageBoxViewModel("Cancel merge?", "There are conflicts remaining to be solved. Really cancel the merge?", MessageBoxViewModel.MessageBoxButtons.None); var yesButton = new MessageBoxViewModel.MessageBoxButton("_Yes"); mbvm.ConfirmButtons.Add(yesButton); mbvm.ConfirmButtons.Add(new MessageBoxViewModel.MessageBoxButton("_No")); Repository.Instance.ViewManager.ShowModal(mbvm); if (yesButton.IsChecked) { finished = false; break; } } } if (finished) { checkInSummary.TemporaryWorkspace = tempWorkspace; checkInSummary.OriginalChangesets = new ITfsChangeset[] { item.Changeset.TfsChangeset }.ToList(); checkInSummary.SourceChangesets = new ITfsChangeset[] { mergeChangeset }.ToList(); checkInSummary.AssociatedWorkItems = item.Changeset.TfsChangeset.RelatedWorkItems; checkInSummary.CheckInComment = BuildCheckInComment( item.Changeset.TfsChangeset, mergeChangeset); if (externalProgress == null) { var view = Repository.Instance.ViewManager.CreateViewFor(checkInSummary); view.Finished += CheckInDialogClosed; } else { checkInSummary.Cancelled = false; CommitMerge(checkInSummary, externalProgress); } returnValue = true; } else { tempWorkspace.UndoAllPendingChanges(); } return(returnValue); }
bool PerformMerge(ChangesetListElement item, TrackProgressParameters externalProgress = null) { SimpleLogger.Checkpoint("PerformMerge: Starting"); bool returnValue = false; bool undoPendingChanges = true; if (item == null) { return(false); } SimpleLogger.Checkpoint("PerformMerge: Getting temporary workspace"); var tempWorkspace = Repository.Instance.TfsBridgeProvider.GetTemporaryWorkspace(MergeSource, MergeTarget); SimpleLogger.Checkpoint("PerformMerge: Undoing pending changes in temporary workspace"); tempWorkspace.UndoAllPendingChanges(); try { var mergeChangeset = TfsItemCache.GetChangesetFromCache(item.SourceCheckinId).TfsChangeset; bool finished = false; try { finished = Repository.Instance.BackgroundTaskManager.RunWithCancelDialog( (progressParams) => { tempWorkspace.Merge( MergeTarget, PathFilter, new ITfsChangeset[] { mergeChangeset }.AsEnumerable(), progressParams.TrackProgress); }, String.Format("Merging changeset #{0} ...", item.SourceCheckinId), externalProgress); } catch (AggregateException ex) { bool otherExceptions = false; foreach (var iex in ex.InnerExceptions) { if (iex is LocalPathTooLongException) { DisplayPathTooLongHelp(); } else { SimpleLogger.Log(ex, false, false); otherExceptions = true; } } if (otherExceptions) { SimpleLogger.Log(ex, true); } } catch (LocalPathTooLongException) { DisplayPathTooLongHelp(); return(false); } catch (Exception ex) { SimpleLogger.Log(ex); return(false); } if (!finished) { return(false); } SimpleLogger.Checkpoint("PerformMerge: Building check-in summary"); var checkInSummary = new CheckInSummaryViewModel(); SimpleLogger.Checkpoint("PerformMerge: Refreshing conflicts"); tempWorkspace.RefreshConflicts(); SimpleLogger.Checkpoint("PerformMerge: Refreshing pending changes"); tempWorkspace.RefreshPendingChanges(); checkInSummary.SourceBranch = MergeSource; checkInSummary.TargetBranch = MergeTarget; checkInSummary.Changes = tempWorkspace.PendingChanges .Select( change => new CheckInSummaryViewModel.PendingChangeWithConflict( change, tempWorkspace.Conflicts.Where(conflict => conflict.ServerPath == change.ServerPath).FirstOrDefault())) .ToList(); // Automerging but conflicts? if (externalProgress != null && tempWorkspace.Conflicts.Count != 0) { return(false); } bool hadConflicts = ResolveConflicts(tempWorkspace, ref finished); if (finished) { SimpleLogger.Checkpoint("PerformMerge: Finished"); if (!item.OriginalChangesetLoaded) { FindOriginalChangeset(item.SourceCheckinId); } checkInSummary.TemporaryWorkspace = tempWorkspace; var originalCsWrapper = item.OriginalChangesetLoaded ? TfsItemCache.GetChangesetFromCache(item.OriginalChangesetId) : null; var originalCs = originalCsWrapper != null ? originalCsWrapper.TfsChangeset : null; checkInSummary.OriginalChangesets = new ITfsChangeset[] { originalCs ?? mergeChangeset }.ToList(); checkInSummary.SourceChangesets = new ITfsChangeset[] { mergeChangeset }.ToList(); checkInSummary.AssociatedWorkItems = item.SourceChangeset.RelatedWorkItems; checkInSummary.CheckInComment = BuildCheckInComment( item.SourceChangeset, mergeChangeset); if (hadConflicts || (externalProgress == null && AutoMergeDirectly == false)) { SimpleLogger.Checkpoint("PerformMerge: Showing check-in dialog"); if (Repository.Instance.Settings.FetchSettings <bool>(Constants.Settings.PerformNonModalMergeKey)) { undoPendingChanges = false; EmbeddedCheckInSummaryViewModel = checkInSummary; _temporaryWorkspace = tempWorkspace; EmbeddedCheckInSummaryViewModel.Finished += EmbeddedCheckInSummaryViewModel_Finished; } else { Repository.Instance.ViewManager.ShowModal(checkInSummary); } if (!checkInSummary.Cancelled) { CommitMerge(checkInSummary); } } else { SimpleLogger.Checkpoint("PerformMerge: Check-in automatically cancelled"); checkInSummary.Cancelled = false; CommitMerge(checkInSummary, externalProgress); } returnValue = !hadConflicts; } else { SimpleLogger.Checkpoint("PerformMerge: Not finished"); } } finally { if (undoPendingChanges) { SimpleLogger.Checkpoint("PerformMerge: Undoing pending changes"); tempWorkspace.UndoAllPendingChanges(); } else { SimpleLogger.Checkpoint("PerformMerge: NOT undoing pending changes"); } } SimpleLogger.Checkpoint("PerformMerge: Returning"); return(returnValue); }
private void LoadAllAssociatedChangesetsIncludingMergesTask(BackgroundTask task) { task.TrackProgress.ProgressInfo = "Loading ..."; var results = new List <ChangesetListElement>(); lock (_changesetLock) { int count = 0; task.TrackProgress.ProgressInfo = "Determining merge status ..."; var candidates = Repository.Instance.TfsBridgeProvider.GetMergeCandidatesForBranchToBranch(MergeSource, MergeTarget, PathFilter).ToList(); count = 0; foreach (var changeset in Changesets) { task.TrackProgress.ProgressInfo = string.Format("Tracking changesets ({0} done) ...", ++count); MergedChangeset mergedCs; if (candidates.Any(mergecs => mergecs.Changeset.ChangesetId == changeset.Changeset.ChangesetId)) { mergedCs = new MergedChangeset() { Source = changeset, Target = null }; } else { mergedCs = changeset.FindMergesForActiveProject(MergeSource, (new ITfsBranch[1] { MergeTarget })).FirstOrDefault(); if (mergedCs.Source != null && mergedCs.Target.Changeset.ChangesetId == changeset.Changeset.ChangesetId) { var temp = mergedCs.Source; mergedCs.Source = mergedCs.Target; mergedCs.Target = temp; } } if (mergedCs.Source != null) { var csl = new ChangesetListElement() { CanBeMerged = mergedCs.Target == null, SourceChangeset = changeset, SourceComment = changeset.Description, SourceCheckinDate = changeset.Changeset.CreationDate, SourceCheckinId = changeset.Changeset.ChangesetId, SourceExists = true, TargetCheckinDate = (mergedCs.Target != null ? new DateTime?(mergedCs.Target.Changeset.CreationDate) : null), TargetCheckinId = (mergedCs.Target != null ? mergedCs.Target.Changeset.ChangesetId : 0), TargetExists = mergedCs.Target != null }; results.Add(csl); } } } Repository.Instance.BackgroundTaskManager.Post( () => { _allAssociatedChangesetsIncludingMergesLoadingTaskActive = false; ChangesetsRefreshing.IsLoading = false; ChangesetsLoading.IsLoading = false; ChangesetList = results; return(true); }); }