src/DependencyManagement/DependencyManagerStorage.cs (135 lines of code) (raw):
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.Azure.Functions.PowerShellWorker.DependencyManagement
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
internal class DependencyManagerStorage : IDependencyManagerStorage
{
private readonly string _functionAppRootPath;
private readonly string _managedDependenciesRootPath;
public DependencyManagerStorage(string functionAppRootPath)
{
_functionAppRootPath = functionAppRootPath;
_managedDependenciesRootPath = ManagedDependenciesPathDetector.GetManagedDependenciesPath(_functionAppRootPath);
}
public IEnumerable<DependencyManifestEntry> GetDependencies()
{
return GetAppDependencyManifest().GetEntries();
}
public bool SnapshotExists(string path)
{
return Directory.Exists(path);
}
public string GetLatestInstalledSnapshot()
{
return GetInstalledSnapshots().Max();
}
public IEnumerable<string> GetInstalledAndInstallingSnapshots()
{
if (!Directory.Exists(_managedDependenciesRootPath))
{
return Enumerable.Empty<string>();
}
return Directory.EnumerateDirectories(_managedDependenciesRootPath);
}
public IEnumerable<string> GetInstalledModuleVersions(string snapshotPath, string moduleName, string majorVersion)
{
var modulePath = Path.Join(snapshotPath, moduleName);
if (!Directory.Exists(modulePath))
{
return Enumerable.Empty<string>();
}
return Directory.EnumerateDirectories(modulePath, $"{majorVersion}.*");
}
public bool IsModuleVersionInstalled(string snapshotPath, string moduleName, string version)
{
var moduleVersionPath = Path.Join(snapshotPath, moduleName, version);
return Directory.Exists(moduleVersionPath);
}
public string CreateNewSnapshotPath()
{
return Path.Join(
_managedDependenciesRootPath,
DependencySnapshotFolderNameTools.CreateUniqueName());
}
public string CreateInstallingSnapshot(string path)
{
var installingPath = DependencySnapshotFolderNameTools.ConvertInstalledToInstalling(path);
Directory.CreateDirectory(installingPath);
return installingPath;
}
public void PromoteInstallingSnapshotToInstalledAtomically(string path)
{
var installingPath = DependencySnapshotFolderNameTools.ConvertInstalledToInstalling(path);
Directory.Move(installingPath, path);
}
public void RemoveSnapshot(string path)
{
Directory.Delete(path, recursive: true);
}
public void SetSnapshotCreationTimeToUtcNow(string path)
{
Directory.SetCreationTimeUtc(path, DateTime.UtcNow);
}
public DateTime GetSnapshotCreationTimeUtc(string path)
{
return Directory.GetCreationTimeUtc(path);
}
public void SetSnapshotAccessTimeToUtcNow(string path)
{
var markerFilePath = DependencySnapshotFolderNameTools.CreateLastAccessMarkerFilePath(path);
if (File.Exists(markerFilePath))
{
File.SetLastWriteTimeUtc(markerFilePath, DateTime.UtcNow);
}
else
{
var file = File.Open(markerFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete);
file.Dispose();
}
}
public DateTime GetSnapshotAccessTimeUtc(string path)
{
var heartbeatFilePath = DependencySnapshotFolderNameTools.CreateLastAccessMarkerFilePath(path);
var heartbeatLastWrite = File.GetLastWriteTimeUtc(heartbeatFilePath);
var snapshotCreation = GetSnapshotCreationTimeUtc(path);
// If heartbeatLastWrite is older than snapshotCreation, this indicates that the heartbeat file
// does not exist (as in this case File.GetLastWriteTimeUtc returns January 1, 1601 A.D.).
// In this situation, we want to use the snapshot creation time as the closest approximation instead.
return heartbeatLastWrite >= snapshotCreation ? heartbeatLastWrite : snapshotCreation;
}
public void PreserveDependencyManifest(string path)
{
var source = GetAppDependencyManifest().GetPath();
var destination = Path.Join(path, Path.GetFileName(source));
File.Copy(source, destination, overwrite: true);
}
public bool IsEquivalentDependencyManifest(string path)
{
var source = GetAppDependencyManifest().GetPath();
if (!File.Exists(source))
{
return false;
}
var destination = Path.Join(path, Path.GetFileName(source));
if (!File.Exists(destination))
{
return false;
}
return File.ReadAllText(source) == File.ReadAllText(destination);
}
private IEnumerable<string> GetInstalledSnapshots()
{
if (!Directory.Exists(_managedDependenciesRootPath))
{
return Enumerable.Empty<string>();
}
return Directory.EnumerateDirectories(
_managedDependenciesRootPath,
DependencySnapshotFolderNameTools.InstalledPattern);
}
private DependencyManifest GetAppDependencyManifest()
{
return new DependencyManifest(_functionAppRootPath);
}
}
}