Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[File Explorer Integration] Git submodule status and commit log inside submodule #3745

Merged
merged 16 commits into from
Sep 7, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,13 @@
<ItemGroup>
<ProjectReference Include="..\FileExplorerGitIntegration\FileExplorerGitIntegration.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="resources\**\*.*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<None Remove="resources\resources_readme.txt" />
</ItemGroup>
<ItemGroup>
<Content Include="SandboxHelper.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using FileExplorerGitIntegration.Models;

namespace FileExplorerGitIntegration.UnitTest;

[TestClass]
public class GitSubmoduleUnitTests
{
private const string FolderStatusProp = "System.VersionControl.CurrentFolderStatus";
private const string StatusProp = "System.VersionControl.Status";
private const string ShaProp = "System.VersionControl.LastChangeID";

private static SandboxHelper? _sandbox;
private static GitLocalRepository? _repo;

[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
_sandbox = new();
var repoPath = _sandbox.CreateSandbox("submodules");
_sandbox.CreateSandbox("submodules_target");
_repo = new GitLocalRepository(repoPath);
}

[ClassCleanup]
public static void ClassCleanup()
{
if (_sandbox is not null)
{
_sandbox.Cleanup();
_sandbox = null;
}

_repo = null;
}

[TestMethod]
[DataRow("", FolderStatusProp, "Branch: main | +1 ~1 -0 | +0 ~7 -0")]
[DataRow(".gitmodules", StatusProp, "Staged, Modified")]
[DataRow("README.txt", StatusProp, "")]
[DataRow("sm_added_and_uncommitted", StatusProp, "Submodule Added")]
[DataRow("sm_changed_file", StatusProp, "Submodule Dirty")]
[DataRow("sm_changed_head", StatusProp, "Submodule Changed")]
[DataRow("sm_changed_index", StatusProp, "Submodule Dirty")]
[DataRow("sm_changed_untracked_file", StatusProp, "Submodule Dirty")]
[DataRow("sm_missing_commits", StatusProp, "Submodule Changed")]
[DataRow("sm_missing_commits_detached", StatusProp, "Submodule Changed")]
[DataRow("sm_unchanged", StatusProp, "")]
[DataRow("sm_unchanged_detached", StatusProp, "")]
public void RootFolderStatus(string path, string property, string value)
{
Assert.IsNotNull(_repo);
var result = _repo.GetProperties([property], path);
Assert.IsNotNull(result);
Assert.AreEqual(value, result[property]);
}

[TestMethod]
[DataRow("", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow(".gitmodules", ShaProp, "d8ebdc0b3c1d5240d4fc1c4cd3728ff561e714ad")]
[DataRow("README.txt", ShaProp, "74b157c3bfd2f24323c3bc6e5e96639a424f157f")]
[DataRow("sm_added_and_uncommitted", ShaProp, "")]
[DataRow("sm_changed_file", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_changed_head", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_changed_index", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_changed_untracked_file", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_missing_commits", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_missing_commits_detached", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_unchanged", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
[DataRow("sm_unchanged_detached", ShaProp, "8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940")]
public void RootFolderCommit(string path, string property, string value)
{
Assert.IsNotNull(_repo);
var result = _repo.GetProperties([property], path);
Assert.IsNotNull(result);
if (result.TryGetValue(property, out var actual))
{
Assert.AreEqual(value, actual);
}
else
{
Assert.AreEqual(value, string.Empty);
}
}

[TestMethod]
[DataRow("sm_added_and_uncommitted\\file_to_modify", ShaProp, "e9a899083a7e2b25d7a41e69463ce083bf9ef6ef")]
[DataRow("sm_changed_file\\file_to_modify", ShaProp, "e9a899083a7e2b25d7a41e69463ce083bf9ef6ef")]
[DataRow("sm_changed_head\\file_to_modify", ShaProp, "2ab664114c928551863c33d694965c79b6b75144")]
[DataRow("sm_changed_index\\file_to_modify", ShaProp, "e9a899083a7e2b25d7a41e69463ce083bf9ef6ef")]
[DataRow("sm_changed_untracked_file\\file_to_modify", ShaProp, "e9a899083a7e2b25d7a41e69463ce083bf9ef6ef")]
[DataRow("sm_missing_commits\\file_to_modify", ShaProp, "8e623bcf5aeceb8af7c0f0b22b82322f6c82fd4b")]
[DataRow("sm_missing_commits_detached\\file_to_modify", ShaProp, "8e623bcf5aeceb8af7c0f0b22b82322f6c82fd4b")]
[DataRow("sm_unchanged\\file_to_modify", ShaProp, "e9a899083a7e2b25d7a41e69463ce083bf9ef6ef")]
[DataRow("sm_unchanged_detached\\file_to_modify", ShaProp, "e9a899083a7e2b25d7a41e69463ce083bf9ef6ef")]
public void SubmoduleFilesCommit(string path, string property, string value)
{
Assert.IsNotNull(_repo);
var result = _repo.GetProperties([property], path);
Assert.IsNotNull(result);
if (result.TryGetValue(property, out var actual))
{
Assert.AreEqual(value, actual);
}
else
{
Assert.AreEqual(value, string.Empty);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Serilog;

namespace FileExplorerGitIntegration.UnitTest;

internal sealed class SandboxHelper
{
private readonly Serilog.ILogger _log = Log.ForContext("SourceContext", nameof(SandboxHelper));

private readonly Dictionary<string, string> _renames = new()
{
{ "dot-git", ".git" },
{ "dot-gitmodules", ".gitmodules" },
};

public DirectoryInfo ResourcesDirectory { get; private set; }

public DirectoryInfo DeployedDirectory { get; private set; }

public SandboxHelper()
{
var parentDir = Directory.GetParent(typeof(SandboxHelper).Assembly.Location) ?? throw new InvalidOperationException("Could not obtain resources directory for sandbox repos");
ResourcesDirectory = new DirectoryInfo(Path.Combine(parentDir.FullName, "resources"));
DeployedDirectory = Directory.CreateTempSubdirectory("SandboxHelper.");
}

public void Cleanup()
{
try
{
Directory.Delete(DeployedDirectory.FullName, true);
}
catch (Exception ex)
{
_log.Warning(ex, $"Failed to delete temp directory {DeployedDirectory.FullName}");
throw;
}
}

public string CreateSandbox(string directory)
{
var source = new DirectoryInfo(Path.Combine(ResourcesDirectory.FullName, directory));
var target = new DirectoryInfo(Path.Combine(DeployedDirectory.FullName, directory));
CopyRecursive(source, target);

return target.FullName;
}

private void CopyRecursive(DirectoryInfo source, DirectoryInfo target)
{
foreach (var dir in source.GetDirectories())
{
CopyRecursive(dir, target.CreateSubdirectory(FixName(dir.Name)));
}

foreach (var file in source.GetFiles())
{
file.CopyTo(Path.Combine(target.FullName, FixName(file.Name)));
}
}

private string FixName(string name)
{
_renames.TryGetValue(name, out var newName);
return newName ?? name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* binary
.gitattributes diff
.gitignore diff
config diff
resources_readme.txt diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
COMMIT_EDITMSG
exclude
logs/
description
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The folders under "resources" are Git repositories that have had ".git" renamed to "dot-git" and ".gitmodules" renamed to "dot-gitmodules".

This makes Git treat them as normal files so they can be checked in. SandboxHelper will rename them back to ".git" and ".gitmodules" when it needs to "clone" the repos for testing.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This is a submodule test repo.
It has various submodules in different states.
Inspired by unit tests in libgit2.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3e1e770f7c28e87cbb3ee0c1541e3417c84a0708
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[submodule "sm_changed_file"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_missing_commits"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_changed_head"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_changed_index"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_changed_untracked_file"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_unchanged"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_unchanged_detached"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_missing_commits_detached"]
url = E:/Repos/GitHub/devhome/extensions/GitExtension/FileExplorerGitIntegration.UnitTest/resources/submodules_target
active = true
[submodule "sm_added_and_uncommitted"]
url = E:/temp/resources/submodules_target
active = true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8a303a1d530d9d4e9f31002d4c9d1d8f1cd78940 refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
worktree = ../../../sm_added_and_uncommitted
[remote "origin"]
url = E:/temp/resources/submodules_target
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/heads/main
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/HEAD
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/main
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
P pack-d3b1b7cf66ad317ab08fb781dba8d8ae68e1b200.pack
P pack-ffa30a089fdbfcfdaaea163fd2f9710ef01a00cf.pack

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pack-refs with: peeled fully-peeled sorted
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/heads/main
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/remotes/origin/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc not-for-merge branch 'main' of ../../submodules_target
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e9a899083a7e2b25d7a41e69463ce083bf9ef6ef
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
worktree = ../../../sm_changed_file
[remote "origin"]
url = ../../submodules_target
fetch = +refs/heads/*:refs/remotes/origin/*
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/heads/main
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/main
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
P pack-d3b1b7cf66ad317ab08fb781dba8d8ae68e1b200.pack
P pack-ffa30a089fdbfcfdaaea163fd2f9710ef01a00cf.pack

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pack-refs with: peeled fully-peeled sorted
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/heads/main
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Committing a change to submodule
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc not-for-merge branch 'main' of ../../submodules_target
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4bb90658751b1d839ee1277368998be69deacca5
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
worktree = ../../../sm_changed_head
[remote "origin"]
url = ../../submodules_target
fetch = +refs/heads/*:refs/remotes/origin/*
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
2ab664114c928551863c33d694965c79b6b75144 refs/heads/main
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/main
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
P pack-d3b1b7cf66ad317ab08fb781dba8d8ae68e1b200.pack
P pack-9201333783142a88b5199747b1d4aa993fd8df68.pack

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pack-refs with: peeled fully-peeled sorted
2ab664114c928551863c33d694965c79b6b75144 refs/heads/main
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc refs/remotes/origin/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8bc132afeabc5cbf67bdaf4f92c3e391472a27dc not-for-merge branch 'main' of ../../submodules_target
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e9a899083a7e2b25d7a41e69463ce083bf9ef6ef
Loading
Loading