/// <summary>
        ///     Download one Cocoapods package and extract it to the target directory.
        /// </summary>
        /// <param name="purl"> Package URL of the package to download. </param>
        /// <returns> n/a </returns>
        public override async Task <IEnumerable <string> > DownloadVersionAsync(PackageURL purl, bool doExtract, bool cached = false)
        {
            Logger.Trace("DownloadVersion {0}", purl?.ToString());

            string?       packageName     = purl?.Name;
            string?       packageVersion  = purl?.Version;
            string?       fileName        = purl?.ToStringFilename();
            List <string> downloadedPaths = new();

            if (string.IsNullOrWhiteSpace(packageName) || string.IsNullOrWhiteSpace(packageVersion) || string.IsNullOrWhiteSpace(fileName))
            {
                Logger.Debug("Error with 'purl' argument. Unable to download [{0} {1}] @ {2}. Both must be defined.", packageName, packageVersion, fileName);
                return(downloadedPaths);
            }

            HttpClient httpClient = CreateHttpClient();
            string     prefix     = GetCocoapodsPrefix(packageName);

            System.Text.Json.JsonDocument podspec = await GetJsonCache(httpClient, $"{ENV_COCOAPODS_SPECS_RAW_ENDPOINT}/Specs/{prefix}/{packageName}/{packageVersion}/{packageName}.podspec.json");

            if (podspec.RootElement.TryGetProperty("source", out System.Text.Json.JsonElement source))
            {
                string?url = null;
                if (source.TryGetProperty("git", out System.Text.Json.JsonElement sourceGit) &&
                    source.TryGetProperty("tag", out System.Text.Json.JsonElement sourceTag))
                {
                    string?sourceGitString = sourceGit.GetString();
                    string?sourceTagString = sourceTag.GetString();

                    if (!string.IsNullOrWhiteSpace(sourceGitString) && sourceGitString.EndsWith(".git"))
                    {
                        sourceGitString = sourceGitString[0..^ 4];
        /// <summary>
        ///     Download one Cargo package and extract it to the target directory.
        /// </summary>
        /// <param name="purl"> Package URL of the package to download. </param>
        /// <returns> Path to the downloaded package </returns>
        public override async Task <IEnumerable <string> > DownloadVersionAsync(PackageURL purl, bool doExtract, bool cached = false)
        {
            Logger.Trace("DownloadVersion {0}", purl?.ToString());

            string?       packageName     = purl?.Name;
            string?       packageVersion  = purl?.Version;
            string?       fileName        = purl?.ToStringFilename();
            List <string> downloadedPaths = new();

            if (string.IsNullOrWhiteSpace(packageName) || string.IsNullOrWhiteSpace(packageVersion) || string.IsNullOrWhiteSpace(fileName))
            {
                Logger.Debug("Error with 'purl' argument. Unable to download [{0} {1}] @ {2}. Both must be defined.", packageName, packageVersion, fileName);
                return(downloadedPaths);
            }

            string url = $"{ENV_CARGO_ENDPOINT}/api/v1/crates/{packageName}/{packageVersion}/download";

            try
            {
                string targetName     = $"cargo-{fileName}";
                string extractionPath = Path.Combine(TopLevelExtractionDirectory, targetName);
                // if the cache is already present, no need to extract
                if (doExtract && cached && Directory.Exists(extractionPath))
                {
                    downloadedPaths.Add(extractionPath);
                    return(downloadedPaths);
                }
                Logger.Debug("Downloading {0}", url);

                HttpClient httpClient = CreateHttpClient();

                System.Net.Http.HttpResponseMessage result = await httpClient.GetAsync(url);

                result.EnsureSuccessStatusCode();

                if (doExtract)
                {
                    downloadedPaths.Add(await ArchiveHelper.ExtractArchiveAsync(TopLevelExtractionDirectory, targetName, await result.Content.ReadAsStreamAsync(), cached));
                }
                else
                {
                    extractionPath += Path.GetExtension(url) ?? "";
                    await File.WriteAllBytesAsync(extractionPath, await result.Content.ReadAsByteArrayAsync());

                    downloadedPaths.Add(extractionPath);
                }
            }
            catch (Exception ex)
            {
                Logger.Debug(ex, "Error downloading Cargo package: {0}", ex.Message);
            }
            return(downloadedPaths);
        }
Beispiel #3
0
        /// <summary>
        ///     Downloads metadata if only metadata is requested; downloads and extracts the package if
        ///     doExtract is requested
        /// </summary>
        /// <param name="_downloader"> </param>
        /// <param name="purl"> </param>
        /// <param name="metadataOnly"> </param>
        /// <param name="doExtract"> </param>
        /// <param name="cached"> </param>
        /// <returns>
        ///     A list with
        ///     1) the name of the file if metadata requested
        ///     2) The name of the file if package download and no extraction is requested
        ///     3) The directory of the downloaded and extracted package, if extraction is requested
        /// </returns>
        public async Task <List <string> > Download(
            PackageURL purl,
            bool metadataOnly,
            bool doExtract)
        {
            List <string> downloadPaths = new List <string>();

            if (packageManager != null)
            {
                if (metadataOnly)
                {
                    var metadata = await packageManager.GetMetadata(purl);

                    if (metadata != null)
                    {
                        var outputFilename = Path.Combine(packageManager.TopLevelExtractionDirectory, $"metadata-{purl.ToStringFilename()}");

                        // this will be effectively the same as above, if the cache doesnt exist
                        if (!this.actualCaching)
                        {
                            while (File.Exists(outputFilename))
                            {
                                outputFilename = Path.Combine(packageManager.TopLevelExtractionDirectory, $"metadata-{purl.ToStringFilename()}-{DateTime.Now.Ticks}");
                            }
                        }
                        File.WriteAllText(outputFilename, metadata);
                        downloadPaths.Add(outputFilename);
                    }
                }
                else
                {
                    // only version download requests reach here
                    downloadPaths.AddRange(await packageManager.DownloadVersion(purl, doExtract, this.actualCaching));
                }
            }

            // Add the return values to our internal storage to be cleaned up later by CleanPackageLocalCopy
            this.downloadPaths.AddRange(downloadPaths);

            return(downloadPaths);
        }
Beispiel #4
0
        public async Task <List <string> > Download(PackageURL purl, string destinationDirectory = null)
        {
            Logger.Trace("Download({0})", purl?.ToString());

            var downloadPaths = new List <string>();

            destinationDirectory ??= (string)Options["download-directory"] ?? ".";
            if (!Directory.Exists(destinationDirectory))
            {
                Logger.Warn("Invalid directory, {0} does not exist.", destinationDirectory);
                return(new List <string>());
            }

            // Use reflection to find the correct package management class
            var downloaderClass = typeof(BaseProjectManager).Assembly.GetTypes()
                                  .Where(type => type.IsSubclassOf(typeof(BaseProjectManager)))
                                  .Where(type => type.Name.Equals($"{purl.Type}ProjectManager",
                                                                  StringComparison.InvariantCultureIgnoreCase))
                                  .FirstOrDefault();

            if (downloaderClass != null)
            {
                var ctor        = downloaderClass.GetConstructor(Array.Empty <Type>());
                var _downloader = (BaseProjectManager)(ctor.Invoke(Array.Empty <object>()));
                _downloader.TopLevelExtractionDirectory = destinationDirectory;
                if ((bool)Options["download-metadata-only"])
                {
                    var metadata = await _downloader.GetMetadata(purl);

                    if (metadata != default)
                    {
                        var outputFilename = Path.Combine(destinationDirectory, $"metadata-{purl.ToStringFilename()}");
                        while (File.Exists(outputFilename))
                        {
                            outputFilename = Path.Combine(destinationDirectory, $"metadata-{purl.ToStringFilename()}-{DateTime.Now.Ticks}");
                        }
                        File.WriteAllText(outputFilename, metadata);
                        downloadPaths.Add(outputFilename);
                    }
                }
                else
                {
                    if (!bool.TryParse(Options["extract"]?.ToString(), out bool doExtract))
                    {
                        doExtract = true;
                    }
                    downloadPaths = await _downloader.Download(purl, doExtract);
                }
            }
            else
            {
                throw new ArgumentException(string.Format("Invalid Package URL type: {0}", purl?.Type));
            }

            return(downloadPaths);
        }