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

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

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().HasFlag(SubmoduleStatus.WorkDirUninitialized));
210+
211+
bool checkoutProgressCalled = false;
212+
bool 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+
10000 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 < 5609 span class="pl-kos">{ 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