/// <summary> /// Merges a range changesets. Does not perform a check in. /// </summary> /// <returns>A tuple, where the boolean signals success, and the string contains and error message in case of failure.</returns> public static Tuple <bool, string> MergeRange(MyTfsConnection tfsConnection, Changeset[] changesets, IList <DirectoryInfo> branches, IProgress <ProgressReportArgs> reporter, CancellationToken cancelToken, FileInfo tfExecutable, IPopupService popupService, MergeOptionsEx mergeOptions = MergeOptionsEx.None) { Debug.Assert(branches.Count == 2, "Merging as range currently only supports two branches (1 source + 1 target)"); //if (doCheckin == false) //{ // Debug.Assert(branches.Count == 2, "Currently not supported to have more than two branches in the chain when not checkin in after each merge."); //} if (changesets.Any() && branches.Count > 1) { DirectoryInfo sourceBranch = branches[0]; DirectoryInfo targetBranch = branches[1]; tfsConnection.SetLocalPath(BranchType.Source, sourceBranch.FullName); tfsConnection.SetLocalPath(BranchType.Target, targetBranch.FullName); string whatAreWeDoing = $"Merging changesets {changesets.First().ChangesetId} - {changesets.Last().ChangesetId}"; reporter?.Report(new ProgressReportArgs(0, null, whatAreWeDoing)); cancelToken.ThrowIfCancellationRequested(); try { CheckInitialConflicts(tfsConnection, targetBranch, whatAreWeDoing); int firstId = changesets.First().ChangesetId; int lastId = changesets.Last().ChangesetId; IList <Conflict> conflicts = tfsConnection.Merge(firstId, lastId, mergeOptions); cancelToken.ThrowIfCancellationRequested(); if (conflicts.Count > 0 && !conflicts.All(c => c.AutoResolved)) { //ResolveConflictsWithAPICall(conflicts, tfsConnection, checkinComment); var conflictRetval = ConflictResolver.ResolveConflictsWithExternalExecutable(tfExecutable, tfsConnection, targetBranch.FullName, popupService); if (!conflictRetval.Item1) { throw new MyTfsConflictException(conflictRetval.Item2.Count() + " unresolved conflicts."); } cancelToken.ThrowIfCancellationRequested(); } reporter?.Report(new ProgressReportArgs(1)); } catch (MyTfsConnectionException ex) { reporter?.Report(new ProgressReportArgs(0, "Error", "Error " + whatAreWeDoing + "\n\n" + ex.ToString())); return(Tuple.Create(false, ex.ToString())); } return(Tuple.Create(true, "Successfully merged.")); } return(Tuple.Create(false, "No changesets, or not >= 2 branches.")); }
/// <summary> /// Will query for conflicts in the folder, then offer a choice to resolve them with tfs.exe. /// </summary> /// <remarks> /// Will asks the user if he wants to launch the tool until either there are no more conflicts, /// or until the user chooses not to launch the tool anymore. /// </remarks> public static Tuple <bool, IList <Conflict> > ResolveConflictsWithExternalExecutable( FileInfo tfExecutable, MyTfsConnection tfsConnection, string targetLocalPath, IPopupService popupService, string checkinComment = null) { Debug.Assert(tfExecutable.Exists, "tfs.exe not found."); Debug.Assert(!string.IsNullOrEmpty(targetLocalPath), "Local path not found."); bool success = true; Conflict[] conflicts = tfsConnection.WorkSpace.QueryConflicts(new string[] { targetLocalPath }, true); while (conflicts.Any()) { string msg = !string.IsNullOrEmpty(checkinComment) ? $"{conflicts.Count()} conflict(s) in target path when merging:\n \"{checkinComment}\"." : msg = $"{conflicts.Count()} conflict(s) in target path."; MessageBoxResult mbResult = popupService.AskYesNoQuestion(msg, "Conflict", "Launch VS merge tool", "Stop the process."); //MessageBoxResult mbResult = Application.Current.Dispatcher.Invoke<MessageBoxResult>(() => //{ // System.Windows.Style style = new System.Windows.Style(); // style.Setters.Add(new Setter(Xceed.Wpf.Toolkit.MessageBox.YesButtonContentProperty, )); // style.Setters.Add(new Setter(Xceed.Wpf.Toolkit.MessageBox.NoButtonContentProperty, )); // return Xceed.Wpf.Toolkit.MessageBox.Show(Application.Current.MainWindow, msg, "Conflict", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes, style); //}); switch (mbResult) { case MessageBoxResult.Yes: // https://www.visualstudio.com/en-us/docs/tfvc/resolve-command var processStartInfo = new ProcessStartInfo { WorkingDirectory = targetLocalPath, FileName = tfExecutable.FullName, Arguments = "resolve", CreateNoWindow = true }; Process myProcess = Process.Start(processStartInfo); myProcess?.WaitForExit(); break; default: success = false; break; } if (success == false) { break; } // Check again. conflicts = tfsConnection.WorkSpace.QueryConflicts(new string[] { targetLocalPath }, true); } List <Conflict> retList = success ? new List <Conflict>() : conflicts.ToList(); return(new Tuple <bool, IList <Conflict> >(success, retList)); }
private static void CheckInitialConflicts(MyTfsConnection tfsConnection, DirectoryInfo targetBranch, string whatAreWeMerging) { var initialConflicts = tfsConnection.WorkSpace.QueryConflicts(new string[] { targetBranch.FullName }, true); if (initialConflicts.Any()) { throw new MyTfsConflictException(initialConflicts.Count() + " unresolved conflict(s) before starting to merge \"" + whatAreWeMerging + "\"\n\nIn folder " + targetBranch.FullName); } }
public MergeSpecificIdViewModel(IEventAggregator eventAggregator, IOutputWindow output, UserSettings settings, MyTfsConnection tfsConnection, IPopupService popups) { BranchList = new List <DirectoryInfo>(); EventAggregator = eventAggregator; Output = output; Settings = settings; TfsConnection = tfsConnection; Popups = popups; Activated += MergeSpecificIdViewModel_Activated; Deactivated += MergeSpecificIdViewModel_Deactivated; }
public ConnectionSetupViewModel(IEventAggregator eventAggregator, IOutputWindow output, UserSettings userSettings, MyTfsConnection tfsConnection, IPopupService popups) { EventAggregator = eventAggregator; Output = output; UserSettings = userSettings; TfsConnection = tfsConnection; Popups = popups; Branches = new BindableCollection <BranchViewModel>(); FirstActivationDone = false; Activated += ConnectionSetupViewModel_Activated; Deactivated += ConnectionSetupViewModel_Deactivated; }
public MergeFromListViewModel(IEventAggregator eventAggregator, IOutputWindow output, UserSettings settings, MyTfsConnection tfsConnection, IPopupService popups) { EventAggregator = eventAggregator; Output = output; Settings = settings; TfsConnection = tfsConnection; Popups = popups; //Shell = shell; CandidateList = new BindableCollection <CandidateListItem>(); CandidateListView = System.Windows.Data.CollectionViewSource.GetDefaultView(CandidateList); Activated += MergingMainViewModel_Activated; Deactivated += MergingMainViewModel_Deactivated; MaxItemCount = 100; GetWorkItemData = true; }
private static string GetWorkItemType(MyTfsConnection tfs, int id) { var workItem = tfs.GetWorkItem(id); return(workItem.Type.Name); }
public CandidateListItem(Changeset changeset, bool partial, bool isSelected, bool getWorkItemDetails, MyTfsConnection myTfsConnection) { this.Changeset = changeset; this.Partial = partial; this.IsSelected = isSelected; if (getWorkItemDetails) { this._tfs = myTfsConnection; GetWorkItemData(); } }
/// <summary> /// Merges the changesets one by one. Each of the changesets is merged through all branches, ie. from first to last. /// </summary> /// <returns>A tuple, where the boolean signals success, and the string contains and error message in case of failure.</returns> public static Tuple <bool, string> MergeAndCommitOneByOne(MyTfsConnection tfsConnection, Changeset[] changesets, IList <DirectoryInfo> branches, IProgress <ProgressReportArgs> reporter, IProgress <FinishedItemReport> finishedItem, CancellationToken cancelToken, FileInfo tfExecutable, IPopupService popupService, MergeOptionsEx mergeOptions = MergeOptionsEx.None, bool doCheckin = true, bool associateWorkItems = true) { if (!changesets.Any() || branches.Count <= 1) { return(Tuple.Create(false, "No changesets, or not >= 2 branches.")); } if (doCheckin == false) { Debug.Assert(branches.Count == 2, "Currently not supported to have more than two branches in the chain when not checkin in after each merge."); } // For the whole length of the list of changeset in the source branch. foreach (var csOriginal in changesets) { cancelToken.ThrowIfCancellationRequested(); // For the whole depth of the list of branch merge chain. var csCurrent = tfsConnection.GetChangeset(csOriginal.ChangesetId); int newCheckinId = 0; for (int ii = 0; ii < branches.Count - 1; ii++) { cancelToken.ThrowIfCancellationRequested(); if (csCurrent != null) { var sourceBranch = branches[ii]; var targetBranch = branches[ii + 1]; tfsConnection.SetLocalPath(BranchType.Source, sourceBranch.FullName); tfsConnection.SetLocalPath(BranchType.Target, targetBranch.FullName); var id = csCurrent.ChangesetId; string checkinComment = CommentBuilder.GetComment(csOriginal.Comment, id, csOriginal.OwnerDisplayName, sourceBranch.Name, targetBranch.Name, mergeOptions); reporter?.Report(new ProgressReportArgs(0, null, "Merging: " + checkinComment)); try { CheckInitialConflicts(tfsConnection, targetBranch, checkinComment); IList <Conflict> conflicts = tfsConnection.Merge(id, id, mergeOptions); cancelToken.ThrowIfCancellationRequested(); if (conflicts.Count > 0 && !conflicts.All(c => c.AutoResolved)) { //ResolveConflictsWithAPICall(conflicts, tfsConnection, checkinComment); var conflictRetval = ConflictResolver.ResolveConflictsWithExternalExecutable( tfExecutable, tfsConnection, targetBranch.FullName, popupService, checkinComment); if (conflictRetval.Item1 == false) { throw new MyTfsConflictException(conflictRetval.Item2.Count() + " unresolved conflicts."); } cancelToken.ThrowIfCancellationRequested(); } if (doCheckin) { reporter?.Report(new ProgressReportArgs(1, null, "Checkin: " + checkinComment)); var workItems = associateWorkItems ? csCurrent.WorkItems : new WorkItem[0]; workItems = FilterWorkItemsToUpdate(workItems); newCheckinId = tfsConnection.Checkin(checkinComment, workItems); } reporter?.Report(new ProgressReportArgs(1)); finishedItem?.Report(new FinishedItemReport() { SourceChangesetId = id, CommitChangesetId = newCheckinId, CommitComment = checkinComment, SourceBranchIndex = ii }); } catch (MyTfsConnectionException ex) { reporter?.Report(new ProgressReportArgs(0, "Error", "Error merging changeset: " + id.ToString() + "\n\n" + ex.ToString())); return(Tuple.Create(false, ex.ToString())); } } else { var errorMsg = "Error getting changeset information for id " + csOriginal.ChangesetId + ". Operation aborted."; reporter?.Report(new ProgressReportArgs(0, "Error", errorMsg)); return(Tuple.Create(false, errorMsg)); } if (newCheckinId > 0) { csCurrent = tfsConnection.GetChangeset(newCheckinId); } } } return(Tuple.Create(true, "Successfully merged.")); }