public ExtractSource(string sourceString, Dictionary <string, string> externalFiles, ThreadLocalZipArchive archive) { if (sourceString[0] == '$') { var externalHash = sourceString.Substring(1); if (!externalFiles.TryGetValue(externalHash, out _localPath)) { throw new Exception("Could not find external file with hash {externalHash}."); } } else { _entryName = sourceString; _archive = archive; } }
public void Extract(string compressedArchivePath, string outputDirectory, IProgress <ProgressReport> progress) { using (var archiveStream = CreateTemporaryFileStream()) { // decompress the LZMA stream using (var lzmaStream = File.OpenRead(compressedArchivePath)) { CompressionUtility.Decompress(lzmaStream, archiveStream, progress); } var archivePath = ((FileStream)archiveStream).Name; // reset the uncompressed stream archiveStream.Seek(0, SeekOrigin.Begin); // read as a zip archive using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Read)) using (var tlArchive = new ThreadLocalZipArchive(archivePath, archive)) { List <ExtractOperation> extractOperations = new List <ExtractOperation>(); Dictionary <string, ExtractSource> sourceCache = new Dictionary <string, ExtractSource>(); // process the index to determine all extraction operations var indexEntry = archive.GetEntry(IndexFileName); using (var indexReader = new StreamReader(indexEntry.Open())) { Dictionary <string, ZipOperation> zipOperations = new Dictionary <string, ZipOperation>(StringComparer.OrdinalIgnoreCase); for (var line = indexReader.ReadLine(); line != null; line = indexReader.ReadLine()) { var lineParts = line.Split(pipeSeperator); if (lineParts.Length != 2) { throw new Exception("Unexpected index line format, too many '|'s."); } string target = lineParts[0]; string source = lineParts[1]; ExtractSource extractSource; if (!sourceCache.TryGetValue(source, out extractSource)) { sourceCache[source] = extractSource = new ExtractSource(source, _externalFiles, tlArchive); } var zipSeperatorIndex = target.IndexOf("::", StringComparison.OrdinalIgnoreCase); if (zipSeperatorIndex != -1) { string zipRelativePath = target.Substring(0, zipSeperatorIndex); string zipEntryName = target.Substring(zipSeperatorIndex + 2); string destinationPath = Path.Combine(outputDirectory, zipRelativePath); // operations on a zip file will be sequential ZipOperation currentZipOperation; if (!zipOperations.TryGetValue(destinationPath, out currentZipOperation)) { extractOperations.Add(currentZipOperation = new ZipOperation(destinationPath)); zipOperations.Add(destinationPath, currentZipOperation); } currentZipOperation.AddEntry(zipEntryName, extractSource); } else { string destinationPath = Path.Combine(outputDirectory, target); extractOperations.Add(new CopyOperation(extractSource, destinationPath)); } } } int opsExecuted = 0; // execute all operations //foreach(var extractOperation in extractOperations) extractOperations.AsParallel().ForAll(extractOperation => { extractOperation.DoOperation(); progress.Report(LocalizableStrings.Expanding, Interlocked.Increment(ref opsExecuted), extractOperations.Count); }); } } }
public void Extract(string compressedArchivePath, string outputDirectory, IProgress<ProgressReport> progress) { using (var archiveStream = CreateTemporaryFileStream()) { // decompress the LZMA stream using (var lzmaStream = File.OpenRead(compressedArchivePath)) { CompressionUtility.Decompress(lzmaStream, archiveStream, progress); } var archivePath = ((FileStream)archiveStream).Name; // reset the uncompressed stream archiveStream.Seek(0, SeekOrigin.Begin); // read as a zip archive using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Read)) using (var tlArchive = new ThreadLocalZipArchive(archivePath, archive)) { List<ExtractOperation> extractOperations = new List<ExtractOperation>(); Dictionary<string, ExtractSource> sourceCache = new Dictionary<string, ExtractSource>(); // process the index to determine all extraction operations var indexEntry = archive.GetEntry(IndexFileName); using (var indexReader = new StreamReader(indexEntry.Open())) { Dictionary<string, ZipOperation> zipOperations = new Dictionary<string, ZipOperation>(StringComparer.OrdinalIgnoreCase); for (var line = indexReader.ReadLine(); line != null; line = indexReader.ReadLine()) { var lineParts = line.Split(pipeSeperator); if (lineParts.Length != 2) { throw new Exception("Unexpected index line format, too many '|'s."); } string target = lineParts[0]; string source = lineParts[1]; ExtractSource extractSource; if (!sourceCache.TryGetValue(source, out extractSource)) { sourceCache[source] = extractSource = new ExtractSource(source, _externalFiles, tlArchive); } var zipSeperatorIndex = target.IndexOf("::", StringComparison.OrdinalIgnoreCase); if (zipSeperatorIndex != -1) { string zipRelativePath = target.Substring(0, zipSeperatorIndex); string zipEntryName = target.Substring(zipSeperatorIndex + 2); string destinationPath = Path.Combine(outputDirectory, zipRelativePath); // operations on a zip file will be sequential ZipOperation currentZipOperation; if (!zipOperations.TryGetValue(destinationPath, out currentZipOperation)) { extractOperations.Add(currentZipOperation = new ZipOperation(destinationPath)); zipOperations.Add(destinationPath, currentZipOperation); } currentZipOperation.AddEntry(zipEntryName, extractSource); } else { string destinationPath = Path.Combine(outputDirectory, target); extractOperations.Add(new CopyOperation(extractSource, destinationPath)); } } } int opsExecuted = 0; // execute all operations //foreach(var extractOperation in extractOperations) extractOperations.AsParallel().ForAll(extractOperation => { extractOperation.DoOperation(); progress.Report("Expanding", Interlocked.Increment(ref opsExecuted), extractOperations.Count); }); } } }
public ExtractSource(string sourceString, Dictionary<string, string> externalFiles, ThreadLocalZipArchive archive) { if (sourceString[0] == '$') { var externalHash = sourceString.Substring(1); if (!externalFiles.TryGetValue(externalHash, out _localPath)) { throw new Exception("Could not find external file with hash {externalHash}."); } } else { _entryName = sourceString; _archive = archive; } }