示例#1
0
        /// <summary>
        /// Query source repository for latest package base given package id
        /// </summary>
        internal static async Task <UIPackageMetadata> GetLatestPackageByIdFromSrcRepo(this SourceRepository srcRepo, string packageId)
        {
            // 7 references none of which uses bool includePrerelease = true, bool includeUnlisted = false
            var metadataResource = await srcRepo.GetResourceAndValidateAsync <UIMetadataResource>();

            return(await metadataResource.GetLatestPackageByIdFromMetaRes(packageId));
        }
示例#2
0
        /// <summary>
        /// Helper function to download package from given url, and place package (only 'content' folder from package) to given folder
        /// </summary>
        /// <param name="identity">Package identity</param>
        /// <param name="destinationFolder">Folder where we copy the package content (content folder only) to</param>
        /// <param name="pathToLocalCopyOfNupkg">File path where we copy the nudpk to</param>
        /// <returns></returns>
        public static async Task DownloadPackageToFolder(this SourceRepository srcRepo, PackageIdentity identity, string destinationFolder, string pathToLocalCopyOfNupkg)
        {
            var downloadResource = await srcRepo.GetResourceAndValidateAsync <DownloadResource>();

            using (Stream packageStream = await srcRepo.GetPackageStream(identity))
            {
                WriteStreamToFile(packageStream, pathToLocalCopyOfNupkg);
                // set position back to the head of stream
                packageStream.Position = 0;

                using (ZipFile zipFile = ZipFile.Read(packageStream))
                {
                    // we only care about stuff under "content" folder
                    int substringStartIndex = @"content/".Length;
                    IEnumerable <ZipEntry> contentEntries = zipFile.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                    foreach (var entry in contentEntries)
                    {
                        string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));
                        FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(fullPath));
                        using (Stream writeStream = FileSystemHelpers.OpenWrite(fullPath))
                        {
                            // let the thread go with itself, so that once file finsihed writing, doesn`t need to request thread context from main thread
                            await entry.OpenReader().CopyToAsync(writeStream).ConfigureAwait(false);
                        }
                    }
                }
            }
        }
示例#3
0
        /// <summary>
        /// Query result by search term, always include pre-released
        /// </summary>
        public static async Task <IEnumerable <UIPackageMetadata> > Search(this SourceRepository srcRepo, string searchTerm, SearchFilter filterOptions = null, int skip = 0, int take = 1000)
        {
            // always include pre-release package
            if (filterOptions == null)
            {
                filterOptions = new SearchFilter();
            }

            filterOptions.IncludePrerelease = true; // keep the good old behavior
            var searchResource = await srcRepo.GetResourceAndValidateAsync <SearchLatestResource>();

            // When using nuget.org, we only look at packages that have our tag. Later, we should switch to filtering
            // by PackageType once nuget.org starts supporting that
            if (srcRepo.PackageSource.Source.StartsWith("https://www.nuget.org/", StringComparison.InvariantCultureIgnoreCase))
            {
                if (String.IsNullOrWhiteSpace(searchTerm))
                {
                    // No user provided search string: just search by tag
                    searchTerm = "tags:AzureSiteExtension";
                }
                else if (searchTerm.Contains(":"))
                {
                    // User provided complex query with fields: add it as is to the tag field query
                    searchTerm = $"tags:AzureSiteExtension {searchTerm}";
                }
                else
                {
                    // User provided simple string: treat it as a title. This is not ideal behavior, but
                    // is the best we can do based on how nuget.org works
                    searchTerm = $"tags:AzureSiteExtension title:\"{searchTerm}\"";
                }
            }

            return(await searchResource.Search(searchTerm, filterOptions, skip, take, CancellationToken.None));
        }
示例#4
0
 /// <summary>
 /// <para>Query source repository for a package base on given package id and version</para>
 /// <para>Will also query pre-release and unlisted packages</para>
 /// </summary>
 /// <param name="packageId">Package id, must not be null</param>
 /// <param name="version">Package version, must not be null</param>
 /// <returns>Package metadata</returns>
 public static async Task<UIPackageMetadata> GetPackageByIdentity(this SourceRepository srcRepo, string packageId, string version)
 {
     var metadataResource = await srcRepo.GetResourceAndValidateAsync<UIMetadataResource>();
     NuGetVersion expectedVersion = NuGetVersion.Parse(version);
     var identity = new PackageIdentity(packageId, expectedVersion);
     return await metadataResource.GetMetadata(identity, CancellationToken.None);
 }
        public async Task <IEnumerable <SiteExtensionInfo> > GetRemoteExtensions(string filter, bool allowPrereleaseVersions, string feedUrl)
        {
            ITracer tracer     = _traceFactory.GetTracer();
            var     extensions = new List <SiteExtensionInfo>();
            IEnumerable <SourceRepository> remoteRepos = GetRemoteRepositories(feedUrl);

            SearchFilter filterOptions = new SearchFilter();

            filterOptions.IncludePrerelease = allowPrereleaseVersions;

            IEnumerable <UIPackageMetadata> packages = new List <UIPackageMetadata>();

            using (tracer.Step("Search site extensions by filter: {0}", filter))
            {
                foreach (SourceRepository remoteRepo in remoteRepos)
                {
                    var foundUIPackages = await remoteRepo.Search(string.IsNullOrWhiteSpace(filter)?string.Empty : filter, filterOptions : filterOptions);

                    if (null != foundUIPackages && foundUIPackages.Count() > 0)
                    {
                        packages = packages.Concat(foundUIPackages);
                    }
                }
                packages = packages.OrderByDescending(p => p.DownloadCount);
            }

            using (tracer.Step("Convert search result to SiteExtensionInfos with max concurrent requests: {0}", System.Environment.ProcessorCount))
            {
                // GetResourceAsync is not thread safe
                var metadataResource = await _localRepository.GetResourceAndValidateAsync <UIMetadataResource>();

                var convertedResult = await ConvertNuGetPackagesToSiteExtensionInfos(
                    packages,
                    async (uiPackage) =>
                {
                    // this function is called in multiple threads simoutaneously
                    return(await ConvertRemotePackageToSiteExtensionInfo(uiPackage, feedUrl, metadataResource));
                });

                extensions.AddRange(convertedResult);
            }

            return(extensions);
        }
示例#6
0
        /// <summary>
        /// Query result by search term, always include pre-released
        /// </summary>
        public static async Task<IEnumerable<UIPackageMetadata>> Search(this SourceRepository srcRepo, string searchTerm, SearchFilter filterOptions = null, int skip = 0, int take = 1000)
        {
            // always include pre-release package
            if (filterOptions == null)
            {
                filterOptions = new SearchFilter();
            }

            filterOptions.IncludePrerelease = true; // keep the good old behavior
            var searchResource = await srcRepo.GetResourceAndValidateAsync<SearchLatestResource>();
            return await searchResource.Search(searchTerm, filterOptions, skip, take, CancellationToken.None);
        }
示例#7
0
        /// <summary>
        /// <para>Query source repository for a package base on given package id and version</para>
        /// <para>Will also query pre-release and unlisted packages</para>
        /// </summary>
        /// <param name="packageId">Package id, must not be null</param>
        /// <param name="version">Package version, must not be null</param>
        /// <returns>Package metadata</returns>
        public static async Task <UIPackageMetadata> GetPackageByIdentity(this SourceRepository srcRepo, string packageId, string version)
        {
            var metadataResource = await srcRepo.GetResourceAndValidateAsync <UIMetadataResource>();

            NuGetVersion      expectedVersion = NuGetVersion.Parse(version);
            var               identity        = new PackageIdentity(packageId, expectedVersion);
            UIPackageMetadata ret             = await metadataResource.GetMetadata(identity, CancellationToken.None);

            // When using nuget.org, we only look at packages that have our tag.
            if (ret != null &&
                IsNuGetRepo(srcRepo.PackageSource.Source) &&
                (ret.Tags.IndexOf("azuresiteextension", StringComparison.OrdinalIgnoreCase) < 0))
            {
                ret = null;
            }
            return(ret);
        }
示例#8
0
        /// <summary>
        /// Query source repository for latest package base given package id
        /// </summary>
        public static async Task <UIPackageMetadata> GetLatestPackageById(this SourceRepository srcRepo, string packageId, bool includePrerelease = true, bool includeUnlisted = false)
        {
            UIPackageMetadata latestPackage = null;
            var metadataResource            = await srcRepo.GetResourceAndValidateAsync <UIMetadataResource>();

            IEnumerable <UIPackageMetadata> packages = await metadataResource.GetMetadata(packageId, includePrerelease, includeUnlisted, token : CancellationToken.None);

            foreach (var p in packages)
            {
                if (latestPackage == null ||
                    latestPackage.Identity.Version < p.Identity.Version)
                {
                    latestPackage = p;
                }
            }

            return(latestPackage);
        }
示例#9
0
        /// <summary>
        /// Helper function to download package from given url, and place package (only 'content' folder from package) to given folder
        /// </summary>
        /// <param name="identity">Package identity</param>
        /// <param name="destinationFolder">Folder where we copy the package content (content folder only) to</param>
        /// <param name="pathToLocalCopyOfNudpk">File path where we copy the nudpk to</param>
        /// <returns></returns>
        public static async Task DownloadPackageToFolder(this SourceRepository srcRepo, PackageIdentity identity, string destinationFolder, string pathToLocalCopyOfNudpk = null)
        {
            var downloadResource = await srcRepo.GetResourceAndValidateAsync <DownloadResource>();

            using (Stream sourceStream = await downloadResource.GetStream(identity, CancellationToken.None))
            {
                if (sourceStream == null)
                {
                    // package not exist from feed
                    throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "Package {0} - {1} not found when try to download.", identity.Id, identity.Version.ToNormalizedString()));
                }

                Stream packageStream = sourceStream;
                try
                {
                    if (!sourceStream.CanSeek)
                    {
                        // V3 DownloadResource.GetStream does not support seek operations.
                        // https://github.com/NuGet/NuGet.Protocol/issues/15

                        MemoryStream memStream = new MemoryStream();

                        try
                        {
                            byte[] buffer = new byte[2048];

                            int bytesRead = 0;
                            do
                            {
                                bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
                                memStream.Write(buffer, 0, bytesRead);
                            } while (bytesRead != 0);

                            await memStream.FlushAsync();

                            memStream.Position = 0;

                            packageStream = memStream;
                        }
                        catch
                        {
                            memStream.Dispose();
                            throw;
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(pathToLocalCopyOfNudpk))
                    {
                        string packageFolderPath = Path.GetDirectoryName(pathToLocalCopyOfNudpk);
                        FileSystemHelpers.CreateDirectory(packageFolderPath);
                        using (Stream writeStream = FileSystemHelpers.OpenWrite(pathToLocalCopyOfNudpk))
                        {
                            OperationManager.Attempt(() => packageStream.CopyTo(writeStream));
                        }

                        // set position back to the head of stream
                        packageStream.Position = 0;
                    }

                    using (ZipFile zipFile = ZipFile.Read(packageStream))
                    {
                        // we only care about stuff under "content" folder
                        int substringStartIndex = @"content/".Length;
                        IEnumerable <ZipEntry> contentEntries = zipFile.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                        foreach (var entry in contentEntries)
                        {
                            string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));
                            FileSystemHelpers.CreateDirectory(Path.GetDirectoryName(fullPath));
                            using (Stream writeStream = FileSystemHelpers.OpenWrite(fullPath))
                            {
                                // let the thread go with itself, so that once file finsihed writing, doesn`t need to request thread context from main thread
                                await entry.OpenReader().CopyToAsync(writeStream).ConfigureAwait(false);
                            }
                        }
                    }
                }
                finally
                {
                    if (packageStream != null && !sourceStream.CanSeek)
                    {
                        // in this case, we created a copy of the source stream in memoery, need to manually dispose
                        packageStream.Dispose();
                    }
                }
            }
        }