Exemple #1
0
        /// <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."));
        }
Exemple #2
0
        /// <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));
        }
Exemple #3
0
        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);
            }
        }
Exemple #4
0
 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;
 }
Exemple #5
0
        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;
        }
Exemple #7
0
        private static string GetWorkItemType(MyTfsConnection tfs, int id)
        {
            var workItem = tfs.GetWorkItem(id);

            return(workItem.Type.Name);
        }
Exemple #8
0
        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();
            }
        }
Exemple #9
0
        /// <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."));
        }