2016-08-22 13:31:52 -04:00
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
|
|
<!-- 7z Task -->
|
|
|
|
<UsingTask TaskName="_7z"
|
|
|
|
TaskFactory="CodeTaskFactory"
|
2016-08-25 19:45:57 -04:00
|
|
|
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
2016-08-22 13:31:52 -04:00
|
|
|
<ParameterGroup>
|
|
|
|
<Inputs Required="true" ParameterType="System.String" />
|
|
|
|
<Output Required="true" ParameterType="System.String" />
|
|
|
|
</ParameterGroup>
|
|
|
|
<Task>
|
|
|
|
<Using Namespace="System"/>
|
|
|
|
<Using Namespace="System.Diagnostics"/>
|
|
|
|
<Using Namespace="System.IO"/>
|
|
|
|
<Code Type="Method" Language="cs">
|
|
|
|
<![CDATA[
|
|
|
|
public override bool Execute()
|
|
|
|
{
|
|
|
|
string appPath = Find7zPath();
|
|
|
|
if (appPath == null)
|
|
|
|
{
|
|
|
|
Log.LogError("Unable to find 7z.exe.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-08-22 15:39:06 -04:00
|
|
|
var argsSB = new StringBuilder();
|
|
|
|
argsSB.Append("a -tzip -mx9 -mtc=off ");
|
|
|
|
argsSB.Append("\"" + Output + "\" ");
|
|
|
|
foreach (string input in Inputs.Split(';'))
|
|
|
|
{
|
|
|
|
argsSB.Append("\"" + input + "\" ");
|
|
|
|
}
|
|
|
|
string args = argsSB.ToString();
|
|
|
|
|
2016-08-22 13:31:52 -04:00
|
|
|
Log.LogMessage(MessageImportance.Normal, "7z " + args);
|
|
|
|
|
|
|
|
var psi = new ProcessStartInfo(appPath, args);
|
|
|
|
psi.CreateNoWindow = true;
|
|
|
|
psi.UseShellExecute = false;
|
|
|
|
psi.RedirectStandardOutput = true;
|
|
|
|
psi.RedirectStandardError = true;
|
|
|
|
var process = Process.Start(psi);
|
|
|
|
process.WaitForExit();
|
|
|
|
if (process.ExitCode != 0)
|
|
|
|
{
|
|
|
|
string appError = process.StandardError.ReadToEnd();
|
|
|
|
appError = appError.Replace("\r\n", "\n");
|
|
|
|
appError = appError.Replace("\r", "\n");
|
|
|
|
appError = appError.Replace("\n", " ");
|
|
|
|
int colonIndex = appError.IndexOf(":");
|
|
|
|
if (colonIndex != -1)
|
|
|
|
{
|
|
|
|
appError = appError.Substring(colonIndex + 1);
|
|
|
|
}
|
|
|
|
appError = appError.Trim();
|
|
|
|
Log.LogError(appError);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
string appOutput = process.StandardOutput.ReadToEnd();
|
|
|
|
Log.LogMessage(MessageImportance.Normal, appOutput);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private string Find7zPath()
|
|
|
|
{
|
|
|
|
const string DefaultAppFileName = "7z.exe";
|
|
|
|
string DefaultAppPath = Path.Combine("7-Zip", DefaultAppFileName);
|
|
|
|
|
|
|
|
// HACK needed as SpecialFolder.ProgramFiles returns x86 for a 32-bit process
|
|
|
|
string programFiles = Path.Combine(Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)), "Program Files");
|
|
|
|
string appPath = Path.Combine(programFiles, DefaultAppPath);
|
|
|
|
if (File.Exists(appPath))
|
|
|
|
{
|
|
|
|
return appPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
|
|
|
appPath = Path.Combine(programFiles, DefaultAppPath);
|
|
|
|
if (File.Exists(appPath))
|
|
|
|
{
|
|
|
|
return appPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
|
|
|
appPath = Path.Combine(programFiles, DefaultAppPath);
|
|
|
|
if (File.Exists(appPath))
|
|
|
|
{
|
|
|
|
return appPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
string[] envPaths = Environment.GetEnvironmentVariable("PATH").Split(';');
|
|
|
|
foreach (string envPath in envPaths)
|
|
|
|
{
|
|
|
|
appPath = Path.Combine(envPath, DefaultAppFileName);
|
|
|
|
if (File.Exists(appPath))
|
|
|
|
{
|
|
|
|
return appPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</Code>
|
|
|
|
</Task>
|
|
|
|
</UsingTask>
|
2016-08-25 19:45:57 -04:00
|
|
|
|
2016-12-16 17:41:11 -05:00
|
|
|
<!-- Unzip task -->
|
2016-08-25 19:45:57 -04:00
|
|
|
<UsingTask TaskName="Unzip"
|
|
|
|
TaskFactory="CodeTaskFactory"
|
|
|
|
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
|
|
|
<ParameterGroup>
|
|
|
|
<Input Required="true" ParameterType="System.String" />
|
|
|
|
<OutputDirectory Required="true" ParameterType="System.String" />
|
|
|
|
</ParameterGroup>
|
|
|
|
<Task>
|
|
|
|
<Reference Include="System.IO.Compression.FileSystem" />
|
|
|
|
<Code Type="Fragment" Language="cs">
|
|
|
|
<![CDATA[
|
|
|
|
Log.LogMessage(MessageImportance.Normal, String.Format("Extracting '{0}' to '{1}'.", Input, OutputDirectory));
|
|
|
|
System.IO.Compression.ZipFile.ExtractToDirectory(Input, OutputDirectory);
|
|
|
|
]]>
|
|
|
|
</Code>
|
|
|
|
</Task>
|
|
|
|
</UsingTask>
|
2016-12-16 17:41:11 -05:00
|
|
|
|
|
|
|
<!-- DownloadDependency task -->
|
|
|
|
<UsingTask TaskName="DownloadDependency"
|
|
|
|
TaskFactory="CodeTaskFactory"
|
|
|
|
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
|
|
|
<ParameterGroup>
|
|
|
|
<Name Required="true" ParameterType="System.String" />
|
|
|
|
<Url Required="true" ParameterType="System.String" />
|
2016-12-16 19:19:44 -05:00
|
|
|
<Sha1 Required="true" ParameterType="System.String" />
|
2016-12-16 17:41:11 -05:00
|
|
|
<CheckFile Required="false" ParameterType="System.String" />
|
|
|
|
<OutputDirectory Required="true" ParameterType="System.String" />
|
|
|
|
</ParameterGroup>
|
|
|
|
<Task>
|
|
|
|
<Reference Include="System.IO.Compression" />
|
|
|
|
<Reference Include="System.IO.Compression.FileSystem" />
|
|
|
|
<Using Namespace="System"/>
|
|
|
|
<Using Namespace="System.IO"/>
|
|
|
|
<Using Namespace="System.IO.Compression"/>
|
|
|
|
<Using Namespace="System.Net"/>
|
|
|
|
<Using Namespace="System.Text"/>
|
|
|
|
<Using Namespace="Microsoft.Build.Framework"/>
|
|
|
|
<Using Namespace="Microsoft.Build.Utilities"/>
|
|
|
|
<Code Type="Method" Language="cs">
|
|
|
|
<![CDATA[
|
|
|
|
public override bool Execute()
|
|
|
|
{
|
|
|
|
if (!String.IsNullOrEmpty(CheckFile))
|
|
|
|
{
|
|
|
|
string checkSha1 = GetSha1FromCheckFile(CheckFile, Name);
|
|
|
|
if (String.Equals(checkSha1, Sha1, StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
Log.LogMessage(MessageImportance.Normal, String.Format("{0} up to date", Name));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
string tempFile = Path.GetTempFileName();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Download the file
|
|
|
|
Log.LogMessage(MessageImportance.Normal, String.Format("Downloading '{0}'.", Url));
|
|
|
|
var client = new WebClient();
|
|
|
|
client.DownloadFile(Url, tempFile);
|
|
|
|
|
|
|
|
// Check the file matches
|
|
|
|
string actualSha1;
|
|
|
|
if (!CheckFileSha1(tempFile, Sha1, out actualSha1))
|
|
|
|
{
|
|
|
|
Log.LogError("Download file did not match expected SHA1\n expected: {0}\n actual: {1}", Sha1, actualSha1);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract contents
|
|
|
|
Log.LogMessage(MessageImportance.Normal, String.Format("Extracting to '{0}'.", OutputDirectory));
|
|
|
|
if (!Directory.Exists(OutputDirectory))
|
|
|
|
{
|
|
|
|
Directory.CreateDirectory(OutputDirectory);
|
|
|
|
}
|
|
|
|
ExtractZip(tempFile, OutputDirectory, overwrite: true);
|
|
|
|
|
|
|
|
SetSha1InCheckFile(CheckFile, Name, Sha1);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Log.LogErrorFromException(ex, showStackTrace: false);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
File.Delete(tempFile);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private string GetSha1FromCheckFile(string checkFile, string name)
|
|
|
|
{
|
|
|
|
string result = null;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (File.Exists(checkFile))
|
|
|
|
{
|
|
|
|
string[] lines = File.ReadAllLines(checkFile);
|
|
|
|
string sha1;
|
|
|
|
GetCheckFileLineIndexSha1(lines, name, out sha1);
|
|
|
|
return sha1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Log.LogWarningFromException(ex, showStackTrace: false);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void SetSha1InCheckFile(string checkFile, string name, string sha1)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
string newLine = String.Format("{0} = {1}", name, sha1.ToLower());
|
|
|
|
string[] lines = new string[0];
|
|
|
|
int lineIndex = -1;
|
|
|
|
if (File.Exists(checkFile))
|
|
|
|
{
|
|
|
|
lines = File.ReadAllLines(checkFile);
|
|
|
|
string oldsha1;
|
|
|
|
lineIndex = GetCheckFileLineIndexSha1(lines, name, out oldsha1);
|
|
|
|
}
|
|
|
|
if (lineIndex == -1)
|
|
|
|
{
|
|
|
|
if (lines.Length == 0 || lines[lines.Length - 1].Trim().Length > 0)
|
|
|
|
{
|
|
|
|
Array.Resize(ref lines, lines.Length + 1);
|
|
|
|
}
|
|
|
|
lineIndex = lines.Length - 1;
|
|
|
|
|
|
|
|
// End with new line
|
|
|
|
Array.Resize(ref lines, lines.Length + 1);
|
|
|
|
}
|
|
|
|
lines[lineIndex] = newLine;
|
|
|
|
File.WriteAllLines(checkFile, lines);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Log.LogWarningFromException(ex, showStackTrace: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private int GetCheckFileLineIndexSha1(string[] lines, string name, out string sha1)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
|
|
{
|
|
|
|
string line = lines[i];
|
|
|
|
string[] lineParts = line.Split('=');
|
|
|
|
if (lineParts.Length == 2)
|
|
|
|
{
|
|
|
|
string lineTag = lineParts[0].Trim();
|
|
|
|
string lineSha1 = lineParts[1].Trim();
|
|
|
|
if (lineTag == name)
|
|
|
|
{
|
|
|
|
sha1 = lineSha1;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sha1 = null;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool CheckFileSha1(string file, string expectedSha1, out string actualSha1)
|
|
|
|
{
|
|
|
|
using (var fs = new FileStream(file, FileMode.Open))
|
|
|
|
{
|
|
|
|
var hasher = System.Security.Cryptography.SHA1.Create();
|
|
|
|
byte[] hash = hasher.ComputeHash(fs);
|
|
|
|
actualSha1 = BytesToHexString(hash);
|
|
|
|
if (String.Equals(actualSha1, expectedSha1, StringComparison.OrdinalIgnoreCase))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private string BytesToHexString(byte[] data)
|
|
|
|
{
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
foreach (byte b in data)
|
|
|
|
{
|
|
|
|
sb.Append(b.ToString("x2"));
|
|
|
|
}
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void ExtractZip(string zipPath, string destinationDirectory, bool overwrite)
|
|
|
|
{
|
|
|
|
var archive = ZipFile.OpenRead(zipPath);
|
|
|
|
if (!overwrite)
|
|
|
|
{
|
|
|
|
archive.ExtractToDirectory(destinationDirectory);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
foreach (ZipArchiveEntry file in archive.Entries)
|
|
|
|
{
|
|
|
|
string fileName = Path.Combine(destinationDirectory, file.FullName);
|
|
|
|
if (file.Name == String.Empty)
|
|
|
|
{
|
|
|
|
string directory = Path.GetDirectoryName(fileName);
|
|
|
|
Directory.CreateDirectory(directory);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
file.ExtractToFile(fileName, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</Code>
|
|
|
|
</Task>
|
|
|
|
</UsingTask>
|
2016-08-22 13:31:52 -04:00
|
|
|
</Project>
|