diff --git a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs
index e8f914b0..83f612de 100644
--- a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs
+++ b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reactive;
@@ -149,6 +150,18 @@ namespace Octokit.Reactive
///
IObservableRepositoryCommentsClient RepositoryComments { get; }
+ ///
+ /// A client for GitHub's Repository Hooks API.
+ ///
+ /// See Hooks API documentation for more information.
+ IObservableRepositoryHooksClient Hooks { get; }
+
+ ///
+ /// A client for GitHub's Repository Forks API.
+ ///
+ /// See Forks API documentation for more information.
+ IObservableRepositoryForksClient Forks { get; }
+
///
/// Client for GitHub's Repository Contents API.
///
diff --git a/Octokit.Reactive/Clients/IObservableRepositoryForksClient.cs b/Octokit.Reactive/Clients/IObservableRepositoryForksClient.cs
new file mode 100644
index 00000000..4131b0e5
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservableRepositoryForksClient.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Octokit.Reactive
+{
+ public interface IObservableRepositoryForksClient
+ {
+ ///
+ /// Gets the list of forks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "This is ok; we're matching HTTP verbs not keyworks")]
+ IObservable Get(string owner, string repositoryName);
+
+ ///
+ /// Creates a fork for a repository. Specify organization in the fork parameter to create for an organization.
+ ///
+ /// See API documentation for more information.
+ ///
+ IObservable Create(string owner, string repositoryName, NewRepositoryFork fork);
+ }
+}
diff --git a/Octokit.Reactive/Clients/IObservableRepositoryHooksClient.cs b/Octokit.Reactive/Clients/IObservableRepositoryHooksClient.cs
new file mode 100644
index 00000000..e8089f61
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservableRepositoryHooksClient.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reactive;
+
+namespace Octokit.Reactive
+{
+ public interface IObservableRepositoryHooksClient
+ {
+ ///
+ /// Gets the list of hooks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "This is ok; we're matching HTTP verbs not keyworks")]
+ IObservable Get(string owner, string repositoryName);
+
+ ///
+ /// Gets a single hook defined for a repository by id
+ ///
+ /// See API documentation for more information.
+ ///
+ IObservable GetById(string owner, string repositoryName, int hookId);
+
+ ///
+ /// Creates a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ IObservable Create(string owner, string repositoryName, NewRepositoryHook hook);
+
+ ///
+ /// Edits a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ IObservable Edit(string owner, string repositoryName, int hookId, EditRepositoryHook hook);
+
+ ///
+ /// Tests a hook for a repository
+ ///
+ /// See API documentation for more information.
+ /// This will trigger the hook with the latest push to the current repository if the hook is subscribed to push events. If the hook
+ /// is not subscribed to push events, the server will respond with 204 but no test POST will be generated.
+ ///
+ IObservable Test(string owner, string repositoryName, int hookId);
+
+ ///
+ /// Deletes a hook for a repository
+ ///
+ ///
+ ///
+ ///
+ /// See API documentation for more information.
+ ///
+ IObservable Delete(string owner, string repositoryName, int hookId);
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs
index a942c2a8..78c59d27 100644
--- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs
+++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs
@@ -20,6 +20,8 @@ namespace Octokit.Reactive
_client = client.Repository;
_connection = client.Connection;
CommitStatus = new ObservableCommitStatusClient(client);
+ Hooks = new ObservableRepositoryHooksClient(client);
+ Forks = new ObservableRepositoryForksClient(client);
RepoCollaborators = new ObservableRepoCollaboratorsClient(client);
Deployment = new ObservableDeploymentsClient(client);
Statistics = new ObservableStatisticsClient(client);
@@ -217,6 +219,18 @@ namespace Octokit.Reactive
///
public IObservableRepositoryCommentsClient RepositoryComments { get; private set; }
+ ///
+ /// A client for GitHub's Repository Hooks API.
+ ///
+ /// See Hooks API documentation for more information.
+ public IObservableRepositoryHooksClient Hooks { get; private set; }
+
+ ///
+ /// A client for GitHub's Repository Forks API.
+ ///
+ /// See Forks API documentation for more information.
+ public IObservableRepositoryForksClient Forks { get; private set; }
+
///
/// Client for GitHub's Repository Contents API.
///
diff --git a/Octokit.Reactive/Clients/ObservableRepositoryForksClient.cs b/Octokit.Reactive/Clients/ObservableRepositoryForksClient.cs
new file mode 100644
index 00000000..bba8e985
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservableRepositoryForksClient.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Reactive.Threading.Tasks;
+using Octokit.Reactive.Internal;
+
+namespace Octokit.Reactive
+{
+ public class ObservableRepositoryForksClient : IObservableRepositoryForksClient
+ {
+ readonly IRepositoryForksClient _client;
+ readonly IConnection _connection;
+
+ ///
+ /// Initializes a new GitHub Repos Fork API client.
+ ///
+ ///
+ public ObservableRepositoryForksClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, "client");
+ _client = client.Repository.Forks;
+ _connection = client.Connection;
+ }
+
+ ///
+ /// Gets the list of forks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable Get(string owner, string repositoryName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.RepositoryForks(owner, repositoryName));
+ }
+
+ ///
+ /// Creates a fork for a repository. Specify organization in the fork parameter to create for an organization.
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable Create(string owner, string repositoryName, NewRepositoryFork fork)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+ Ensure.ArgumentNotNull(fork, "fork");
+
+ return _client.Create(owner, repositoryName, fork).ToObservable();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/Clients/ObservableRepositoryHooksClient.cs b/Octokit.Reactive/Clients/ObservableRepositoryHooksClient.cs
new file mode 100644
index 00000000..8b8d5fa3
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservableRepositoryHooksClient.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Reactive;
+using System.Reactive.Threading.Tasks;
+using Octokit.Reactive.Internal;
+
+namespace Octokit.Reactive
+{
+ public class ObservableRepositoryHooksClient : IObservableRepositoryHooksClient
+ {
+ readonly IRepositoryHooksClient _client;
+ readonly IConnection _connection;
+
+ public ObservableRepositoryHooksClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, "client");
+
+ _client = client.Repository.Hooks;
+ _connection = client.Connection;
+ }
+
+ ///
+ /// Gets the list of hooks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable Get(string owner, string repositoryName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.RepositoryHooks(owner, repositoryName));
+ }
+
+ ///
+ /// Gets a single hook defined for a repository by id
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable GetById(string owner, string repositoryName, int hookId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return _client.GetById(owner, repositoryName, hookId).ToObservable();
+ }
+
+ ///
+ /// Creates a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable Create(string owner, string repositoryName, NewRepositoryHook hook)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+ Ensure.ArgumentNotNull(hook, "hook");
+
+ return _client.Create(owner, repositoryName, hook).ToObservable();
+ }
+
+ ///
+ /// Edits a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable Edit(string owner, string repositoryName, int hookId, EditRepositoryHook hook)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+ Ensure.ArgumentNotNull(hook, "hook");
+
+ return _client.Edit(owner, repositoryName, hookId, hook).ToObservable();
+ }
+
+ ///
+ /// Tests a hook for a repository
+ ///
+ /// See API documentation for more information.
+ /// This will trigger the hook with the latest push to the current repository if the hook is subscribed to push events. If the hook
+ /// is not subscribed to push events, the server will respond with 204 but no test POST will be generated.
+ ///
+ public IObservable Test(string owner, string repositoryName, int hookId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return _client.Test(owner, repositoryName, hookId).ToObservable();
+ }
+
+ ///
+ /// Deletes a hook for a repository
+ ///
+ ///
+ ///
+ ///
+ /// See API documentation for more information.
+ ///
+ public IObservable Delete(string owner, string repositoryName, int hookId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return _client.Delete(owner, repositoryName, hookId).ToObservable();
+ }
+ }
+}
diff --git a/Octokit.Reactive/Octokit.Reactive-Mono.csproj b/Octokit.Reactive/Octokit.Reactive-Mono.csproj
index 25f81385..3fb661c4 100644
--- a/Octokit.Reactive/Octokit.Reactive-Mono.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-Mono.csproj
@@ -148,6 +148,10 @@
+
+
+
+
diff --git a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
index e663b82d..52e6fd19 100644
--- a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
@@ -157,6 +157,10 @@
+
+
+
+
diff --git a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
index a1441ae8..66d08a2a 100644
--- a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
@@ -152,6 +152,10 @@
+
+
+
+
diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj
index 19db4fc6..dd48a648 100644
--- a/Octokit.Reactive/Octokit.Reactive.csproj
+++ b/Octokit.Reactive/Octokit.Reactive.csproj
@@ -85,6 +85,8 @@
+
+
@@ -145,6 +147,7 @@
+
@@ -156,6 +159,7 @@
+
diff --git a/Octokit.Tests/Clients/RepositoryForksClientTests.cs b/Octokit.Tests/Clients/RepositoryForksClientTests.cs
new file mode 100644
index 00000000..d640ef88
--- /dev/null
+++ b/Octokit.Tests/Clients/RepositoryForksClientTests.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Threading.Tasks;
+using NSubstitute;
+using Octokit.Tests.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Clients
+{
+ public class RepositoryForksClientTests
+ {
+ public class TheGetMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+
+ client.Forks.Get("fake", "repo");
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/forks"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Forks.Get(null, "name"));
+ await AssertEx.Throws(async () => await client.Forks.Get("owner", null));
+ }
+ }
+
+ public class TheCreateMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+ var newRepositoryFork = new NewRepositoryFork();
+
+ client.Forks.Create("fake", "repo", newRepositoryFork);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "repos/fake/repo/forks"), newRepositoryFork);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Forks.Create(null, "name", new NewRepositoryFork()));
+ await AssertEx.Throws(async () => await client.Forks.Create("owner", null, new NewRepositoryFork()));
+ await AssertEx.Throws(async () => await client.Forks.Create("owner", "name", null));
+ }
+
+ [Fact]
+ public void UsesTheSuppliedHook()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+ var newRepositoryFork = new NewRepositoryFork { Organization = "aName" };
+
+ client.Forks.Create("owner", "repo", newRepositoryFork);
+
+ connection.Received().Post(Arg.Any(), newRepositoryFork);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Tests/Clients/RepositoryHooksClientTest.cs b/Octokit.Tests/Clients/RepositoryHooksClientTest.cs
new file mode 100644
index 00000000..c94dc0a4
--- /dev/null
+++ b/Octokit.Tests/Clients/RepositoryHooksClientTest.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Threading.Tasks;
+using NSubstitute;
+using Octokit.Tests.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Clients
+{
+ public class RepositoryHooksClientTests
+ {
+ public class TheGetMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+
+ client.Hooks.Get("fake", "repo");
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/hooks"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Hooks.Get(null, "name"));
+ await AssertEx.Throws(async () => await client.Hooks.Get("owner", null));
+ }
+ }
+
+ public class TheGetByIdMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+
+ client.Hooks.GetById("fake", "repo", 12345678);
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/hooks/12345678"), null);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Hooks.GetById(null, "name", 123));
+ await AssertEx.Throws(async () => await client.Hooks.GetById("owner", null, 123));
+ }
+ }
+
+ public class TheCreateMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+ var hook = new NewRepositoryHook();
+
+ client.Hooks.Create("fake", "repo", hook);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "repos/fake/repo/hooks"), hook);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Hooks.Create(null, "name", new NewRepositoryHook()));
+ await AssertEx.Throws(async () => await client.Hooks.Create("owner", null, new NewRepositoryHook()));
+ await AssertEx.Throws(async () => await client.Hooks.Create("owner", "name", null));
+ }
+
+ [Fact]
+ public void UsesTheSuppliedHook()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+ var newRepositoryHook = new NewRepositoryHook { Name = "aName" };
+
+ client.Hooks.Create("owner", "repo", newRepositoryHook);
+
+ connection.Received().Post(Arg.Any(), newRepositoryHook);
+ }
+ }
+
+ public class TheEditMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+ var hook = new EditRepositoryHook();
+
+ client.Hooks.Edit("fake", "repo", 12345678, hook);
+
+ connection.Received().Patch(Arg.Is(u => u.ToString() == "repos/fake/repo/hooks/12345678"), hook);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Hooks.Edit(null, "name", 12345678, new EditRepositoryHook()));
+ await AssertEx.Throws(async () => await client.Hooks.Edit("owner", null, 12345678, new EditRepositoryHook()));
+ await AssertEx.Throws(async () => await client.Hooks.Edit("owner", "name", 12345678, null));
+ }
+
+ [Fact]
+ public void UsesTheSuppliedHook()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+ var editRepositoryHook = new EditRepositoryHook() { Active = false };
+
+ client.Hooks.Edit("owner", "repo", 12345678, editRepositoryHook);
+
+ connection.Received().Patch(Arg.Any(), editRepositoryHook);
+ }
+ }
+
+ public class TheTestMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+
+ client.Hooks.Test("fake", "repo", 12345678);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "repos/fake/repo/hooks/12345678/tests"), Arg.Any());
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Hooks.Test(null, "name", 12345678));
+ await AssertEx.Throws(async () => await client.Hooks.Test("owner", null, 12345678));
+ }
+
+ [Fact]
+ public void CallsPost()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+
+ client.Hooks.Test("owner", "repo", 12345678);
+
+ connection.Received().Post(Arg.Any(), Arg.Any());
+ }
+ }
+
+ public class TheDeleteMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new RepositoriesClient(connection);
+
+ client.Hooks.Delete("fake", "repo", 12345678);
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "repos/fake/repo/hooks/12345678"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new RepositoriesClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Hooks.Delete(null, "name", 12345678));
+ await AssertEx.Throws(async () => await client.Hooks.Delete("owner", null, 12345678));
+ }
+ }
+ }
+}
diff --git a/Octokit.Tests/OctoKit.Tests-NetCore45.csproj b/Octokit.Tests/OctoKit.Tests-NetCore45.csproj
index 304e2083..963ae8ea 100644
--- a/Octokit.Tests/OctoKit.Tests-NetCore45.csproj
+++ b/Octokit.Tests/OctoKit.Tests-NetCore45.csproj
@@ -84,6 +84,8 @@
+
+
diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj
index 2984c8ba..b3d33ec2 100644
--- a/Octokit.Tests/Octokit.Tests.csproj
+++ b/Octokit.Tests/Octokit.Tests.csproj
@@ -102,6 +102,8 @@
+
+
diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs
index a6c8cdc0..648e9415 100644
--- a/Octokit/Clients/IRepositoriesClient.cs
+++ b/Octokit/Clients/IRepositoriesClient.cs
@@ -200,6 +200,18 @@ namespace Octokit
///
ICommitStatusClient CommitStatus { get; }
+ ///
+ /// A client for GitHub's Repository Hooks API.
+ ///
+ /// See Hooks API documentation for more information.
+ IRepositoryHooksClient Hooks { get; }
+
+ ///
+ /// A client for GitHub's Repository Forks API.
+ ///
+ /// See Forks API documentation for more information.
+ IRepositoryForksClient Forks { get; }
+
///
/// A client for GitHub's Repo Collaborators.
///
diff --git a/Octokit/Clients/IRepositoryForksClient.cs b/Octokit/Clients/IRepositoryForksClient.cs
new file mode 100644
index 00000000..049e2969
--- /dev/null
+++ b/Octokit/Clients/IRepositoryForksClient.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public interface IRepositoryForksClient
+ {
+ ///
+ /// Gets the list of forks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "This is ok; we're matching HTTP verbs not keyworks")]
+ Task> Get(string owner, string repositoryName);
+
+ ///
+ /// Creates a fork for a repository. Specify organization in the fork parameter to create for an organization.
+ ///
+ /// See API documentation for more information.
+ ///
+ Task Create(string owner, string repositoryName, NewRepositoryFork fork);
+ }
+}
diff --git a/Octokit/Clients/IRepositoryHooksClient.cs b/Octokit/Clients/IRepositoryHooksClient.cs
new file mode 100644
index 00000000..c9ba580e
--- /dev/null
+++ b/Octokit/Clients/IRepositoryHooksClient.cs
@@ -0,0 +1,60 @@
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public interface IRepositoryHooksClient
+ {
+ ///
+ /// Gets the list of hooks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "This is ok; we're matching HTTP verbs not keyworks")]
+ Task> Get(string owner, string repositoryName);
+
+ ///
+ /// Gets a single hook by Id
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// See API documentation for more information.
+ Task GetById(string owner, string repositoryName, int hookId);
+
+ ///
+ /// Creates a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ Task Create(string owner, string repositoryName, NewRepositoryHook hook);
+
+ ///
+ /// Edits a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ Task Edit(string owner, string repositoryName, int hookId, EditRepositoryHook hook);
+
+ ///
+ /// Tests a hook for a repository
+ ///
+ /// See API documentation for more information.
+ /// This will trigger the hook with the latest push to the current repository if the hook is subscribed to push events. If the hook
+ /// is not subscribed to push events, the server will respond with 204 but no test POST will be generated.
+ ///
+ Task Test(string owner, string repositoryName, int hookId);
+
+ ///
+ /// Deletes a hook for a repository
+ ///
+ ///
+ ///
+ ///
+ /// See API documentation for more information.
+ ///
+ Task Delete(string owner, string repositoryName, int hookId);
+ }
+}
diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs
index b8f68c83..1cb7f0ea 100644
--- a/Octokit/Clients/RepositoriesClient.cs
+++ b/Octokit/Clients/RepositoriesClient.cs
@@ -23,6 +23,8 @@ namespace Octokit
public RepositoriesClient(IApiConnection apiConnection) : base(apiConnection)
{
CommitStatus = new CommitStatusClient(apiConnection);
+ Hooks = new RepositoryHooksClient(apiConnection);
+ Forks = new RepositoryForksClient(apiConnection);
RepoCollaborators = new RepoCollaboratorsClient(apiConnection);
Statistics = new StatisticsClient(apiConnection);
Deployment = new DeploymentsClient(apiConnection);
@@ -296,6 +298,25 @@ namespace Octokit
///
public ICommitStatusClient CommitStatus { get; private set; }
+ ///
+ /// A client for GitHub's Repository Hooks API.
+ ///
+ /// See Hooks API documentation for more information.
+ public IRepositoryHooksClient Hooks
+ {
+ get; private set;
+ }
+
+ ///
+ /// A client for GitHub's Repository Forks API.
+ ///
+ /// See Forks API documentation for more information.
+ public IRepositoryForksClient Forks
+ {
+ get;
+ private set;
+ }
+
///
/// A client for GitHub's Repo Collaborators.
///
diff --git a/Octokit/Clients/RepositoryForksClient.cs b/Octokit/Clients/RepositoryForksClient.cs
new file mode 100644
index 00000000..aa346aad
--- /dev/null
+++ b/Octokit/Clients/RepositoryForksClient.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public class RepositoryForksClient : ApiClient, IRepositoryForksClient
+ {
+ ///
+ /// Initializes a new GitHub Repos Fork API client.
+ ///
+ /// An API connection.
+ public RepositoryForksClient(IApiConnection apiConnection) : base(apiConnection)
+ {
+ }
+
+ ///
+ /// Gets the list of forks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public Task> Get(string owner, string repositoryName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return ApiConnection.GetAll(ApiUrls.RepositoryForks(owner, repositoryName));
+ }
+
+ ///
+ /// Creates a fork for a repository. Specify organization in the fork parameter to create for an organization.
+ ///
+ /// See API documentation for more information.
+ ///
+ public Task Create(string owner, string repositoryName, NewRepositoryFork fork)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+ Ensure.ArgumentNotNull(fork, "fork");
+
+ return ApiConnection.Post(ApiUrls.RepositoryForks(owner, repositoryName), fork);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Clients/RepositoryHooksClient.cs b/Octokit/Clients/RepositoryHooksClient.cs
new file mode 100644
index 00000000..b6d98b69
--- /dev/null
+++ b/Octokit/Clients/RepositoryHooksClient.cs
@@ -0,0 +1,104 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public class RepositoryHooksClient : ApiClient, IRepositoryHooksClient
+ {
+ ///
+ /// Initializes a new GitHub Repos API client.
+ ///
+ /// An API connection.
+ public RepositoryHooksClient(IApiConnection apiConnection) : base(apiConnection)
+ {
+ }
+
+ ///
+ /// Gets the list of hooks defined for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public Task> Get(string owner, string repositoryName)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return ApiConnection.GetAll(ApiUrls.RepositoryHooks(owner, repositoryName));
+ }
+
+ ///
+ /// Gets a single hook by Id
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// See API documentation for more information.
+ public Task GetById(string owner, string repositoryName, int hookId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return ApiConnection.Get(ApiUrls.RepositoryHookById(owner, repositoryName, hookId));
+ }
+
+ ///
+ /// Creates a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public Task Create(string owner, string repositoryName, NewRepositoryHook hook)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+ Ensure.ArgumentNotNull(hook, "hook");
+
+ return ApiConnection.Post(ApiUrls.RepositoryHooks(owner, repositoryName), hook);
+ }
+
+ ///
+ /// Edits a hook for a repository
+ ///
+ /// See API documentation for more information.
+ ///
+ public Task Edit(string owner, string repositoryName, int hookId, EditRepositoryHook hook)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+ Ensure.ArgumentNotNull(hook, "hook");
+
+ return ApiConnection.Patch(ApiUrls.RepositoryHookById(owner, repositoryName, hookId), hook);
+ }
+
+ ///
+ /// Tests a hook for a repository
+ ///
+ /// See API documentation for more information.
+ /// This will trigger the hook with the latest push to the current repository if the hook is subscribed to push events. If the hook
+ /// is not subscribed to push events, the server will respond with 204 but no test POST will be generated.
+ ///
+ public Task Test(string owner, string repositoryName, int hookId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return ApiConnection.Post(ApiUrls.RepositoryHookTest(owner, repositoryName, hookId), new TestRepositoryHook());
+ }
+
+ ///
+ /// Deletes a hook for a repository
+ ///
+ ///
+ ///
+ ///
+ /// See API documentation for more information.
+ ///
+ public Task Delete(string owner, string repositoryName, int hookId)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
+
+ return ApiConnection.Delete(ApiUrls.RepositoryHookById(owner, repositoryName, hookId));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs
index 192fe138..75604677 100644
--- a/Octokit/Helpers/ApiUrls.cs
+++ b/Octokit/Helpers/ApiUrls.cs
@@ -556,6 +556,41 @@ namespace Octokit
return "repos/{0}/{1}/statuses/{2}".FormatUri(owner, name, reference);
}
+ ///
+ /// Returns the that lists the repository hooks for the specified reference.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ ///
+ public static Uri RepositoryHooks(string owner, string repositoryName)
+ {
+ return "repos/{0}/{1}/hooks".FormatUri(owner, repositoryName);
+ }
+
+ ///
+ /// Returns the that gets the repository hook for the specified reference.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The identifier of the repository hook
+ ///
+ public static Uri RepositoryHookById(string owner, string repositoryName, int hookId)
+ {
+ return "repos/{0}/{1}/hooks/{2}".FormatUri(owner, repositoryName, hookId);
+ }
+
+ ///
+ /// Returns the that can tests a specified repository hook
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The identifier of the repository hook
+ ///
+ public static Uri RepositoryHookTest(string owner, string repositoryName, int hookId)
+ {
+ return "repos/{0}/{1}/hooks/{2}/tests".FormatUri(owner, repositoryName, hookId);
+ }
+
///
/// Returns the that lists the commit statuses for the specified reference.
///
@@ -580,6 +615,17 @@ namespace Octokit
return "repos/{0}/{1}/commits/{2}/status".FormatUri(owner, name, reference);
}
+ ///
+ /// Returns the that lists the repository forks for the specified reference.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ ///
+ public static Uri RepositoryForks(string owner, string repositoryName)
+ {
+ return "repos/{0}/{1}/forks".FormatUri(owner, repositoryName);
+ }
+
///
/// Returns the that lists the watched repositories for the authenticated user.
///
diff --git a/Octokit/Models/Request/EditRepositoryHook.cs b/Octokit/Models/Request/EditRepositoryHook.cs
new file mode 100644
index 00000000..acff18c0
--- /dev/null
+++ b/Octokit/Models/Request/EditRepositoryHook.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class EditRepositoryHook
+ {
+ public dynamic Config { get; set; }
+ public IEnumerable Events { get; set; }
+ public IEnumerable AddEvents { get; set; }
+ public IEnumerable RemoveEvents { get; set; }
+ public bool Active { get; set; }
+
+ internal string DebuggerDisplay
+ {
+ get
+ {
+ return String.Format(CultureInfo.InvariantCulture,
+ "Repository Hook: Replacing Events: {0}, Adding Events: {1}, Removing Events: {2}", Events == null ? "no" : string.Join(", ", Events),
+ AddEvents == null ? "no" : string.Join(", ", AddEvents),
+ RemoveEvents == null ? "no" : string.Join(", ", RemoveEvents));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Models/Request/NewRepositoryFork.cs b/Octokit/Models/Request/NewRepositoryFork.cs
new file mode 100644
index 00000000..86d97ba8
--- /dev/null
+++ b/Octokit/Models/Request/NewRepositoryFork.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class NewRepositoryFork
+ {
+ public string Organization { get; set; }
+
+ internal string DebuggerDisplay
+ {
+ get
+ {
+ return String.Format(CultureInfo.InvariantCulture,
+ "Repository Hook: Organization: {0}", Organization);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Models/Request/NewRepositoryHook.cs b/Octokit/Models/Request/NewRepositoryHook.cs
new file mode 100644
index 00000000..2f9f5ac0
--- /dev/null
+++ b/Octokit/Models/Request/NewRepositoryHook.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class NewRepositoryHook
+ {
+ public string Name { get; set; }
+ public dynamic Config { get; set; }
+ public IEnumerable Events { get; set; }
+ public bool Active { get; set; }
+
+ internal string DebuggerDisplay
+ {
+ get
+ {
+ return String.Format(CultureInfo.InvariantCulture,
+ "Repository Hook: Name: {0}, Events: {1}", Name,string.Join(", ", Events));
+ }
+ }
+ }
+}
diff --git a/Octokit/Models/Request/TestRepositoryHook.cs b/Octokit/Models/Request/TestRepositoryHook.cs
new file mode 100644
index 00000000..f04f1f70
--- /dev/null
+++ b/Octokit/Models/Request/TestRepositoryHook.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public class TestRepositoryHook
+ {
+ }
+}
diff --git a/Octokit/Models/Response/RepositoryHook.cs b/Octokit/Models/Response/RepositoryHook.cs
new file mode 100644
index 00000000..92e22fdc
--- /dev/null
+++ b/Octokit/Models/Response/RepositoryHook.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class RepositoryHook
+ {
+ public string Url { get; set; }
+ public DateTimeOffset CreatedAt { get; set; }
+ public DateTimeOffset UpdatedAt { get; set; }
+ public string Name { get; set; }
+ public IEnumerable Events { get; set; }
+ public bool Active { get; set; }
+ public dynamic Config { get; set; }
+ public int Id { get; set; }
+
+ internal string DebuggerDisplay
+ {
+ get
+ {
+ return String.Format(CultureInfo.InvariantCulture,
+ "Repository Hook: Name: {0} Url: {1}, Events: {2}", Name, Url, string.Join(", ", Events));
+ }
+ }
+ }
+}
diff --git a/Octokit/Models/Response/RepositoryHookConfiguration.cs b/Octokit/Models/Response/RepositoryHookConfiguration.cs
new file mode 100644
index 00000000..603967f2
--- /dev/null
+++ b/Octokit/Models/Response/RepositoryHookConfiguration.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class RepositoryHookConfiguration
+ {
+ public string Url { get; set; }
+ public string ContentType { get; set; }
+
+ internal string DebuggerDisplay
+ {
+ get
+ {
+ return String.Format(CultureInfo.InvariantCulture,
+ "Send {0} to {1}", ContentType, Url);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj
index 64a01234..a61b2202 100644
--- a/Octokit/Octokit-Mono.csproj
+++ b/Octokit/Octokit-Mono.csproj
@@ -64,6 +64,8 @@
+
+
@@ -78,6 +80,8 @@
+
+
@@ -94,6 +98,7 @@
+
@@ -105,6 +110,8 @@
+
+
@@ -118,6 +125,7 @@
+
@@ -164,6 +172,7 @@
+
diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj
index 14f5eae9..eddacf68 100644
--- a/Octokit/Octokit-MonoAndroid.csproj
+++ b/Octokit/Octokit-MonoAndroid.csproj
@@ -252,6 +252,7 @@
+
@@ -275,10 +276,18 @@
+
+
+
+
+
+
+
+
@@ -392,4 +401,4 @@
-
\ No newline at end of file
+
diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj
index 2becca9b..8266661c 100644
--- a/Octokit/Octokit-Monotouch.csproj
+++ b/Octokit/Octokit-Monotouch.csproj
@@ -356,6 +356,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj
index f4092e19..f8c1579d 100644
--- a/Octokit/Octokit-Portable.csproj
+++ b/Octokit/Octokit-Portable.csproj
@@ -88,6 +88,8 @@
+
+
@@ -110,6 +112,8 @@
+
+
@@ -170,6 +174,7 @@
+
@@ -190,6 +195,8 @@
+
+
@@ -205,6 +212,7 @@
+
@@ -260,6 +268,8 @@
+
+
diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj
index 077ffd01..e33d7286 100644
--- a/Octokit/Octokit-netcore45.csproj
+++ b/Octokit/Octokit-netcore45.csproj
@@ -93,6 +93,8 @@
+
+
@@ -114,6 +116,8 @@
+
+
@@ -176,6 +180,7 @@
+
@@ -193,6 +198,8 @@
+
+
@@ -209,6 +216,7 @@
+
@@ -266,6 +274,8 @@
+
+
diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj
index ec335c5e..577b7094 100644
--- a/Octokit/Octokit.csproj
+++ b/Octokit/Octokit.csproj
@@ -229,6 +229,8 @@
+
+
@@ -238,6 +240,8 @@
+
+
@@ -247,6 +251,7 @@
+
@@ -257,7 +262,10 @@
+
+
+
@@ -286,6 +294,7 @@
+