private async Task UpdateAndCommitAsync(string package, IPackagePatch patch) { var overview = await _repository.GetPackageAsync(package).ConfigureAwait(false); if (overview == null) { throw new PackageNotFoundException(package); } var updatedPatch = new PackagePatch() { PublishedVersions = patch.PublishedVersions, DeletedVersions = patch.DeletedVersions, UpdatedDistTags = patch.UpdatedDistTags, DeletedDistTags = patch.DeletedDistTags, // Ensure that we're only updating allowed fields on the Manifest by cloning the patch and inverting the updates UpdatedVersions = patch.UpdatedVersions.Select(version => { var matching = overview.Versions.SingleOrDefault(v => v.Id == version.Id) ?? throw new PackageVersionNotFoundException(version.Id); // Treat empty strings as equivalent to null matching.Manifest.Deprecated = string.IsNullOrEmpty(version.Manifest.Deprecated) ? null : version.Manifest.Deprecated; return(matching); }).ToList() }; await _repository.CommitAsync(package, updatedPatch).ConfigureAwait(false); } }
private static string GetResults(IPackagePatch patch) { var results = new[] { Tuple.Create(patch.PublishedVersions.Count, "published"), Tuple.Create(patch.UpdatedVersions.Count, "updated"), Tuple.Create(patch.DeletedVersions.Count, "unpublished") }; return(string.Join(", ", results.Where(t => t.Item1 > 0).Select(t => $"{t.Item1} {t.Item2}"))); }
public Task CommitAsync(string package, IPackagePatch patch) { return(patch.UpdatedVersions == null || patch.UpdatedVersions.Count == 0 ? _repository.CommitAsync(package, patch) : UpdateAndCommitAsync(package, patch)); }
public async Task CommitAsync(string package, IPackagePatch patch) { using (var connection = await _connectionProvider.GetConnectionAsync().ConfigureAwait(false)) using (var transaction = connection.BeginTransaction()) { var tasks = new List <Task>(); // Publish versions if (patch.PublishedVersions?.Count > 0) { var packages = new List <PackageVersionEntity>(); var tarballs = new List <TarballEntity>(); foreach (var version in patch.PublishedVersions) { packages.Add(ToEntity(version)); tarballs.Add(ToEntity(version.Tarball)); } tasks.Add(connection.ExecuteAsync(CreatePackageVersionQuery, packages, transaction)); tasks.Add(connection.ExecuteAsync(CreateTarballQuery, tarballs, transaction)); } // Update versions if (patch.UpdatedVersions?.Count > 0) { var versions = patch.UpdatedVersions.Select(ToEntity); tasks.Add(connection.ExecuteAsync(UpdatePackageVersionQuery, versions, transaction)); } // Delete versions if (patch.DeletedVersions?.Count > 0) { var versions = patch.DeletedVersions.Select(id => new PackageVersionEntity() { Package = id.Name, Version = id.Version, Published = false, Manifest = null // This is COALESCED in the UPDATE so it won't actually clobber the manifest }); tasks.Add(connection.ExecuteAsync(UpdatePackageVersionQuery, versions, transaction)); } // Update/create dist tags if (patch.UpdatedDistTags?.Count > 0) { var tags = patch.UpdatedDistTags.Select(kvp => new DistTagEntity() { Package = package, Tag = kvp.Key, Version = kvp.Value }); tasks.Add(connection.ExecuteAsync(CreateDistTagQuery, tags, transaction)); } // Delete dist tags if (patch.DeletedDistTags?.Count > 0) { var param = new { Package = package, Tags = patch.DeletedDistTags }; tasks.Add(connection.ExecuteAsync(DeleteDistTagsQuery, param, transaction)); } try { await Task.WhenAll(tasks).ConfigureAwait(false); transaction.Commit(); } catch (SqliteException ex) { if (ex.SqliteErrorCode != ErrorSqliteConstraint || ex.SqliteExtendedErrorCode != ErrorSqliteConstraintUnique) { throw; } var identifier = patch.PublishedVersions?.Count == 1 ? patch.PublishedVersions[0].Id : null; throw new DuplicatePackageVersionException(identifier, ex); } } }