Exemple #1
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."));
        }