This commit is contained in:
Raúl Alarcón 2017-03-13 18:05:52 +01:00
Родитель a29dde58ce
Коммит 902728992e
10 изменённых файлов: 291 добавлений и 97 удалений

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

@ -13,7 +13,7 @@ Write-Host "Version Number" $versionNumber
Write-Host "Destination Directory" $destinationDirectory
Write-Host "Destination File" $destinationFile
$TfsBuildVersionRegEx = "_v(\d+)\.(\S+)\.(\d+)"
$TfsBuildVersionRegEx = "_(\d+)\.(\S+)\.(\d+)"
if($buildNumber -match $TfsBuildVersionRegEx){

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

@ -22,6 +22,7 @@ namespace Microsoft.Templates.Core
public string RepositoryFolderName { get; set; } = @"UWPTemplates";
public TraceEventType DiagnosticsTraceLevel { get; set; } = TraceEventType.Verbose;
public int DaysToKeepDiagnosticsLogs { get; set; } = 5;
public int DaysToKeepTempDownloads { get; set; } = 5;
public int VersionCheckingExpirationMinutes { get; set; } = 5;
public List<string> AllowedPublicKeysPins { get; set; } = new List<string>() { };

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

@ -9,21 +9,29 @@ namespace Microsoft.Templates.Core.Locations
{
public class LocalTemplatesLocation : TemplatesLocation
{
public override void Adquire(string workingFolder)
protected override string LocationId { get => "Local"; }
public override void Adquire()
{
//NO ADQUSITION REQUIRED;
}
public override bool Update(string workingFolder)
public override bool Update()
{
var targetFolder = Path.Combine(workingFolder, TemplatesName);
Copy($@"..\..\..\..\..\{TemplatesLocation.TemplatesName}", targetFolder);
File.WriteAllText(Path.Combine(targetFolder, VersionFileName), $"1.0.0-local{DateTime.Now.ToString("yyyyMMddHHmmss")}");
Copy($@"..\..\..\..\..\{TemplatesLocation.TemplatesName}", CurrentTemplatesVersionFolder);
File.WriteAllText(CurrentTemplatesVersionFilePath, $"0.0.0.0");
return true;
}
public override void Purge()
{
//No purge required
}
protected override string GetCurrentTemplatesFolderName() {
return "0.0.0.0-local";
}
protected static void Copy(string sourceFolder, string targetFolder)
{
SafeDelete(targetFolder);
SafeDeleteDirectory(targetFolder);
CopyRecursive(sourceFolder, targetFolder);
}
}

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

@ -16,36 +16,68 @@ namespace Microsoft.Templates.Core.Locations
private readonly string CdnUrl = Configuration.Current.CdnUrl;
private const string CdnTemplatesFileName = "Templates.mstx";
protected override string LocationId { get => "Remote_" + CdnUrl.Obfuscate(); }
public override void Adquire(string workingFolder)
public override void Adquire()
{
Download(workingFolder, CdnTemplatesFileName);
Download();
}
public override bool Update(string workingFolder)
public override bool Update()
{
return UpdateTemplates(workingFolder);
}
private void Download(string workingFolder, string fileName)
{
if (IsDownloadExpired(workingFolder))
bool updated = UpdateTemplates();
if (updated)
{
var sourceUrl = $"{CdnUrl}/{fileName}";
var tempFolder = Path.Combine(workingFolder, TempFolderName);
var file = Path.Combine(workingFolder, fileName);
RefreshWorkingFolders();
}
return updated;
}
public override void Purge()
{
PurgeOldContent();
}
protected override string GetCurrentTemplatesFolderName()
{
Version latestVersion = new Version(0, 0, 0, 0);
string currentTemplatesFolder = string.Empty;
if (Directory.Exists(TemplatesFolder))
{
DirectoryInfo di = new DirectoryInfo(TemplatesFolder);
foreach (DirectoryInfo sdi in di.EnumerateDirectories())
{
Version.TryParse(sdi.Name, out Version v);
EnsureWorkingFolder(workingFolder);
if (v > latestVersion)
{
currentTemplatesFolder = sdi.Name;
}
//TODO: Version DOWNLOADED (EXISTING IN TEMP FOLDER MUST BE COORDINATED WIHT THE EXTENSION Mayor.Minor;
}
}
return currentTemplatesFolder;
}
private void Download()
{
if (IsDownloadExpired())
{
var sourceUrl = $"{CdnUrl}/{CdnTemplatesFileName}";
var tempFolder = Path.Combine(TempDownloadsFolder, Path.GetRandomFileName());
var file = Path.Combine(LocationFolder, CdnTemplatesFileName);
EnsureFolder(LocationFolder);
EnsureFolder(tempFolder);
DownloadContent(sourceUrl, file);
ExtractContent(file, tempFolder);
}
}
private bool IsDownloadExpired(string workingFolder)
private bool IsDownloadExpired()
{
var currentFileVersion = Path.Combine(workingFolder, Path.Combine(TemplatesName, VersionFileName));
var currentFileVersion = CurrentTemplatesVersionFilePath;
if (!File.Exists(currentFileVersion))
{
return true;
@ -73,13 +105,19 @@ namespace Microsoft.Templates.Core.Locations
}
}
private static void ExtractContent(string file, string targetFolder)
private void ExtractContent(string file, string intermediateTempFolder)
{
try
{
Templatex.Extract(file, targetFolder);
var ver = GetVersionFromFile(Path.Combine(targetFolder, Path.Combine(TemplatesName, VersionFileName)));
AppHealth.Current.Verbose.TrackAsync($"Templates content extracted to {targetFolder}. Version adquired: {ver}").FireAndForget();
var ver = GetVersionFromPackage(file);
Templatex.Extract(file, intermediateTempFolder);
var finalTarget = Path.Combine(intermediateTempFolder, ver.ToString());
SafeMoveDirectory(Path.Combine(intermediateTempFolder, TemplatesName), finalTarget);
AppHealth.Current.Verbose.TrackAsync($"Templates content extracted to {finalTarget}. Version adquired: {ver.ToString()}").FireAndForget();
}
catch (Exception ex)
{
@ -96,15 +134,17 @@ namespace Microsoft.Templates.Core.Locations
}
}
private static bool UpdateTemplates(string workingFolder)
private bool UpdateTemplates()
{
bool templatesUpdated = false;
var tempFolder = Path.Combine(workingFolder, TempFolderName);
try
{
templatesUpdated = CopyContentIfNeeded(workingFolder);
SafeCleanUpTempFolder(tempFolder);
var tempContentFolder = GetTempContentFolder();
if (!String.IsNullOrEmpty(tempContentFolder) && Directory.Exists(tempContentFolder))
{
templatesUpdated = CopyContentIfNeeded(tempContentFolder);
//SafeDeleteDirectory(tempContentFolder);
}
}
catch (Exception ex)
{
@ -115,16 +155,34 @@ namespace Microsoft.Templates.Core.Locations
return templatesUpdated;
}
private static bool CopyContentIfNeeded(string workingFolder)
private string GetTempContentFolder()
{
DateTime latest = new DateTime(1900, 1, 1);
string latestDir = null;
if (Directory.Exists(TempDownloadsFolder))
{
DirectoryInfo di = new DirectoryInfo(TempDownloadsFolder);
foreach (DirectoryInfo sdi in di.EnumerateDirectories())
{
if (sdi.LastWriteTimeUtc > latest)
{
latest = sdi.LastWriteTimeUtc;
latestDir = sdi.FullName;
}
//TODO: Version DOWNLOADED (EXISTING IN TEMP FOLDER MUST BE COORDINATED WIHT THE EXTENSION Mayor.Minor;
}
}
return latestDir;
}
private bool CopyContentIfNeeded(string tempContentFolder)
{
bool updated = false;
string tempContentDir = Path.Combine(workingFolder, Path.Combine(TempFolderName, TemplatesName));
string currentContentDir = Path.Combine(workingFolder, TemplatesName);
if (UpdateAvailable(workingFolder))
if (UpdateAvailable(tempContentFolder))
{
SafeDelete(currentContentDir);
CopyRecursive(tempContentDir, currentContentDir);
CopyRecursive(tempContentFolder, TemplatesFolder);
AppHealth.Current.Warning.TrackAsync($"Templates successfully updated").FireAndForget();
updated = true;
@ -132,16 +190,14 @@ namespace Microsoft.Templates.Core.Locations
return updated;
}
private static bool UpdateAvailable(string workingFolder)
private bool UpdateAvailable(string tempContentFolder)
{
string tempContentDir = Path.Combine(workingFolder, Path.Combine(TempFolderName, TemplatesName));
string tempFileVersion = Path.Combine(tempContentDir, VersionFileName);
string currentFileVersion = Path.Combine(workingFolder, Path.Combine(TemplatesName, VersionFileName));
string tempFileVersion = GetVersionFilePathFromTempContentFolder(tempContentFolder);
var tempVersion = GetVersionFromFile(tempFileVersion);
var currentVersion = GetVersionFromFile(currentFileVersion);
var currentVersion = GetVersionFromFile(CurrentTemplatesVersionFilePath);
bool update = tempVersion != "0.0.0" && tempVersion != currentVersion;
bool update = tempVersion > currentVersion;
if (update)
{
@ -150,10 +206,23 @@ namespace Microsoft.Templates.Core.Locations
if (!update && tempVersion == currentVersion)
{
RefreshVersionFileExpiration(currentFileVersion, currentVersion);
RefreshVersionFileExpiration(CurrentTemplatesVersionFilePath, currentVersion.ToString());
}
return update;
}
private string GetVersionFilePathFromTempContentFolder(string tempContentFolder)
{
if (Directory.Exists(tempContentFolder))
{
return Directory.EnumerateFiles(tempContentFolder, VersionFileName, SearchOption.AllDirectories).FirstOrDefault();
}
else
{
return String.Empty;
}
}
private static void RefreshVersionFileExpiration(string installedVersionFile, string installedVersion)
{
if (File.Exists(installedVersionFile))
@ -162,28 +231,25 @@ namespace Microsoft.Templates.Core.Locations
}
}
private static void SafeCleanUpTempFolder(string usedTempFolder)
private static void EnsureFolder(string folder)
{
try
if (!Directory.Exists(folder))
{
if (Directory.Exists(usedTempFolder))
{
Directory.Delete(usedTempFolder, true);
}
}
catch (Exception ex)
{
var msg = $"The temp folder {usedTempFolder} can't be delete. Error: {ex.Message}";
AppHealth.Current.Warning.TrackAsync(msg).FireAndForget();
Directory.CreateDirectory(folder);
}
}
private static void EnsureWorkingFolder(string workingFolder)
private void PurgeOldContent()
{
if (!Directory.Exists(workingFolder))
DirectoryInfo di = new DirectoryInfo(TempDownloadsFolder);
var tobedeleted = di.EnumerateDirectories().Where(sdi => sdi.LastWriteTimeUtc.AddDays(Configuration.Current.DaysToKeepTempDownloads) < DateTime.UtcNow);
foreach (var sdi in tobedeleted)
{
Directory.CreateDirectory(workingFolder);
SafeDeleteDirectory(sdi.FullName);
}
//TODO: Purge old templates.
}
}
}

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

@ -1,6 +1,9 @@
using System;
using Microsoft.Templates.Core.Diagnostics;
using Microsoft.Templates.Core.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -9,28 +12,45 @@ namespace Microsoft.Templates.Core.Locations
{
public abstract class TemplatesLocation
{
public const string PackagesName = "Packages";
public const string TemplatesName = "Templates";
public const string VersionFileName = "version.txt";
public const string ProjectTypes = "Projects";
public const string Frameworks = "Frameworks";
public const string TempFolderName = "Temp";
public const string TempFolderName = "TempDownloads";
public abstract void Adquire(string workingFolder);
public abstract bool Update(string workingFolder);
public string TemplatesFolder { get; protected set; }
public string TempDownloadsFolder { get; protected set; }
public string GetVersion(string workingFolder)
public string CurrentTemplatesVersionFilePath { get; protected set; }
public string CurrentTemplatesVersionFolder { get; protected set; }
public string LocationFolder { get; protected set; }
private string _workingFolder = String.Empty;
public void InitializeWorkingFolder(string workingFolder)
{
var fileName = Path.Combine(workingFolder, Path.Combine(TemplatesName, VersionFileName));
return GetVersionFromFile(fileName);
_workingFolder = workingFolder;
RefreshWorkingFolders();
}
protected static void SafeDelete(string directoryPath)
protected void RefreshWorkingFolders()
{
if (Directory.Exists(directoryPath))
{
Directory.Delete(directoryPath, true);
}
LocationFolder = Path.Combine(_workingFolder, LocationId);
TemplatesFolder = Path.Combine(LocationFolder, TemplatesName);
TempDownloadsFolder = Path.Combine(LocationFolder, TempFolderName);
CurrentTemplatesVersionFolder = Path.Combine(TemplatesFolder, GetCurrentTemplatesFolderName());
CurrentTemplatesVersionFilePath = Path.Combine(CurrentTemplatesVersionFolder, VersionFileName);
}
protected abstract string LocationId { get; }
public abstract void Adquire();
public abstract bool Update();
public abstract void Purge();
protected abstract string GetCurrentTemplatesFolderName();
public string GetVersion()
{
return GetVersionFromFile(CurrentTemplatesVersionFilePath).ToString();
}
protected static void SafeCopyFile(string sourceFile, string destFolder)
@ -56,15 +76,74 @@ namespace Microsoft.Templates.Core.Locations
CopyRecursive(directory, Path.Combine(targetDir, Path.GetFileName(directory)));
}
}
protected static string GetVersionFromFile(string versionFilePath)
protected static void SafeDeleteDirectory(string dir)
{
var version = "0.0.0";
try
{
if (Directory.Exists(dir))
{
Directory.Delete(dir, true);
}
}
catch (Exception ex)
{
var msg = $"The folder {dir} can't be delete. Error: {ex.Message}";
AppHealth.Current.Warning.TrackAsync(msg, ex).FireAndForget();
}
}
protected static void SafeMoveDirectory(string sourceDir, string targetDir)
{
try
{
if (Directory.Exists(sourceDir))
{
Directory.Move(sourceDir, targetDir);
}
}
catch (Exception ex)
{
var msg = $"The folder {sourceDir} can't be moved to {targetDir}. Error: {ex.Message}";
AppHealth.Current.Warning.TrackAsync(msg, ex).FireAndForget();
}
}
protected static Version GetVersionFromFile(string versionFilePath)
{
var version = "0.0.0.0";
if (File.Exists(versionFilePath))
{
version = File.ReadAllText(versionFilePath);
version = File.ReadAllText(versionFilePath).Replace("v", ""); //TODO: quitar cuando no sea necesario.
}
return version;
if (!Version.TryParse(version, out Version result))
{
result = new Version(0, 0, 0, 0);
}
return result;
}
protected static Version GetVersionFromPackage(string packagePath)
{
string version = String.Empty;
if (File.Exists(packagePath))
{
using (ZipArchive zip = ZipFile.Open(packagePath, ZipArchiveMode.Read))
{
var versionFile = zip.Entries.Where(e => e.Name == $"{VersionFileName}").FirstOrDefault();
if (versionFile != null)
{
using (StreamReader sr = new StreamReader(versionFile.Open()))
{
version = sr.ReadToEnd().Replace("v", ""); //TODO: Quitar una vez se haya configurado bien la build.
}
}
}
}
if (!Version.TryParse(version, out Version result))
{
result = new Version(0, 0, 0, 0);
}
return result;
}
}
}

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

@ -32,11 +32,14 @@ namespace Microsoft.Templates.Core
private readonly Lazy<string> _workingFolder = new Lazy<string>(() => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), FolderName));
public string WorkingFolder => _workingFolder.Value;
private string FileVersionPath => Path.Combine(WorkingFolder, TemplatesLocation.TemplatesName, TemplatesLocation.VersionFileName);
public string CurrentTemplatesFolder { get => _location.CurrentTemplatesVersionFolder; }
//private string FileVersionPath => Path.Combine(WorkingFolder, TemplatesLocation.TemplatesName, TemplatesLocation.VersionFileName);
public TemplatesRepository(TemplatesLocation location)
{
_location = location ?? throw new ArgumentNullException("location");
_location.InitializeWorkingFolder(WorkingFolder);
}
public async Task SynchronizeAsync(bool forceUpdate = false)
@ -55,7 +58,7 @@ namespace Microsoft.Templates.Core
public string GetVersion()
{
return _location.GetVersion(WorkingFolder);
return _location.GetVersion();
}
private async Task AdquireContentAsync()
@ -69,7 +72,7 @@ namespace Microsoft.Templates.Core
{
try
{
_location.Adquire(WorkingFolder);
_location.Adquire();
}
catch (Exception ex)
{
@ -88,10 +91,10 @@ namespace Microsoft.Templates.Core
{
try
{
if (_location.Update(WorkingFolder))
if (_location.Update())
{
CodeGen.Instance.Cache.DeleteAllLocaleCacheFiles();
CodeGen.Instance.Cache.Scan(WorkingFolder + $@"\{TemplatesLocation.TemplatesName}");
CodeGen.Instance.Cache.Scan(CurrentTemplatesFolder);
CodeGen.Instance.Cache.WriteTemplateCaches();
}
}
@ -102,14 +105,13 @@ namespace Microsoft.Templates.Core
}
private bool ExistsTemplates()
{
string templatesDir = Path.Combine(WorkingFolder, TemplatesLocation.TemplatesName);
if (!Directory.Exists(templatesDir))
if (!Directory.Exists(_location.CurrentTemplatesVersionFolder))
{
return false;
}
else
{
DirectoryInfo di = new DirectoryInfo(templatesDir);
DirectoryInfo di = new DirectoryInfo(CurrentTemplatesFolder);
return di.EnumerateFiles("*", SearchOption.AllDirectories).Any();
}
}
@ -145,12 +147,12 @@ namespace Microsoft.Templates.Core
public ProjectInfo GetProjectTypeInfo(string projectType)
{
return GetProyectInfo(Path.Combine(WorkingFolder, TemplatesLocation.TemplatesName, TemplatesLocation.ProjectTypes, projectType, "Info"));
return GetProyectInfo(Path.Combine(CurrentTemplatesFolder, TemplatesLocation.ProjectTypes, projectType, "Info"));
}
public ProjectInfo GetFrameworkTypeInfo(string fxType)
{
return GetProyectInfo(Path.Combine(WorkingFolder, TemplatesLocation.TemplatesName, TemplatesLocation.Frameworks, fxType, "Info"));
return GetProyectInfo(Path.Combine(CurrentTemplatesFolder, TemplatesLocation.Frameworks, fxType, "Info"));
}
private ProjectInfo GetProyectInfo(string folderName)

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

@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("0.0.0.0")]

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

@ -50,7 +50,7 @@ namespace Microsoft.Templates.Core.Test
var target = GetTarget("ProjectTemplate");
var result = target.GetIcon();
var expected = Path.Combine(_fixture.Repository.WorkingFolder, @"Templates\ProjectTemplate", ".template.config",
var expected = Path.Combine(_fixture.Repository.CurrentTemplatesFolder, @"ProjectTemplate", ".template.config",
"icon.png");
Assert.Equal(expected, result);
}

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

@ -259,12 +259,40 @@ namespace Microsoft.Templates.Core.Test.Locations
}
[Fact]
public void UseRemote()
public void UseRemoteDownloadAndUpdate()
{
string workingFolder = Path.Combine(@"C:\Temp", Path.GetRandomFileName());
RemoteTemplatesLocation remote = new RemoteTemplatesLocation();
remote.Adquire(@"C:\Temp\WorkingFolder");
remote.InitializeWorkingFolder(workingFolder);
remote.Adquire();
Assert.True(remote.Update());
if (Directory.Exists(workingFolder))
{
Directory.Delete(workingFolder, true);
}
}
[Fact]
public void UseRemoteDownloadAndUpdateTwice()
{
string workingFolder = Path.Combine(@"C:\Temp", Path.GetRandomFileName());
RemoteTemplatesLocation remote = new RemoteTemplatesLocation();
remote.InitializeWorkingFolder(workingFolder);
remote.Adquire();
Assert.True(remote.Update());
remote.Adquire();
Assert.False(remote.Update());
if (Directory.Exists(workingFolder))
{
Directory.Delete(workingFolder, true);
}
}
private void ModifyContent(string signedPack, string contentFile)
{
using (ZipArchive zip = ZipFile.Open(signedPack, ZipArchiveMode.Update))

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

@ -6,21 +6,31 @@ namespace Microsoft.Templates.Core.Test.Locations
{
public class UnitTestsTemplatesLocation : TemplatesLocation
{
public override void Adquire(string workingFolder)
protected override string LocationId { get => "Unit"; }
public override void Adquire()
{
//NO ADQUSITION REQUIRED;
}
public override bool Update(string workingFolder)
public override bool Update()
{
var targetFolder = Path.Combine(workingFolder, TemplatesName);
Copy($@"..\..\TestData\{TemplatesLocation.TemplatesName}", targetFolder);
Copy($@"..\..\TestData\{TemplatesLocation.TemplatesName}", CurrentTemplatesVersionFolder);
File.WriteAllText(CurrentTemplatesVersionFilePath, $"0.0.0.0");
return true;
}
protected override string GetCurrentTemplatesFolderName()
{
return "0.0.0.0-unit";
}
public override void Purge()
{
//No purge required
}
protected static void Copy(string sourceFolder, string targetFolder)
{
SafeDelete(targetFolder);
SafeDeleteDirectory(targetFolder);
CopyRecursive(sourceFolder, targetFolder);
}
}