Ejemplo n.º 1
0
        /// <nodoc />
        private async Task <EvaluationResult> ValidateAndStoreIncrementalExtractState(PipConstructionHelper pipConstructionHelper, DownloadData downloadData)
        {
            var archive = downloadData.DownloadedFilePath.ToString(m_context.PathTable);
            var target  = downloadData.ContentsFolder.Path.ToString(m_context.PathTable);

            try
            {
                var allFiles = new List <FileArtifact>();

                var enumeratResult = FileUtilities.EnumerateDirectoryEntries(target, true, "*",
                                                                             (dir, fileName, attributes) =>
                {
                    if ((attributes & FileAttributes.Directory) == 0)
                    {
                        var filePath = Path.Combine(dir, fileName);
                        allFiles.Add(FileArtifact.CreateSourceFile(AbsolutePath.Create(m_context.PathTable, filePath)));
                    }
                });

                if (!enumeratResult.Succeeded)
                {
                    var error = new Win32Exception(enumeratResult.NativeErrorCode);
                    m_logger.ErrorListingPackageContents(m_context.LoggingContext, downloadData.Settings.ModuleName, archive, target, error.Message);
                    return(EvaluationResult.Error);
                }

                if (allFiles.Count == 0)
                {
                    m_logger.ErrorListingPackageContents(m_context.LoggingContext, downloadData.Settings.ModuleName, archive, target, "file list is empty");
                    return(EvaluationResult.Error);
                }

                var sortedFiles = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .CloneAndSort(
                    allFiles,
                    OrdinalFileArtifactComparer.Instance);

                var hashes = new Dictionary <AbsolutePath, ContentHash>();
                foreach (var file in allFiles)
                {
                    var hash = await GetContentHashAsync(file);

                    hashes.Add(file.Path, hash);
                }

                var incrementalState = new ExtractIncrementalState(downloadData, sortedFiles, hashes);
                await incrementalState.SaveAsync(m_context);

                return(SealDirectory(pipConstructionHelper, downloadData, downloadData.ContentsFolder, sortedFiles));
            }
            catch (Exception e)
                when(e is BuildXLException || e is IOException || e is UnauthorizedAccessException)
                {
                    m_logger.ErrorExtractingArchive(m_context.LoggingContext, downloadData.Settings.ModuleName, archive, target, e.Message);
                    return(EvaluationResult.Error);
                }
        }
Ejemplo n.º 2
0
        /// <nodoc />
        private async Task <EvaluationResult> CheckIfExtractIsNeededAsync(PipConstructionHelper pipConstructionHelper, DownloadData downloadData)
        {
            try
            {
                if (m_context.FileSystem.IsDirectory(downloadData.ContentsFolder))
                {
                    var incrementalState = await ExtractIncrementalState.TryLoadAsync(m_logger, m_context, downloadData);

                    if (incrementalState != null)
                    {
                        // Check all files still have the same hash. This should use the hash cache based on USN so be very fast.
                        foreach (var hashKv in incrementalState.Hashes)
                        {
                            if (!m_context.FileSystem.Exists(hashKv.Key))
                            {
                                // File is not present, extraction is needed.
                                return(EvaluationResult.Continue);
                            }

                            var hash = await GetContentHashAsync(hashKv.Key);

                            if (hash != hashKv.Value)
                            {
                                // File has changed, extraction is needed.
                                return(EvaluationResult.Continue);
                            }
                        }

                        // All hashes verified, update the manifest
                        await incrementalState.SaveAsync(m_context);

                        return(SealDirectory(pipConstructionHelper, downloadData, downloadData.ContentsFolder, incrementalState.Files));
                    }
                }
            }
            catch (IOException e)
            {
                m_logger.ErrorCheckingIncrementality(m_context.LoggingContext, downloadData.Settings.ModuleName, e.Message);
                return(EvaluationResult.Error);
            }
            catch (UnauthorizedAccessException e)
            {
                m_logger.ErrorCheckingIncrementality(m_context.LoggingContext, downloadData.Settings.ModuleName, e.Message);
                return(EvaluationResult.Error);
            }

            // Extraction is needed
            return(EvaluationResult.Continue);
        }
Ejemplo n.º 3
0
        /// <nodoc />
        public static async Task <ExtractIncrementalState> TryLoadAsync(Logger logger, FrontEndContext context, DownloadData downloadData)
        {
            var manifestFilePath = downloadData.ExtractManifestFile.ToString(context.PathTable);

            ExtractIncrementalState result = null;

            if (!FileUtilities.Exists(manifestFilePath))
            {
                return(null);
            }

            using (var reader = new StreamReader(manifestFilePath))
            {
                var versionLine = await reader.ReadLineAsync();

                if (versionLine == null || !string.Equals(versionLine, ManifestVersion, StringComparison.Ordinal))
                {
                    logger.ExtractManifestDoesNotMatch(context.LoggingContext, downloadData.Settings.ModuleName, downloadData.Settings.Url, "version", ManifestVersion, versionLine);
                    return(null);
                }

                var urlLine = await reader.ReadLineAsync();

                if (!string.Equals(urlLine, downloadData.Settings.Url, StringComparison.Ordinal))
                {
                    logger.ExtractManifestDoesNotMatch(context.LoggingContext, downloadData.Settings.ModuleName, downloadData.Settings.Url, "url", downloadData.Settings.Url, urlLine);
                    return(null);
                }

                var archiveTypeLine = await reader.ReadLineAsync();

                if (archiveTypeLine == null || !Enum.TryParse <DownloadArchiveType>(archiveTypeLine, out var archiveType) || archiveType != downloadData.Settings.ArchiveType)
                {
                    logger.ExtractManifestDoesNotMatch(context.LoggingContext, downloadData.Settings.ModuleName, downloadData.Settings.Url, "archiveType", downloadData.Settings.ArchiveType.ToString(), archiveTypeLine);
                    return(null);
                }

                var fileCountLine = await reader.ReadLineAsync();

                if (fileCountLine == null || !uint.TryParse(fileCountLine, out var fileCount))
                {
                    return(null);
                }

                var hashes = new Dictionary <AbsolutePath, ContentHash>();
                var files  = new FileArtifact[fileCount];
                for (int i = 0; i < fileCount; i++)
                {
                    var filePathLine = await reader.ReadLineAsync();

                    if (filePathLine == null || !RelativePath.TryCreate(context.StringTable, filePathLine, out var relativeFilePath))
                    {
                        return(null);
                    }

                    var hashLine = await reader.ReadLineAsync();

                    if (hashLine == null || !ContentHash.TryParse(hashLine, out var contentHash))
                    {
                        return(null);
                    }

                    var filePath = downloadData.ContentsFolder.Path.Combine(context.PathTable, relativeFilePath);
                    files[i]         = FileArtifact.CreateSourceFile(filePath);
                    hashes[filePath] = contentHash;
                }

                var sortedFiles = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .SortUnsafe(
                    files,
                    OrdinalFileArtifactComparer.Instance);

                result = new ExtractIncrementalState(downloadData, sortedFiles, hashes);
            }

            return(result);
        }