-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix problems with application path and installation directory resolut…
…ion (#951) When we introduced the rename warning in #551, there was broken logic for resolving the actual invoked program name on Mac and Linux. **Windows** We continue to use `CommandLineToArgvW(GetCommandLine(), ..)` to return the _absolute, full path_ to the entry executable. **macOS** Switch from `_NSGetArgv()` to `_NSGetExecutablePath(..)` which, like the Windows APIs above, returns the full path to the entry executable (or symlink). **Linux** As there is no equivalent to `CommandLineToArgvW` or `_NSGetExecutablePath` here, we instead do some path computation based on the form of `argv[0]` that we get from `/proc/self/cmdline`. - If the value is an absolute path, just use that. - If the value is relative to the current directory (`./name`) then combine this with the current directory. - If the value contains a directory separator (`dir/name`) then also resolve this from the current directory. - Otherwise, this `argv[0]` value must have been a file name (`name`) resolved from the `$PATH`. If we still don't manage to resolve from the `$PATH`, try and resolve the symlink `/proc/self/exe` that points to the executable image that was loaded from disk. Note that we may miss any intermediate link names here, but it's better than nothing. --- In addition, we also never tested the .NET Tool scenario after updating the `ICommandContext.ApplicationPath` to use the entry executable name, whereas previously this was computed from the .NET assembly path. Introduce a separate concept, the `InstallationDirectory` that always points to the home of the core assemblies. This is used for resolving things like in-box UI helpers.
- Loading branch information
Showing
39 changed files
with
646 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
src/shared/Atlassian.Bitbucket.UI/Atlassian.Bitbucket.UI.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
src/shared/Core.Tests/Interop/Linux/LinuxFileSystemTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using System.IO; | ||
using GitCredentialManager.Interop.Linux; | ||
using Xunit; | ||
using static GitCredentialManager.Tests.TestUtils; | ||
|
||
namespace GitCredentialManager.Tests.Interop.Linux | ||
{ | ||
public class LinuxFileSystemTests | ||
{ | ||
[PlatformFact(Platforms.Linux)] | ||
public static void LinuxFileSystem_IsSamePath_SamePath_ReturnsTrue() | ||
{ | ||
var fs = new LinuxFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA = CreateFile(baseDir, "a.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA, fileA)); | ||
} | ||
|
||
[PlatformFact(Platforms.Linux)] | ||
public static void LinuxFileSystem_IsSamePath_DifferentFile_ReturnsFalse() | ||
{ | ||
var fs = new LinuxFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA = CreateFile(baseDir, "a.file"); | ||
string fileB = CreateFile(baseDir, "b.file"); | ||
|
||
Assert.False(fs.IsSamePath(fileA, fileB)); | ||
Assert.False(fs.IsSamePath(fileB, fileA)); | ||
} | ||
|
||
[PlatformFact(Platforms.Linux)] | ||
public static void LinuxFileSystem_IsSamePath_SameFileDifferentCase_ReturnsFalse() | ||
{ | ||
var fs = new LinuxFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = Path.Combine(baseDir, "A.file"); | ||
|
||
Assert.False(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.False(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.Linux)] | ||
public static void LinuxFileSystem_IsSamePath_SameFileDifferentPathNormalization_ReturnsTrue() | ||
{ | ||
var fs = new LinuxFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string subDir = CreateDirectory(baseDir, "subDir1", "subDir2"); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = Path.Combine(subDir, "..", "..", "a.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.Linux)] | ||
public static void LinuxFileSystem_IsSamePath_SameFileViaSymlink_ReturnsTrue() | ||
{ | ||
var fs = new LinuxFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = CreateFileSymlink(baseDir, "a.link", fileA1); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.Linux)] | ||
public static void LinuxFileSystem_IsSamePath_SameFileRelativePath_ReturnsTrue() | ||
{ | ||
var fs = new LinuxFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = "./a.file"; | ||
|
||
using (ChangeDirectory(baseDir)) | ||
{ | ||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
} | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
src/shared/Core.Tests/Interop/MacOS/MacOSFileSystemTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using System.IO; | ||
using GitCredentialManager.Interop.MacOS; | ||
using Xunit; | ||
using static GitCredentialManager.Tests.TestUtils; | ||
|
||
namespace GitCredentialManager.Tests.Interop.MacOS | ||
{ | ||
public class MacOSFileSystemTests | ||
{ | ||
[PlatformFact(Platforms.MacOS)] | ||
public static void MacOSFileSystem_IsSamePath_SamePath_ReturnsTrue() | ||
{ | ||
var fs = new MacOSFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA = CreateFile(baseDir, "a.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA, fileA)); | ||
} | ||
|
||
[PlatformFact(Platforms.MacOS)] | ||
public static void MacOSFileSystem_IsSamePath_DifferentFile_ReturnsFalse() | ||
{ | ||
var fs = new MacOSFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA = CreateFile(baseDir, "a.file"); | ||
string fileB = CreateFile(baseDir, "b.file"); | ||
|
||
Assert.False(fs.IsSamePath(fileA, fileB)); | ||
Assert.False(fs.IsSamePath(fileB, fileA)); | ||
} | ||
|
||
[PlatformFact(Platforms.MacOS)] | ||
public static void MacOSFileSystem_IsSamePath_SameFileDifferentCase_ReturnsTrue() | ||
{ | ||
var fs = new MacOSFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = Path.Combine(baseDir, "A.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.MacOS)] | ||
public static void MacOSFileSystem_IsSamePath_SameFileDifferentPathNormalization_ReturnsTrue() | ||
{ | ||
var fs = new MacOSFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string subDir = CreateDirectory(baseDir, "subDir1", "subDir2"); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = Path.Combine(subDir, "..", "..", "a.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.MacOS)] | ||
public static void MacOSFileSystem_IsSamePath_SameFileViaSymlink_ReturnsTrue() | ||
{ | ||
var fs = new MacOSFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = CreateFileSymlink(baseDir, "a.link", fileA1); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.MacOS)] | ||
public static void MacOSFileSystem_IsSamePath_SameFileRelativePath_ReturnsTrue() | ||
{ | ||
var fs = new MacOSFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = "./a.file"; | ||
|
||
using (ChangeDirectory(baseDir)) | ||
{ | ||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
} | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
src/shared/Core.Tests/Interop/Posix/PosixFileSystemTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System.IO; | ||
using GitCredentialManager.Interop.Posix; | ||
using Xunit; | ||
using static GitCredentialManager.Tests.TestUtils; | ||
|
||
namespace GitCredentialManager.Tests.Interop.Posix | ||
{ | ||
public class PosixFileSystemTests | ||
{ | ||
[PlatformFact(Platforms.Posix)] | ||
public void PosixFileSystem_ResolveSymlinks_FileLinks() | ||
{ | ||
string baseDir = GetTempDirectory(); | ||
string realPath = CreateFile(baseDir, "realFile.txt"); | ||
string linkPath = CreateFileSymlink(baseDir, "linkFile.txt", realPath); | ||
|
||
string actual = PosixFileSystem.ResolveSymbolicLinks(linkPath); | ||
|
||
Assert.Equal(realPath, actual); | ||
} | ||
|
||
[PlatformFact(Platforms.Posix)] | ||
public void PosixFileSystem_ResolveSymlinks_DirectoryLinks() | ||
{ | ||
// | ||
// Create a real file inside of a directory that is a symlink | ||
// to another directory. | ||
// | ||
// /tmp/{uuid}/linkDir/ -> /tmp/{uuid}/realDir/ | ||
// | ||
string baseDir = GetTempDirectory(); | ||
string realDir = CreateDirectory(baseDir, "realDir"); | ||
string linkDir = CreateDirectorySymlink(baseDir, "linkDir", realDir); | ||
string filePath = CreateFile(linkDir, "file.txt"); | ||
|
||
string actual = PosixFileSystem.ResolveSymbolicLinks(filePath); | ||
|
||
string expected = Path.Combine(realDir, "file.txt"); | ||
|
||
Assert.Equal(expected, actual); | ||
} | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
src/shared/Core.Tests/Interop/Windows/WindowsFileSystemTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
using System.IO; | ||
using GitCredentialManager.Interop.Windows; | ||
using Xunit; | ||
using static GitCredentialManager.Tests.TestUtils; | ||
|
||
namespace GitCredentialManager.Tests.Interop.Windows | ||
{ | ||
public class WindowsFileSystemTests | ||
{ | ||
[PlatformFact(Platforms.Windows)] | ||
public static void WindowsFileSystem_IsSamePath_SamePath_ReturnsTrue() | ||
{ | ||
var fs = new WindowsFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA = CreateFile(baseDir, "a.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA, fileA)); | ||
} | ||
|
||
[PlatformFact(Platforms.Windows)] | ||
public static void WindowsFileSystem_IsSamePath_DifferentFile_ReturnsFalse() | ||
{ | ||
var fs = new WindowsFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA = CreateFile(baseDir, "a.file"); | ||
string fileB = CreateFile(baseDir, "b.file"); | ||
|
||
Assert.False(fs.IsSamePath(fileA, fileB)); | ||
Assert.False(fs.IsSamePath(fileB, fileA)); | ||
} | ||
|
||
[PlatformFact(Platforms.Windows)] | ||
public static void WindowsFileSystem_IsSamePath_SameFileDifferentCase_ReturnsTrue() | ||
{ | ||
var fs = new WindowsFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = Path.Combine(baseDir, "A.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.Windows)] | ||
public static void WindowsFileSystem_IsSamePath_SameFileDifferentPathNormalization_ReturnsTrue() | ||
{ | ||
var fs = new WindowsFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string subDir = CreateDirectory(baseDir, "subDir1", "subDir2"); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = Path.Combine(subDir, "..", "..", "a.file"); | ||
|
||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
|
||
[PlatformFact(Platforms.Windows)] | ||
public static void WindowsFileSystem_IsSamePath_SameFileRelativePath_ReturnsTrue() | ||
{ | ||
var fs = new WindowsFileSystem(); | ||
|
||
string baseDir = GetTempDirectory(); | ||
string fileA1 = CreateFile(baseDir, "a.file"); | ||
string fileA2 = @".\a.file"; | ||
|
||
using (ChangeDirectory(baseDir)) | ||
{ | ||
Assert.True(fs.IsSamePath(fileA1, fileA2)); | ||
Assert.True(fs.IsSamePath(fileA2, fileA1)); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.