Skip to content

Commit

Permalink
Wrapper for Path Combine/GetExtension
Browse files Browse the repository at this point in the history
Avoid throwing when handling Git items, that  allows other characters than
Windows file systems.
Similar to the .NET Core 2.1 API
  • Loading branch information
gerhardol committed Nov 8, 2020
1 parent bda7376 commit 60379e3
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 33 deletions.
6 changes: 3 additions & 3 deletions GitCommands/FileAssociatedIconProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public FileAssociatedIconProvider()
/// </remarks>
public Icon Get(string workingDirectory, string relativeFilePath)
{
var extension = Path.GetExtension(relativeFilePath);
var extension = PathUtil.GetExtension(relativeFilePath);
if (string.IsNullOrWhiteSpace(extension))
{
return null;
Expand All @@ -68,7 +68,7 @@ public Icon Get(string workingDirectory, string relativeFilePath)
// extensions from the registry and using p/invokes and WinAPI, which have
// significantly higher maintenance overhead.
var fullPath = Path.Combine(workingDirectory, relativeFilePath);
var fullPath = PathUtil.Combine(workingDirectory, relativeFilePath);
if (!_fileSystem.File.Exists(fullPath))
{
tempFile = CreateTempFile(Path.GetFileName(fullPath));
Expand Down Expand Up @@ -117,4 +117,4 @@ internal void ResetCache()
LoadedFileIcons.Clear();
}
}
}
}
4 changes: 2 additions & 2 deletions GitCommands/Git/GitItemStatusFileExtensionComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public override int Compare(GitItemStatus x, GitItemStatus y)

var lhsPath = GetPrimarySortingPath(x);
var rhsPath = GetPrimarySortingPath(y);
var lhsExt = Path.GetExtension(lhsPath);
var rhsExt = Path.GetExtension(rhsPath);
var lhsExt = PathUtil.GetExtension(lhsPath);
var rhsExt = PathUtil.GetExtension(rhsPath);

var comparisonResult = StringComparer.InvariantCulture.Compare(lhsExt, rhsExt);
if (comparisonResult == 0)
Expand Down
4 changes: 1 addition & 3 deletions GitCommands/GitRevisionInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ IEnumerable<IGitItem> YieldSubItems()
{
if (subItem is GitItem gitItem)
{
gitItem.FileName = Path.Combine(
basePath,
gitItem.FileName ?? string.Empty);
gitItem.FileName = PathUtil.Combine(basePath, gitItem.FileName) ?? string.Empty;
}

yield return subItem;
Expand Down
56 changes: 52 additions & 4 deletions GitCommands/PathUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,54 @@ public static string NormalizePath([NotNull] this string path)
}
}

/// <summary>
/// Wrapper for Path.Combine
/// </summary>
/// <remark>
/// Similar to the .NET Core 2.1 variant, except that null is returned if Windows
/// invalid characters (that may be accepted in Git or other filesystems)
/// are in the paths instead of a possible path (the OS or file system will throw
/// if the paths are invalid).
/// </remark>
/// <param name="path1">initial part</param>
/// <param name="path2">second part</param>
/// <returns>path if it can be combined, null otherwise</returns>
[CanBeNull]
public static string Combine(string path1, string path2)
{
try
{
return Path.Combine(path1, path2);
}
catch (ArgumentException)
{
return null;
}
}

/// <summary>
/// Wrapper for Path.GetExtension
/// </summary>
/// <remark>
/// <see cref="Combine"/> for motivation.
/// </remark>
/// <param name="path">path to check</param>
/// <returns>path if it can be combined, empty otherwise</returns>
[NotNull]
public static string GetExtension(string path)
{
try
{
return Path.GetExtension(path);
}
catch (ArgumentException)
{
// This could return part after a '.' using string commands,
// but wait for .NET Core with this edge case
return string.Empty;
}
}

[NotNull]
public static string Resolve([NotNull] string path, string relativePath = "")
{
Expand Down Expand Up @@ -223,7 +271,7 @@ public static bool TryFindFullPath([NotNull] string fileName, out string fullPat

foreach (var path in EnvironmentPathsProvider.GetEnvironmentValidPaths())
{
fullPath = Path.Combine(path, fileName);
fullPath = Combine(path, fileName);
if (File.Exists(fullPath))
{
return true;
Expand Down Expand Up @@ -251,7 +299,7 @@ public static bool TryFindShellPath([NotNull] string shell, out string shellPath
return true;
}

shellPath = Path.Combine(AppSettings.GitBinDir, shell);
shellPath = Combine(AppSettings.GitBinDir, shell);
if (File.Exists(shellPath))
{
return true;
Expand Down Expand Up @@ -369,7 +417,7 @@ string FindFileInEnvVarFolder(string environmentVariable, string location, strin
return null;
}

var path = Path.Combine(envVarFolder, location);
var path = Combine(envVarFolder, location);
if (!Directory.Exists(path))
{
return null;
Expand All @@ -380,7 +428,7 @@ string FindFileInEnvVarFolder(string environmentVariable, string location, strin

string FindFile(string location, string fileName1)
{
string fullName = Path.Combine(location, fileName1);
string fullName = Combine(location, fileName1);
if (File.Exists(fullName))
{
return fullName;
Expand Down
4 changes: 2 additions & 2 deletions GitUI/AutoCompletion/CommitAutoCompleteProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task<IEnumerable<AutoCompleteWord>> GetAutoCompleteWordsAsync(Cance
{
cancellationToken.ThrowIfCancellationRequested();

var regex = GetRegexForExtension(Path.GetExtension(file.Name));
var regex = GetRegexForExtension(PathUtil.GetExtension(file.Name));

if (regex != null)
{
Expand Down Expand Up @@ -94,7 +94,7 @@ private static Regex GetRegexForExtension(string extension)

private static IEnumerable<string> ReadOrInitializeAutoCompleteRegexes()
{
var path = Path.Combine(AppSettings.ApplicationDataPath.Value, "AutoCompleteRegexes.txt");
var path = PathUtil.Combine(AppSettings.ApplicationDataPath.Value, "AutoCompleteRegexes.txt");

if (File.Exists(path))
{
Expand Down
15 changes: 13 additions & 2 deletions GitUI/CommandsDialogs/FormBrowse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2015,14 +2015,20 @@ public static void CopyFullPathToClipboard(FileStatusList diffFiles, GitModule m
var fileNames = new StringBuilder();
foreach (var item in diffFiles.SelectedItems)
{
var path = PathUtil.Combine(module.WorkingDir, item.Item.Name);
if (string.IsNullOrWhiteSpace(path))
{
continue;
}

// Only use append line when multiple items are selected.
// This to make it easier to use the text from clipboard when 1 file is selected.
if (fileNames.Length > 0)
{
fileNames.AppendLine();
}

fileNames.Append(Path.Combine(module.WorkingDir, item.Item.Name).ToNativePath());
fileNames.Append(path.ToNativePath());
}

ClipboardUtil.TrySetText(fileNames.ToString());
Expand Down Expand Up @@ -2423,7 +2429,12 @@ public static void OpenContainingFolder(FileStatusList diffFiles, GitModule modu

foreach (var item in diffFiles.SelectedItems)
{
string filePath = Path.Combine(module.WorkingDir, item.Item.Name.ToNativePath());
string filePath = PathUtil.Combine(module.WorkingDir, item.Item.Name.ToNativePath());
if (string.IsNullOrWhiteSpace(filePath))
{
continue;
}

FormBrowseUtil.ShowFileOrParentFolderInFileExplorer(filePath);
}
}
Expand Down
6 changes: 3 additions & 3 deletions GitUI/CommandsDialogs/FormResolveConflicts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,17 +314,17 @@ private bool TryMergeWithScript(string fileName, string baseFileName, string loc

try
{
string extension = Path.GetExtension(fileName).ToLower();
string extension = PathUtil.GetExtension(fileName).ToLower();
if (extension.Length <= 1)
{
return false;
}

string dir = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Diff-Scripts").EnsureTrailingPathSeparator();
string dir = PathUtil.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Diff-Scripts").EnsureTrailingPathSeparator();
if (Directory.Exists(dir))
{
if (_mergeScripts.TryGetValue(extension, out var mergeScript) &&
File.Exists(Path.Combine(dir, mergeScript)))
File.Exists(PathUtil.Combine(dir, mergeScript)))
{
if (MessageBox.Show(this, string.Format(_uskUseCustomMergeScript.Text, mergeScript),
_uskUseCustomMergeScriptCaption.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
Expand Down
7 changes: 4 additions & 3 deletions GitUI/CommandsDialogs/RevisionFileTreeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,17 @@ public void LoadChildren(IGitItem item, TreeNodeCollection nodes, ImageList.Imag

case GitObjectType.Blob:
{
var extension = Path.GetExtension(gitItem.FileName);
var extension = PathUtil.GetExtension(gitItem.FileName);

if (string.IsNullOrWhiteSpace(extension))
{
continue;
}

if (!imageCollection.ContainsKey(extension))
{
// a little optimisation - initialise the first time it is required
workingDir = workingDir ?? _getWorkingDir();
// lazy - initialise the first time used
workingDir ??= _getWorkingDir();

var fileIcon = _iconProvider.Get(workingDir, gitItem.FileName);
if (fileIcon == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,8 @@ private bool CheckGitExtensionRegistrySettings()
null)))
{
// Check if shell extensions are installed
string path32 = Path.Combine(AppSettings.GetInstallDir(), CommonLogic.GitExtensionsShellEx32Name);
string path64 = Path.Combine(AppSettings.GetInstallDir(), CommonLogic.GitExtensionsShellEx64Name);
string path32 = PathUtil.Combine(AppSettings.GetInstallDir(), CommonLogic.GitExtensionsShellEx32Name);
string path64 = PathUtil.Combine(AppSettings.GetInstallDir(), CommonLogic.GitExtensionsShellEx64Name);
if (!File.Exists(path32) || (IntPtr.Size == 8 && !File.Exists(path64)))
{
RenderSettingSet(ShellExtensionsRegistered, ShellExtensionsRegistered_Fix, _shellExtNoInstalled.Text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected override void OnLoad(EventArgs e)

foreach (string translation in translations)
{
var imagePath = Path.Combine(Translator.GetTranslationDir(), translation + ".gif");
var imagePath = PathUtil.Combine(Translator.GetTranslationDir(), translation + ".gif");
if (File.Exists(imagePath))
{
var image = Image.FromFile(imagePath);
Expand Down
10 changes: 5 additions & 5 deletions GitUI/CommandsDialogs/SettingsDialog/Pages/FormFixHome.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private static bool IsFixHome()
try
{
if (!string.IsNullOrEmpty(candidate) &&
File.Exists(Path.Combine(candidate, ".gitconfig")))
File.Exists(PathUtil.Combine(candidate, ".gitconfig")))
{
return true;
}
Expand Down Expand Up @@ -138,7 +138,7 @@ private void LoadSettings()
try
{
string userHomeDir = Environment.GetEnvironmentVariable("HOME", EnvironmentVariableTarget.User);
if (!string.IsNullOrEmpty(userHomeDir) && File.Exists(Path.Combine(userHomeDir, ".gitconfig")))
if (!string.IsNullOrEmpty(userHomeDir) && File.Exists(PathUtil.Combine(userHomeDir, ".gitconfig")))
{
MessageBox.Show(this, string.Format(_gitconfigFoundHome.Text, userHomeDir), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
defaultHome.Checked = true;
Expand All @@ -156,7 +156,7 @@ private void LoadSettings()
{
var path = Environment.GetEnvironmentVariable("HOMEDRIVE") +
Environment.GetEnvironmentVariable("HOMEPATH");
if (!string.IsNullOrEmpty(path) && File.Exists(Path.Combine(path, ".gitconfig")))
if (!string.IsNullOrEmpty(path) && File.Exists(PathUtil.Combine(path, ".gitconfig")))
{
MessageBox.Show(this, string.Format(_gitconfigFoundHomedrive.Text, path), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
defaultHome.Checked = true;
Expand All @@ -173,7 +173,7 @@ private void LoadSettings()
try
{
var path = Environment.GetEnvironmentVariable("USERPROFILE");
if (!string.IsNullOrEmpty(path) && File.Exists(Path.Combine(path, ".gitconfig")))
if (!string.IsNullOrEmpty(path) && File.Exists(PathUtil.Combine(path, ".gitconfig")))
{
MessageBox.Show(this, string.Format(_gitconfigFoundUserprofile.Text, path), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
userprofileHome.Checked = true;
Expand All @@ -190,7 +190,7 @@ private void LoadSettings()
try
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
if (!string.IsNullOrEmpty(path) && File.Exists(Path.Combine(path, ".gitconfig")))
if (!string.IsNullOrEmpty(path) && File.Exists(PathUtil.Combine(path, ".gitconfig")))
{
MessageBox.Show(this, string.Format(_gitconfigFoundPersonalFolder.Text, Environment.GetFolderPath(Environment.SpecialFolder.Personal)),
"Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
Expand Down
2 changes: 1 addition & 1 deletion GitUI/Editor/FileViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ public Task ViewGitItemAsync(GitItemStatus file, [CanBeNull] Action openWithDiff
{
// File system access for other than Worktree,
// to handle that git-status does not detect details for untracked (git-diff --no-index will not give info)
var fullPath = Path.Combine(Module.WorkingDir, file.Name);
var fullPath = PathUtil.Combine(Module.WorkingDir, file.Name);
if (Directory.Exists(fullPath) && GitModule.IsValidGitWorkingDir(fullPath))
{
isSubmodule = true;
Expand Down
5 changes: 3 additions & 2 deletions Plugins/Statistics/GitStatistics/LineCounter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using GitCommands;

namespace GitStatistics
{
Expand Down Expand Up @@ -53,7 +54,7 @@ IEnumerable<FileInfo> GetFiles()
{
foreach (var file in filesToCheck)
{
if (extensions.Contains(Path.GetExtension(file)))
if (extensions.Contains(PathUtil.GetExtension(file)))
{
FileInfo fileInfo;
try
Expand Down Expand Up @@ -98,4 +99,4 @@ void AddFile(FileInfo file)
}
}
}
}
}
18 changes: 18 additions & 0 deletions UnitTests/GitCommands.Tests/Helpers/PathUtilTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,24 @@ public void NormalizePath(string path, string expected)
PathUtil.NormalizePath(path).Should().Be(expected);
}

[TestCase(@"C:\work\t.txt", "whatever", @"C:\work\t.txt\whatever")]
[TestCase(@"C:\wor""k\t.txt", "whatever", null)]
[TestCase(@"\\WSL$\Ubuntu\home\jack\.\work\", "whatever", @"\\WSL$\Ubuntu\home\jack\.\work\whatever")]
public void Combine(string path1, string path2, string expected)
{
PathUtil.Combine(path1, path2).Should().Be(expected);
}

[TestCase(@"C:\work\t.txt", @".txt")]
[TestCase(@"C:\work\t.", @"")]
[TestCase(@"work/t.bmp", @".bmp")]
[TestCase(@"work""/t.bmp", @"")]
[TestCase(@"\\WSL$\Ubuntu\home\jack\.\work", @"")]
public void GetExtension(string path, string expected)
{
PathUtil.GetExtension(path).Should().Be(expected);
}

[TestCase(@"C:\WORK\GitExtensions\", @"C:\WORK\GitExtensions\")]
[TestCase(@"\\my-pc\Work\GitExtensions\", @"\\my-pc\Work\GitExtensions\")]
[TestCase(@"\\wsl$\Ubuntu\home\jack\work\", @"\\wsl$\Ubuntu\home\jack\work\")]
Expand Down

0 comments on commit 60379e3

Please sign in to comment.