Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 109 additions & 107 deletions src/AutoMerge/Branches/BranchValidator.cs
Original file line number Diff line number Diff line change
@@ -1,111 +1,113 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.Linq;

namespace AutoMerge
{
public class BranchValidator
{
private readonly Workspace _workspace;
private readonly IEnumerable<ExtendedMerge> _trackMerges;

public BranchValidator(Workspace workspace, IEnumerable<ExtendedMerge> trackMerges)
{
_workspace = workspace;
_trackMerges = trackMerges;
}

public MergeInfoViewModel Validate(MergeInfoViewModel branchInfo)
{
branchInfo.ValidationResult = ValidateItem(_workspace, branchInfo, _trackMerges);
branchInfo.ValidationMessage = ToMessage(branchInfo.ValidationResult);

return branchInfo;
}

private static BranchValidationResult ValidateItem(Workspace workspace, MergeInfoViewModel mergeInfoViewModel, IEnumerable<ExtendedMerge> trackMerges)
{
var result = BranchValidationResult.Success;

if (result == BranchValidationResult.Success)
{
var isMerged = IsMerged(mergeInfoViewModel.SourcePath, mergeInfoViewModel.TargetPath, trackMerges);
if (isMerged)
result = BranchValidationResult.AlreadyMerged;
}

if (result == BranchValidationResult.Success)
{
var userHasAccess = UserHasAccess(workspace.VersionControlServer, mergeInfoViewModel.TargetPath);
if (!userHasAccess)
result = BranchValidationResult.NoAccess;
}

if (result == BranchValidationResult.Success)
{
var isMapped = IsMapped(workspace, mergeInfoViewModel.TargetPath);
if (!isMapped)
result = BranchValidationResult.BranchNotMapped;
}

if (result == BranchValidationResult.Success)
{
var hasLocalChanges = HasLocalChanges(workspace, mergeInfoViewModel.TargetPath);
if (hasLocalChanges)
result = BranchValidationResult.ItemHasLocalChanges;
}
return result;
}

private static bool IsMerged(string sourcePath, string targetPath, IEnumerable<ExtendedMerge> trackMerges)
{
if (trackMerges == null)
return false;

return trackMerges.Any(m => (m.TargetItem.Item == sourcePath && m.SourceItem.Item.ServerItem == targetPath)
|| (m.TargetItem.Item == targetPath && m.SourceItem.Item.ServerItem == sourcePath));
}

private static bool UserHasAccess(VersionControlServer versionControlServer, string targetPath)
{
var permissions = versionControlServer.GetEffectivePermissions(versionControlServer.AuthorizedUser, targetPath);

if (permissions == null || permissions.Length < 4)
return false;

return permissions.Contains("Read")
&& permissions.Contains("PendChange")
&& permissions.Contains("Checkin")
&& permissions.Contains("Merge");
}

private static bool IsMapped(Workspace workspace, string targetItem)
{
return workspace.IsServerPathMapped(targetItem);
}

private static bool HasLocalChanges(Workspace workspace, string targetPath)
{
return workspace.GetPendingChangesEnumerable(targetPath, RecursionType.Full).Any();
}

private static string ToMessage(BranchValidationResult validationResult)
{
switch (validationResult)
{
case BranchValidationResult.Success:
return null;
case BranchValidationResult.AlreadyMerged:
return "Already merged";
case BranchValidationResult.BranchNotMapped:
return "Branch not mapped";
case BranchValidationResult.ItemHasLocalChanges:
return "Folder has local changes. Check-in or undo it";
case BranchValidationResult.NoAccess:
return "You have not rights for edit";
default:
return "Unknown error";
}
}
}
{
public class BranchValidator
{
private readonly Workspace _workspace;
private readonly IEnumerable<ExtendedMerge> _trackMerges;

public BranchValidator(Workspace workspace, IEnumerable<ExtendedMerge> trackMerges)
{
_workspace = workspace;
_trackMerges = trackMerges;
}

public MergeInfoViewModel Validate(MergeInfoViewModel branchInfo)
{
branchInfo.ValidationResult = ValidateItem(_workspace, branchInfo, _trackMerges);
branchInfo.ValidationMessage = ToMessage(branchInfo.ValidationResult);

return branchInfo;
}

private static BranchValidationResult ValidateItem(Workspace workspace, MergeInfoViewModel mergeInfoViewModel, IEnumerable<ExtendedMerge> trackMerges)
{
var result = BranchValidationResult.Success;

if (result == BranchValidationResult.Success)
{
var isMerged = IsMerged(mergeInfoViewModel.SourcePath, mergeInfoViewModel.TargetPath, trackMerges);
if (isMerged)
result = BranchValidationResult.AlreadyMerged;
}

if (result == BranchValidationResult.Success)
{
var userHasAccess = UserHasAccess(workspace.VersionControlServer, mergeInfoViewModel.TargetPath);
if (!userHasAccess)
result = BranchValidationResult.NoAccess;
}

if (result == BranchValidationResult.Success)
{
var isMapped = IsMapped(workspace, mergeInfoViewModel.TargetPath);
if (!isMapped)
result = BranchValidationResult.BranchNotMapped;
}

if (result == BranchValidationResult.Success)
{
var hasLocalChanges = HasLocalChanges(workspace, mergeInfoViewModel.TargetPath);
if (hasLocalChanges)
result = BranchValidationResult.ItemHasLocalChanges;
}
return result;
}

private static bool IsMerged(string sourcePath, string targetPath, IEnumerable<ExtendedMerge> trackMerges)
{
if (trackMerges == null)
return false;

return trackMerges.Any(m =>
(string.Equals(m.TargetItem.Item, sourcePath, StringComparison.OrdinalIgnoreCase) && string.Equals(m.SourceItem.Item.ServerItem, targetPath, StringComparison.OrdinalIgnoreCase))
|| (string.Equals(m.TargetItem.Item, targetPath, StringComparison.OrdinalIgnoreCase) && string.Equals(m.SourceItem.Item.ServerItem, sourcePath, StringComparison.OrdinalIgnoreCase)));
}

private static bool UserHasAccess(VersionControlServer versionControlServer, string targetPath)
{
var permissions = versionControlServer.GetEffectivePermissions(versionControlServer.AuthorizedUser, targetPath);

if (permissions == null || permissions.Length < 4)
return false;

return permissions.Contains("Read")
&& permissions.Contains("PendChange")
&& permissions.Contains("Checkin")
&& permissions.Contains("Merge");
}

private static bool IsMapped(Workspace workspace, string targetItem)
{
return workspace.IsServerPathMapped(targetItem);
}

private static bool HasLocalChanges(Workspace workspace, string targetPath)
{
return workspace.GetPendingChangesEnumerable(targetPath, RecursionType.Full).Any();
}

private static string ToMessage(BranchValidationResult validationResult)
{
switch (validationResult)
{
case BranchValidationResult.Success:
return null;
case BranchValidationResult.AlreadyMerged:
return "Already merged";
case BranchValidationResult.BranchNotMapped:
return "Branch not mapped";
case BranchValidationResult.ItemHasLocalChanges:
return "Folder has local changes. Check-in or undo it";
case BranchValidationResult.NoAccess:
return "You have not rights for edit";
default:
return "Unknown error";
}
}
}
}
23 changes: 14 additions & 9 deletions src/AutoMerge/Branches/BranchesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

using AutoMerge.Events;
using AutoMerge.Prism.Command;
using AutoMerge.Prism.Events;

using EnvDTE80;

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common.Internal;
using Microsoft.TeamFoundation.Controls;
Expand All @@ -17,6 +20,7 @@
using Microsoft.TeamFoundation.VersionControl.Common;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.VisualStudio.Shell.Interop;

using TeamExplorerSectionViewModelBase = AutoMerge.Base.TeamExplorerSectionViewModelBase;

namespace AutoMerge
Expand Down Expand Up @@ -406,7 +410,7 @@ private TrackMergeInfo GetTrackMergeInfo(VersionControlServer versionControl,
{
FromOriginalToSourceBranches = new List<string>(),
};
var trackMerges = allTrackMerges.Where(m => m.TargetItem.Item == sourcePath).ToArray();
var trackMerges = allTrackMerges.Where(m => string.Equals(m.TargetItem.Item, sourcePath, StringComparison.OrdinalIgnoreCase)).ToArray();
if (!trackMerges.IsNullOrEmpty())
{
var changesetIds = trackMerges.Select(t => t.SourceChangeset.ChangesetId).ToArray();
Expand Down Expand Up @@ -478,7 +482,8 @@ private static ItemIdentifier GetTargetPath(ICollection<ItemIdentifier> mergesRe

private static bool IsTargetPath(ItemIdentifier mergeRelations, ItemIdentifier branch)
{
return mergeRelations.Item.Contains(branch.Item + "/");
return mergeRelations.Item.IndexOf(branch.Item + '/', StringComparison.OrdinalIgnoreCase) >= 0 ||
string.Compare(mergeRelations.Item, branch.Item, StringComparison.OrdinalIgnoreCase) == 0;
}

private static string CalculateTopFolder(IList<Change> changes)
Expand Down Expand Up @@ -523,7 +528,7 @@ private static string CalculateTopFolder(IList<Change> changes)

private static string FindShareFolder(string topFolder, string changeFolder)
{
if ((topFolder == null) || topFolder.Contains(changeFolder))
if ((topFolder == null) || topFolder.IndexOf(changeFolder, StringComparison.OrdinalIgnoreCase) >= 0)
{
return changeFolder;
}
Expand Down Expand Up @@ -884,11 +889,11 @@ private static List<MergeRelation> GetMergeRelationships(List<PendingChange> pen
foreach (var shareFolderRelationship in shareFolderRelationships.Where(r => !r.IsDeleted))
{
var targetBranch =
targetBranches.FirstOrDefault(branch => shareFolderRelationship.Item.Contains(branch));
targetBranches.FirstOrDefault(branch => shareFolderRelationship.Item.IndexOf(branch, StringComparison.OrdinalIgnoreCase) >= 0);
if (targetBranch != null)
{
var sourceRelationship = sourceRelationships
.FirstOrDefault(r => r.Item.Contains(targetBranch));
.FirstOrDefault(r => r.Item.IndexOf(targetBranch, StringComparison.OrdinalIgnoreCase) >= 0);
mergeRelationships.Add(new MergeRelation
{
Item = pendingChange.ServerItem,
Expand Down Expand Up @@ -999,7 +1004,7 @@ private MergeResult MergeByFile(Change[] changes, string targetBranch, List<Merg
{
var mergeRelation =
mergeRelationships.FirstOrDefault(
r => r.Item == change.Item.ServerItem && r.Target.StartsWith(targetBranch));
r => r.Item == change.Item.ServerItem && r.Target.StartsWith(targetBranch, StringComparison.OrdinalIgnoreCase));
if (mergeRelation != null)
{
var recursionType = CalculateRecursionType(mergeRelation);
Expand Down Expand Up @@ -1076,7 +1081,7 @@ private static List<PendingChange> GetPendingChanges(string target, Workspace wo
{
var allPendingChanges = workspace.GetPendingChangesEnumerable(target, RecursionType.Full);
var targetPendingChanges = allPendingChanges
.Where(p => p.IsMerge && p.ServerItem.Contains(target))
.Where(p => p.IsMerge && p.ServerItem.IndexOf(target, StringComparison.OrdinalIgnoreCase) >= 0)
.ToList();
return targetPendingChanges;
}
Expand All @@ -1086,7 +1091,7 @@ private static List<PendingChange> GetPendingChangesByFile(List<MergeRelation> m
var itemSpecs = new List<ItemSpec>();
foreach (var mergeRelationship in mergeRelationships)
{
if (mergeRelationship.Target.StartsWith(targetBranch))
if (mergeRelationship.Target.StartsWith(targetBranch, StringComparison.OrdinalIgnoreCase))
{
var recursionType = CalculateRecursionType(mergeRelationship);
itemSpecs.Add(new ItemSpec(mergeRelationship.Target, recursionType));
Expand All @@ -1110,7 +1115,7 @@ private static bool GetLatest(string targetPath, List<MergeRelation> mergeRelati
var getLatestFiles = new List<string>();
foreach (var mergeRelationship in mergeRelationships.Where(r => r.TargetItemType == ItemType.File && r.GetLatesPath != null))
{
if (mergeRelationship.GetLatesPath.StartsWith(targetPath))
if (mergeRelationship.GetLatesPath.StartsWith(targetPath, StringComparison.OrdinalIgnoreCase))
getLatestFiles.Add(mergeRelationship.GetLatesPath);
}

Expand Down