148 lines
7.3 KiB
C#
148 lines
7.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.TeamFoundation.VersionControl.Client;
|
|
using Sep.Git.Tfs.Core;
|
|
using Sep.Git.Tfs.Core.BranchVisitors;
|
|
using Sep.Git.Tfs.Core.TfsInterop;
|
|
using StructureMap;
|
|
|
|
namespace Sep.Git.Tfs.VsCommon
|
|
{
|
|
public abstract class TfsHelperVs2010Base : TfsHelperBase
|
|
{
|
|
TfsApiBridge _bridge;
|
|
|
|
public TfsHelperVs2010Base(TextWriter stdout, TfsApiBridge bridge, IContainer container)
|
|
: base(stdout, bridge, container)
|
|
{
|
|
_bridge = bridge;
|
|
}
|
|
|
|
public override bool CanGetBranchInformation { get { return true; } }
|
|
|
|
public override IEnumerable<string> GetAllTfsRootBranchesOrderedByCreation()
|
|
{
|
|
return VersionControl.QueryRootBranchObjects(RecursionType.Full)
|
|
.Where(b => b.Properties.ParentBranch == null)
|
|
.Select(b => b.Properties.RootItem.Item);
|
|
}
|
|
|
|
public override IEnumerable<IBranchObject> GetBranches()
|
|
{
|
|
var branches = VersionControl.QueryRootBranchObjects(RecursionType.Full)
|
|
.Where(b => b.Properties.RootItem.IsDeleted == false);
|
|
return _bridge.Wrap<WrapperForBranchObject, BranchObject>(branches);
|
|
}
|
|
|
|
public override int GetRootChangesetForBranch(string tfsPathBranchToCreate, string tfsPathParentBranch = null)
|
|
{
|
|
try
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(tfsPathParentBranch))
|
|
Trace.WriteLine("Parameter about parent branch will be ignored because this version of TFS is able to find the parent!");
|
|
|
|
Trace.WriteLine("Looking for all branches...");
|
|
var allTfsBranches = VersionControl.QueryRootBranchObjects(RecursionType.Full);
|
|
var tfsBranchToCreate = allTfsBranches.FirstOrDefault(b => b.Properties.RootItem.Item.ToLower() == tfsPathBranchToCreate.ToLower());
|
|
if (tfsBranchToCreate == null)
|
|
{
|
|
Trace.WriteLine("error: TFS branches "+ tfsPathBranchToCreate +" not found!");
|
|
return -1;
|
|
}
|
|
tfsPathParentBranch = tfsBranchToCreate.Properties.ParentBranch.Item;
|
|
Trace.WriteLine("Found parent branch : " + tfsPathParentBranch);
|
|
|
|
var firstChangesetInBranchToCreate = VersionControl.QueryHistory(tfsPathBranchToCreate, VersionSpec.Latest, 0, RecursionType.Full,
|
|
null, null, null, int.MaxValue, true, false, false).Cast<Changeset>().LastOrDefault();
|
|
|
|
if (firstChangesetInBranchToCreate == null)
|
|
{
|
|
throw new GitTfsException("An unexpected error occured when trying to find the root changeset.\nFailed to find first changeset for " + tfsPathBranchToCreate);
|
|
}
|
|
|
|
var mergedItemsToFirstChangesetInBranchToCreate = VersionControl
|
|
.TrackMerges(new int[] {firstChangesetInBranchToCreate.ChangesetId},
|
|
new ItemIdentifier(tfsPathBranchToCreate),
|
|
new ItemIdentifier[] {new ItemIdentifier(tfsPathParentBranch),},
|
|
null)
|
|
.OrderBy(x => x.SourceChangeset.ChangesetId);
|
|
|
|
var rootChangesetInParentBranch =
|
|
GetRelevantChangesetBasedOnChangeType(mergedItemsToFirstChangesetInBranchToCreate, tfsPathParentBranch, tfsPathBranchToCreate);
|
|
|
|
return rootChangesetInParentBranch.ChangesetId;
|
|
}
|
|
catch (FeatureNotSupportedException ex)
|
|
{
|
|
Trace.WriteLine(ex.Message);
|
|
return base.GetRootChangesetForBranch(tfsPathBranchToCreate, tfsPathParentBranch);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the relevant TFS <see cref="ChangesetSummary"/> for the root changeset given a set
|
|
/// of <see cref="ExtendedMerge"/> objects and a given <paramref name="tfsPathParentBranch"/>.
|
|
/// </summary>
|
|
/// <param name="merges">An array of <see cref="ExtendedMerge"/> objects describing the a set of merges.</param>
|
|
/// <param name="tfsPathParentBranch">The tfs Path Parent Branch.</param>
|
|
/// <param name="tfsPathBranchToCreate">The tfs Path Branch To Create.</param>
|
|
/// <remarks>
|
|
/// Each <see cref="ChangeType"/> uses the SourceChangeset, SourceItem, TargetChangeset, and TargetItem
|
|
/// properties with different semantics, depending on what it needs to describe, so the strategy to determine
|
|
/// whether we are interested in a given ExtendedMerge summary depends on the SourceItem's <see cref="ChangeType"/>.
|
|
/// </remarks>
|
|
/// <returns><value>True</value> if the given <paramref name="merge"/> is relevant; <value>False</value> otherwise.
|
|
/// </returns>
|
|
private static ChangesetSummary GetRelevantChangesetBasedOnChangeType(IEnumerable<ExtendedMerge> merges, string tfsPathParentBranch, string tfsPathBranchToCreate)
|
|
{
|
|
merges = (merges ?? new ExtendedMerge[] {}).ToArray();
|
|
var merge = merges.LastOrDefault(m => m.SourceItem.Item.ServerItem.Equals(tfsPathParentBranch, StringComparison.InvariantCultureIgnoreCase))
|
|
?? merges.LastOrDefault();
|
|
|
|
if (merge == null)
|
|
{
|
|
throw new GitTfsException("An unexpected error occured when trying to find the root changeset.\nFailed to find root changeset for " + tfsPathBranchToCreate + " branch in " + tfsPathParentBranch + " branch");
|
|
}
|
|
|
|
if (merge.SourceItem.ChangeType.HasFlag(ChangeType.Branch)
|
|
|| merge.SourceItem.ChangeType.HasFlag(ChangeType.Merge)
|
|
|| merge.SourceItem.ChangeType.HasFlag(ChangeType.Add))
|
|
{
|
|
Trace.WriteLine("Found C" + merge.SourceChangeset.ChangesetId + " on branch " + merge.SourceItem.Item.ServerItem);
|
|
return merge.SourceChangeset;
|
|
}
|
|
if (merge.SourceItem.ChangeType.HasFlag(ChangeType.Rename)
|
|
|| merge.SourceItem.ChangeType.HasFlag(ChangeType.SourceRename))
|
|
{
|
|
Trace.WriteLine("Found C" + merge.TargetChangeset.ChangesetId + " on branch " + merge.TargetItem.Item);
|
|
return merge.TargetChangeset;
|
|
}
|
|
throw new GitTfsException(
|
|
"Don't know (yet) how to find the root changeset for an ExtendedMerge of type " +
|
|
merge.SourceItem.ChangeType,
|
|
new string[]
|
|
{
|
|
"Open an Issue on Github to notify the community that you need support for '" +
|
|
merge.SourceItem.ChangeType + "': https://github.com/git-tfs/git-tfs/issues"
|
|
});
|
|
}
|
|
|
|
public override void CreateBranch(string sourcePath, string targetPath, int changesetId, string comment = null)
|
|
{
|
|
var changesetToBranch = new ChangesetVersionSpec(changesetId);
|
|
int branchChangesetId = VersionControl.CreateBranch(sourcePath, targetPath, changesetToBranch);
|
|
|
|
if (comment != null)
|
|
{
|
|
Changeset changeset = VersionControl.GetChangeset(branchChangesetId);
|
|
changeset.Comment = comment;
|
|
changeset.Update();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|