new option --no-parallel to fix issue #1242

This commit is contained in:
Nils Andresen
2019-04-20 20:38:05 +02:00
parent 405c35ff00
commit 76e1d8a497
14 changed files with 110 additions and 64 deletions
+1
View File
@@ -26,6 +26,7 @@ a TFS source tree and fetch all the changesets
--except-regex=VALUE a regex of exceptions to ignore-regex
-u, --username=VALUE TFS username
-p, --password=VALUE TFS password
--no-parallel disable parallel access of the TFS server
--all, --fetch-all
--parents
--authors=VALUE Path to an Authors file to map TFS users to Git users
+1
View File
@@ -30,6 +30,7 @@ Prefer the [clone](clone.md) or [init](init.md) command if the project folder al
--except-regex=VALUE a regex of exceptions to ingore-regex
-u, --username=VALUE TFS username
-p, --password=VALUE TFS password
--no-parallel disable parallel access of the TFS server
--all, --fetch-all
--parents
--authors=VALUE Path to an Authors file to map TFS users to Git
+2
View File
@@ -26,8 +26,10 @@ Prefer the [clone](clone.md) command to initialize and fetch changesets from a T
messages
Use this when you're exporting from TFS and
don't need to put data back into TFS.
--no-parallel disable parallel access of the TFS server
-u, --username=VALUE TFS username
-p, --password=VALUE TFS password
--no-parallel disable parallel access of the TFS server
## Examples
+4
View File
@@ -65,3 +65,7 @@ key for the remote `default` is `tfs-remote.default.url`.
can be set to `true` to make git-tfs create a tag for each
TFS commit. This is disabled by default, because creating
a lot of tags will slow down your git operations.
* `noparallel`
can be set to `true` to make disable parallel access to the TFS.
This can be useful in cases where the TFS has problems with
parallel access and reports `TF400030`. (See issue #1242)
+15 -14
View File
@@ -1,14 +1,14 @@
using GitTfs.Core;
using GitTfs.Core.TfsInterop;
using GitTfs.Util;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.VersionControl.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using GitTfs.Core;
using GitTfs.Core.TfsInterop;
using GitTfs.Util;
using Microsoft.TeamFoundation.VersionControl.Common;
namespace GitTfs.VsCommon
{
@@ -469,20 +469,20 @@ namespace GitTfs.VsCommon
Retry.Do(() => DoUntilNoFailures(() => _workspace.Get(new ChangesetVersionSpec(changeset), GetOptions.Overwrite | GetOptions.GetAll)));
}
public void GetSpecificVersion(int changesetId, IEnumerable<IItem> items)
public void GetSpecificVersion(int changesetId, IEnumerable<IItem> items, bool noParallel)
{
var version = new ChangesetVersionSpec(changesetId);
GetRequests(items.Select(e => new GetRequest(new ItemSpec(e.ServerItem, RecursionType.Full), version)));
GetRequests(items.Select(e => new GetRequest(new ItemSpec(e.ServerItem, RecursionType.Full), version)), noParallel);
}
public void GetSpecificVersion(IChangeset changeset)
public void GetSpecificVersion(IChangeset changeset, bool noParallel)
{
GetSpecificVersion(changeset.ChangesetId, changeset.Changes);
GetSpecificVersion(changeset.ChangesetId, changeset.Changes, noParallel);
}
public void GetSpecificVersion(int changesetId, IEnumerable<IChange> changes)
public void GetSpecificVersion(int changesetId, IEnumerable<IChange> changes, bool noParallel)
{
GetRequests(changes.Select(change => new GetRequest(new ItemSpec(change.Item.ServerItem, RecursionType.None, change.Item.DeletionId), changesetId)));
GetRequests(changes.Select(change => new GetRequest(new ItemSpec(change.Item.ServerItem, RecursionType.None, change.Item.DeletionId), changesetId)), noParallel);
}
public string GetLocalItemForServerItem(string serverItem)
@@ -536,8 +536,9 @@ namespace GitTfs.VsCommon
}
}
public void GetRequests(IEnumerable<GetRequest> source, int batchSize = 20)
public void GetRequests(IEnumerable<GetRequest> source, bool noParallel, int batchSize = 20)
{
source.ToBatch(batchSize).DoParallel(batch =>
{
var items = batch;
@@ -554,7 +555,7 @@ namespace GitTfs.VsCommon
items = status.GetFailures().Join(items, e => e.ServerItem, e => e.ItemSpec.Item, (failure, request) => request).ToArray();
}
});
});
}, noParallel);
}
}
+9 -9
View File
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using GitTfs.Commands;
using GitTfs.Core;
using GitTfs.Core.TfsInterop;
using GitTfs.Util;
using StructureMap;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace GitTfs.VsFake
{
@@ -258,17 +258,17 @@ namespace GitTfs.VsFake
_repositoryRoot = repositoryRoot;
}
public void GetSpecificVersion(int changesetId, IEnumerable<IItem> items)
public void GetSpecificVersion(int changesetId, IEnumerable<IItem> items, bool noParallel)
{
throw new NotImplementedException();
}
public void GetSpecificVersion(IChangeset changeset)
public void GetSpecificVersion(IChangeset changeset, bool noParallel)
{
GetSpecificVersion(changeset.ChangesetId, changeset.Changes);
GetSpecificVersion(changeset.ChangesetId, changeset.Changes, noParallel);
}
public void GetSpecificVersion(int changeset, IEnumerable<IChange> changes)
public void GetSpecificVersion(int changeset, IEnumerable<IChange> changes, bool noParallel)
{
var repositoryRoot = _repositoryRoot.ToLower();
if (!repositoryRoot.EndsWith("/")) repositoryRoot += "/";
+4 -1
View File
@@ -1,5 +1,5 @@
using NDesk.Options;
using GitTfs.Util;
using NDesk.Options;
namespace GitTfs.Commands
{
@@ -20,6 +20,8 @@ namespace GitTfs.Commands
v => Username = v },
{ "p|password=", "TFS password",
v => Password = v },
{ "no-parallel", "Do not access tfs in parallel",
v => NoParallel = (v != null) },
};
}
}
@@ -28,5 +30,6 @@ namespace GitTfs.Commands
public string ExceptRegex { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool NoParallel { get; set; }
}
}
+31 -19
View File
@@ -1,3 +1,6 @@
using GitTfs.Commands;
using NDesk.Options;
using StructureMap;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -5,9 +8,6 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NDesk.Options;
using GitTfs.Commands;
using StructureMap;
namespace GitTfs.Core
{
@@ -175,7 +175,7 @@ namespace GitTfs.Core
public static IEnumerable<TResult[]> ToBatch<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, int batchSize)
{
var batch = new List<TResult>(batchSize);
foreach (var item in source)
{
if (batch.Count >= batchSize)
@@ -211,17 +211,24 @@ namespace GitTfs.Core
/// </summary>
/// <param name="source">The source sequence.</param>
/// <param name="action">The action to execute.</param>
/// <param name="noParallel">set to true> to disable parallel processing</param>
/// <typeparam name="T">The source item type</typeparam>
public static void DoParallel<T>(this IEnumerable<T> source, Action<T> action)
public static void DoParallel<T>(this IEnumerable<T> source, Action<T> action, bool noParallel)
{
#if DEBUG && NO_PARALLEL
foreach (var item in source)
{
action(item);
}
#else
(source as ParallelQuery<T> ?? source.AsParallel()).ForAll(action);
noParallel = true;
#endif
if (noParallel)
{
foreach (var item in source)
{
action(item);
}
}
else
{
(source as ParallelQuery<T> ?? source.AsParallel()).ForAll(action);
}
}
/// <summary>
@@ -236,15 +243,17 @@ namespace GitTfs.Core
/// <param name="retryInterval">
/// The delay between retries.
/// </param>
/// <param name="parallel">set to true to disable parallel processing</param>
/// <typeparam name="T">The type of items in the <paramref name="source"/>.</typeparam>
/// <returns>
/// Returns <b>true</b> when all items processed successfully.</returns>
public static void DoParallelRetry<T>(
this IEnumerable<T> source,
Action<T> action,
TimeSpan retryInterval)
TimeSpan retryInterval,
bool noParallel)
{
DoParallelRetry(source, action, 10, retryInterval);
DoParallelRetry(source, action, 10, retryInterval, noParallel);
}
/// <summary>
@@ -256,12 +265,13 @@ namespace GitTfs.Core
/// <param name="action">
/// The action to process of the item.
/// </param>
/// <param name="noParallel">set to true to disable parallel processing</param>
/// <typeparam name="T">The type of items in the <paramref name="source"/>.</typeparam>
/// <returns>
/// Returns <b>true</b> when all items processed successfully.</returns>
public static void DoParallelRetry<T>(this IEnumerable<T> source, Action<T> action)
public static void DoParallelRetry<T>(this IEnumerable<T> source, Action<T> action, bool noParallel)
{
DoParallelRetry(source, action, 10, TimeSpan.FromSeconds(1));
DoParallelRetry(source, action, 10, TimeSpan.FromSeconds(1), noParallel);
}
/// <summary>
@@ -276,12 +286,13 @@ namespace GitTfs.Core
/// <param name="retryCount">
/// TThe number of retries.
/// </param>
/// <param name="noParallel">set to true to disable parallel processing</param>
/// <typeparam name="T">The type of items in the <paramref name="source"/>.</typeparam>
/// <returns>
/// Returns <b>true</b> when all items processed successfully.</returns>
public static void DoParallelRetry<T>(this IEnumerable<T> source, Action<T> action, int retryCount)
public static void DoParallelRetry<T>(this IEnumerable<T> source, Action<T> action, int retryCount, bool noParallel)
{
DoParallelRetry(source, action, retryCount, TimeSpan.FromSeconds(1));
DoParallelRetry(source, action, retryCount, TimeSpan.FromSeconds(1), noParallel);
}
/// <summary>
@@ -299,10 +310,11 @@ namespace GitTfs.Core
/// <param name="retryInterval">
/// The delay between retries.
/// </param>
/// <param name="noParallel">set to true to disable parallel processing</param>
/// <typeparam name="T">The type of items in the <paramref name="source"/>.</typeparam>
/// <returns>
/// Returns <b>true</b> when all items processed successfully.</returns>
public static void DoParallelRetry<T>(this IEnumerable<T> source, Action<T> action, int retryCount, TimeSpan retryInterval)
public static void DoParallelRetry<T>(this IEnumerable<T> source, Action<T> action, int retryCount, TimeSpan retryInterval, bool noParallel)
{
var fails = new ConcurrentBag<Exception>();
@@ -340,7 +352,7 @@ namespace GitTfs.Core
{
fails.Add(new AggregateException(exceptions));
}
});
}, noParallel);
if (fails.Count > 0)
{
+5 -2
View File
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using LibGit2Sharp;
using System.Collections.Generic;
using System.Linq;
using LibGit2Sharp;
namespace GitTfs.Core
{
@@ -35,6 +35,8 @@ namespace GitTfs.Core
remote.Aliases = entry.Value.Split(',');
else if (key == "autotag")
remote.Autotag = bool.Parse(entry.Value);
else if (key == "noparallel")
remote.NoParallel = bool.Parse(entry.Value);
}
}
return remotes.Values.Where(r => !string.IsNullOrWhiteSpace(r.Url));
@@ -53,6 +55,7 @@ namespace GitTfs.Core
yield return c(prefix + "ignore-except", remote.IgnoreExceptRegex);
yield return c(prefix + "legacy-urls", remote.Aliases == null ? null : string.Join(",", remote.Aliases));
yield return c(prefix + "autotag", remote.Autotag ? "true" : null);
yield return c(prefix + "noparallel", remote.NoParallel ? "true" : null);
}
}
+5 -4
View File
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using GitTfs.Commands;
using GitTfs.Commands;
using System.Collections.Generic;
namespace GitTfs.Core
{
@@ -14,11 +14,12 @@ namespace GitTfs.Core
public string IgnoreExceptRegex { get; set; }
public IEnumerable<string> Aliases { get; set; }
public bool Autotag { get; set; }
public bool NoParallel { get; set; }
public RemoteOptions RemoteOptions
{
get { return new RemoteOptions { IgnoreRegex = IgnoreRegex, ExceptRegex = IgnoreExceptRegex, Username = Username, Password = Password }; }
set { IgnoreRegex = value.IgnoreRegex; IgnoreExceptRegex = value.ExceptRegex; Username = value.Username; Password = value.Password; }
get { return new RemoteOptions { IgnoreRegex = IgnoreRegex, ExceptRegex = IgnoreExceptRegex, Username = Username, Password = Password, NoParallel = NoParallel }; }
set { IgnoreRegex = value.IgnoreRegex; IgnoreExceptRegex = value.ExceptRegex; Username = value.Username; Password = value.Password; NoParallel = value.NoParallel; }
}
}
}
+3 -3
View File
@@ -14,9 +14,9 @@ namespace GitTfs.Core.TfsInterop
int PendRename(string pathFrom, string pathTo);
void ForceGetFile(string path, int changeset);
void GetSpecificVersion(int changeset);
void GetSpecificVersion(int changeset, IEnumerable<IItem> items);
void GetSpecificVersion(IChangeset changeset);
void GetSpecificVersion(int changeset, IEnumerable<IChange> changes);
void GetSpecificVersion(int changeset, IEnumerable<IItem> items, bool noParallel);
void GetSpecificVersion(IChangeset changeset, bool noParallel);
void GetSpecificVersion(int changeset, IEnumerable<IChange> changes, bool noParallel);
string GetLocalItemForServerItem(string serverItem);
string GetServerItemForLocalItem(string localItem);
string OwnerName { get; }
+6 -6
View File
@@ -1,11 +1,11 @@
using GitTfs.Commands;
using GitTfs.Core.TfsInterop;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using GitTfs.Commands;
using GitTfs.Core.TfsInterop;
using System.Diagnostics;
namespace GitTfs.Core
{
@@ -237,19 +237,19 @@ namespace GitTfs.Core
public void Get(int changesetId, IEnumerable<IItem> items)
{
_workspace.GetSpecificVersion(changesetId, items);
_workspace.GetSpecificVersion(changesetId, items, Remote.RemoteInfo.NoParallel);
}
public void Get(IChangeset changeset)
{
_workspace.GetSpecificVersion(changeset);
_workspace.GetSpecificVersion(changeset, Remote.RemoteInfo.NoParallel);
}
public void Get(int changesetId, IEnumerable<IChange> changes)
{
if (changes.Any())
{
_workspace.GetSpecificVersion(changesetId, changes);
_workspace.GetSpecificVersion(changesetId, changes, Remote.RemoteInfo.NoParallel);
}
}
@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;
using GitTfs.Commands;
using GitTfs.Core;
using LibGit2Sharp;
using GitTfs.Commands;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace GitTfs.Test.Core
{
@@ -39,6 +39,7 @@ namespace GitTfs.Test.Core
AssertContainsConfig("tfs-remote.default.ignore-paths", null, config);
AssertContainsConfig("tfs-remote.default.legacy-urls", null, config);
AssertContainsConfig("tfs-remote.default.autotag", null, config);
AssertContainsConfig("tfs-remote.default.noparallel", null, config);
}
[Fact]
@@ -55,6 +56,7 @@ namespace GitTfs.Test.Core
IgnoreExceptRegex = "def",
Autotag = true,
Aliases = new string[] { "http://abc", "http://def" },
NoParallel = true,
};
var config = _dumper.Dump(remote);
AssertContainsConfig("tfs-remote.default.url", "http://server/path", config);
@@ -65,6 +67,7 @@ namespace GitTfs.Test.Core
AssertContainsConfig("tfs-remote.default.ignore-except", "def", config);
AssertContainsConfig("tfs-remote.default.legacy-urls", "http://abc,http://def", config);
AssertContainsConfig("tfs-remote.default.autotag", "true", config);
AssertContainsConfig("tfs-remote.default.noparallel", "true", config);
}
/// <summary>
@@ -83,7 +86,8 @@ namespace GitTfs.Test.Core
Username = "user",
Password = "pass",
IgnoreRegex = "abc",
ExceptRegex = "def"
ExceptRegex = "def",
NoParallel = true
},
Autotag = true,
Aliases = new[] { "http://abc", "http://def" },
@@ -97,6 +101,7 @@ namespace GitTfs.Test.Core
AssertContainsConfig("tfs-remote.default.ignore-except", "def", config);
AssertContainsConfig("tfs-remote.default.legacy-urls", "http://abc,http://def", config);
AssertContainsConfig("tfs-remote.default.autotag", "true", config);
AssertContainsConfig("tfs-remote.default.noparallel", "true", config);
}
/// <summary>
@@ -116,6 +121,7 @@ namespace GitTfs.Test.Core
IgnoreExceptRegex = "def",
Autotag = true,
Aliases = new[] { "http://abc", "http://def" },
NoParallel = true
};
var remoteOptions = remote.RemoteOptions;
@@ -123,6 +129,7 @@ namespace GitTfs.Test.Core
Assert.Equal("pass", remoteOptions.Password);
Assert.Equal("abc", remoteOptions.IgnoreRegex);
Assert.Equal("def", remoteOptions.ExceptRegex);
Assert.True(remoteOptions.NoParallel);
}
private void AssertContainsConfig(string key, string value, IEnumerable<KeyValuePair<string, string>> configs)
@@ -183,7 +190,8 @@ namespace GitTfs.Test.Core
c("tfs-remote.default.ignore-paths", "ignorethis.zip"),
c("tfs-remote.default.ignore-except", "dontignorethis.zip"),
c("tfs-remote.default.legacy-urls", "http://old:8080/,http://other/"),
c("tfs-remote.default.autotag", "true"));
c("tfs-remote.default.autotag", "true"),
c("tfs-remote.default.noparallel", "true"));
Assert.Single(remotes);
var remote = remotes.First();
Assert.Equal("default", remote.Id);
@@ -195,6 +203,7 @@ namespace GitTfs.Test.Core
Assert.Equal("dontignorethis.zip", remote.IgnoreExceptRegex);
Assert.Equal(new string[] { "http://old:8080/", "http://other/" }, remote.Aliases);
Assert.True(remote.Autotag);
Assert.True(remote.NoParallel);
}
+9
View File
@@ -45,5 +45,14 @@ namespace GitTfs.Test.Integration
h.AssertRef("MyProject", "refs/remotes/tfs/default", expectedSha);
h.AssertRef("MyProject", "refs/tags/tfs/default/C1", expectedSha);
}
[FactExceptOnUnix]
public void InitializesConfigUsingNoParallel()
{
h.SetupFake(r => { });
h.Run("init", "http://my-tfs.local/tfs", "$/MyProject", "MyProject", "--no-parallel");
h.AssertConfig("MyProject", "tfs-remote.default.noparallel", "true");
}
}
}