Skip to content
Snippets Groups Projects
Commit 0304e182 authored by Stanley Goldman's avatar Stanley Goldman
Browse files

Start of PortableGitManagerTests

parent 52a5023c
No related branches found
No related tags found
No related merge requests found
Showing
with 477 additions and 155 deletions
......@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http-net_3_5", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CopyLibrariesToDevelopmentFolder", "src\packaging\CopyLibrariesToDevelopmentFolder\CopyLibrariesToDevelopmentFolder.csproj", "{44257C81-EE4A-4817-9AF4-A26C02AA6DD4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitHub.Api.Tests", "src\GitHub.Api.Tests\GitHub.Api.Tests.csproj", "{1AC3F82E-AEAE-4C84-825C-207BB264FCFA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -61,6 +63,10 @@ Global
{44257C81-EE4A-4817-9AF4-A26C02AA6DD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44257C81-EE4A-4817-9AF4-A26C02AA6DD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44257C81-EE4A-4817-9AF4-A26C02AA6DD4}.Release|Any CPU.Build.0 = Release|Any CPU
{1AC3F82E-AEAE-4C84-825C-207BB264FCFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AC3F82E-AEAE-4C84-825C-207BB264FCFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AC3F82E-AEAE-4C84-825C-207BB264FCFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AC3F82E-AEAE-4C84-825C-207BB264FCFA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
......@@ -15,6 +15,7 @@ using System.Runtime.InteropServices;
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: InternalsVisibleTo("GitHub.Unity.Tests", AllInternalsVisible = true)]
[assembly: InternalsVisibleTo("GitHub.Api.Tests", AllInternalsVisible = true)]
//Required for NSubstitute
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2", AllInternalsVisible = true)]
......
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1AC3F82E-AEAE-4C84-825C-207BB264FCFA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GitHub.Unity.Tests</RootNamespace>
<AssemblyName>GitHub.Api.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FluentAssertions.4.19.0\lib\net45\FluentAssertions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FluentAssertions.Core, Version=4.19.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FluentAssertions.4.19.0\lib\net45\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NSubstitute, Version=2.0.1.0, Culture=neutral, PublicKeyToken=92dd2e9066daa5ca, processorArchitecture=MSIL">
<HintPath>..\..\packages\NSubstitute.2.0.1-rc\lib\net45\NSubstitute.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.6.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PortableGitManagerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GitHub.Api\GitHub.Api.csproj">
<Project>{b389adaf-62cc-486e-85b4-2d8b078df763}</Project>
<Name>GitHub.Api</Name>
</ProjectReference>
<ProjectReference Include="..\GitHub.Logging\GitHub.Logging.csproj">
<Project>{bb6a8eda-15d8-471b-a6ed-ee551e0b3ba0}</Project>
<Name>GitHub.Logging</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<ProjectConfiguration>
<Settings>
<PreviouslyBuiltSuccessfully>True</PreviouslyBuiltSuccessfully>
</Settings>
</ProjectConfiguration>
\ No newline at end of file
using GitHub.Api;
using NSubstitute;
using NUnit.Framework;
namespace GitHub.Unity.Tests
{
[TestFixture]
public class PortableGitManagerTests
{
private const string Extensionfolder = @"c:\ExtensionFolder";
private const string WindowsPortableGitZip = Extensionfolder + @"\resources\windows\PortableGit.zip";
private static IEnvironment CreateEnvironment()
{
var environment = Substitute.For<IEnvironment>();
environment.ExtensionInstallPath.Returns(Extensionfolder);
return environment;
}
private static IFileSystem CreateFileSystem()
{
var fileSystem = Substitute.For<IFileSystem>();
var realFileSystem = new FileSystem();
fileSystem.Combine(Arg.Any<string>(), Arg.Any<string>())
.Returns(info => realFileSystem.Combine((string)info[0], (string)info[1]));
fileSystem.FileExists(WindowsPortableGitZip).Returns(info => true);
var archiveFolderName = realFileSystem.GetRandomFileName();
fileSystem.GetRandomFileName().Returns(info => archiveFolderName);
return fileSystem;
}
private static ISharpZipLibHelper CreateSharpZipLibHelper()
{
var sharpZipLibHelper = Substitute.For<ISharpZipLibHelper>();
return sharpZipLibHelper;
}
[OneTimeSetUp]
public void TestFixtureSetup()
{
Logging.LoggerFactory = s => new ConsoleLogAdapter(s);
}
[Test]
public void Test()
{
var environment = CreateEnvironment();
var sharpZipLibHelper = CreateSharpZipLibHelper();
var fileSystem = CreateFileSystem();
var portableGitManager = new PortableGitManager(environment, fileSystem, sharpZipLibHelper);
portableGitManager.ExtractGitIfNeeded();
}
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("GitHub.Api.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GitHub.Api.Tests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1ac3f82e-aeae-4c84-825c-207bb264fcfa")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAssertions" version="4.19.0" targetFramework="net452" />
<package id="NSubstitute" version="2.0.1-rc" targetFramework="net452" />
<package id="NUnit" version="3.6.0" targetFramework="net452" />
</packages>
\ No newline at end of file
......@@ -44,6 +44,10 @@
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup>
<StartupObject>
</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="AsyncBridge.Net35, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b3b1c0202c0d6a87, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)packages\AsyncBridge.Net35.0.2.0\lib\net35-Client\AsyncBridge.Net35.dll</HintPath>
......@@ -76,15 +80,17 @@
<Compile Include="Authentication\ILoginManager.cs" />
<Compile Include="Installer\ICleanupService.cs" />
<Compile Include="Installer\IPortableGitManager.cs" />
<Compile Include="Installer\ISharpZipLibHelper.cs" />
<Compile Include="Installer\PortableGitManager.cs" />
<Compile Include="Installer\PortablePackageManager.cs" />
<Compile Include="Installer\ProgressResult.cs" />
<Compile Include="Installer\Util.cs" />
<Compile Include="Installer\SharpZipLibHelper.cs" />
<Compile Include="Localization.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Localization.resx</DependentUpon>
</Compile>
<Compile Include="Platform\FileSystem.cs" />
<Compile Include="Platform\GitEnvironment.cs" />
<Compile Include="Platform\IFileSystem.cs" />
<Compile Include="Platform\IGitEnvironment.cs" />
......
namespace GitHub.Helpers
namespace GitHub.Api
{
/// <summary>
/// Represents a service that needs to perform some cleanup when the app starts up.
/// </summary>
public interface ICleanupService
interface ICleanupService
{
/// <summary>
/// Called when the app starts, this method performs some cleanup.
......
namespace GitHub.PortableGit.Helpers
namespace GitHub.Api
{
public interface IPortableGitManager
interface IPortableGitManager
{
// void ExtractGitIfNeeded();
// void EnsureSystemConfigFileExtracted();
......
namespace GitHub.Api
{
interface ISharpZipLibHelper
{
void ExtractZipFile(string archive, string outFolder);
}
}
\ No newline at end of file
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using GitHub.Api;
using GitHub.Helpers;
namespace GitHub.PortableGit.Helpers
namespace GitHub.Api
{
public class PortableGitManager : PortablePackageManager, IPortableGitManager
class PortableGitManager : PortablePackageManager, IPortableGitManager
{
readonly Lazy<string> gitExecutablePath;
readonly Lazy<string> gitEtcDirPath;
......@@ -67,8 +63,8 @@ namespace GitHub.PortableGit.Helpers
// () => operatingSystem.GetFile(Path.Combine(EtcDirectoryPath, "gitconfig")));
// }
public PortableGitManager(IEnvironment environment)
: base(environment)
public PortableGitManager(IEnvironment environment, IFileSystem fileSystem, ISharpZipLibHelper sharpZipLibHelper)
: base(environment, fileSystem, sharpZipLibHelper)
{
}
......@@ -94,7 +90,7 @@ namespace GitHub.PortableGit.Helpers
/// extracted, this will return 100 and Complete.</returns>
public void ExtractGitIfNeeded()
{
ExtractPackageIfNeeded("PortableGit.zip", null, null, 5221);
ExtractPackageIfNeeded("PortableGit.zip", null, null);
}
void ExecuteBashLogin()
......
using System;
using System.Collections.Concurrent;
using System.Globalization;
using System.IO;
using GitHub.Api;
using GitHub.Unity;
namespace GitHub.Helpers
namespace GitHub.Api
{
public abstract class PortablePackageManager : ICleanupService
abstract class PortablePackageManager : ICleanupService
{
private readonly IEnvironment environment;
private readonly ILogging log = Logging.GetLogger<PortablePackageManager>();
private readonly IFileSystem fileSystem;
private readonly ISharpZipLibHelper sharpZipLibHelper;
private readonly ILogging logger;
private const string TemporaryFolderSuffix = ".deleteme";
private const string WindowsPortableGitZip = @"resources\windows\PortableGit.zip";
readonly ConcurrentDictionary<string, ProgressResult> extractResults =
new ConcurrentDictionary<string, ProgressResult>();
readonly ConcurrentDictionary<string, bool> extractResults =
new ConcurrentDictionary<string, bool>();
// readonly IOperatingSystem operatingSystem;
readonly IProgram program;
// readonly IZipArchive zipArchive;
// protected PortablePackageManager(IOperatingSystem operatingSystem, IProgram program, IZipArchive zipArchive)
protected PortablePackageManager(IEnvironment environment)
protected PortablePackageManager(IEnvironment environment, IFileSystem fileSystem, ISharpZipLibHelper sharpZipLibHelper)
{
this.environment = environment;
Guard.ArgumentNotNull(environment, nameof(environment));
Guard.ArgumentNotNull(fileSystem, nameof(fileSystem));
Guard.ArgumentNotNull(sharpZipLibHelper, nameof(sharpZipLibHelper));
// Ensure.ArgumentNotNull(operatingSystem, "operatingSystem");
// Ensure.ArgumentNotNull(program, "program");
// Ensure.ArgumentNotNull(zipArchive, "zipArchive");
//
// this.operatingSystem = operatingSystem;
// this.program = program;
// this.zipArchive = zipArchive;
logger = Logging.GetLogger(GetType());
this.environment = environment;
this.fileSystem = fileSystem;
this.sharpZipLibHelper = sharpZipLibHelper;
}
// protected IOperatingSystem OperatingSystem { get { return operatingSystem; } }
public bool IsPackageExtracted()
{
var target = GetPackageDestinationDirectory();
throw new NotImplementedException();
// var target = GetPackageDestinationDirectory();
// var canaryFile = operatingSystem.GetFile(GetPathToCanary(target));
// if (!canaryFile.Exists) return false;
//
......@@ -85,18 +87,15 @@ namespace GitHub.Helpers
// return GetPackageName() + "_" + GetExpectedVersion();
}
// protected PathString RootPackageDirectory
// {
// get { return operatingSystem.Environment.LocalGitHubApplicationDataPath; }
// }
protected void ExtractPackageIfNeeded(string fileName, Action preExtract = null, Action postExtract = null,
int? estimatedFileCount = null)
protected string RootPackageDirectory
{
var newResult = new ProgressResult();
get { throw new NotImplementedException();}
}
var extractResult = extractResults.GetOrAdd(fileName, newResult);
if (extractResult != newResult)
protected void ExtractPackageIfNeeded(string fileName, Action preExtract = null, Action postExtract = null)
{
var extractResult = extractResults.GetOrAdd(fileName, false);
if (!extractResult)
{
return;
}
......@@ -104,101 +103,54 @@ namespace GitHub.Helpers
// First, check to see if we're already done
if (IsPackageExtracted())
{
log.Info("Already extracted {0}, returning", fileName);
logger.Info("Already extracted {0}, returning", fileName);
return;
}
// return Observable.Defer(() =>
// {
if (preExtract != null)
{
preExtract();
}
string environmentPath = null;
var tempPath = Path.Combine(environmentPath, Path.GetRandomFileName());
// IDirectory temporaryDirectory;
// try
// {
// temporaryDirectory = operatingSystem.GetDirectory(tempPath);
// temporaryDirectory.Create();
// }
// catch (Exception ex)
// {
// log.Error("Couldn't create temp dir: " + tempPath, ex);
// extractResult.OnError(ex);
// return extractResult;
// }
//
// var archiveFilePath = Path.Combine(program.ExecutingAssemblyDirectory, fileName);
// var archiveFile = operatingSystem.GetFile(archiveFilePath);
// if (!archiveFile.Exists)
// {
// var exception = new FileNotFoundException("Could not find file", archiveFilePath);
// log.Error(String.Format(CultureInfo.InvariantCulture, "Trying to extract {0}, but it doesn't exist", archiveFilePath), exception);
// extractResult.OnError(exception);
// return extractResult;
// }
//
// var proc = zipArchive.ExtractToDirectory(archiveFilePath, temporaryDirectory.FullName);
//
// IObservable<ProgressResult> progress;
// if (estimatedFileCount != null)
// {
// progress = proc.CombinedOutput
// .TakeUntil(proc)
// .Scan(0, (acc, _) => acc + 1)
// .Select(x => (int)(((double)x / estimatedFileCount) * 95.0))
// .Select(x => new ProgressResult(x));
// }
// else
// {
// progress = Observable.Timer(DateTimeOffset.MinValue, TimeSpan.FromSeconds(0.5), RxApp.TaskpoolScheduler)
// .TakeUntil(proc)
// .Select(x => (int)Math.Min(x * 5, 95))
// .Select(x => new ProgressResult(x));
// }
//
// progress = progress
// .Concat(Observable.Return(new ProgressResult(95)))
// .Concat(Observable.Defer(() =>
// // It's conceivable that during the time we've been extracting the
// // package another process of GHfW has completed the extract so
// // right before we do the final move we'll do another check to see
// // if it's already extracted. If it is we'll bail and let the scavenger
// // take care of cleaning us up on the next run.
// IsPackageExtracted()
// ? Observable.Return(new ProgressResult(100))
// : MoveTemporaryPackageToFinalDestination(temporaryDirectory)));
//
// var ret = progress
// .Multicast(extractResult);
//
// // We Multicast so if someone subscribes later, they'll just see
// // "100, Finished" as fast as possible (since the op already finished)
// log.Info(CultureInfo.InvariantCulture, "Extracting {0} is (so far) successful", fileName);
// ret.Connect();
//
// return extractResult.Do(_ => {},
// ex =>
// {
// log.Warn("Failed to extract package successfully: " + fileName, ex);
// ReplaySubject<ProgressResult> res;
// extractResults.TryRemove(fileName, out res);
// }, () =>
// {
// ReplaySubject<ProgressResult> res;
// extractResults.TryRemove(fileName, out res);
// log.Info("Extracted package successfully: " + fileName);
//
// if (postExtract != null)
// {
// postExtract();
// }
// });
// });
var environmentPath = environment.ExtensionInstallPath;
var tempPath = Path.Combine(environmentPath, fileSystem.GetRandomFileName() + TemporaryFolderSuffix);
var archiveFilePath = Path.Combine(environmentPath, WindowsPortableGitZip);
try
{
fileSystem.CreateDirectory(tempPath);
}
catch (Exception ex)
{
logger.Error(ex, "Couldn't create temp dir: " + tempPath);
extractResults.TryRemove(fileName, out extractResult);
throw;
}
if (!fileSystem.FileExists(archiveFilePath))
{
var exception = new FileNotFoundException("Could not find file", archiveFilePath);
logger.Error(exception, "Trying to extract {0}, but it doesn't exist", archiveFilePath);
extractResults.TryRemove(fileName, out extractResult);
throw exception;
}
try
{
sharpZipLibHelper.ExtractZipFile(archiveFilePath, tempPath);
}
catch (Exception ex)
{
logger.Error(ex, "Error Extracting Archive:\"{0}\" OutDir:\"{1}\"", archiveFilePath, tempPath);
extractResults.TryRemove(fileName, out extractResult);
throw;
}
}
// IObservable<ProgressResult> MoveTemporaryPackageToFinalDestination(IDirectory temporaryDirectory)
......
using System.Globalization;
using System.Text.RegularExpressions;
using System;
namespace GitHub.Helpers
namespace GitHub.Api
{
public class ProgressResult
{
public ProgressResult() { }
public ProgressResult(int value) : this(value, string.Empty) { }
public ProgressResult(int value, string text)
public ProgressResult()
{}
public ProgressResult(int value)
{
ProgressValue = value;
ProgressText = text;
}
public int ProgressValue { get; private set; }
public string ProgressText { get; private set; }
static readonly Regex userFacingCloneMessageRegex = new Regex(
@"^(Cloning into \'|Receiving objects\:|Resolving deltas\:|Checking out files\:|Fetching from upstream repo \')",
RegexOptions.Compiled | RegexOptions.Singleline);
public bool IsUserFacingMessage
public ProgressResult(Exception exception)
{
get { return userFacingCloneMessageRegex.IsMatch(ProgressText); }
Exception = exception;
}
// public override string ToString()
// {
// return string.IsNullOrWhiteSpace(ProgressText)
// ? ProgressValue.ToString(CultureInfo.InvariantCulture)
// : string.Format(CultureInfo.InvariantCulture, "{0} - '{1}'", ProgressValue, ProgressText);
// }
public Exception Exception { get; private set; }
public int ProgressValue { get; private set; }
}
}
\ No newline at end of file
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
namespace GitHub.Api.Installer
namespace GitHub.Api
{
class Util
class SharpZipLibHelper : ISharpZipLibHelper
{
void ExtractZipFile(string archive, string outFolder)
public static bool Copy(Stream source, Stream destination, int chunkSize, long totalSize,
Func<long, long, bool> progress, int progressUpdateRate)
{
ZipFile zf = null;
EstimatedDuration = 1L;
DateTime startTime = DateTime.Now;
int processed = 0;
long totalBytes = 0L;
try
{
FileStream fs = File.OpenRead(archive);
zf = new ZipFile(fs);
foreach (ZipEntry zipEntry in zf)
{
if (zipEntry.IsDirectory)
continue; // Ignore directories
String entryFileName = zipEntry.Name;
// to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
// Optionally match entrynames against a selection list here to skip as desired.
// The unpacked length is available in the zipEntry.Size property.
Stream zipStream = zf.GetInputStream(zipEntry);
String fullZipToPath = Path.Combine(outFolder, entryFileName);
string directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
Directory.CreateDirectory(directoryName);
#if !WINDOWS
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
{
if (zipEntry.ExternalFileAttributes > 0)
{
int fd = Mono.Unix.Native.Syscall.open(fullZipToPath,
Mono.Unix.Native.OpenFlags.O_CREAT | Mono.Unix.Native.OpenFlags.O_TRUNC,
(Mono.Unix.Native.FilePermissions)zipEntry.ExternalFileAttributes);
Mono.Unix.Native.Syscall.close(fd);
}
}
#endif
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
FileInfo targetFile = new FileInfo(fullZipToPath);
using (FileStream streamWriter = targetFile.OpenWrite())
{
Utils.Copy(zipStream, streamWriter, 4096, targetFile.Length,
(totalRead, timeToFinish) =>
{
EstimatedDuration = timeToFinish;
UpdateProgress((float)(totalBytes + totalRead) / targetFile.Length);
return !CancelRequested;
},
100);
//Utils.Copy (zipStream, streamWriter, 4096);// 4K is optimum
}
targetFile.LastWriteTime = zipEntry.DateTime;
processed++;
totalBytes += zipEntry.Size;
double elapsedMillisecondsPerFile = (DateTime.Now - startTime).TotalMilliseconds / processed;
EstimatedDuration = Math.Max(1L, (long)((fs.Length - totalBytes) * elapsedMillisecondsPerFile));
UpdateProgress((float)processed / zf.Size);
}
}
catch
{
throw;
}
finally
{
if (zf != null)
{
//zf.IsStreamOwner = true; // Makes close also shut the underlying stream
zf.Close(); // Ensure we release resources
}
}
}
public static bool Copy(Stream source, Stream destination,
int chunkSize, long totalSize, Func<long, long, bool> progress, int progressUpdateRate)
{
byte[] buffer = new byte[chunkSize];
int bytesRead = 0;
var buffer = new byte[chunkSize];
var bytesRead = 0;
long totalRead = 0;
float averageSpeed = -1f;
float lastSpeed = 0f;
float smoothing = 0.005f;
var averageSpeed = -1f;
var lastSpeed = 0f;
var smoothing = 0.005f;
long readLastSecond = 0;
long timeToFinish = 0;
Stopwatch watch = null;
bool success = true;
var success = true;
bool trackProgress = totalSize > 0 && progress != null;
var trackProgress = totalSize > 0 && progress != null;
if (trackProgress)
{
watch = new Stopwatch();
}
do
{
if (trackProgress)
{
watch.Start();
}
bytesRead = source.Read(buffer, 0, chunkSize);
if (trackProgress)
{
watch.Stop();
}
totalRead += bytesRead;
......@@ -131,20 +54,112 @@ namespace GitHub.Api.Installer
watch.Reset();
lastSpeed = readLastSecond;
readLastSecond = 0;
averageSpeed = averageSpeed < 0f ? lastSpeed : smoothing * lastSpeed + (1f - smoothing) * averageSpeed;
timeToFinish = Math.Max(1L, (long)((totalSize - totalRead) / (averageSpeed / progressUpdateRate)));
averageSpeed = averageSpeed < 0f
? lastSpeed
: smoothing * lastSpeed + (1f - smoothing) * averageSpeed;
timeToFinish = Math.Max(1L,
(long)((totalSize - totalRead) / (averageSpeed / progressUpdateRate)));
if (!progress(totalRead, timeToFinish))
{
break;
}
}
}
}
} while (bytesRead > 0);
if (totalRead > 0)
{
destination.Flush();
}
return success;
}
public void ExtractZipFile(string archive, string outFolder)
{
ZipFile zf = null;
// EstimatedDuration = 1L;
var startTime = DateTime.Now;
var processed = 0;
var totalBytes = 0L;
try
{
var fs = File.OpenRead(archive);
zf = new ZipFile(fs);
foreach (ZipEntry zipEntry in zf)
{
if (zipEntry.IsDirectory)
{
continue; // Ignore directories
}
var entryFileName = zipEntry.Name;
// to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
// Optionally match entrynames against a selection list here to skip as desired.
// The unpacked length is available in the zipEntry.Size property.
var zipStream = zf.GetInputStream(zipEntry);
var fullZipToPath = Path.Combine(outFolder, entryFileName);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
{
Directory.CreateDirectory(directoryName);
}
//#if !WINDOWS
// if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
// {
// if (zipEntry.ExternalFileAttributes > 0)
// {
// int fd = Mono.Unix.Native.Syscall.open(fullZipToPath,
// Mono.Unix.Native.OpenFlags.O_CREAT | Mono.Unix.Native.OpenFlags.O_TRUNC,
// (Mono.Unix.Native.FilePermissions)zipEntry.ExternalFileAttributes);
// Mono.Unix.Native.Syscall.close(fd);
// }
// }
//#endif
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
var targetFile = new FileInfo(fullZipToPath);
using (var streamWriter = targetFile.OpenWrite())
{
Copy(zipStream, streamWriter, 4096, targetFile.Length, (totalRead, timeToFinish) => {
// EstimatedDuration = timeToFinish;
// UpdateProgress((float)(totalBytes + totalRead) / targetFile.Length);
// return !CancelRequested;
return true;
}, 100);
//Utils.Copy (zipStream, streamWriter, 4096);// 4K is optimum
}
targetFile.LastWriteTime = zipEntry.DateTime;
processed++;
totalBytes += zipEntry.Size;
//var elapsedMillisecondsPerFile = (DateTime.Now - startTime).TotalMilliseconds / processed;
//EstimatedDuration = Math.Max(1L, (long)((fs.Length - totalBytes) * elapsedMillisecondsPerFile));
//UpdateProgress((float)processed / zf.Size);
}
}
catch
{
throw;
}
finally
{
if (zf != null)
{
//zf.IsStreamOwner = true; // Makes close also shut the underlying stream
zf.Close(); // Ensure we release resources
}
}
}
}
}
using GitHub.Api;
using System.Collections.Generic;
using System.IO;
namespace GitHub.Unity
namespace GitHub.Api
{
class FileSystem : IFileSystem
{
......@@ -45,5 +44,15 @@ namespace GitHub.Unity
{
return Directory.GetParent(path).FullName;
}
public string GetRandomFileName()
{
return Path.GetRandomFileName();
}
public void CreateDirectory(string path)
{
Directory.CreateDirectory(path);
}
}
}
\ No newline at end of file
......@@ -12,5 +12,7 @@ namespace GitHub.Api
string GetDirectoryName(string path);
bool DirectoryExists(string path);
string GetParentDirectory(string path);
string GetRandomFileName();
void CreateDirectory(string path);
}
}
\ No newline at end of file
......@@ -5,4 +5,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("GitHub.Logging")]
[assembly: AssemblyDescription("GitHub Logging")]
[assembly: Guid("bb6a8eda-15d8-471b-a6ed-ee551e0b3ba0")]
[assembly: InternalsVisibleTo("GitHub.Api", AllInternalsVisible = true)]
[assembly: InternalsVisibleTo("GitHub.Unity", AllInternalsVisible = true)]
......@@ -75,7 +75,6 @@
<Compile Include="IO\BaseOutputProcessor.cs" />
<Compile Include="IO\BranchListOutputProcessor.cs" />
<Compile Include="IO\DefaultEnvironment.cs" />
<Compile Include="IO\FileSystem.cs" />
<Compile Include="IO\GitRemote.cs" />
<Compile Include="IO\GitStatusEntry.cs" />
<Compile Include="IO\GitObjectFactory.cs" />
......@@ -223,7 +222,7 @@
<PropertyGroup>
</PropertyGroup>
<Target Name="CleanUnityFiles" AfterTargets="Clean">
<Exec Command="for %%i in ($(SolutionDir)unity\TestProject\Assets\Editor\*) do if not %%i == $(SolutionDir)unity\TestProject\Assets\Editor\.placeholder echo %%i"/>
<Exec Command="for %%i in ($(SolutionDir)unity\TestProject\Assets\Editor\*) do if not %%i == $(SolutionDir)unity\TestProject\Assets\Editor\.placeholder echo %%i" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment