Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 258776a

Browse files
Merge pull request #130 from github-for-unity/fixes/break-up-git-add
Fix to handle large git add operations
2 parents fd2a568 + b8e6420 commit 258776a

File tree

8 files changed

+126
-18
lines changed

8 files changed

+126
-18
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace GitHub.Unity
6+
{
7+
public static class ListExtensions
8+
{
9+
public static string Join<T>(this IEnumerable<T> list, string separator)
10+
{
11+
if (list == null)
12+
return null;
13+
return String.Join(separator, list.Select(x => x?.ToString()).ToArray());
14+
}
15+
16+
public static IEnumerable<IList<string>> Spool<T>(this IEnumerable<T> items, int spoolLength)
17+
{
18+
var currentSpoolLength = 0;
19+
var currentList= new List<string>();
20+
21+
foreach (var item in items)
22+
{
23+
var itemValue = item.ToString();
24+
var itemValueLength = itemValue.Length;
25+
26+
if (currentSpoolLength + itemValueLength > spoolLength)
27+
{
28+
yield return currentList;
29+
30+
currentSpoolLength = 0;
31+
currentList = new List<string>();
32+
}
33+
34+
currentSpoolLength += itemValueLength;
35+
currentList.Add(itemValue);
36+
}
37+
38+
if (currentList.Any())
39+
{
40+
yield return currentList;
41+
}
42+
}
43+
}
44+
}

src/GitHub.Api/Extensions/StringExtensions.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,6 @@ public static string LeftBeforeLast(this string s, char search)
151151
}
152152
}
153153

154-
public static class ListExtensions
155-
{
156-
public static string Join<T>(this IEnumerable<T> list, string separator)
157-
{
158-
if (list == null)
159-
return null;
160-
return String.Join(separator, list.Select(x => x?.ToString()).ToArray());
161-
}
162-
}
163-
164154
public struct StringResult
165155
{
166156
public string Chunk;

src/GitHub.Api/Git/GitClient.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ ITask<string> Commit(string message, string body,
6262
ITask<string> Add(IList<string> files,
6363
IOutputProcessor<string> processor = null);
6464

65+
ITask<string> AddAll(IOutputProcessor<string> processor = null);
66+
6567
ITask<string> Remove(IList<string> files,
6668
IOutputProcessor<string> processor = null);
6769

@@ -296,13 +298,35 @@ public ITask<string> Commit(string message, string body,
296298
.Configure(processManager);
297299
}
298300

301+
public ITask<string> AddAll(IOutputProcessor<string> processor = null)
302+
{
303+
Logger.Trace("Add all files");
304+
305+
return new GitAddTask(cancellationToken, processor)
306+
.Configure(processManager);
307+
}
308+
299309
public ITask<string> Add(IList<string> files,
300310
IOutputProcessor<string> processor = null)
301311
{
302-
Logger.Trace("Add");
312+
Logger.Trace("Add Files");
303313

304-
return new GitAddTask(files, cancellationToken, processor)
305-
.Configure(processManager);
314+
GitAddTask last = null;
315+
foreach (var batch in files.Spool(5000))
316+
{
317+
var current = new GitAddTask(batch, cancellationToken, processor).Configure(processManager);
318+
if (last == null)
319+
{
320+
last = current;
321+
}
322+
else
323+
{
324+
last.Then(current);
325+
last = current;
326+
}
327+
}
328+
329+
return last;
306330
}
307331

308332
public ITask<string> Remove(IList<string> files,

src/GitHub.Api/Git/Tasks/GitAddTask.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Threading;
34

@@ -8,9 +9,8 @@ class GitAddTask : ProcessTask<string>
89
private const string TaskName = "git add";
910
private readonly string arguments;
1011

11-
public GitAddTask(IEnumerable<string> files,
12-
CancellationToken token, IOutputProcessor<string> processor = null)
13-
: base(token, processor ?? new SimpleOutputProcessor())
12+
public GitAddTask(IEnumerable<string> files, CancellationToken token,
13+
IOutputProcessor<string> processor = null) : base(token, processor ?? new SimpleOutputProcessor())
1414
{
1515
Guard.ArgumentNotNull(files, "files");
1616
Name = TaskName;
@@ -24,6 +24,12 @@ public GitAddTask(IEnumerable<string> files,
2424
}
2525
}
2626

27+
public GitAddTask(CancellationToken token,
28+
IOutputProcessor<string> processor = null) : base(token, processor ?? new SimpleOutputProcessor())
29+
{
30+
arguments = "add -A";
31+
}
32+
2733
public override string ProcessArguments { get { return arguments; } }
2834
public override TaskAffinity Affinity { get { return TaskAffinity.Exclusive; } }
2935
}

src/GitHub.Api/GitHub.Api.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
<Compile Include="Application\ApplicationInfo.cs" />
9797
<Compile Include="Application\LoginResult.cs" />
9898
<Compile Include="Application\AppConfiguration.cs" />
99+
<Compile Include="Extensions\ListExtensions.cs" />
99100
<Compile Include="Helpers\AssemblyResources.cs" />
100101
<Compile Include="Authentication\IKeychain.cs" />
101102
<Compile Include="Authentication\Keychain.cs" />

src/UnityExtension/Assets/Editor/GitHub.Unity/UI/ChangesView.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,23 @@ private void Commit()
189189
// Do not allow new commits before we have received one successful update
190190
busy = true;
191191

192-
var files = Enumerable.Range(0, tree.Entries.Count).Where(i => tree.CommitTargets[i].All).Select(i => tree.Entries[i].Path).ToArray();
192+
var files = Enumerable.Range(0, tree.Entries.Count)
193+
.Where(i => tree.CommitTargets[i].All)
194+
.Select(i => tree.Entries[i].Path)
195+
.ToArray();
193196

194-
GitClient.Add(files)
197+
ITask<string> addTask;
198+
199+
if (files.Length == tree.Entries.Count)
200+
{
201+
addTask = GitClient.AddAll();
202+
}
203+
else
204+
{
205+
addTask = GitClient.Add(files);
206+
}
207+
208+
addTask
195209
.Then(GitClient.Commit(commitMessage, commitBody))
196210
.Then(GitClient.Status())
197211
.FinallyInUI((b, exception) =>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Linq;
2+
using FluentAssertions;
3+
using GitHub.Unity;
4+
using NUnit.Framework;
5+
6+
namespace UnitTests
7+
{
8+
[TestFixture]
9+
public class ListExtensionTests
10+
{
11+
[Test]
12+
public void SpoolTest()
13+
{
14+
var results = new[] { "qwer", "asdf", "zxcv", "wert", "1234" }.Spool(10).ToArray();
15+
results.Length.Should().Be(3);
16+
results[0].Count.Should().Be(2);
17+
results[0][0].Should().Be("qwer");
18+
results[0][1].Should().Be("asdf");
19+
20+
results[1].Count.Should().Be(2);
21+
results[1][0].Should().Be("zxcv");
22+
results[1][1].Should().Be("wert");
23+
24+
results[2].Count.Should().Be(1);
25+
results[2][0].Should().Be("1234");
26+
}
27+
}
28+
}

src/tests/UnitTests/UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
</ItemGroup>
8282
<ItemGroup>
8383
<Compile Include="Authentication\KeychainTests.cs" />
84+
<Compile Include="Extensions\ListExtensionTests.cs" />
8485
<Compile Include="Git\ValidationTests.cs" />
8586
<Compile Include="Git\GitConfigTests.cs" />
8687
<Compile Include="IO\BranchListOutputProcessorTests.cs" />

0 commit comments

Comments
 (0)