diff --git a/src/GitLabApiClient/BranchClient.cs b/src/GitLabApiClient/BranchClient.cs
index 2746d61b..bfb49e53 100644
--- a/src/GitLabApiClient/BranchClient.cs
+++ b/src/GitLabApiClient/BranchClient.cs
@@ -4,6 +4,7 @@
using GitLabApiClient.Internal.Http;
using GitLabApiClient.Internal.Paths;
using GitLabApiClient.Internal.Queries;
+using GitLabApiClient.Internal.Utilities;
using GitLabApiClient.Models.Branches.Requests;
using GitLabApiClient.Models.Branches.Responses;
using GitLabApiClient.Models.Projects.Responses;
@@ -30,7 +31,7 @@ internal BranchClient(
/// The branch name.
///
public async Task GetAsync(ProjectId projectId, string branchName) =>
- await _httpFacade.Get($"projects/{projectId}/repository/branches/{branchName}");
+ await _httpFacade.Get($"projects/{projectId}/repository/branches/{branchName.UrlEncode()}");
///
///
@@ -62,7 +63,7 @@ public async Task CreateAsync(ProjectId projectId, CreateBranchRequest r
/// The ID, path or of the project.
/// The branch, you want deleted.
public async Task DeleteBranch(ProjectId projectId, string branchName) =>
- await _httpFacade.Delete($"projects/{projectId}/repository/branches/{branchName}");
+ await _httpFacade.Delete($"projects/{projectId}/repository/branches/{branchName.UrlEncode()}");
///
/// Deletes the merged branches
@@ -78,7 +79,7 @@ public async Task DeleteMergedBranches(ProjectId projectId) =>
/// The protected branch
/// A protected branch
public async Task GetProtectedBranchesAsync(ProjectId projectId, string branchName) =>
- await _httpFacade.Get($"projects/{projectId}/protected_branches/{branchName}");
+ await _httpFacade.Get($"projects/{projectId}/protected_branches/{branchName.UrlEncode()}");
///
/// Retrieves a list of Protected Branches from a project.
@@ -103,6 +104,6 @@ public async Task ProtectBranchAsync(ProjectId projectId, Prote
/// The ID, path or of the project.
/// The Branch, you want to unprotect.
public async Task UnprotectBranchAsync(ProjectId projectId, string branchName) =>
- await _httpFacade.Delete($"projects/{projectId}/protected_branches/{branchName}");
+ await _httpFacade.Delete($"projects/{projectId}/protected_branches/{branchName.UrlEncode()}");
}
}
diff --git a/src/GitLabApiClient/IProjectsClient.cs b/src/GitLabApiClient/IProjectsClient.cs
index 75df4984..6447cbe6 100644
--- a/src/GitLabApiClient/IProjectsClient.cs
+++ b/src/GitLabApiClient/IProjectsClient.cs
@@ -82,6 +82,14 @@ public interface IProjectsClient
/// Newly created project.
Task CreateAsync(CreateProjectRequest request);
+ ///
+ /// Create a new fork of a project
+ ///
+ /// The ID, path or of the project.
+ /// Create fork request
+ ///
+ Task CreateForkAsync(ProjectId projectId, CreateProjectForkRequest request);
+
///
/// Creates new project label.
///
diff --git a/src/GitLabApiClient/Models/Projects/Requests/CreateProjectForkRequest.cs b/src/GitLabApiClient/Models/Projects/Requests/CreateProjectForkRequest.cs
new file mode 100644
index 00000000..885c4401
--- /dev/null
+++ b/src/GitLabApiClient/Models/Projects/Requests/CreateProjectForkRequest.cs
@@ -0,0 +1,68 @@
+using GitLabApiClient.Internal.Utilities;
+using Newtonsoft.Json;
+
+namespace GitLabApiClient.Models.Projects.Requests
+{
+ public sealed class CreateProjectForkRequest
+ {
+
+ ///
+ /// Initializes a new instance of the class.
+ /// The name of the new project.
+ ///
+ public static CreateProjectForkRequest FromName(string name)
+ {
+ Guard.NotEmpty(name, nameof(name));
+ return new CreateProjectForkRequest
+ {
+ Name = name,
+ Path = name.ToLower()
+ };
+ }
+
+ private CreateProjectForkRequest() { }
+
+ ///
+ /// The description assigned to the resultant project after forking
+ ///
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ ///
+ /// For forked projects, target merge requests to this project. If , the target is the upstream project
+ ///
+ [JsonProperty("mr_default_target_self")]
+ public bool DefaultTargetSelf { get; set; }
+
+ ///
+ /// The name assigned to the resultant project after forking
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// The ID of the namespace that the project is forked to
+ ///
+ [JsonProperty("namespace_id")]
+ public int NamespaceId { get; set; }
+
+ ///
+ /// The path of the namespace that the project is forked to
+ ///
+ [JsonProperty("namespace_path")]
+ public int NamespacePath { get; set; }
+
+ ///
+ /// The path assigned to the resultant project after forking
+ ///
+ [JsonProperty("path")]
+ public string Path { get; set; }
+
+ ///
+ /// The assigned to the resultant project after forking
+ ///
+ [JsonProperty("visibility")]
+ public ProjectVisibilityLevel? Visibility { get; set; }
+
+ }
+}
diff --git a/src/GitLabApiClient/ProjectsClient.cs b/src/GitLabApiClient/ProjectsClient.cs
index ffd52c0f..fba71036 100644
--- a/src/GitLabApiClient/ProjectsClient.cs
+++ b/src/GitLabApiClient/ProjectsClient.cs
@@ -136,6 +136,19 @@ public async Task CreateAsync(CreateProjectRequest request)
return await _httpFacade.Post("projects", request);
}
+ ///
+ /// Create a new fork of a project
+ ///
+ /// The ID, path or of the project.
+ /// Create fork request
+ /// Newly created project.
+ /// The forking operation for a project is asynchronous and is completed in a background job. The request returns immediately. To determine whether the fork of the project has completed, query the import_status for the new project.
+ public async Task CreateForkAsync(ProjectId projectId, CreateProjectForkRequest request)
+ {
+ Guard.NotNull(request, nameof(request));
+ return await _httpFacade.Post($"projects/{projectId}/fork", request);
+ }
+
///
/// Creates new project label.
///