Skip to content

Commit

Permalink
Ability to upload to Generic Packages Repository
Browse files Browse the repository at this point in the history
  • Loading branch information
gep13 committed Sep 12, 2023
1 parent f2d7b02 commit cf00481
Show file tree
Hide file tree
Showing 19 changed files with 435 additions and 2 deletions.
2 changes: 2 additions & 0 deletions NGitLab.Mock/Clients/GitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public GitLabClient(ClientContext context)

public IGroupsClient Groups => new GroupClient(Context);

public IPackageClient Packages => new PackageClient(Context);

public IUserClient Users => new UserClient(Context);

public IProjectClient Projects => new ProjectClient(Context);
Expand Down
30 changes: 30 additions & 0 deletions NGitLab.Mock/Clients/PackageClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NGitLab.Models;

namespace NGitLab.Mock.Clients
{
internal sealed class PackageClient : ClientBase, IPackageClient
{
public PackageClient(ClientContext context)
: base(context)
{
}

public Task<Package> PublishAsync(int projectId, PackagePublish packagePublish, CancellationToken cancellationToken = default)
{
throw new System.NotImplementedException();
}

public IEnumerable<PackageSearchResult> Get(int projectId, PackageQuery packageQuery)
{
throw new System.NotImplementedException();
}

public Task<PackageSearchResult> GetByIdAsync(int projectId, int packageId, CancellationToken cancellationToken = default)
{
throw new System.NotImplementedException();
}
}
}
40 changes: 40 additions & 0 deletions NGitLab.Tests/PackageTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NGitLab.Models;
using NGitLab.Tests.Docker;
using NUnit.Framework;

namespace NGitLab.Tests
{
public class PackageTests
{
[Test]
[NGitLabRetry]
public async Task Test_publish_package()
{
using var context = await GitLabTestContext.CreateAsync();
var project = context.CreateProject();
var packagesClient = context.Client.Packages;

var packagePublish = new PackagePublish
{
FileName = "README.md",
PackageName = "Packages",
PackageVersion = "1.0.0",
Status = "default",
PackageStream = File.OpenRead("../../../../README.md"),
};

var newGenericPackage = await packagesClient.PublishAsync(project.Id, packagePublish);

var packageQuery = new PackageQuery { PackageType = PackageType.generic };
var genericPackages = packagesClient.Get(project.Id, packageQuery).ToList();
var singleGenericPackage = await packagesClient.GetByIdAsync(project.Id, newGenericPackage.PackageId);

Assert.AreEqual(1, genericPackages.Count);
Assert.AreEqual(newGenericPackage.PackageId, genericPackages[0].PackageId);
Assert.AreEqual(singleGenericPackage.PackageId, newGenericPackage.PackageId);
}
}
}
3 changes: 3 additions & 0 deletions NGitLab/GitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class GitLabClient : IGitLabClient
{
private readonly API _api;

public IPackageClient Packages { get; }

public IUserClient Users { get; }

public IProjectClient Projects { get; }
Expand Down Expand Up @@ -73,6 +75,7 @@ public GitLabClient(string hostUrl, string userName, string password, RequestOpt
private GitLabClient(GitLabCredentials credentials, RequestOptions options)
{
_api = new API(credentials, options);
Packages = new PackageClient(_api);
Users = new UserClient(_api);
Projects = new ProjectClient(_api);
MergeRequests = new MergeRequestClient(_api);
Expand Down
2 changes: 2 additions & 0 deletions NGitLab/IGitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{
public interface IGitLabClient
{
IPackageClient Packages { get; }

IUserClient Users { get; }

IProjectClient Projects { get; }
Expand Down
34 changes: 34 additions & 0 deletions NGitLab/IPackageClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NGitLab.Models;

namespace NGitLab
{
public interface IPackageClient
{
/// <summary>
/// Add a package file with the proposed information to the GitLab Generic Package Repository for the selected Project Id.
/// </summary>
/// <param name="packagePublish">The information about the package file to publish.</param>
/// <returns>The package if it was created. Null if not.</returns>
Task<Package> PublishAsync(int projectId, PackagePublish packagePublish, CancellationToken cancellationToken = default);

/// <summary>
/// Gets all project packages based on the provided query parameters.
/// </summary>
/// <param name="projectId">The project id to search for packages in.</param>
/// <param name="packageQuery">The query parameters to be used for the search.</param>
/// <returns></returns>
IEnumerable<PackageSearchResult> Get(int projectId, PackageQuery packageQuery);

/// <summary>
/// Gets a single project package using the provided project and package ids.
/// </summary>
/// <param name="projectId">The project id that the package resides in.</param>
/// <param name="packageId">The package id that is being selected.</param>
/// <param name="cancellationToken">The cancellation token used to halt the request.</param>
/// <returns></returns>
Task<PackageSearchResult> GetByIdAsync(int projectId, int packageId, CancellationToken cancellationToken = default);
}
}
19 changes: 17 additions & 2 deletions NGitLab/Impl/HttpRequestor.GitLabRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ private sealed class GitLabRequest

public string JsonData { get; }

public FileContent FileContent { get; }

public FormDataContent FormData { get; }

private MethodType Method { get; }
Expand Down Expand Up @@ -60,7 +62,11 @@ public GitLabRequest(Uri url, MethodType method, object data, string apiToken, R
Headers.Add("User-Agent", options.UserAgent);
}

if (data is FormDataContent formData)
if (data is FileContent fileContent)
{
FileContent = fileContent;
}
else if (data is FormDataContent formData)
{
FormData = formData;
}
Expand Down Expand Up @@ -165,7 +171,11 @@ private HttpWebRequest CreateRequest(RequestOptions options)

if (HasOutput)
{
if (FormData != null)
if (FileContent != null)
{
AddFileContent(request, options);
}
else if (FormData != null)
{
AddFileData(request, options);
}
Expand All @@ -182,6 +192,11 @@ private HttpWebRequest CreateRequest(RequestOptions options)
return request;
}

private void AddFileContent(HttpWebRequest request, RequestOptions options)
{
FileContent.Stream.CopyTo(options.GetRequestStream(request));
}

private void AddJsonData(HttpWebRequest request, RequestOptions options)
{
request.ContentType = "application/json";
Expand Down
72 changes: 72 additions & 0 deletions NGitLab/Impl/PackageClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using NGitLab.Models;

namespace NGitLab.Impl
{
public class PackageClient : IPackageClient
{
private const string PublishPackageUrl = "/projects/{0}/packages/generic/{1}/{2}/{3}?status={4}&select=package_file";
private const string GetPackagesUrl = "/projects/{0}/packages";
private const string GetPackageUrl = "/projects/{0}/packages/{1}";

private readonly API _api;

public PackageClient(API api)
{
_api = api;
}

public Task<Package> PublishAsync(int projectId, PackagePublish packagePublish, CancellationToken cancellationToken = default)
{
var formData = new FileContent(packagePublish.PackageStream);

return _api.Put().With(formData).ToAsync<Package>(string.Format(CultureInfo.InvariantCulture,
PublishPackageUrl, projectId, Uri.EscapeDataString(packagePublish.PackageName),
Uri.EscapeDataString(packagePublish.PackageVersion), Uri.EscapeDataString(packagePublish.FileName),
Uri.EscapeDataString(packagePublish.Status)), cancellationToken);
}

public IEnumerable<PackageSearchResult> Get(int projectId, PackageQuery packageQuery)
{
var url = CreateGetUrl(projectId, packageQuery);
return _api.Get().GetAllAsync<PackageSearchResult>(url);
}

public Task<PackageSearchResult> GetByIdAsync(int projectId, int packageId, CancellationToken cancellationToken = default)
{
return _api.Get().ToAsync<PackageSearchResult>(string.Format(CultureInfo.InvariantCulture, GetPackageUrl, projectId, packageId), cancellationToken);
}

private static string CreateGetUrl(int projectId, PackageQuery query)
{
var url = string.Format(CultureInfo.InvariantCulture, GetPackagesUrl, projectId);

url = Utils.AddParameter(url, "order_by", query.OrderBy);
url = Utils.AddParameter(url, "sort", query.Sort);
url = Utils.AddParameter(url, "status", query.Status);
url = Utils.AddParameter(url, "page", query.Page);
url = Utils.AddParameter(url, "per_page", query.PerPage);

if (query.PackageType != PackageType.all)
{
url = Utils.AddParameter(url, "package_type", query.PackageType);
}

if (!string.IsNullOrWhiteSpace(query.PackageName))
{
url = Utils.AddParameter(url, "package_name", query.PackageName);
}

if (query.IncludeVersionless)
{
url = Utils.AddParameter(url, "include_versionless", true);
}

return url;
}
}
}
17 changes: 17 additions & 0 deletions NGitLab/Models/FileContent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.IO;

namespace NGitLab.Models
{
public sealed class FileContent
{
public FileContent(Stream stream)
{
Stream = stream;
}

/// <summary>
/// The stream to be uploaded.
/// </summary>
public Stream Stream { get; }
}
}
74 changes: 74 additions & 0 deletions NGitLab/Models/Package.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using System.Text.Json.Serialization;
using NGitLab.Impl.Json;

namespace NGitLab.Models
{
public class Package
{
[JsonPropertyName("id")]
public int Id { get; set; }

[JsonPropertyName("package_id")]
public int PackageId { get; set; }

[JsonPropertyName("created_at")]
[JsonConverter(typeof(DateOnlyConverter))]
public DateTime CreatedAt { get; set; }

[JsonPropertyName("updated_at")]
[JsonConverter(typeof(DateOnlyConverter))]
public DateTime? UpdatedAt { get; set; }

[JsonPropertyName("size")]
public int Size { get; set; }

[JsonPropertyName("file_store")]
public int FileStore { get; set; }

[JsonPropertyName("file_md5")]
public string FileMD5 { get; set; }

[JsonPropertyName("file_sha1")]
public string FileSHA1 { get; set; }

[JsonPropertyName("file_sha256")]
public string FileSHA256 { get; set; }

[JsonPropertyName("file_name")]
public string FileName { get; set; }

[JsonPropertyName("verification_retry_at")]
[JsonConverter(typeof(DateOnlyConverter))]
public DateTime? VerificationRetryAt { get; set; }

[JsonPropertyName("verified_at")]
[JsonConverter(typeof(DateOnlyConverter))]
public DateTime? VerifiedAt { get; set; }

[JsonPropertyName("verification_failure")]
public string VerificationFailure { get; set; }

[JsonPropertyName("verification_retry_count")]
public string VerificationRetryCount { get; set; }

[JsonPropertyName("verification_checksum")]
public string VerificationChecksum { get; set; }

[JsonPropertyName("verification_state")]
public int VerificationState { get; set; }

[JsonPropertyName("verification_started_at")]
[JsonConverter(typeof(DateOnlyConverter))]
public DateTime? VerificationStartedAt { get; set; }

[JsonPropertyName("new_file_path")]
public string NewFilePath { get; set; }

[JsonPropertyName("status")]
public string Status { get; set; }

[JsonPropertyName("file")]
public PackageFile File { get; set; }
}
}
10 changes: 10 additions & 0 deletions NGitLab/Models/PackageFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Text.Json.Serialization;

namespace NGitLab.Models
{
public class PackageFile
{
[JsonPropertyName("url")]
public string Url { get; set; }
}
}
13 changes: 13 additions & 0 deletions NGitLab/Models/PackageLink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Text.Json.Serialization;

namespace NGitLab.Models
{
public class PackageLinks
{
[JsonPropertyName("web_path")]
public string WebPath { get; set; }

[JsonPropertyName("delete_api_path")]
public string DeleteApiPath { get; set; }
}
}
10 changes: 10 additions & 0 deletions NGitLab/Models/PackageOrderBy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace NGitLab.Models
{
public enum PackageOrderBy
{
created_at,
name,
version,
type,
}
}
Loading

0 comments on commit cf00481

Please sign in to comment.