8000 Merge pull request #840 from libgit2/jamill/submodule_update · GiTechLab/libgit2sharp@d8a1f64 · GitHub
[go: up one dir, main page]

Skip to content

Commit d8a1f64

Browse files
committed
Merge pull request libgit2#840 from libgit2/jamill/submodule_update
Introduce Submodule Init and Update
2 parents 5de56d4 + 854857b commit d8a1f64

24 files changed

+402
-14
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "submodule_target_wd"]
2+
path = submodule_target_wd
3+
url = ../submodule_target_wd
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ref: refs/heads/master
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[core]
2+
repositoryformatversion = 0
3+
filemode = false
4+
bare = false
5+
logallrefupdates = true
6+
symlinks = false
7+
ignorecase = true
8+
hideDotFiles = dotGitOnly
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Unnamed repository; edit this file 'description' to name the repository.
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# git ls-files --others --exclude-from=.git/info/exclude
2+
# Lines that start with '#' are comments.
3+
# For a project mostly in C, the following would be a good set of
4+
# exclude patterns (uncomment them if you want to use them):
5+
# *.[oa]
6+
# *~
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
31be1072bafa80f8b4386eb35b90e284d9ee672d
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7d3aeaa887efe60fb664ba92a203a4fb50249f5b

LibGit2Sharp.Tests/SubmoduleFixture.cs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,163 @@ public void CanStageChangeInSubmoduleViaIndexStageWithOtherPaths(string submodul
151151
Assert.Equal(SubmoduleStatus.IndexModified, statusAfter & SubmoduleStatus.IndexModified);
152152
}
153153
}
154+
155+
[Fact]
156+
public void CanInitSubmodule()
157+
{
158+
var path = SandboxSubmoduleSmallTestRepo();
159+
string submoduleName = "submodule_target_wd";
160+
string expectedSubmodulePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), submoduleName));
161+
string expectedSubmoduleUrl = expectedSubmodulePath.Replace('\\', '/');
162+
163+
using (var repo = new Repository(path))
164+
{
165+
var submodule = repo.Submodules[submoduleName];
166+
167+
Assert.NotNull(submodule);
168+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized));
169+
170+
var configEntryBeforeInit = repo.Config.Get<string>(string.Format("submodule.{0}.url", submoduleName));
171+
Assert.Null(configEntryBeforeInit);
172+
173+
repo.Submodules.Init(submodule.Name, false);
174+
175+
var configEntryAfterInit = repo.Config.Get<string>(string.Format("submodule.{0}.url", submoduleName));
176+
Assert.NotNull(configEntryAfterInit);
177+
Assert.Equal(expectedSubmoduleUrl, configEntryAfterInit.Value);
178+
}
179+
}
180+
181+
[Fact]
182+
public void UpdatingUninitializedSubmoduleThrows()
183+
{
184+
var path = SandboxSubmoduleSmallTestRepo();
185+
string submoduleName = "submodule_target_wd";
186+
187+
using (var repo = new Repository(path))
188+
{
189+
var submodule = repo.Submodules[submoduleName];
190+
191+
Assert.NotNull(submodule);
192+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized));
193+
194+
Assert.Throws<LibGit2SharpException>(() => repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions()));
195+
}
196+
}
197+
198+
[Fact]
199+
public void CanUpdateSubmodule()
200+
{
201+
var path = SandboxSubmoduleSmallTestRepo();
202+
string submoduleName = "submodule_target_wd";
203+
204+
using (var repo = new Repository(path))
205+
{
206+
var submodule = repo.Submodules[submoduleName];
207+
208+
Assert.NotNull(submodule);
209+
Assert.True(submodule.RetrieveStatus() 1241 .HasFlag(SubmoduleStatus.WorkDirUninitialized));
210+
211+
bool checkoutProgressCalled = false;
212+
bool< F438 /span> checkoutNotifyCalled = false;
213+
bool updateTipsCalled = false;
214+
var options = new SubmoduleUpdateOptions()
215+
{
216+
OnCheckoutProgress = (x, y, z) => checkoutProgressCalled = true,
217+
OnCheckoutNotify = (x, y) => { checkoutNotifyCalled = true; return true; },
218+
CheckoutNotifyFlags = CheckoutNotifyFlags.Updated,
219+
OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; },
220+
};
221+
222+
repo.Submodules.Init(submodule.Name, false);
223+
repo.Submodules.Update(submodule.Name, options);
224+
225+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir));
226+
Assert.True(checkoutProgressCalled);
227+
Assert.True(checkoutNotifyCalled);
228+
Assert.True(updateTipsCalled);
229+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.HeadCommitId);
230+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.IndexCommitId);
231+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.WorkDirCommitId);
232+
}
233+
}
234+
235+
[Fact]
236+
public void CanInitializeAndUpdateSubmodule()
237+
{
238+
var path = SandboxSubmoduleSmallTestRepo();
239+
string submoduleName = "submodule_target_wd";
240+
241+
using (var repo = new Repository(path))
242+
{
243+
var submodule = repo.Submodules[submoduleName];
244+
245+
Assert.NotNull(submodule);
246+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized));
247+
248+
repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions() { Init = true });
249+
250+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir));
251+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.HeadCommitId);
252+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.IndexCommitId);
253+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.WorkDirCommitId);
254+
}
255+
}
256+
257+
[Fact]
258+
public void CanUpdateSubmoduleAfterCheckout()
259+
{
260+
var path = SandboxSubmoduleSmallTestRepo();
261+
string submoduleName = "submodule_target_wd";
262+
263+
using (var repo = new Repository(path))
264+
{
265+
var submodule = repo.Submodules[submoduleName];
266+
267+
Assert.NotNull(submodule);
268+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized));
269+
270+
repo.Submodules.Init(submodule.Name, false);
271+
repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions());
272+
273+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir));
274+
275+
repo.Checkout("alternate");
276+
Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirModified));
277+
278+
submodule = repo.Submodules[submoduleName];
279+
280+
Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.HeadCommitId);
281+
Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.IndexCommitId);
282+
Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.WorkDirCommitId);
283+
284+
repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions());
285+
submodule = repo.Submodules[submoduleName];
286+
287+
Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.HeadCommitId);
288+
Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.IndexCommitId);
289+
Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.WorkDirCommitId);
290+
}
291+
}
292+
293+
[Fact]
294+
public void CanReadSubmoduleProperties()
295+
{
296+
var path = SandboxSubmoduleSmallTestRepo();
297+
string submoduleName = "submodule_target_wd";
298+
299+
using (var repo = new Repository(path))
300+
{
301+
var submodule = repo.Submodules[submoduleName];
302+
303+
Assert.Equal(SubmoduleUpdate.Checkout, submodule.UpdateRule);
304+
Assert.Equal(SubmoduleIgnore.None, submodule.IgnoreRule);
305+
306+
// Libgit2 currently returns No by default, which seems incorrect -
307+
// I would expect OnDemand. For now, just test that we can query
308+
// lg2 for this property.
309+
Assert.Equal(SubmoduleRecurse.No, submodule.FetchRecurseSubmodulesRule);
310+
}
311+
}
154312
}
155313
}

LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static BaseFixture()
4040
public static string SubmoduleTestRepoWorkingDirPath { get; private set; }
4141
private static string SubmoduleTargetTestRepoWorkingDirPath { get; set; }
4242
private static string AssumeUnchangedRepoWorkingDirPath { get; set; }
43+
private static string SubmoduleSmallTestRepoWorkingDirPath { get; set; }
44+
4345
public static DirectoryInfo ResourcesDirectory { get; private set; }
4446

4547
public static bool IsFileSystemCaseSensitive { get; private set; }
@@ -69,6 +71,7 @@ private static void SetUpTestEnvironment()
6971
SubmoduleTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_wd");
7072
SubmoduleTargetTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_target_wd");
7173
AssumeUnchangedRepoWorkingDirPath = Path.Combine(sourceRelativePath, "assume_unchanged_wd");
74+
SubmoduleSmallTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_small_wd");
7275
}
7376

7477
private static bool IsFileSystemCaseSensitiveInternal()
@@ -153,6 +156,15 @@ public string SandboxAssumeUnchangedTestRepo()
153156
{
154157
return Sandbox(AssumeUnchangedRepoWorkingDirPath);
155158
}
159+
160+
public string SandboxSubmoduleSmallTestRepo()
161+
{
162+
var submoduleTarget = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd");
163+
var path = Sandbox(SubmoduleSmallTestRepoWorkingDirPath, submoduleTarget);
164+
Directory.CreateDirectory(Path.Combine(path, "submodule_target_wd"));
165+
166+
return path;
167+
}
156168

157169
protected string Sandbox(string sourceDirectoryPath, params string[] additionalSourcePaths)
158170
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace LibGit2Sharp.Core
5+
{
6+
[StructLayout(LayoutKind.Sequential)]
7+
internal struct GitSubmoduleOptions
8+
{
9+
public uint Version;
10+
11+
public GitCheckoutOpts CheckoutOptions;
12+
13+
public GitRemoteCallbacks RemoteCallbacks;
14+
15+
public CheckoutStrategy CloneCheckoutStrategy;
16+
17+
public IntPtr Signature;
18+
}
19+
}

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,12 @@ internal static extern int git_submodule_lookup(
13361336
RepositorySafeHandle repo,
13371337
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath name);
13381338

1339+
[DllImport(libgit2)]
1340+
internal static extern int git_submodule_update(
1341+
SubmoduleSafeHandle sm,
1342+
[MarshalAs(UnmanagedType.Bool)] bool init,
1343+
ref GitSubmoduleOptions submoduleUpdateOptions);
1344+
13391345
internal delegate int submodule_callback(
13401346
IntPtr sm,
13411347
IntPtr name,
@@ -1387,11 +1393,11 @@ internal static extern SubmoduleIgnore git_submodule_ignore(
13871393
SubmoduleSafeHandle submodule);
13881394

13891395
[DllImport(libgit2)]
1390-
internal static extern SubmoduleUpdate git_submodule_update(
1396+
internal static extern SubmoduleUpdate git_submodule_update_strategy(
13911397
SubmoduleSafeHandle submodule);
13921398

13931399
[DllImport(libgit2)]
1394-
internal static extern bool git_submodule_fetch_recurse_submodules(
1400+
internal static extern SubmoduleRecurse git_submodule_fetch_recurse_submodules(
13951401
SubmoduleSafeHandle submodule);
13961402

13971403
[DllImport(libgit2)]
@@ -1404,6 +1410,11 @@ internal static extern int git_submodule_status(
14041410
out SubmoduleStatus status,
14051411
SubmoduleSafeHandle submodule);
14061412

1413+
[DllImport(libgit2)]
1414+
internal static extern int git_submodule_init(
1415+
SubmoduleSafeHandle submodule,
1416+
[MarshalAs(UnmanagedType.Bool)] bool overwrite);
1417+
14071418
[DllImport(libgit2)]
14081419
internal static extern int git_tag_annotation_create(
14091420
out GitOid oid,

LibGit2Sharp/Core/Proxy.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,6 +2715,15 @@ public static void git_submodule_save(SubmoduleSafeHandle submodule)
27152715
}
27162716
}
27172717

2718+
public static void git_submodule_update(SubmoduleSafeHandle submodule, bool init, ref GitSubmoduleOptions options)
2719+
{
2720+
using (ThreadAffinity())
2721+
{
2722+
var res = NativeMethods.git_submodule_update(submodule, init, ref options);
2723+
Ensure.ZeroResult(res);
2724+
}
2725+
}
2726+
27182727
public static void git_submodule_free(IntPtr submodule)
27192728
{
27202729
NativeMethods.git_submodule_free(submodule);
@@ -2750,12 +2759,12 @@ public static SubmoduleIgnore git_submodule_ignore(SubmoduleSafeHandle submodule
27502759
return NativeMethods.git_submodule_ignore(submodule);
27512760
}
27522761

2753-
public static SubmoduleUpdate git_submodule_update(SubmoduleSafeHandle submodule)
2762+
public static SubmoduleUpdate git_submodule_update_strategy(SubmoduleSafeHandle submodule)
27542763
{
2755-
return NativeMethods.git_submodule_update(submodule);
2764+
return NativeMethods.git_submodule_update_strategy(submodule);
27562765
}
27572766

2758-
public static bool git_submodule_fetch_recurse_submodules(SubmoduleSafeHandle submodule)
2767+
public static SubmoduleRecurse git_submodule_fetch_recurse_submodules(SubmoduleSafeHandle submodule)
27592768
{
27602769
return NativeMethods.git_submodule_fetch_recurse_submodules(submodule);
27612770
}
@@ -2780,6 +2789,15 @@ public static SubmoduleStatus git_submodule_status(SubmoduleSafeHandle submodule
27802789
}
27812790
}
27822791

2792+
public static void git_submodule_init(SubmoduleSafeHandle submodule, bool overwrite)
2793+
{
2794+
using (ThreadAffinity())
2795+
{
2796+
var res = NativeMethods.git_submodule_init(submodule, overwrite);
2797+
Ensure.ZeroResult(res);
2798+
}
2799+
}
2800+
27832801
#endregion
27842802

27852803
#region git_tag_

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
<Compile Include="CommitSortStrategies.cs" />
7070
<Compile Include="CompareOptions.cs" />
7171
<Compile Include="Core\GitIndexReucEntry.cs" />
72+
<Compile Include="Core\GitSubmoduleOptions.cs" />
7273
<Compile Include="Core\Handles\IndexNameEntrySafeHandle.cs" />
7374
<Compile Include="Core\Handles\IndexReucEntrySafeHandle.cs" />
7475
<Compile Include="EntryExistsException.cs" />
@@ -133,6 +134,8 @@
133134
<Compile Include="Log.cs" />
134135
<Compile Include="LogConfiguration.cs" />
135136
<Compile Include="LogLevel.cs" />
137+
<Compile Include="SubmoduleRecurse.cs" />
138+
<Compile Include="SubmoduleUpdateOptions.cs" />
136139
<Compile Include="UnbornBranchException.cs" />
137140
<Compile Include="LockedFileException.cs" />
138141
<Compile Include="Core\GitRepositoryInitOptions.cs" />

LibGit2Sharp/Submodule.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class Submodule : IEquatable<Submodule>, IBelongToARepository
2121
private readonly ILazy<ObjectId> headCommitId;
2222
private readonly ILazy<ObjectId> indexCommitId;
2323
private readonly ILazy<ObjectId> workdirCommitId;
24-
private readonly ILazy<bool> fetchRecurseSubmodulesRule;
24+
private readonly ILazy<SubmoduleRecurse> fetchRecurseSubmodulesRule;
2525
private readonly ILazy<SubmoduleIgnore> ignoreRule;
2626
private readonly ILazy<SubmoduleUpdate> updateRule;
2727

@@ -46,7 +46,7 @@ internal Submodule(Repository repo, string name, string path, string url)
4646
var rules = new SubmoduleLazyGroup(repo, name);
4747
fetchRecurseSubmodulesRule = rules.AddLazy(Proxy.git_submodule_fetch_recurse_submodules);
4848
ignoreRule = rules.AddLazy(Proxy.git_submodule_ignore);
49-
updateRule = rules.AddLazy(Proxy.git_submodule_update);
49+
updateRule = rules.AddLazy(Proxy.git_submodule_update_strategy);
5050
}
5151

5252
/// <summary>
@@ -85,7 +85,7 @@ internal Submodule(Repository repo, string name, string path, string url)
8585
/// Note that at this time, LibGit2Sharp does not honor this setting and the
8686
/// fetch functionality current ignores submodules.
8787
/// </summary>
88-
public virtual bool FetchRecurseSubmodulesRule { get { return fetchRecurseSubmodulesRule.Value; } }
88+
public virtual SubmoduleRecurse FetchRecurseSubmodulesRule { get { return fetchRecurseSubmodulesRule.Value; } }
8989

9090
/// <summary>
9191
/// The ignore rule of the submodule.

0 commit comments

Comments
 (0)
0