Upgrade: introduce platform strategy

This commit is contained in:
Jameson Miller 2019-05-30 10:57:25 -04:00
Родитель fe04e7daf4
Коммит 6ca0311af7
10 изменённых файлов: 236 добавлений и 1 удалений

Просмотреть файл

@ -73,6 +73,10 @@ namespace GVFS.Common
ITracer tracer,
string lockPath);
public abstract ProductUpgraderPlatformStrategy CreateProductUpgraderPlatformInteractions(
PhysicalFileSystem fileSystem,
ITracer tracer);
public bool TryGetNormalizedPathRoot(string path, out string pathRoot, out string errorMessage)
{
pathRoot = null;

Просмотреть файл

@ -20,6 +20,7 @@ namespace GVFS.Common
public abstract class ProductUpgrader : IDisposable
{
public const string ToolsDirectory = "Tools";
protected readonly Version installedVersion;
protected readonly ITracer tracer;
protected readonly PhysicalFileSystem fileSystem;
@ -27,7 +28,6 @@ namespace GVFS.Common
protected bool noVerify;
protected bool dryRun;
private const string ToolsDirectory = "Tools";
private static readonly string UpgraderToolName = GVFSPlatform.Instance.Constants.GVFSUpgraderExecutableName;
public ProductUpgrader(

Просмотреть файл

@ -0,0 +1,38 @@
using GVFS.Common.FileSystem;
using GVFS.Common.Tracing;
using System;
using System.IO;
namespace GVFS.Common
{
public abstract class ProductUpgraderPlatformStrategy
{
public ProductUpgraderPlatformStrategy(PhysicalFileSystem fileSystem, ITracer tracer)
{
this.FileSystem = fileSystem;
this.Tracer = tracer;
}
protected PhysicalFileSystem FileSystem { get; }
protected ITracer Tracer { get; }
public abstract bool TryPrepareLogDirectory(out string error);
public abstract bool TryPrepareApplicationDirectory(out string error);
public abstract bool TryPrepareDownloadDirectory(out string error);
protected void TraceException(Exception exception, string method, string message)
{
this.TraceException(this.Tracer, exception, method, message);
}
protected void TraceException(ITracer tracer, Exception exception, string method, string message)
{
EventMetadata metadata = new EventMetadata();
metadata.Add("Method", method);
metadata.Add("Exception", exception.ToString());
tracer.RelatedError(metadata, message);
}
}
}

Просмотреть файл

@ -82,6 +82,13 @@ namespace GVFS.Platform.Mac
return result;
}
public override ProductUpgraderPlatformStrategy CreateProductUpgraderPlatformInteractions(
PhysicalFileSystem fileSystem,
ITracer tracer)
{
return new MacProductUpgraderPlatformStrategy(fileSystem, tracer);
}
public class MacPlatformConstants : POSIXPlatformConstants
{
public override string InstallerExtension

Просмотреть файл

@ -0,0 +1,63 @@
using GVFS.Common;
using GVFS.Common.FileSystem;
using GVFS.Common.Tracing;
using System;
using System.IO;
namespace GVFS.Platform.Mac
{
public class MacProductUpgraderPlatformStrategy : ProductUpgraderPlatformStrategy
{
public MacProductUpgraderPlatformStrategy(PhysicalFileSystem fileSystem, ITracer tracer)
: base(fileSystem, tracer)
{
}
public override bool TryPrepareLogDirectory(out string error)
{
error = null;
return true;
}
public override bool TryPrepareApplicationDirectory(out string error)
{
string rootDirectoryPath = ProductUpgraderInfo.GetUpgradesDirectoryPath();
string toolsDirectoryPath = Path.Combine(rootDirectoryPath, ProductUpgrader.ToolsDirectory);
Exception deleteDirectoryException;
if (this.FileSystem.DirectoryExists(toolsDirectoryPath) &&
!this.FileSystem.TryDeleteDirectory(toolsDirectoryPath, out deleteDirectoryException))
{
error = $"Failed to delete {toolsDirectoryPath} - {deleteDirectoryException.Message}";
this.TraceException(deleteDirectoryException, nameof(this.TryPrepareApplicationDirectory), $"Error deleting {toolsDirectoryPath}.");
return false;
}
this.FileSystem.CreateDirectory(toolsDirectoryPath);
error = null;
return true;
}
public override bool TryPrepareDownloadDirectory(out string error)
{
string directory = ProductUpgraderInfo.GetAssetDownloadsPath();
Exception deleteDirectoryException;
if (this.FileSystem.DirectoryExists(directory) &&
!this.FileSystem.TryDeleteDirectory(directory, out deleteDirectoryException))
{
error = $"Failed to delete {directory} - {deleteDirectoryException.Message}";
this.TraceException(deleteDirectoryException, nameof(this.TryPrepareDownloadDirectory), $"Error deleting {directory}.");
return false;
}
this.FileSystem.CreateDirectory(directory);
error = null;
return true;
}
}
}

Просмотреть файл

@ -92,6 +92,7 @@
<Compile Include="WindowsPhysicalDiskInfo.cs" />
<Compile Include="WindowsPlatform.cs" />
<Compile Include="WindowsPlatform.Shared.cs" />
<Compile Include="WindowsProductUpgraderPlatformStrategy.cs" />
<Compile Include="WindowsFileSystem.cs" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -340,6 +340,13 @@ namespace GVFS.Platform.Windows
{
return new WindowsFileBasedLock(fileSystem, tracer, lockPath);
}
public override ProductUpgraderPlatformStrategy CreateProductUpgraderPlatformInteractions(
PhysicalFileSystem fileSystem,
ITracer tracer)
{
return new WindowsProductUpgraderPlatformStrategy(fileSystem, tracer);
}
public override bool TryGetGVFSEnlistmentRoot(string directory, out string enlistmentRoot, out string errorMessage)
{

Просмотреть файл

@ -0,0 +1,76 @@
using GVFS.Common;
using GVFS.Common.FileSystem;
using GVFS.Common.Tracing;
using System;
using System.IO;
namespace GVFS.Platform.Windows
{
public class WindowsProductUpgraderPlatformStrategy : ProductUpgraderPlatformStrategy
{
public WindowsProductUpgraderPlatformStrategy(PhysicalFileSystem fileSystem, ITracer tracer)
: base(fileSystem, tracer)
{
}
public override bool TryPrepareLogDirectory(out string error)
{
// Under normal circumstances
// ProductUpgraderInfo.GetLogDirectoryPath will have
// already been created by GVFS.Service. If for some
// reason it does not (e.g. the service failed to start),
// we need to create
// ProductUpgraderInfo.GetLogDirectoryPath() explicity to
// ensure that it has the correct ACLs (so that both admin
// and non-admin users can create log files). If the logs
// directory does not already exist, this call could fail
// when running as a non-elevated user.
string createDirectoryError;
if (!this.FileSystem.TryCreateDirectoryWithAdminAndUserModifyPermissions(ProductUpgraderInfo.GetLogDirectoryPath(), out createDirectoryError))
{
error = $"ERROR: Unable to create directory `{ProductUpgraderInfo.GetLogDirectoryPath()}`";
error += $"\n{createDirectoryError}";
error += $"\n\nTry running {GVFSConstants.UpgradeVerbMessages.GVFSUpgrade} from an elevated command prompt.";
return false;
}
error = null;
return true;
}
public override bool TryPrepareApplicationDirectory(out string error)
{
string rootDirectoryPath = ProductUpgraderInfo.GetUpgradesDirectoryPath();
string toolsDirectoryPath = Path.Combine(rootDirectoryPath, ProductUpgrader.ToolsDirectory);
Exception deleteDirectoryException;
if (this.FileSystem.DirectoryExists(toolsDirectoryPath) &&
!this.FileSystem.TryDeleteDirectory(toolsDirectoryPath, out deleteDirectoryException))
{
error = $"Failed to delete {toolsDirectoryPath} - {deleteDirectoryException.Message}";
this.TraceException(deleteDirectoryException, nameof(this.TryPrepareApplicationDirectory), $"Error deleting {toolsDirectoryPath}.");
return false;
}
if (!this.FileSystem.TryCreateOrUpdateDirectoryToAdminModifyPermissions(
this.Tracer,
toolsDirectoryPath,
out error))
{
return false;
}
error = null;
return true;
}
public override bool TryPrepareDownloadDirectory(out string error)
{
return this.FileSystem.TryCreateOrUpdateDirectoryToAdminModifyPermissions(
this.Tracer,
ProductUpgraderInfo.GetAssetDownloadsPath(),
out error);
}
}
}

Просмотреть файл

@ -150,6 +150,13 @@ namespace GVFS.UnitTests.Mock.Common
{
return new MockFileBasedLock(fileSystem, tracer, lockPath);
}
public override ProductUpgraderPlatformStrategy CreateProductUpgraderPlatformInteractions(
PhysicalFileSystem fileSystem,
ITracer tracer)
{
return new MockProductUpgraderPlatformStrategy(fileSystem, tracer);
}
public override bool TryKillProcessTree(int processId, out int exitCode, out string error)
{

Просмотреть файл

@ -0,0 +1,32 @@
using GVFS.Common;
using GVFS.Common.FileSystem;
using GVFS.Common.Tracing;
namespace GVFS.UnitTests.Mock.Common
{
public class MockProductUpgraderPlatformStrategy : ProductUpgraderPlatformStrategy
{
public MockProductUpgraderPlatformStrategy(PhysicalFileSystem fileSystem, ITracer tracer)
: base(fileSystem, tracer)
{
}
public override bool TryPrepareLogDirectory(out string error)
{
error = null;
return true;
}
public override bool TryPrepareApplicationDirectory(out string error)
{
error = null;
return true;
}
public override bool TryPrepareDownloadDirectory(out string error)
{
error = null;
return true;
}
}
}