diff --git a/src/Microsoft.DotNet.Archive/CompressionUtility.cs b/src/Microsoft.DotNet.Archive/CompressionUtility.cs index 11deeb311..0b4e937dc 100644 --- a/src/Microsoft.DotNet.Archive/CompressionUtility.cs +++ b/src/Microsoft.DotNet.Archive/CompressionUtility.cs @@ -1,4 +1,7 @@ -using SevenZip; +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using SevenZip; using System; using System.IO; diff --git a/src/Microsoft.DotNet.Archive/ConsoleProgressReport.cs b/src/Microsoft.DotNet.Archive/ConsoleProgressReport.cs index a3e1b8a52..636e35970 100644 --- a/src/Microsoft.DotNet.Archive/ConsoleProgressReport.cs +++ b/src/Microsoft.DotNet.Archive/ConsoleProgressReport.cs @@ -8,42 +8,43 @@ namespace Microsoft.DotNet.Archive { public class ConsoleProgressReport : IProgress { - string currentPhase; - int lastLineLength = 0; - double lastProgress = -1; - Stopwatch stopwatch; + private string _currentPhase; + private int _lastLineLength = 0; + private double _lastProgress = -1; + private Stopwatch _stopwatch; + private object _stateLock = new object(); public void Report(ProgressReport value) { long progress = (long)(100 * ((double)value.Ticks / value.Total)); - if (progress == lastProgress && value.Phase == currentPhase) + if (progress == _lastProgress && value.Phase == _currentPhase) { return; } - lastProgress = progress; + _lastProgress = progress; - lock (this) + lock (_stateLock) { string line = $"{value.Phase} {progress}%"; - if (value.Phase == currentPhase) + if (value.Phase == _currentPhase) { - Console.Write(new string('\b', lastLineLength)); + Console.Write(new string('\b', _lastLineLength)); Console.Write(line); - lastLineLength = line.Length; + _lastLineLength = line.Length; if (progress == 100) { - Console.WriteLine($" {stopwatch.ElapsedMilliseconds} ms"); + Console.WriteLine($" {_stopwatch.ElapsedMilliseconds} ms"); } } else { Console.Write(line); - currentPhase = value.Phase; - lastLineLength = line.Length; - stopwatch = Stopwatch.StartNew(); + _currentPhase = value.Phase; + _lastLineLength = line.Length; + _stopwatch = Stopwatch.StartNew(); } } } diff --git a/src/Microsoft.DotNet.Archive/IndexedArchive.cs b/src/Microsoft.DotNet.Archive/IndexedArchive.cs index caee1aac8..6e5e81030 100644 --- a/src/Microsoft.DotNet.Archive/IndexedArchive.cs +++ b/src/Microsoft.DotNet.Archive/IndexedArchive.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -47,24 +50,19 @@ namespace Microsoft.DotNet.Archive // maps file hash to archve path // $ prefix indicates that the file is not in the archive and path is a hash - Dictionary archiveFiles = new Dictionary(); + private Dictionary _archiveFiles = new Dictionary(); // maps file hash to external path - Dictionary externalFiles = new Dictionary(); + private Dictionary _externalFiles = new Dictionary(); // lists all extracted files & hashes - List destFiles = new List(); - bool disposed = false; - ThreadLocal sha = new ThreadLocal(() => SHA256.Create()); + private List _destFiles = new List(); + private bool _disposed = false; + private ThreadLocal _sha = new ThreadLocal(() => SHA256.Create()); public IndexedArchive() - { - - } - - + { } + private static Stream CreateTemporaryStream() { - // return new MemoryStream(); - string temp = Path.GetTempPath(); string tempFile = Path.Combine(temp, Guid.NewGuid().ToString()); return File.Create(tempFile, 4096, FileOptions.DeleteOnClose); @@ -74,7 +72,6 @@ namespace Microsoft.DotNet.Archive { string temp = Path.GetTempPath(); string tempFile = Path.Combine(temp, Guid.NewGuid().ToString()); - //return File.Create(tempFile, 4096, FileOptions.DeleteOnClose); return new FileStream(tempFile, FileMode.Create, FileAccess.ReadWrite, FileShare.Read | FileShare.Delete, 4096, FileOptions.DeleteOnClose); } @@ -82,8 +79,7 @@ namespace Microsoft.DotNet.Archive { CheckDisposed(); - //using (var archiveStream = CreateTemporaryStream()) - using (var archiveStream = File.Create(archivePath + ".zip")) + using (var archiveStream = CreateTemporaryStream()) { using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true)) { @@ -107,10 +103,10 @@ namespace Microsoft.DotNet.Archive using (var stream = indexEntry.Open()) using (var textWriter = new StreamWriter(stream)) { - foreach (var entry in destFiles) + foreach (var entry in _destFiles) { - var archiveFile = archiveFiles[entry.Hash]; - string archivePath = archiveFiles[entry.Hash].ArchivePath; + var archiveFile = _archiveFiles[entry.Hash]; + string archivePath = _archiveFiles[entry.Hash].ArchivePath; if (archiveFile.Stream == null) { archivePath = "$" + archivePath; @@ -121,7 +117,7 @@ namespace Microsoft.DotNet.Archive } // sort the files so that similar files are close together - var filesToArchive = archiveFiles.Values.ToList(); + var filesToArchive = _archiveFiles.Values.ToList(); filesToArchive.Sort((f1, f2) => { // first sort by extension @@ -337,7 +333,7 @@ namespace Microsoft.DotNet.Archive ExtractSource extractSource; if (!sourceCache.TryGetValue(source, out extractSource)) { - sourceCache[source] = extractSource = new ExtractSource(source, externalFiles, tlArchive); + sourceCache[source] = extractSource = new ExtractSource(source, _externalFiles, tlArchive); } var zipSeperatorIndex = target.IndexOf("::", StringComparison.OrdinalIgnoreCase); @@ -394,8 +390,8 @@ namespace Microsoft.DotNet.Archive { string hash = GetHash(fs); // $ prefix indicates that the file is not in the archive and path is relative to an external directory - archiveFiles[hash] = new ArchiveFileInfo(null, "$" + hash , hash); - externalFiles[hash] = externalFile; + _archiveFiles[hash] = new ArchiveFileInfo(null, "$" + hash , hash); + _externalFiles[hash] = externalFile; } } public void AddDirectory(string sourceDirectory, IProgress progress, string destinationDirectory = null) @@ -463,24 +459,20 @@ namespace Microsoft.DotNet.Archive else { var copy = CreateTemporaryStream(); -#if NET45 - hash = CopyWithHash(stream, copy); -#else stream.CopyTo(copy); copy.Seek(0, SeekOrigin.Begin); hash = GetHash(copy); -#endif stream.Dispose(); stream = copy; } - lock (archiveFiles) + lock (_archiveFiles) { - destFiles.Add(new DestinationFileInfo(destinationPath, hash)); + _destFiles.Add(new DestinationFileInfo(destinationPath, hash)); // see if we already have this file in the archive/external ArchiveFileInfo existing = null; - if (archiveFiles.TryGetValue(hash, out existing)) + if (_archiveFiles.TryGetValue(hash, out existing)) { // reduce memory pressure if (!(stream is MemoryStream) && (existing.Stream is MemoryStream)) @@ -502,39 +494,14 @@ namespace Microsoft.DotNet.Archive stream.Seek(0, SeekOrigin.Begin); var archivePath = Path.Combine(hash, Path.GetFileName(destinationPath)); - archiveFiles.Add(hash, new ArchiveFileInfo(stream, archivePath, hash)); + _archiveFiles.Add(hash, new ArchiveFileInfo(stream, archivePath, hash)); } } } -#if NET45 - /// - /// Calculates the hash while copying the file to avoid multiple reads - /// - private const int _DefaultCopyBufferSize = 81920; - public string CopyWithHash(Stream source, Stream destination) - { - byte[] buffer = new byte[_DefaultCopyBufferSize]; - int read; - while ((read = source.Read(buffer, 0, buffer.Length)) != 0) - { - sha.Value.TransformBlock(buffer, 0, read, null, 0); - destination.Write(buffer, 0, read); - } - sha.Value.TransformFinalBlock(buffer, 0, 0); - var hash = sha.Value.Hash; - - // follow pattern in ComputeHash(stream) where it re-initializes after finishing. - sha.Value.Initialize(); - - return GetHashString(hash); - } -#endif - - public string GetHash(Stream stream) { - var hashBytes = sha.Value.ComputeHash(stream); + var hashBytes = _sha.Value.ComputeHash(stream); return GetHashString(hashBytes); } @@ -551,11 +518,11 @@ namespace Microsoft.DotNet.Archive public void Dispose() { - if (!disposed) + if (!_disposed) { - if (archiveFiles != null) + if (_archiveFiles != null) { - foreach(var archiveFile in archiveFiles.Values) + foreach(var archiveFile in _archiveFiles.Values) { if (archiveFile.Stream != null) { @@ -565,17 +532,17 @@ namespace Microsoft.DotNet.Archive } } - if (sha != null) + if (_sha != null) { - sha.Dispose(); - sha = null; + _sha.Dispose(); + _sha = null; } } } private void CheckDisposed() { - if (disposed) + if (_disposed) { throw new ObjectDisposedException(nameof(IndexedArchive)); } diff --git a/src/Microsoft.DotNet.Archive/ProgressReport.cs b/src/Microsoft.DotNet.Archive/ProgressReport.cs index 0a2622008..6eb955563 100644 --- a/src/Microsoft.DotNet.Archive/ProgressReport.cs +++ b/src/Microsoft.DotNet.Archive/ProgressReport.cs @@ -1,24 +1,28 @@ -using System; +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; namespace Microsoft.DotNet.Archive { public struct ProgressReport { - public string Phase; - public long Ticks; - public long Total; + public ProgressReport(string phase, long ticks, long total) + { + Phase = phase; + Ticks = ticks; + Total = total; + } + public string Phase { get; } + public long Ticks { get; } + public long Total { get; } } public static class ProgressReportExtensions { public static void Report(this IProgress progress, string phase, long ticks, long total) { - progress.Report(new ProgressReport() - { - Phase = phase, - Ticks = ticks, - Total = total - }); + progress.Report(new ProgressReport(phase, ticks, total)); } } diff --git a/src/Microsoft.DotNet.Archive/ThreadLocalZipArchive.cs b/src/Microsoft.DotNet.Archive/ThreadLocalZipArchive.cs index d7ed42120..7f61207cb 100644 --- a/src/Microsoft.DotNet.Archive/ThreadLocalZipArchive.cs +++ b/src/Microsoft.DotNet.Archive/ThreadLocalZipArchive.cs @@ -1,15 +1,20 @@ -using System; +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; using System.IO; using System.IO.Compression; using System.Threading; namespace Microsoft.DotNet.Archive { - // wraps ThreadLocal and exposes Dispose semantics that dispose all archives - class ThreadLocalZipArchive : IDisposable + /// + /// Wraps ThreadLocal and exposes Dispose semantics that dispose all archives + /// + internal class ThreadLocalZipArchive : IDisposable { private ThreadLocal _archive; - private bool disposed = false; + private bool _disposed = false; public ThreadLocalZipArchive(string archivePath, ZipArchive local = null) { @@ -28,7 +33,7 @@ namespace Microsoft.DotNet.Archive public void Dispose() { - if (!disposed) + if (!_disposed) { if (_archive != null) { diff --git a/src/Microsoft.DotNet.Archive/project.json b/src/Microsoft.DotNet.Archive/project.json index 0dec6c409..564b171cf 100644 --- a/src/Microsoft.DotNet.Archive/project.json +++ b/src/Microsoft.DotNet.Archive/project.json @@ -5,15 +5,11 @@ }, "description": "Archive and compression types.", "dependencies": { - "NETStandard.Library": "1.6.0-rc3-24201-00" + "NETStandard.Library": "1.6.0-rc3-24201-00", + "System.Linq.Parallel": "4.0.1-rc3-24201-00" }, "frameworks": { - "net45": {}, - "netstandard1.3": { - "dependencies": { - "System.Linq.Parallel": "4.0.1-rc3-24201-00" - } - } + "netstandard1.3": {} }, "scripts": {} } diff --git a/src/dotnet-archive/Program.cs b/src/dotnet-archive/Program.cs index 5457c8c7f..0c8a1be39 100644 --- a/src/dotnet-archive/Program.cs +++ b/src/dotnet-archive/Program.cs @@ -1,4 +1,7 @@ -using Microsoft.DotNet.Cli.CommandLine; +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.DotNet.Cli.CommandLine; //using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Archive; using System; @@ -28,7 +31,6 @@ namespace Microsoft.DotNet.Tools.Archive var externals = app.Option("--external ...", "External files and directories to consider for extraction", CommandOptionType.MultipleValue); var sources = app.Argument("...", "Files & directory to include in the archive", multipleValues:true); - var dotnetNew = new ArchiveCommand(); app.OnExecute(() => { if (extract.HasValue() && sources.Values.Any()) @@ -79,7 +81,7 @@ namespace Microsoft.DotNet.Tools.Archive archive.Save(archiveFile.Value(), progress); } - else // extract.HasValue() + else // sources not specified, extract must have been specified { archive.Extract(archiveFile.Value(), extract.Value(), progress);