예제 #1
0
        public async Task <JObject> CreatePackageBlobAsync(PackageInput packageInput)
        {
            var rootUri = GetPackageUri(packageInput.Identity);

            var json = JsonUtility.Create(rootUri, new string[] { "Package", "http://schema.nuget.org/catalog#Permalink" });

            json.Add("catalogEntry", packageInput.PackageDetails.GetIdUri().AbsoluteUri);
            json.Add("packageContent", packageInput.PackageDetails["packageContent"].ToString());
            json.Add("registration", GetIndexUri(packageInput.Identity));

            var copyProperties = new List <string>()
            {
                "listed",
                "published",
            };

            JsonUtility.CopyProperties(packageInput.PackageDetails, json, copyProperties, skipEmpty: true);

            // Copy the catalog entry into the package blob. This allows the feed to
            // save this info even if the catalog is disabled.
            // Note that this is different from NuGet.org, so the sleet: namespace is used.
            var catalogEntry = (JObject)packageInput.PackageDetails.DeepClone();

            // Clear packageEntries, this can be very large in some cases.
            catalogEntry.Remove("packageEntries");

            json.Add("sleet:catalogEntry", catalogEntry);

            var context = await JsonUtility.GetContextAsync("Package");

            json.Add("@context", context);

            return(JsonLDTokenComparer.Format(json));
        }
예제 #2
0
        /// <summary>
        /// Create a PackageDetails page that contains all the package information.
        /// </summary>
        public static Task <JObject> CreatePackageDetailsAsync(PackageInput packageInput, Uri catalogBaseURI, Uri nupkgUri, Guid commitId, bool writeFileList)
        {
            var pageId  = Guid.NewGuid().ToString().ToLowerInvariant();
            var rootUri = UriUtility.GetPath(catalogBaseURI, $"data/{pageId}.json");

            return(CreatePackageDetailsWithExactUriAsync(packageInput, rootUri, nupkgUri, commitId, writeFileList));
        }
예제 #3
0
        public async Task <JObject> CreatePackageBlob(PackageInput packageInput)
        {
            var rootUri = GetPackageUri(packageInput.Identity);

            var json = JsonUtility.Create(rootUri, new string[] { "Package", "http://schema.nuget.org/catalog#Permalink" });

            var packageDetailsFile = _context.Source.Get(packageInput.PackageDetailsUri);

            if (!await packageDetailsFile.Exists(_context.Log, _context.Token))
            {
                throw new FileNotFoundException($"Unable to find {packageDetailsFile.EntityUri.AbsoluteUri}");
            }

            var detailsJson = await packageDetailsFile.GetJson(_context.Log, _context.Token);

            json.Add("catalogEntry", packageInput.PackageDetailsUri.AbsoluteUri);
            json.Add("packageContent", detailsJson["packageContent"].ToString());
            json.Add("registration", GetIndexUri(packageInput.Identity));

            var copyProperties = new List <string>()
            {
                "listed",
                "published",
            };

            JsonUtility.CopyProperties(detailsJson, json, copyProperties, skipEmpty: true);

            var context = JsonUtility.GetContext("Package");

            json.Add("@context", context);

            return(JsonLDTokenComparer.Format(json));
        }
예제 #4
0
        public async Task AddPackageAsync(PackageInput packageInput)
        {
            // Create package details page
            var packageDetails = await CatalogUtility.CreatePackageDetailsAsync(packageInput, CatalogBaseURI, _context.CommitId, writeFileList : false);

            packageInput.PackageDetails = packageDetails;
        }
예제 #5
0
파일: Catalog.cs 프로젝트: skarllot/Sleet
        /// <summary>
        /// Add a package to the catalog.
        /// </summary>
        public async Task AddPackageAsync(PackageInput packageInput)
        {
            // Create package details page
            var addFileList = _context.SourceSettings.CatalogEnabled;

            var packageDetails = await CatalogUtility.CreatePackageDetailsAsync(packageInput, CatalogBaseURI, _context.CommitId, addFileList);

            var packageDetailsUri = JsonUtility.GetIdUri(packageDetails);

            // Add output to the package input for other services to use.
            packageInput.PackageDetails = packageDetails;

            var packageDetailsFile = _context.Source.Get(packageDetailsUri);
            await packageDetailsFile.Write(packageDetails, _context.Log, _context.Token);

            // Create commit
            var pageCommit = CatalogUtility.CreatePageCommit(
                packageInput.Identity,
                packageDetailsUri,
                _context.CommitId,
                SleetOperation.Add,
                "nuget:PackageDetails");

            await AddCatalogEntry(pageCommit, "nuget:lastCreated");
        }
예제 #6
0
        private static Task<PackageInput> GetPackageInput(string file, ILogger log)
        {
            // Validate package
            log.LogVerbose($"Reading {file}");
            PackageInput packageInput = null;

            try
            {
                // Read basic info from the package and verify that it isn't broken.
                packageInput = PackageInput.Create(file);
            }
            catch
            {
                log.LogError($"Invalid package '{file}'.");
                throw;
            }

            // Display a message for non-normalized packages
            if (packageInput.Identity.Version.ToString() != packageInput.Identity.Version.ToNormalizedString())
            {
                var message = $"Package '{packageInput.PackagePath}' does not contain a normalized version. Normalized: '{packageInput.Identity.Version.ToNormalizedString()}' Nuspec version: '{packageInput.Identity.Version.ToString()}'. See https://semver.org/ for details.";
                log.LogVerbose(message);
            }

            return Task.FromResult(packageInput);
        }
예제 #7
0
        private async Task CreateDetailsForAdd(PackageInput packageInput)
        {
            // Create a a details page and assign it to the input
            var nupkgUri       = packageInput.GetNupkgUri(_context);
            var packageDetails = await CatalogUtility.CreatePackageDetailsAsync(packageInput, CatalogBaseURI, nupkgUri, _context.CommitId, writeFileList : false);

            packageInput.PackageDetails = packageDetails;
        }
예제 #8
0
 private Task AddPackageAsync(PackageInput packageInput)
 {
     return(Task.WhenAll(new[]
     {
         AddNuspecAsync(packageInput),
         AddNupkgAsync(packageInput)
     }));
 }
예제 #9
0
        private static PackageInput GetPackageInput(string file, ILogger log)
        {
            // Validate package
            log.LogInformation($"Reading {file}");

            PackageIdentity identity           = null;
            var             isSymbolsPackage   = false;
            var             hasNuspec          = false;
            var             hasMultipleNuspecs = false;
            var             nuspecName         = string.Empty;

            try
            {
                // Read basic info from the package and verify that it isn't broken.
                using (var zip = new ZipArchive(File.OpenRead(file), ZipArchiveMode.Read, leaveOpen: false))
                    using (var package = new PackageArchiveReader(zip))
                    {
                        identity         = package.GetIdentity();
                        isSymbolsPackage = SymbolsUtility.IsSymbolsPackage(zip, file);

                        // Check for correct nuspec name
                        nuspecName = identity.Id + ".nuspec";
                        var nuspecs = zip.Entries.Where(entry => entry.FullName.EndsWith(".nuspec", StringComparison.OrdinalIgnoreCase)).ToList();

                        hasNuspec          = nuspecs.Count == 1;
                        hasMultipleNuspecs = nuspecs.Count > 1;
                    }
            }
            catch
            {
                log.LogError($"Invalid package '{file}'.");
                throw;
            }

            var packageInput = new PackageInput(file, identity, isSymbolsPackage);

            // Display a message for non-normalized packages
            if (packageInput.Identity.Version.ToString() != packageInput.Identity.Version.ToNormalizedString())
            {
                var message = $"Package '{packageInput.PackagePath}' does not contain a normalized version. Normalized: '{packageInput.Identity.Version.ToNormalizedString()}' Nuspec version: '{packageInput.Identity.Version.ToString()}'. See https://semver.org/ for details.";
                log.LogVerbose(message);
            }

            // Check for correct nuspec name
            if (!hasNuspec)
            {
                throw new InvalidDataException($"'{packageInput.PackagePath}' does not contain '{nuspecName}'.");
            }

            // Check for multiple nuspec files
            if (hasMultipleNuspecs)
            {
                throw new InvalidDataException($"'{packageInput.PackagePath}' contains multiple nuspecs and cannot be consumed.");
            }

            return(packageInput);
        }
예제 #10
0
        /// <summary>
        /// Add a package to all services.
        /// </summary>
        public static async Task AddPackage(SleetContext context, PackageInput package)
        {
            var services = GetServices(context);

            foreach (var service in services)
            {
                await service.AddPackage(package);
            }
        }
예제 #11
0
        private Task AddNupkgAsync(PackageInput packageInput)
        {
            // Add the nupkg by linking it instead of copying it to the local cache.
            var nupkgFile = _context.Source.Get(GetNupkgPath(packageInput.Identity));

            nupkgFile.Link(packageInput.PackagePath, _context.Log, _context.Token);

            return(Task.FromResult(true));
        }
예제 #12
0
파일: Symbols.cs 프로젝트: zdarovka/Sleet
        private async Task AddAssemblyAsync(PackageFile assembly, PackageInput packageInput)
        {
            var file = _context.Source.Get(SymbolsIndexUtility.GetAssemblyFilePath(assembly.FileName, assembly.Hash));

            if (await file.Exists(_context.Log, _context.Token) == false)
            {
                // Write assembly
                await file.Write(assembly.Stream, _context.Log, _context.Token);
            }
        }
예제 #13
0
        /// <summary>
        /// Create a package details page for a package id/version.
        /// </summary>
        private async Task CreatePackagePageAsync(PackageInput package)
        {
            // Create package page
            var packageUri  = GetPackageUri(package.Identity);
            var packageFile = _context.Source.Get(packageUri);
            var packageJson = await CreatePackageBlobAsync(package);

            // Write package page
            await packageFile.Write(packageJson, _context.Log, _context.Token);
        }
예제 #14
0
        public static SleetOperations CreateDelete(PackageSets originalIndex, IEnumerable <PackageIdentity> packagesToRemove, IEnumerable <PackageIdentity> symbolsPackagesToRemove)
        {
            var toAdd    = new List <PackageInput>();
            var toRemove = new List <PackageInput>();

            toRemove.AddRange(packagesToRemove.Select(e => PackageInput.CreateForDelete(e, isSymbols: false)));
            toRemove.AddRange(symbolsPackagesToRemove.Select(e => PackageInput.CreateForDelete(e, isSymbols: true)));

            return(Create(originalIndex, toAdd, toRemove));
        }
예제 #15
0
        public async Task AddSymbolsPackageAsync(PackageInput packageInput)
        {
            // Load existing index
            var sets = await GetPackageSetsAsync();

            // Add package
            await sets.Symbols.AddPackageAsync(packageInput);

            // Write file
            await Save(sets);
        }
예제 #16
0
        private async Task AddNuspecAsync(PackageInput packageInput)
        {
            // Add nuspec
            var nuspecPath = $"{packageInput.Identity.Id}.nuspec".ToLowerInvariant();
            var entryFile  = _context.Source.Get(GetZipFileUri(packageInput.Identity, nuspecPath));

            using (var nuspecStream = packageInput.Nuspec.Xml.AsMemoryStream())
            {
                await entryFile.Write(nuspecStream, _context.Log, _context.Token);
            }
        }
예제 #17
0
        private async Task AddAssemblyAsync(PackageFile assembly, PackageInput packageInput)
        {
            var file = _context.Source.Get(SymbolsIndexUtility.GetAssemblyFilePath(assembly.FileName, assembly.Hash));

            if (await file.Exists(_context.Log, _context.Token) == false)
            {
                // Write assembly
                using (var stream = await packageInput.GetEntryStreamWithLockAsync(assembly.ZipEntry))
                {
                    await file.Write(stream, _context.Log, _context.Token);
                }
            }
        }
예제 #18
0
        /// <summary>
        /// file/hash/index -> package
        /// </summary>
        private Task AddAssemblyToPackageIndexAsync(PackageInput package, ISleetFile indexFile, bool isSymbolsPackage)
        {
            var index = new PackageIndexFile(_context, indexFile, persistWhenEmpty: false);

            if (isSymbolsPackage)
            {
                return(index.AddSymbolsPackageAsync(package));
            }
            else
            {
                return(index.AddPackageAsync(package));
            }
        }
예제 #19
0
        private static void CheckForDuplicates(List<PackageInput> packages)
        {
            PackageInput lastPackage = null;
            foreach (var package in packages.OrderBy(e => e))
            {
                if (package.Equals(lastPackage))
                {
                    throw new InvalidOperationException($"Duplicate packages detected for '{package.Identity}'.");
                }

                lastPackage = package;
            }
        }
예제 #20
0
        /// <summary>
        /// Create a package details page for a package id/version.
        /// </summary>
        private async Task CreatePackagePageAsync(PackageInput package)
        {
            // Create package page
            var packageUri  = GetPackageUri(package.Identity);
            var packageFile = _context.Source.Get(packageUri);

            using (var timer = PerfEntryWrapper.CreateModifyTimer(packageFile, _context))
            {
                var packageJson = await CreatePackageBlobAsync(package);

                // Write package page
                await packageFile.Write(packageJson, _context.Log, _context.Token);
            }
        }
예제 #21
0
        private async Task AddNupkgAsync(PackageInput packageInput)
        {
            // Add nupkg
            var nupkgFile = _context.Source.Get(GetNupkgPath(packageInput.Identity));

            await nupkgFile.Write(File.OpenRead(packageInput.PackagePath), _context.Log, _context.Token);

            // Add nuspec
            var nuspecPath = $"{packageInput.Identity.Id}.nuspec".ToLowerInvariant();

            using (var nuspecStream = packageInput.Nuspec.Xml.AsMemoryStreamAsync())
            {
                var entryFile = _context.Source.Get(GetZipFileUri(packageInput.Identity, nuspecPath));
                await entryFile.Write(nuspecStream, _context.Log, _context.Token);
            }
        }
예제 #22
0
        /// <summary>
        /// Create a package item entry.
        /// </summary>
        public async Task <JObject> CreateItem(PackageInput packageInput)
        {
            var rootUri = GetPackageUri(packageInput.Identity);

            var json = JsonUtility.Create(rootUri, "Package");

            json.Add("commitId", _context.CommitId.ToString().ToLowerInvariant());
            json.Add("commitTimeStamp", DateTimeOffset.UtcNow.GetDateString());

            var packageDetailsFile = _context.Source.Get(packageInput.PackageDetailsUri);
            var detailsJson        = await packageDetailsFile.GetJson(_context.Log, _context.Token);

            json.Add("packageContent", detailsJson["packageContent"].ToString());
            json.Add("registration", GetIndexUri(packageInput.Identity));

            var copyProperties = new List <string>()
            {
                "@id",
                "@type",
                "authors",
                "dependencyGroups",
                "description",
                "iconUrl",
                "id",
                "language",
                "licenseUrl",
                "listed",
                "minClientVersion",
                "packageContent",
                "projectUrl",
                "published",
                "requireLicenseAcceptance",
                "summary",
                "tags",
                "title",
                "version"
            };

            var catalogEntry = new JObject();

            JsonUtility.CopyProperties(detailsJson, catalogEntry, copyProperties, skipEmpty: true);

            json.Add("catalogEntry", catalogEntry);

            return(JsonLDTokenComparer.Format(json));
        }
예제 #23
0
파일: Symbols.cs 프로젝트: zdarovka/Sleet
        private async Task AddPackageAsync(PackageInput packageInput, bool isSymbolsPackage)
        {
            var tasks = new List <Task>();

            if (isSymbolsPackage)
            {
                // Add symbols packages to the feed regardless of assemblies
                tasks.Add(AddSymbolsNupkgToFeed(packageInput));
            }

            // Read dll/pdb files from the package.
            var assemblies = await GetAssembliesAsync(packageInput);

            if (assemblies.Count > 0)
            {
                // Add the id/version to the package index.
                if (isSymbolsPackage)
                {
                    tasks.Add(PackageIndex.AddSymbolsPackageAsync(packageInput));
                }
                else
                {
                    tasks.Add(PackageIndex.AddPackageAsync(packageInput));
                }

                // Add dll/pdb files to the feed.
                tasks.AddRange(assemblies.Select(e => AddAssemblyAsync(e, packageInput)));

                // Add assembly -> package reverse lookup
                tasks.AddRange(assemblies.Select(e => AddAssemblyToPackageIndexAsync(packageInput, e.IndexFile, isSymbolsPackage: isSymbolsPackage)));

                // Add index of all dll/pdb files added for the package.
                tasks.Add(AddPackageToAssemblyIndexAsync(packageInput.Identity, assemblies, isSymbolsPackage: isSymbolsPackage));
            }
            else
            {
                await _context.Log.LogAsync(LogLevel.Verbose, $"No files found that could be added to the symbols feed. Skipping package {packageInput.Identity}");
            }

            // Wait for everything to finish
            await Task.WhenAll(tasks);

            // Dispose of memory streams
            assemblies.ForEach(e => e.Dispose());
        }
예제 #24
0
파일: Symbols.cs 프로젝트: zdarovka/Sleet
        // Copy the symbols nupkg to the symbols folder and create a catalog details page for it.
        private async Task AddSymbolsNupkgToFeed(PackageInput package)
        {
            // Write .nupkg to feed
            var packagePath = SymbolsIndexUtility.GetSymbolsNupkgPath(package.Identity);
            var packageFile = _context.Source.Get(packagePath);

            await packageFile.Write(File.OpenRead(package.PackagePath), _context.Log, _context.Token);

            // Write catalog entry to the symbols folder for the package
            var detailsPath = SymbolsIndexUtility.GetSymbolsPackageDetailsPath(package.Identity);
            var detailsFile = _context.Source.Get(detailsPath);

            var commitId = Guid.NewGuid();

            var detailsJson = await CatalogUtility.CreatePackageDetailsWithExactUriAsync(package, detailsFile.EntityUri, packageFile.EntityUri, commitId, writeFileList : false);

            await detailsFile.Write(detailsJson, _context.Log, _context.Token);
        }
예제 #25
0
        /// <summary>
        /// Create a package item entry.
        /// </summary>
        public JObject CreateItem(PackageInput packageInput)
        {
            var rootUri = GetPackageUri(packageInput.Identity);

            var json = JsonUtility.Create(rootUri, "Package");

            json.Add("commitId", _context.CommitId.ToString().ToLowerInvariant());
            json.Add("commitTimeStamp", DateTimeOffset.UtcNow.GetDateString());

            json.Add("packageContent", packageInput.PackageDetails["packageContent"].ToString());
            json.Add("registration", GetIndexUri(packageInput.Identity));

            var copyProperties = new List <string>()
            {
                "@id",
                "@type",
                "authors",
                "dependencyGroups",
                "description",
                "iconUrl",
                "id",
                "language",
                "licenseUrl",
                "listed",
                "minClientVersion",
                "packageContent",
                "projectUrl",
                "published",
                "requireLicenseAcceptance",
                "summary",
                "tags",
                "title",
                "version"
            };

            var catalogEntry = new JObject();

            JsonUtility.CopyProperties(packageInput.PackageDetails, catalogEntry, copyProperties, skipEmpty: true);

            json.Add("catalogEntry", catalogEntry);

            // Format package details at creation time, and avoid doing it again later to improve perf.
            return(JsonLDTokenComparer.Format(json));
        }
예제 #26
0
        public async Task AddPackage(PackageInput package)
        {
            // Retrieve index
            var rootUri  = GetIndexUri(package.Identity);
            var rootFile = _context.Source.Get(rootUri);

            var packages = new List <JObject>();

            if (await rootFile.Exists(_context.Log, _context.Token))
            {
                var json = await rootFile.GetJson(_context.Log, _context.Token);

                // Get all entries
                packages = await GetPackageDetails(json);
            }

            // Add entry
            var newEntry = await CreateItem(package);

            var removed = packages.RemoveAll(p => GetPackageVersion(p) == package.Identity.Version);

            if (removed > 0)
            {
                _context.Log.LogWarning($"Removed duplicate registration entry for: {package.Identity}");
            }

            packages.Add(newEntry);

            // Create index
            var newIndexJson = CreateIndex(rootUri, packages);

            // Write
            await rootFile.Write(newIndexJson, _context.Log, _context.Token);

            // Create package page
            var packageUri  = GetPackageUri(package.Identity);
            var packageFile = _context.Source.Get(packageUri);

            var packageJson = await CreatePackageBlob(package);

            // Write package page
            await packageFile.Write(packageJson, _context.Log, _context.Token);
        }
예제 #27
0
        public async Task AddPackage(PackageInput packageInput)
        {
            // Add nupkg
            var nupkgFile = _context.Source.Get(GetNupkgPath(packageInput.Identity));

            await nupkgFile.Write(File.OpenRead(packageInput.PackagePath), _context.Log, _context.Token);

            // Add nuspec
            var nuspecPath = $"{packageInput.Identity.Id}.nuspec".ToLowerInvariant();

            var nuspecEntry = packageInput.Zip.Entries
                              .Where(entry => nuspecPath.Equals(nuspecPath, StringComparison.OrdinalIgnoreCase))
                              .FirstOrDefault();

            if (nuspecEntry == null)
            {
                throw new InvalidDataException($"Unable to find '{nuspecPath}'. Path: '{packageInput.PackagePath}'.");
            }

            var entryFile = _context.Source.Get(GetZipFileUri(packageInput.Identity, nuspecPath));

            using (var stream = nuspecEntry.Open())
                using (var ms = new MemoryStream())
                {
                    stream.CopyTo(ms);
                    ms.Seek(0, SeekOrigin.Begin);
                    await entryFile.Write(ms, _context.Log, _context.Token);
                }

            // Update index
            var indexFile = _context.Source.Get(GetIndexUri(packageInput.Identity.Id));

            var versions = await GetVersions(packageInput.Identity.Id);

            versions.Add(packageInput.Identity.Version);

            var indexJson = CreateIndex(versions);

            await indexFile.Write(indexJson, _context.Log, _context.Token);

            // Set nupkg url
            packageInput.NupkgUri = nupkgFile.EntityUri;
        }
예제 #28
0
        private static Task <bool> AddZipEntry(PackageInput packageInput, Uri detailsUri, JArray packageEntriesArray)
        {
            var packageEntryIndex = 0;

            // This method is called from RunWithLockAsync
            foreach (var entry in packageInput.Zip.Entries.OrderBy(e => e.FullName, StringComparer.OrdinalIgnoreCase))
            {
                var fileEntry = JsonUtility.Create(detailsUri, $"packageEntry/{packageEntryIndex}", "packageEntry");
                fileEntry.Add("fullName", entry.FullName);
                fileEntry.Add("length", entry.Length);
                fileEntry.Add("lastWriteTime", entry.LastWriteTime.GetDateString());

                packageEntriesArray.Add(fileEntry);
                packageEntryIndex++;
            }

            // Result is not used
            return(Task.FromResult(true));
        }
예제 #29
0
        private async Task AddIconAsync(PackageInput packageInput)
        {
            // Find icon path in package from nuspec
            var iconPath = packageInput.Nuspec.GetIcon();

            if (!string.IsNullOrWhiteSpace(iconPath))
            {
                iconPath = PathUtility.StripLeadingDirectorySeparators(iconPath).Trim();

                using (var zip = packageInput.CreateZip())
                {
                    var entry = zip.GetEntry(iconPath);
                    if (entry != null)
                    {
                        var entryFile = _context.Source.Get(GetIconPath(packageInput.Identity));
                        await entryFile.Write(entry.Open(), _context.Log, _context.Token);
                    }
                }
            }
        }
예제 #30
0
파일: FlatContainer.cs 프로젝트: gmfx/Sleet
        public async Task AddPackageAsync(PackageInput packageInput)
        {
            // Add nupkg
            var nupkgFile = _context.Source.Get(GetNupkgPath(packageInput.Identity));

            await nupkgFile.Write(File.OpenRead(packageInput.PackagePath), _context.Log, _context.Token);

            // Add nuspec
            var nuspecPath = $"{packageInput.Identity.Id}.nuspec".ToLowerInvariant();

            var nuspecEntry = await packageInput.RunWithLockAsync((p) => Task.FromResult(p.Zip.Entries
                                                                                         .Where(entry => entry.FullName.Equals(nuspecPath, StringComparison.OrdinalIgnoreCase))
                                                                                         .FirstOrDefault()));

            if (nuspecEntry == null)
            {
                throw new InvalidDataException($"Unable to find '{nuspecPath}'. Path: '{packageInput.PackagePath}'.");
            }

            var nuspecStream = await packageInput.RunWithLockAsync(async p => await nuspecEntry.Open().AsMemoryStreamAsync());

            using (nuspecStream)
            {
                var entryFile = _context.Source.Get(GetZipFileUri(packageInput.Identity, nuspecPath));
                await entryFile.Write(nuspecStream, _context.Log, _context.Token);
            }

            // Update index
            var indexFile = _context.Source.Get(GetIndexUri(packageInput.Identity.Id));

            var versions = await GetVersions(packageInput.Identity.Id);

            versions.Add(packageInput.Identity.Version);

            var indexJson = CreateIndex(versions);

            await indexFile.Write(indexJson, _context.Log, _context.Token);

            // Set nupkg url
            packageInput.NupkgUri = nupkgFile.EntityUri;
        }