Skip to content

Commit

Permalink
Reduce calls to git-rev-parse for submodule status
Browse files Browse the repository at this point in the history
Partial workaround for gitextensions#6357

Encoding not really needed for submodule status
GitModule: Optionally reuse gitCommonDir when creating GitModule()

This avoids calls to git-rev-parse when initiating
submodule status
  • Loading branch information
gerhardol committed Mar 10, 2019
1 parent 63af57e commit 7ca908b
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 21 deletions.
2 changes: 1 addition & 1 deletion GitCommands/Git/GitCommandHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ public static ArgumentString GetAllChangedFilesCmd(bool excludeIgnoredFiles, Unt
[CanBeNull]
public static GitSubmoduleStatus GetCurrentSubmoduleChanges(GitModule module, string fileName, string oldFileName, bool staged, bool noLocks = false)
{
Patch patch = module.GetCurrentChanges(fileName, oldFileName, staged, "", module.FilesEncoding, noLocks: noLocks);
Patch patch = module.GetCurrentChanges(fileName, oldFileName, staged, "", null, noLocks: noLocks);
string text = patch != null ? patch.Text : "";
return ParseSubmoduleStatus(text, module, fileName);
}
Expand Down
9 changes: 5 additions & 4 deletions GitCommands/Git/GitModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ public sealed class GitModule : IGitModule
private readonly IGitCommandRunner _gitCommandRunner;
private readonly IExecutable _gitExecutable;

public GitModule([CanBeNull] string workingDir, [CanBeNull] IExecutable executable = null)
public GitModule([CanBeNull] string workingDir, [CanBeNull] IExecutable executable = null, string gitCommonDir = null)
{
WorkingDir = (workingDir ?? "").EnsureTrailingPathSeparator();
WorkingDirGitDir = GitDirectoryResolverInstance.Resolve(WorkingDir);
_gitCommonDirectory = gitCommonDir;
_indexLockManager = new IndexLockManager(this);
_commitDataManager = new CommitDataManager(() => this);
_gitExecutable = executable ?? new Executable(() => AppSettings.GitCommand, WorkingDir);
Expand Down Expand Up @@ -2593,7 +2594,7 @@ public bool IsDirtyDir()
}

internal GitArgumentBuilder GetCurrentChangesCmd(string fileName, [CanBeNull] string oldFileName, bool staged,
string extraDiffArguments, Encoding encoding, bool noLocks)
string extraDiffArguments, bool noLocks)
{
return new GitArgumentBuilder("diff", gitOptions:
noLocks && GitVersion.Current.SupportNoOptionalLocks
Expand All @@ -2613,10 +2614,10 @@ internal GitArgumentBuilder GetCurrentChangesCmd(string fileName, [CanBeNull] st
[CanBeNull]
public Patch GetCurrentChanges(string fileName, [CanBeNull] string oldFileName, bool staged, string extraDiffArguments, Encoding encoding, bool noLocks = false)
{
var output = _gitExecutable.GetOutput(GetCurrentChangesCmd(fileName, oldFileName, staged, extraDiffArguments, encoding, noLocks),
var output = _gitExecutable.GetOutput(GetCurrentChangesCmd(fileName, oldFileName, staged, extraDiffArguments, noLocks),
outputEncoding: LosslessEncoding);

var patches = PatchProcessor.CreatePatchesFromString(output, encoding).ToList();
var patches = PatchProcessor.CreatePatchesFromString(output, encoding ?? GitModule.SystemEncoding).ToList();

return GetPatch(patches, fileName, oldFileName);
}
Expand Down
20 changes: 10 additions & 10 deletions GitCommands/Submodules/SubmoduleStatusProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface ISubmoduleStatusProvider : IDisposable
void Init();
bool HasChangedToNone([CanBeNull] IReadOnlyList<GitItemStatus> allChangedFiles);
bool HasStatusChanges([CanBeNull] IReadOnlyList<GitItemStatus> allChangedFiles);
void UpdateSubmodulesStatus(bool updateStatus, string workingDirectory, string noBranchText);
void UpdateSubmodulesStatus(bool updateStatus, GitModule gitModule, string noBranchText);
}

public sealed class SubmoduleStatusProvider : ISubmoduleStatusProvider
Expand Down Expand Up @@ -81,7 +81,7 @@ public bool HasStatusChanges([CanBeNull] IReadOnlyList<GitItemStatus> allChanged
return allChangedFiles.Any(i => i.IsSubmodule && (i.IsChanged || !i.IsTracked));
}

public void UpdateSubmodulesStatus(bool updateStatus, string workingDirectory, string noBranchText)
public void UpdateSubmodulesStatus(bool updateStatus, GitModule gitModule, string noBranchText)
{
ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
{
Expand All @@ -100,7 +100,7 @@ public void UpdateSubmodulesStatus(bool updateStatus, string workingDirectory, s
// First task: Gather list of submodules on a background thread.
// Don't access Module directly because it's not thread-safe. Use a thread-local version:
var threadModule = new GitModule(workingDirectory);
var threadModule = new GitModule(gitModule.WorkingDir, null, gitModule.GitCommonDirectory);
var result = new SubmoduleInfoResult
{
Module = threadModule
Expand Down Expand Up @@ -130,7 +130,7 @@ private void OnStatusUpdated(SubmoduleInfoResult info, CancellationToken token)
StatusUpdated?.Invoke(this, new SubmoduleStatusEventArgs(info, token));
}

private async Task GetRepositorySubmodulesStatusAsync(bool updateStatus, SubmoduleInfoResult result, IGitModule module, CancellationToken cancelToken, string noBranchText)
private async Task GetRepositorySubmodulesStatusAsync(bool updateStatus, SubmoduleInfoResult result, GitModule module, CancellationToken cancelToken, string noBranchText)
{
List<Task> tasks = new List<Task>();
foreach (var submodule in module.GetSubmodulesLocalPaths().OrderBy(submoduleName => submoduleName))
Expand All @@ -145,13 +145,13 @@ private async Task GetRepositorySubmodulesStatusAsync(bool updateStatus, Submodu

var smi = new SubmoduleInfo { Text = name, Path = path };
result.OurSubmodules.Add(smi);
tasks.Add(GetSubmoduleStatusAsync(updateStatus, smi, cancelToken));
tasks.Add(GetSubmoduleStatusAsync(updateStatus, smi, null, cancelToken));
}

await Task.WhenAll(tasks);
}

private async Task GetSubmoduleStatusAsync(bool updateStatus, SubmoduleInfo info, CancellationToken cancelToken)
private async Task GetSubmoduleStatusAsync(bool updateStatus, SubmoduleInfo info, GitModule submodule, CancellationToken cancelToken)
{
if (!updateStatus)
{
Expand All @@ -161,7 +161,7 @@ private async Task GetSubmoduleStatusAsync(bool updateStatus, SubmoduleInfo info
await TaskScheduler.Default;
cancelToken.ThrowIfCancellationRequested();

var submodule = new GitModule(info.Path);
submodule = submodule ?? new GitModule(info.Path);
var supermodule = submodule.SuperprojectModule;
var submoduleName = submodule.GetCurrentSubmoduleLocalPath();

Expand Down Expand Up @@ -239,7 +239,7 @@ private async Task SetSuperProjectSubmoduleInfoAsync(bool updateStatus, Submodul
string path = module.SuperprojectModule.WorkingDir;
name += GetBranchNameSuffix(path, noBranchText);
result.SuperProject = new SubmoduleInfo { Text = name, Path = module.SuperprojectModule.WorkingDir };
await GetSubmoduleStatusAsync(updateStatus, result.SuperProject, cancelToken);
await GetSubmoduleStatusAsync(updateStatus, result.SuperProject, module.SuperprojectModule, cancelToken);
}

private async Task SetTopProjectSubmoduleInfoAsync(bool updateStatus, SubmoduleInfoResult result, GitModule module, CancellationToken cancelToken, string noBranchText, IGitModule topProject, bool isParentTopProject)
Expand All @@ -253,7 +253,7 @@ private async Task SetTopProjectSubmoduleInfoAsync(bool updateStatus, SubmoduleI
string path = topProject.WorkingDir;
string name = Path.GetFileName(Path.GetDirectoryName(topProject.WorkingDir)) + GetBranchNameSuffix(path, noBranchText);
result.TopProject = new SubmoduleInfo { Text = name, Path = topProject.WorkingDir };
await GetSubmoduleStatusAsync(updateStatus, result.TopProject, cancelToken);
await GetSubmoduleStatusAsync(updateStatus, result.TopProject, module, cancelToken);
}
}

Expand Down Expand Up @@ -282,7 +282,7 @@ private async Task SetSubmoduleDataAsync(bool updateStatus, SubmoduleInfoResult

var smi = new SubmoduleInfo { Text = name, Path = path, Bold = bold };
result.SuperSubmodules.Add(smi);
subTasks.Add(GetSubmoduleStatusAsync(updateStatus, smi, cancelToken));
subTasks.Add(GetSubmoduleStatusAsync(updateStatus, smi, null, cancelToken));
}

await Task.WhenAll(subTasks);
Expand Down
2 changes: 1 addition & 1 deletion GitUI/CommandsDialogs/FormBrowse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2659,7 +2659,7 @@ private void UpdateSubmodulesStructure(bool updateStatus = false)
updateStatus = updateStatus || (AppSettings.ShowSubmoduleStatus && _gitStatusMonitor.Active && (Module.SuperprojectModule != null));

toolStripButtonLevelUp.ToolTipText = "";
_submoduleStatusProvider.UpdateSubmodulesStatus(updateStatus, Module.WorkingDir, _noBranchTitle.Text);
_submoduleStatusProvider.UpdateSubmodulesStatus(updateStatus, Module, _noBranchTitle.Text);
}

private void SubmoduleStatusProvider_StatusUpdating(object sender, EventArgs e)
Expand Down
10 changes: 5 additions & 5 deletions UnitTests/GitCommandsTests/GitModuleTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -511,14 +511,14 @@ public void GetStashesCmd(bool noLocks, string expected)
Assert.AreEqual(expected, _gitModule.GetStashesCmd(noLocks).ToString());
}

[TestCase(@"-c diff.submodule=short -c diff.noprefix=false diff --no-color -M -C --cached extra -- ""new"" ""old""", "new", "old", true, "extra", null, false)]
[TestCase(@"-c diff.submodule=short -c diff.noprefix=false diff --no-color extra -- ""new""", "new", "old", false, "extra", null, false)]
[TestCase(@"--no-optional-locks -c diff.submodule=short -c diff.noprefix=false diff --no-color -M -C --cached extra -- ""new"" ""old""", "new", "old", true, "extra", null, true)]
[TestCase(@"-c diff.submodule=short -c diff.noprefix=false diff --no-color -M -C --cached extra -- ""new"" ""old""", "new", "old", true, "extra", false)]
[TestCase(@"-c diff.submodule=short -c diff.noprefix=false diff --no-color extra -- ""new""", "new", "old", false, "extra", false)]
[TestCase(@"--no-optional-locks -c diff.submodule=short -c diff.noprefix=false diff --no-color -M -C --cached extra -- ""new"" ""old""", "new", "old", true, "extra", true)]
public void GetCurrentChangesCmd(string expected, string fileName, [CanBeNull] string oldFileName, bool staged,
string extraDiffArguments, Encoding encoding, bool noLocks)
string extraDiffArguments, bool noLocks)
{
Assert.AreEqual(expected, _gitModule.GetCurrentChangesCmd(fileName, oldFileName, staged,
extraDiffArguments, encoding, noLocks).ToString());
extraDiffArguments, noLocks).ToString());
}

[TestCase(@"for-each-ref --sort=-committerdate --format=""%(objectname) %(refname)"" refs/heads/", false)]
Expand Down

0 comments on commit 7ca908b

Please sign in to comment.