/// <summary>
        /// Searches the package manager metadata to figure out the source code repository.
        /// </summary>
        /// <param name="purl">The <see cref="PackageURL"/> that we need to find the source code repository.</param>
        /// <param name="metadata">The json representation of this package's metadata.</param>
        /// <remarks>If no version specified, defaults to latest version.</remarks>
        /// <returns>
        /// A dictionary, mapping each possible repo source entry to its probability/empty dictionary
        /// </returns>
        protected override async Task <Dictionary <PackageURL, double> > SearchRepoUrlsInPackageMetadata(PackageURL purl, string metadata)
        {
            Dictionary <PackageURL, double> mapping = new();

            try
            {
                string?version = purl.Version;
                if (string.IsNullOrEmpty(version))
                {
                    version = (await EnumerateVersionsAsync(purl)).First();
                }
                NuspecReader?      nuspecReader       = GetNuspec(purl.Name, version);
                RepositoryMetadata?repositoryMetadata = nuspecReader?.GetRepositoryMetadata();
                if (repositoryMetadata != null && GitHubProjectManager.IsGitHubRepoUrl(repositoryMetadata.Url, out PackageURL? githubPurl))
                {
                    if (githubPurl != null)
                    {
                        mapping.Add(githubPurl, 1.0F);
                    }
                }

                return(mapping);
            }
            catch (Exception ex)
            {
                Logger.Debug(ex, $"Error fetching/parsing NuGet repository metadata: {ex.Message}");
            }

            // If nothing worked, return the default empty dictionary
            return(mapping);
        }
示例#2
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        protected async Task <Dictionary <PackageURL, double> > SearchRepoUrlsInPackageMetadata(PackageURL purl,
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
                                                                                                JsonDocument contentJSON)
        {
            Dictionary <PackageURL, double>?mapping = new();

            if (purl.Name is string purlName && (purlName.StartsWith('_') || npm_internal_modules.Contains(purlName)))
            {
                // url = 'https://github.com/nodejs/node/tree/master/lib' + package.name,

                mapping.Add(new PackageURL(purl.Type, purl.Namespace, purl.Name,
                                           null, null, "node/tree/master/lib"), 1.0F);
                return(mapping);
            }

            // if a version is provided, search that JSONElement, otherwise, just search the latest
            // version, which is more likely best maintained
            // TODO: If the latest version JSONElement doesnt have the repo infor, should we search all elements
            // on that chance that one of them might have it?
            JsonElement?versionJSON = string.IsNullOrEmpty(purl?.Version) ? GetLatestVersionElement(contentJSON) :
                                      GetVersionElement(contentJSON, new Version(purl.Version));

            if (versionJSON is JsonElement notNullVersionJSON)
            {
                try
                {
                    if (!notNullVersionJSON.TryGetProperty("repository", out JsonElement repository))
                    {
                        return(mapping);
                    }
                    if (repository.ValueKind == JsonValueKind.Object)
                    {
                        string?repoType = OssUtilities.GetJSONPropertyStringIfExists(repository, "type")?.ToLower();
                        string?repoURL  = OssUtilities.GetJSONPropertyStringIfExists(repository, "url");

                        // right now we deal with only github repos
                        if (repoType == "git" && repoURL is not null)
                        {
                            PackageURL gitPURL = GitHubProjectManager.ParseUri(new Uri(repoURL));
                            // we got a repository value the author specified in the metadata - so no
                            // further processing needed
                            mapping.Add(gitPURL, 1.0F);
                            return(mapping);
                        }
                    }
                }
                catch (KeyNotFoundException) { /* continue onwards */ }
                catch (UriFormatException) { /* the uri specified in the metadata invalid */ }
            }

            return(mapping);
        }
        /// <summary>
        /// Updates the <see cref="Repository"/> for this package version in the <see cref="PackageMetadata"/>.
        /// </summary>
        /// <param name="metadata">The <see cref="PackageMetadata"/> object to update with the values for this version.</param>
        private async Task UpdateMetadataRepository(PackageMetadata metadata)
        {
            NuspecReader?      nuspecReader       = GetNuspec(metadata.Name !, metadata.PackageVersion !);
            RepositoryMetadata?repositoryMetadata = nuspecReader?.GetRepositoryMetadata();

            if (repositoryMetadata != null && GitHubProjectManager.IsGitHubRepoUrl(repositoryMetadata.Url, out PackageURL? githubPurl))
            {
                Repository ghRepository = new()
                {
                    Type = "github"
                };

                await ghRepository.ExtractRepositoryMetadata(githubPurl !);

                metadata.Repository ??= new List <Repository>();
                metadata.Repository.Add(ghRepository);
            }
        }
示例#4
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        protected override async Task <Dictionary <PackageURL, double> > SearchRepoUrlsInPackageMetadata(PackageURL purl, string metadata)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            Dictionary <PackageURL, double> mapping = new();

            if (purl.Name?.StartsWith('_') ?? false) // TODO: there are internal modules which do not start with _
            {
                // TODO: internal modules could also be in https://github.com/python/cpython/tree/master/Modules/
                mapping.Add(new PackageURL(purl.Type, purl.Namespace, purl.Name, null, null, "cpython/tree/master/Lib/"), 1.0F);
                return(mapping);
            }
            if (string.IsNullOrEmpty(metadata))
            {
                return(mapping);
            }
            JsonDocument contentJSON = JsonDocument.Parse(metadata);

            List <string> possibleProperties = new() { "homepage", "home_page" };
            JsonElement   infoJSON;

            try
            {
                infoJSON = contentJSON.RootElement.GetProperty("info");
            }
            catch (Exception)
            {
                return(mapping);
            }

            foreach (JsonProperty property in infoJSON.EnumerateObject())
            {   // there are a couple of possibilities where the repository url might be present - check all of them
                try
                {
                    if (possibleProperties.Contains(property.Name.ToLower()))
                    {
                        string homepage = property.Value.ToString() ?? string.Empty;
                        IEnumerable <PackageURL>?packageUrls = GitHubProjectManager.ExtractGitHubPackageURLs(homepage);
                        // if we were able to extract a github url, return
                        if (packageUrls != null && packageUrls.Any())
                        {
                            mapping.Add(packageUrls.First(), 1.0F);
                            return(mapping);
                        }
                    }
                    else if (property.Name.Equals("project_urls"))
                    {
                        if (property.Value.TryGetProperty("Source", out JsonElement jsonElement))
                        {
                            string?sourceLoc = jsonElement.GetString();
                            if (sourceLoc != null)
                            {
                                IEnumerable <PackageURL>?packageUrls = GitHubProjectManager.ExtractGitHubPackageURLs(sourceLoc);
                                if (packageUrls != null && packageUrls.Any())
                                {
                                    mapping.Add(packageUrls.First(), 1.0F);
                                    return(mapping);
                                }
                            }
                        }
                    }
                }
                catch (Exception) { continue; /* try the next property */ }
            }

            return(mapping);
        }