Пример #1
0
        private void UnpackMissingContent(ref List <FileName> candidateFileNames)
        {
            bool          success            = true;
            string        unpackingDirectory = Path.Combine(OutputPath, "UnpackedZipArchives");
            StringBuilder missingFiles       = new StringBuilder();

            Directory.CreateDirectory(unpackingDirectory);

            var unpackNeeded = (from file in candidateFileNames
                                where !File.Exists(file.FullPath)
                                select file).ToList();

            // Nothing to do
            if (unpackNeeded.Count() == 0)
            {
                return;
            }

            // Get all Zip Archives in the manifest recursively.
            Queue <FileName> allZipsWeKnowAbout = new Queue <FileName>(ZipContainerNames);

            while (allZipsWeKnowAbout.Count > 0)
            {
                FileName zipFile      = allZipsWeKnowAbout.Dequeue();
                string   unpackFolder = Path.Combine(unpackingDirectory, zipFile.SHA256Hash);

                // Assumption:  If a zip with a given hash is already unpacked, it's probably OK.
                if (!Directory.Exists(unpackFolder))
                {
                    Directory.CreateDirectory(unpackFolder);
                    ZipFile.ExtractToDirectory(zipFile.FullPath, unpackFolder);
                }
                // Add any zips we just unzipped.
                foreach (string file in Directory.GetFiles(unpackFolder, "*", SearchOption.AllDirectories))
                {
                    if (PathUtil.IsZipContainer(file))
                    {
                        string relativePath = (new Uri(unpackingDirectory).MakeRelativeUri(new Uri(file))).OriginalString;
                        allZipsWeKnowAbout.Enqueue(new FileName(unpackingDirectory, relativePath, contentUtil.GetChecksum(file)));
                    }
                }
            }
            // Lazy : Disks are fast, just calculate ALL hashes.  Could optimize by only files we intend to sign
            Dictionary <string, string> existingHashLookup = new Dictionary <string, string>();

            foreach (string file in Directory.GetFiles(unpackingDirectory, "*", SearchOption.AllDirectories))
            {
                existingHashLookup.Add(file, contentUtil.GetChecksum(file));
            }

            Dictionary <FileName, FileName> fileNameUpdates = new Dictionary <FileName, FileName>();

            // At this point, we've unpacked every Zip we can possibly pull out into folders named for the zip's hash into 'unpackingDirectory'
            foreach (FileName missingFileWithHashToFind in unpackNeeded)
            {
                string matchFile = (from filePath in existingHashLookup.Keys
                                    where Path.GetFileName(filePath).Equals(missingFileWithHashToFind.Name, StringComparison.OrdinalIgnoreCase)
                                    where existingHashLookup[filePath] == missingFileWithHashToFind.SHA256Hash
                                    select filePath).SingleOrDefault();
                if (matchFile == null)
                {
                    success = false;
                    missingFiles.AppendLine($"File: {missingFileWithHashToFind.Name} Hash: '{missingFileWithHashToFind.SHA256Hash}'");
                }
                else
                {
                    string   relativePath    = (new Uri(OutputPath).MakeRelativeUri(new Uri(matchFile))).OriginalString.Replace('/', Path.DirectorySeparatorChar);
                    FileName updatedFileName = new FileName(OutputPath, relativePath, missingFileWithHashToFind.SHA256Hash);
                    candidateFileNames.Remove(missingFileWithHashToFind);
                    candidateFileNames.Add(updatedFileName);
                }
            }

            if (!success)
            {
                throw new Exception($"Failure attempting to find one or more files:\n{missingFiles.ToString()}");
            }
        }
Пример #2
0
 internal ZipData(FileName name, ImmutableArray <ZipPart> nestedBinaryParts, ImmutableArray <string> nestedExternalNames)
 {
     Name                = name;
     NestedParts         = nestedBinaryParts;
     NestedExternalNames = nestedExternalNames;
 }