diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 41ffb8b4..c03d26f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ But first things first... * Fork the repository on GitHub by clicking on the "Clone in Windows" button or run the following command in a git shell. ``` -git clone git@github.com:github/Octokit.net.git Octokit +git clone git@github.com:octokit/Octokit.net.git Octokit ``` * Make sure the project builds and all tests pass on your machine by running the `build.cmd` script (this calls a [FAKE](https://github.com/fsharp/fake) script, `build.fsx`). diff --git a/Octokit.Reactive/Clients/IObservableGistCommentsClient.cs b/Octokit.Reactive/Clients/IObservableGistCommentsClient.cs new file mode 100644 index 00000000..2d7372a5 --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableGistCommentsClient.cs @@ -0,0 +1,56 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reactive; + +namespace Octokit.Reactive +{ + public interface IObservableGistCommentsClient + { + /// + /// Gets a single comment by gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#get-a-single-comment + /// The id of the gist + /// The id of the comment + /// IObservable{GistComment}. + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + IObservable Get(int gistId, int commentId); + + /// + /// Gets all comments for the gist with the specified id. + /// + /// http://developer.github.com/v3/gists/comments/#list-comments-on-a-gist + /// The id of the gist + /// IObservable{GistComment}. + IObservable GetForGist(int gistId); + + /// + /// Creates a comment for the gist with the specified id. + /// + /// http://developer.github.com/v3/gists/comments/#create-a-comment + /// The id of the gist + /// The body of the comment + /// IObservable{GistComment}. + IObservable Create(int gistId, string comment); + + /// + /// Updates the comment with the specified gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#edit-a-comment + /// The id of the gist + /// The id of the comment + /// The updated body of the comment + /// IObservable{GistComment}. + IObservable Update(int gistId, int commentId, string comment); + + /// + /// Deletes the comment with the specified gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#delete-a-comment + /// The id of the gist + /// The id of the comment + /// IObservable{Unit}. + IObservable Delete(int gistId, int commentId); + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableGistsClient.cs b/Octokit.Reactive/Clients/IObservableGistsClient.cs new file mode 100644 index 00000000..5bb29ede --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableGistsClient.cs @@ -0,0 +1,21 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Octokit.Reactive +{ + public interface IObservableGistsClient + { + IObservableGistCommentsClient Comment { get; set; } + + /// + /// Gets a gist + /// + /// + /// http://developer.github.com/v3/gists/#get-a-single-gist + /// + /// The id of the gist + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + IObservable Get(string id); + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableGitDatabaseClient.cs b/Octokit.Reactive/Clients/IObservableGitDatabaseClient.cs index d071c78a..9f38c345 100644 --- a/Octokit.Reactive/Clients/IObservableGitDatabaseClient.cs +++ b/Octokit.Reactive/Clients/IObservableGitDatabaseClient.cs @@ -5,7 +5,10 @@ /// public interface IObservableGitDatabaseClient { + IObservableBlobClient Blob { get; set; } IObservableTagsClient Tag { get; set; } + IObservableTreesClient Tree { get; set; } IObservableCommitsClient Commit { get; set; } + IObservableReferencesClient Reference { get; set; } } } \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs b/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs index 58269a62..7dc0b2b6 100644 --- a/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssuesEventsClient.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Octokit.Reactive.Clients +namespace Octokit.Reactive { public interface IObservableIssuesEventsClient { diff --git a/Octokit.Reactive/Clients/IObservableMilestonesClient.cs b/Octokit.Reactive/Clients/IObservableMilestonesClient.cs index 321790a1..f1ad38e3 100644 --- a/Octokit.Reactive/Clients/IObservableMilestonesClient.cs +++ b/Octokit.Reactive/Clients/IObservableMilestonesClient.cs @@ -1,9 +1,8 @@ using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reactive; -namespace Octokit +namespace Octokit.Reactive { public interface IObservableMilestonesClient { diff --git a/Octokit.Reactive/Clients/IObservableOrganizationTeamsClient.cs b/Octokit.Reactive/Clients/IObservableOrganizationTeamsClient.cs index a7911838..9c9dfc33 100644 --- a/Octokit.Reactive/Clients/IObservableOrganizationTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableOrganizationTeamsClient.cs @@ -16,7 +16,7 @@ namespace Octokit.Reactive /// Returns all s for the current org. /// /// Thrown when a general API error occurs. - /// A list of the orgs's teams s. + /// A list of the orgs's teams s. IObservable GetAllTeams(string org); /// diff --git a/Octokit.Reactive/Clients/IObservableReferencesClient.cs b/Octokit.Reactive/Clients/IObservableReferencesClient.cs new file mode 100644 index 00000000..86b7eb89 --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableReferencesClient.cs @@ -0,0 +1,83 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reactive; + +namespace Octokit.Reactive +{ + public interface IObservableReferencesClient + { + /// + /// Gets a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#get-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + IObservable Get(string owner, string name, string reference); + + /// + /// Gets all references for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// + IObservable GetAll(string owner, string name); + + /// + /// Gets references for a given repository by sub-namespace, i.e. "tags" or "heads" + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// The sub-namespace to get references for + /// + IObservable GetAll(string owner, string name, string subNamespace); + + /// + /// Creates a reference for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#create-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The reference to create + /// + IObservable Create(string owner, string name, NewReference reference); + + /// + /// Updates a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#update-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// The updated reference data + /// + IObservable Update(string owner, string name, string reference, ReferenceUpdate referenceUpdate); + + /// + /// Deletes a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#delete-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + IObservable Delete(string owner, string name, string reference); + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableStarredClient.cs b/Octokit.Reactive/Clients/IObservableStarredClient.cs new file mode 100644 index 00000000..382260c9 --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableStarredClient.cs @@ -0,0 +1,78 @@ +using System; + +namespace Octokit.Reactive +{ + public interface IObservableStarredClient + { + /// + /// Retrieves all of the stargazers for the passed repository + /// + /// The owner of the repository + /// The name of the repository + /// Thrown if the client is not authenticated + /// A of starring the passed repository + IObservable GetAllStargazers(string owner, string name); + + /// + /// Retrieves all of the starred (ies) for the current user + /// + /// Thrown if the client is not authenticated + /// + /// A of (ies) starred by the current user + /// + IObservable GetAllForCurrent(); + + /// + /// Retrieves all of the starred (ies) for the current user + /// + /// Star-specific request parameters that sort the results + /// Thrown if the client is not authenticated + /// + /// A of (ies) starred by the current user, + /// sorted according to the passed request parameters + /// + IObservable GetAllForCurrent(StarredRequest request); + + /// + /// Retrieves all of the (ies) starred by the specified user + /// + /// The login of the user + /// Thrown if the client is not authenticated + /// A starred by the specified user + IObservable GetAllForUser(string user); + + /// + /// Retrieves all of the (ies) starred by the specified user + /// + /// The login of the user + /// Star-specific request parameters that sort the results + /// Thrown if the client is not authenticated + /// A starred by the specified user + IObservable GetAllForUser(string user, StarredRequest request); + + /// + /// Check if a repository is starred by the current authenticated user + /// + /// The owner of the repository + /// The name of the repository + /// Thrown if the client is not authenticated. + /// A bool representing the success of the operation + IObservable CheckStarred(string owner, string name); + + /// + /// Stars a repository for the authenticated user + /// + /// The owner of the repository to star + /// The name of the repository to star + /// A bool representing the success of starring + IObservable StarRepo(string owner, string name); + + /// + /// Unstars a repository for the authenticated user + /// + /// The owner of the repository to unstar + /// The name of the repository to unstar + /// A bool representing the success of the operation + IObservable RemoveStarFromRepo(string owner, string name); + } +} diff --git a/Octokit.Reactive/Clients/ObservableGistCommentsClient.cs b/Octokit.Reactive/Clients/ObservableGistCommentsClient.cs new file mode 100644 index 00000000..e1e6f576 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableGistCommentsClient.cs @@ -0,0 +1,95 @@ +using System; +using System.Reactive; +using System.Reactive.Threading.Tasks; +using Octokit.Reactive.Internal; + +namespace Octokit.Reactive +{ + public class ObservableGistCommentsClient : IObservableGistCommentsClient + { + readonly IGistCommentsClient _client; + readonly IConnection _connection; + + public ObservableGistCommentsClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _client = client.Gist.Comment; + _connection = client.Connection; + } + + /// + /// Gets a single comment by gist- and comment id. + /// + /// + /// http://developer.github.com/v3/gists/comments/#get-a-single-comment + /// + /// The id of the gist + /// The id of the comment + /// IObservable{GistComment}. + public IObservable Get(int gistId, int commentId) + { + return _client.Get(gistId, commentId).ToObservable(); + } + + /// + /// Gets all comments for the gist with the specified id. + /// + /// + /// http://developer.github.com/v3/gists/comments/#list-comments-on-a-gist + /// + /// The id of the gist + /// IObservable{GistComment}. + public IObservable GetForGist(int gistId) + { + return _connection.GetAndFlattenAllPages(ApiUrls.GistComments(gistId)); + } + + /// + /// Creates a comment for the gist with the specified id. + /// + /// + /// http://developer.github.com/v3/gists/comments/#create-a-comment + /// + /// The id of the gist + /// The body of the comment + /// IObservable{GistComment}. + public IObservable Create(int gistId, string comment) + { + Ensure.ArgumentNotNullOrEmptyString(comment, "comment"); + + return _client.Create(gistId, comment).ToObservable(); + } + + /// + /// Updates the comment with the specified gist- and comment id. + /// + /// + /// http://developer.github.com/v3/gists/comments/#edit-a-comment + /// + /// The id of the gist + /// The id of the comment + /// The updated body of the comment + /// IObservable{GistComment}. + public IObservable Update(int gistId, int commentId, string comment) + { + Ensure.ArgumentNotNullOrEmptyString(comment, "comment"); + + return _client.Update(gistId, commentId, comment).ToObservable(); + } + + /// + /// Deletes the comment with the specified gist- and comment id. + /// + /// + /// http://developer.github.com/v3/gists/comments/#delete-a-comment + /// + /// The id of the gist + /// The id of the comment + /// IObservable{Unit}. + public IObservable Delete(int gistId, int commentId) + { + return _client.Delete(gistId, commentId).ToObservable(); + } + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableGistsClient.cs b/Octokit.Reactive/Clients/ObservableGistsClient.cs new file mode 100644 index 00000000..63c2e6b7 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableGistsClient.cs @@ -0,0 +1,35 @@ +using System; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + public class ObservableGistsClient : IObservableGistsClient + { + readonly IGistsClient _client; + + public ObservableGistsClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _client = client.Gist; + Comment = new ObservableGistCommentsClient(client); + } + + public IObservableGistCommentsClient Comment { get; set; } + + /// + /// Gets a gist + /// + /// + /// http://developer.github.com/v3/gists/#get-a-single-gist + /// + /// The id of the gist + /// IObservable{Gist}. + public IObservable Get(string id) + { + Ensure.ArgumentNotNullOrEmptyString(id, "id"); + + return _client.Get(id).ToObservable(); + } + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableGitDatabaseClient.cs b/Octokit.Reactive/Clients/ObservableGitDatabaseClient.cs index 48a65d0a..c3b338ca 100644 --- a/Octokit.Reactive/Clients/ObservableGitDatabaseClient.cs +++ b/Octokit.Reactive/Clients/ObservableGitDatabaseClient.cs @@ -4,11 +4,17 @@ { public ObservableGitDatabaseClient(IGitHubClient client) { + Blob = new ObservableBlobClient(client); Tag = new ObservableTagsClient(client); + Tree = new ObservableTreesClient(client); Commit = new ObservableCommitsClient(client); + Reference = new ObservableReferencesClient(client); } + public IObservableBlobClient Blob { get; set; } public IObservableTagsClient Tag { get; set; } + public IObservableTreesClient Tree { get; set; } public IObservableCommitsClient Commit { get; set; } + public IObservableReferencesClient Reference { get; set; } } } \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableIssuesClient.cs b/Octokit.Reactive/Clients/ObservableIssuesClient.cs index 38db8211..c9042400 100644 --- a/Octokit.Reactive/Clients/ObservableIssuesClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssuesClient.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Reactive.Threading.Tasks; -using Octokit.Reactive.Clients; using Octokit.Reactive.Internal; namespace Octokit.Reactive diff --git a/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs b/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs index 50e54300..67ff9184 100644 --- a/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssuesEventsClient.cs @@ -1,9 +1,8 @@ using System; -using System.Reactive; using System.Reactive.Threading.Tasks; using Octokit.Reactive.Internal; -namespace Octokit.Reactive.Clients +namespace Octokit.Reactive { public class ObservableIssuesEventsClient : IObservableIssuesEventsClient { diff --git a/Octokit.Reactive/Clients/ObservableMilestonesClient.cs b/Octokit.Reactive/Clients/ObservableMilestonesClient.cs index bd33ad53..65dcaf86 100644 --- a/Octokit.Reactive/Clients/ObservableMilestonesClient.cs +++ b/Octokit.Reactive/Clients/ObservableMilestonesClient.cs @@ -3,7 +3,7 @@ using System.Reactive; using System.Reactive.Threading.Tasks; using Octokit.Reactive.Internal; -namespace Octokit.Reactive.Clients +namespace Octokit.Reactive { public class ObservableMilestonesClient : IObservableMilestonesClient { diff --git a/Octokit.Reactive/Clients/ObservableNotificationsClient.cs b/Octokit.Reactive/Clients/ObservableNotificationsClient.cs index 40893408..f7a3889d 100644 --- a/Octokit.Reactive/Clients/ObservableNotificationsClient.cs +++ b/Octokit.Reactive/Clients/ObservableNotificationsClient.cs @@ -1,7 +1,7 @@ using System; using Octokit.Reactive.Internal; -namespace Octokit.Reactive.Clients +namespace Octokit.Reactive { public class ObservableNotificationsClient : IObservableNotificationsClient { diff --git a/Octokit.Reactive/Clients/ObservableOrganizationTeamsClient.cs b/Octokit.Reactive/Clients/ObservableOrganizationTeamsClient.cs index 609375cc..1888a2a4 100644 --- a/Octokit.Reactive/Clients/ObservableOrganizationTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableOrganizationTeamsClient.cs @@ -25,7 +25,7 @@ namespace Octokit.Reactive /// Returns all s for the current org. /// /// Thrown when a general API error occurs. - /// A list of the orgs's teams s. + /// A list of the orgs's teams s. public IObservable GetAllTeams(string org) { Ensure.ArgumentNotNullOrEmptyString(org, "org"); diff --git a/Octokit.Reactive/Clients/ObservableReferencesClient.cs b/Octokit.Reactive/Clients/ObservableReferencesClient.cs new file mode 100644 index 00000000..4f578098 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableReferencesClient.cs @@ -0,0 +1,135 @@ +using System; +using System.Reactive; +using System.Reactive.Threading.Tasks; +using Octokit.Reactive.Internal; + +namespace Octokit.Reactive +{ + public class ObservableReferencesClient : IObservableReferencesClient + { + readonly IReferencesClient _reference; + readonly IConnection _connection; + + public ObservableReferencesClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _reference = client.GitDatabase.Reference; + _connection = client.Connection; + } + + /// + /// Gets a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#get-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + public IObservable Get(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + + return _reference.Get(owner, name, reference).ToObservable(); + } + + /// + /// Gets all references for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// + public IObservable GetAll(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Reference(owner, name)); + } + + /// + /// Gets references for a given repository by sub-namespace, i.e. "tags" or "heads" + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// The sub-namespace to get references for + /// + public IObservable GetAll(string owner, string name, string subNamespace) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(subNamespace, "subNamespace"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Reference(owner, name, subNamespace)); + } + + /// + /// Creates a reference for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#create-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The reference to create + /// + public IObservable Create(string owner, string name, NewReference reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNull(reference, "reference"); + + return _reference.Create(owner, name, reference).ToObservable(); + } + + /// + /// Updates a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#update-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// The updated reference data + /// + public IObservable Update(string owner, string name, string reference, ReferenceUpdate referenceUpdate) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + Ensure.ArgumentNotNull(referenceUpdate, "update"); + + return _reference.Update(owner, name, reference, referenceUpdate).ToObservable(); + } + + /// + /// Deletes a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#delete-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + public IObservable Delete(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + + return _reference.Delete(owner, name, reference).ToObservable(); + } + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Clients/ObservableStarredClient.cs b/Octokit.Reactive/Clients/ObservableStarredClient.cs new file mode 100644 index 00000000..7439c111 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableStarredClient.cs @@ -0,0 +1,132 @@ +using System; +using System.Reactive.Threading.Tasks; + +using Octokit.Reactive.Internal; + +namespace Octokit.Reactive +{ + public class ObservableStarredClient + { + private IStarredClient _client; + private IConnection _connection; + + public ObservableStarredClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, "client"); + + _client = client.Activity.Starring; + _connection = client.Connection; + } + + /// + /// Retrieves all of the stargazers for the passed repository + /// + /// The owner of the repository + /// The name of the repository + /// Thrown if the client is not authenticated + /// A of s starring the passed repository + public IObservable GetAllStargazers(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Stargazers(owner, name)); + } + + /// + /// Retrieves all of the starred (ies) for the current user + /// + /// Thrown if the client is not authenticated + /// A of + public IObservable GetAllForCurrent() + { + return _connection.GetAndFlattenAllPages(ApiUrls.Starred()); + } + + /// + /// Retrieves all of the starred (ies) for the current user + /// + /// Star-specific request parameters that sort the results + /// Thrown if the client is not authenticated + /// A of (ies) starred by the current user + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] + public IObservable GetAllForCurrent(StarredRequest request) + { + Ensure.ArgumentNotNull(request, "request"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Starred(), request.ToParametersDictionary()); + } + + /// + /// Retrieves all of the (ies) starred by the specified user + /// + /// The login of the user + /// Thrown if the client is not authenticated + /// A starred by the specified user + public IObservable GetAllForUser(string user) + { + Ensure.ArgumentNotNullOrEmptyString(user, "user"); + + return _connection.GetAndFlattenAllPages(ApiUrls.StarredByUser(user)); + } + + /// + /// Retrieves all of the (ies) starred by the specified user + /// + /// The login of the user + /// Star-specific request parameters that sort the results + /// Thrown if the client is not authenticated + /// A starred by the specified user + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] + public IObservable GetAllForUser(string user, StarredRequest request) + { + Ensure.ArgumentNotNullOrEmptyString(user, "user"); + Ensure.ArgumentNotNull(request, "request"); + + return _connection.GetAndFlattenAllPages(ApiUrls.StarredByUser(user), request.ToParametersDictionary()); + } + + /// + /// Check if a repository is starred by the current authenticated user + /// + /// The owner of the repository + /// The name of the repository + /// Thrown if the client is not authenticated + /// A bool representing the success of the operation + public IObservable CheckStarred(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return _client.CheckStarred(owner, name).ToObservable(); + } + + /// + /// Stars a repository for the authenticated user. + /// + /// The owner of the repository to star + /// The name of the repository to star + /// A bool representing the success of starring + public IObservable StarRepo(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return _client.StarRepo(owner, name).ToObservable(); + } + + /// + /// Unstars a repository for the authenticated user. + /// + /// The owner of the repository to unstar + /// The name of the repository to unstar + /// A bool representing the success of the operation + public IObservable RemoveStarFromRepo(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return _client.RemoveStarFromRepo(owner, name).ToObservable(); + } + } +} diff --git a/Octokit.Reactive/IObservableGitHubClient.cs b/Octokit.Reactive/IObservableGitHubClient.cs index f8b2531c..4f0cb79d 100644 --- a/Octokit.Reactive/IObservableGitHubClient.cs +++ b/Octokit.Reactive/IObservableGitHubClient.cs @@ -14,5 +14,6 @@ IObservableUsersClient User { get; } IObservableGitDatabaseClient GitDatabase { get; } IObservableTreesClient Tree { get; } + IObservableGistsClient Gist { get; } } } \ No newline at end of file diff --git a/Octokit.Reactive/ObservableGitHubClient.cs b/Octokit.Reactive/ObservableGitHubClient.cs index 42e1f19b..f5fad6f4 100644 --- a/Octokit.Reactive/ObservableGitHubClient.cs +++ b/Octokit.Reactive/ObservableGitHubClient.cs @@ -1,6 +1,5 @@ using System; using System.Net.Http.Headers; -using Octokit.Reactive.Clients; namespace Octokit.Reactive { @@ -45,6 +44,7 @@ namespace Octokit.Reactive Release = new ObservableReleasesClient(gitHubClient); GitDatabase = new ObservableGitDatabaseClient(gitHubClient); Tree = new ObservableTreesClient(gitHubClient); + Gist = new ObservableGistsClient(gitHubClient); } public IConnection Connection @@ -64,5 +64,6 @@ namespace Octokit.Reactive public IObservableUsersClient User { get; private set; } public IObservableGitDatabaseClient GitDatabase { get; private set; } public IObservableTreesClient Tree { get; private set; } + public IObservableGistsClient Gist { get; private set; } } } diff --git a/Octokit.Reactive/Octokit.Reactive-Mono.csproj b/Octokit.Reactive/Octokit.Reactive-Mono.csproj index 7ba1b53c..25077498 100644 --- a/Octokit.Reactive/Octokit.Reactive-Mono.csproj +++ b/Octokit.Reactive/Octokit.Reactive-Mono.csproj @@ -110,6 +110,10 @@ + + + + diff --git a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj index 908b2364..74bcb523 100644 --- a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj +++ b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj @@ -119,6 +119,10 @@ + + + + diff --git a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj index b2499e14..c3bae660 100644 --- a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj +++ b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj @@ -114,6 +114,10 @@ + + + + diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj index 0c19d334..f14d3158 100644 --- a/Octokit.Reactive/Octokit.Reactive.csproj +++ b/Octokit.Reactive/Octokit.Reactive.csproj @@ -74,12 +74,19 @@ Properties\SolutionInfo.cs + + + + + + + @@ -109,6 +116,7 @@ + diff --git a/Octokit.Reactive/Octokit.Reactive.csproj.DotSettings b/Octokit.Reactive/Octokit.Reactive.csproj.DotSettings new file mode 100644 index 00000000..a4f335fe --- /dev/null +++ b/Octokit.Reactive/Octokit.Reactive.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Octokit.Tests.Integration/AssigneesClientTests.cs b/Octokit.Tests.Integration/Clients/AssigneesClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/AssigneesClientTests.cs rename to Octokit.Tests.Integration/Clients/AssigneesClientTests.cs diff --git a/Octokit.Tests.Integration/Clients/BlobClientTests.cs b/Octokit.Tests.Integration/Clients/BlobClientTests.cs new file mode 100644 index 00000000..72364dfe --- /dev/null +++ b/Octokit.Tests.Integration/Clients/BlobClientTests.cs @@ -0,0 +1,107 @@ +using System; +using System.Net.Http.Headers; +using Octokit; +using Octokit.Tests.Integration; +using System.Threading.Tasks; +using Xunit; +using System.Text; + +public class BlobClientTests : IDisposable +{ + readonly IBlobsClient _fixture; + readonly Repository _repository; + readonly string _owner; + + public BlobClientTests() + { + var client = new GitHubClient(new ProductHeaderValue("OctokitTests")) + { + Credentials = Helper.Credentials + }; + _fixture = client.GitDatabase.Blob; + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + _repository = client.Repository.Create(new NewRepository { Name = repoName, AutoInit = true }).Result; + _owner = _repository.Owner.Login; + } + + [IntegrationTest] + public async Task CanCreateABlob() + { + var blob = new NewBlob + { + Content = "Hello World!", + Encoding = EncodingType.Utf8 + }; + + var result = await _fixture.Create(_owner, _repository.Name, blob); + + Assert.False(String.IsNullOrWhiteSpace(result.Sha)); + } + + [IntegrationTest] + public async Task CanCreateABlobWithBase64Contents() + { + var utf8Bytes = Encoding.UTF8.GetBytes("Hello World!"); + var base64String = Convert.ToBase64String(utf8Bytes); + + var blob = new NewBlob + { + Content = base64String, + Encoding = EncodingType.Base64 + }; + + var result = await _fixture.Create(_owner, _repository.Name, blob); + + Assert.False(String.IsNullOrWhiteSpace(result.Sha)); + } + + [IntegrationTest] + public async Task CanGetABlob() + { + var newBlob = new NewBlob + { + Content = "Hello World!", + Encoding = EncodingType.Utf8 + }; + + var result = await _fixture.Create(_owner, _repository.Name, newBlob); + var blob = await _fixture.Get(_owner, _repository.Name, result.Sha); + + Assert.Equal(result.Sha, blob.Sha); + Assert.Equal(EncodingType.Base64, blob.Encoding); + + var contents = Encoding.UTF8.GetString(Convert.FromBase64String(blob.Content)); + + Assert.Equal("Hello World!", contents); + } + + [IntegrationTest] + public async Task CanGetABlobWithBase64Text() + { + var utf8Bytes = Encoding.UTF8.GetBytes("Hello World!"); + var base64String = Convert.ToBase64String(utf8Bytes); + + var newBlob = new NewBlob + { + Content = base64String, + Encoding = EncodingType.Base64 + }; + + var result = await _fixture.Create(_owner, _repository.Name, newBlob); + var blob = await _fixture.Get(_owner, _repository.Name, result.Sha); + + Assert.Equal(result.Sha, blob.Sha); + Assert.Equal(EncodingType.Base64, blob.Encoding); + + // NOTE: it looks like the blobs you get back from the GitHub API + // will have an additional \n on the end. :cool:! + var expectedOutput = base64String + "\n"; + Assert.Equal(expectedOutput, blob.Content); + } + + public void Dispose() + { + Helper.DeleteRepo(_repository); + } +} diff --git a/Octokit.Tests.Integration/CommitStatusClientTests.cs b/Octokit.Tests.Integration/Clients/CommitStatusClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/CommitStatusClientTests.cs rename to Octokit.Tests.Integration/Clients/CommitStatusClientTests.cs diff --git a/Octokit.Tests.Integration/Clients/CommitsClientTests.cs b/Octokit.Tests.Integration/Clients/CommitsClientTests.cs new file mode 100644 index 00000000..b6c6340e --- /dev/null +++ b/Octokit.Tests.Integration/Clients/CommitsClientTests.cs @@ -0,0 +1,63 @@ +using System; +using System.Linq; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Octokit; +using Octokit.Tests.Integration; +using Xunit; + +public class CommitsClientTests : IDisposable +{ + readonly IGitHubClient _client; + readonly Repository _repository; + readonly ICommitsClient _fixture; + readonly string _owner; + + public CommitsClientTests() + { + _client = new GitHubClient(new ProductHeaderValue("OctokitTests")) + { + Credentials = Helper.Credentials + }; + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + _fixture = _client.GitDatabase.Commit; + _repository = _client.Repository.Create(new NewRepository { Name = repoName, AutoInit = true }).Result; + _owner = _repository.Owner.Login; + } + + [IntegrationTest] + public async Task CanCreateAndRetrieveCommit() + { + var blob = new NewBlob + { + Content = "Hello World!", + Encoding = EncodingType.Utf8 + }; + var blobResult = await _client.GitDatabase.Blob.Create(_owner, _repository.Name, blob); + + var newTree = new NewTree(); + newTree.Tree.Add(new NewTreeItem + { + Type = TreeType.Blob, + Mode = FileMode.File, + Path = "README.md", + Sha = blobResult.Sha + }); + + var treeResult = await _client.GitDatabase.Tree.Create(_owner, _repository.Name, newTree); + + var newCommit = new NewCommit("test-commit", treeResult.Sha, Enumerable.Empty()); + + var commit = await _fixture.Create(_owner, _repository.Name, newCommit); + Assert.NotNull(commit); + + var retrieved = await _fixture.Get(_owner, _repository.Name, commit.Sha); + Assert.NotNull(retrieved); + } + + public void Dispose() + { + Helper.DeleteRepo(_repository); + } +} diff --git a/Octokit.Tests.Integration/Clients/GistsClientTests.cs b/Octokit.Tests.Integration/Clients/GistsClientTests.cs new file mode 100644 index 00000000..e9de24ae --- /dev/null +++ b/Octokit.Tests.Integration/Clients/GistsClientTests.cs @@ -0,0 +1,31 @@ +using System; +using System.Linq; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Xunit; + +namespace Octokit.Tests.Integration +{ + public class GistsClientTests + { + readonly IGitHubClient _gitHubClient; + readonly IGistsClient _gistsClient; + + public GistsClientTests() + { + this._gitHubClient = new GitHubClient(new ProductHeaderValue("OctokitTests")) + { + Credentials = Helper.Credentials + }; + + this._gistsClient = this._gitHubClient.Gist; + } + + [IntegrationTest] + public async Task CanGetGist() + { + var retrieved = await this._gistsClient.Get("6305249"); + Assert.NotNull(retrieved); + } + } +} \ No newline at end of file diff --git a/Octokit.Tests.Integration/IssuesClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/IssuesClientTests.cs rename to Octokit.Tests.Integration/Clients/IssuesClientTests.cs diff --git a/Octokit.Tests.Integration/IssuesEventsClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/IssuesEventsClientTests.cs rename to Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs diff --git a/Octokit.Tests.Integration/MilestonesClientTests.cs b/Octokit.Tests.Integration/Clients/MilestonesClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/MilestonesClientTests.cs rename to Octokit.Tests.Integration/Clients/MilestonesClientTests.cs diff --git a/Octokit.Tests.Integration/MiscellaneousClientTests.cs b/Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/MiscellaneousClientTests.cs rename to Octokit.Tests.Integration/Clients/MiscellaneousClientTests.cs diff --git a/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs b/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs new file mode 100644 index 00000000..64425a53 --- /dev/null +++ b/Octokit.Tests.Integration/Clients/ReferencesClientTests.cs @@ -0,0 +1,132 @@ +using System; +using System.Linq; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Octokit; +using Octokit.Tests.Helpers; +using Octokit.Tests.Integration; +using Xunit; + +public class ReferencesClientTests : IDisposable +{ + readonly IReferencesClient _fixture; + readonly Repository _repository; + readonly GitHubClient _client; + readonly string _owner; + + public ReferencesClientTests() + { + _client = new GitHubClient(new ProductHeaderValue("OctokitTests")) + { + Credentials = Helper.Credentials + }; + _fixture = _client.GitDatabase.Reference; + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + _repository = _client.Repository.Create(new NewRepository { Name = repoName, AutoInit = true }).Result; + _owner = _repository.Owner.Login; + } + + [IntegrationTest] + public async Task CanGetAReference() + { + var @ref = await _fixture.Get("octokit", "octokit.net", "heads/master"); + + // validate the top-level properties + Assert.Equal("refs/heads/master", @ref.Ref); + Assert.Equal("https://api.github.com/repos/octokit/octokit.net/git/refs/heads/master", @ref.Url); + + // validate the git reference + Assert.Equal(TaggedType.Commit, @ref.Object.Type); + Assert.False(String.IsNullOrWhiteSpace(@ref.Object.Sha)); + } + + [IntegrationTest] + public async Task CanGetListOfReferences() + { + var list = await _fixture.GetAll("octokit", "octokit.net"); + Assert.NotEmpty(list); + } + + [IntegrationTest] + public async Task CanGetListOfReferencesInNamespace() + { + var list = await _fixture.GetAllForSubNamespace("octokit", "octokit.net", "heads"); + Assert.NotEmpty(list); + } + + [IntegrationTest(Skip="See ")] + public async Task CanGetErrorForInvalidNamespace() + { + await AssertEx.Throws( + async () => { await _fixture.GetAllForSubNamespace("octokit", "octokit.net", "666"); }); + } + + [IntegrationTest(Skip = "Investigating a 'Server Error' API response when creating a commit")] + public async Task CanCreateAReference() + { + var blob = new NewBlob + { + Content = "Hello World!", + Encoding = EncodingType.Utf8 + }; + var blobResult = await _client.GitDatabase.Blob.Create(_owner, _repository.Name, blob); + + var newTree = new NewTree(); + newTree.Tree.Add(new NewTreeItem + { + Mode = FileMode.File, + Type = TreeType.Blob, + Path = "README.md", + Sha = blobResult.Sha + }); + + var treeResult = await _client.GitDatabase.Tree.Create(_owner, _repository.Name, newTree); + + var newCommit = new NewCommit("This is a new commit", treeResult.Sha, Enumerable.Empty()); + + var commitResult = await _client.GitDatabase.Commit.Create(_owner, _repository.Name, newCommit); + + var newReference = new NewReference("heads/develop", commitResult.Sha); + var result = await _fixture.Create(_owner, _repository.Name, newReference); + + Assert.NotNull(result); + } + + [IntegrationTest(Skip="TODO")] + public async Task CanUpdateAReference() + { + // TODO: create a blob + // TODO: create a tree + // TODO: create a commit + // TODO: use the SHA to create a reference + + var newReference = new NewReference("heads/develop", "sha"); + await _fixture.Create("owner", "repo", newReference); + + var referenceUpdate = new ReferenceUpdate("sha"); + + var result = await _fixture.Update("owner", "repo", "heads/develop", referenceUpdate); + + Assert.NotNull(result); + } + + [IntegrationTest(Skip="TODO")] + public async Task CanDeleteAReference() + { + // TODO: create a blob + // TODO: create a tree + // TODO: create a commit + // TODO: use the SHA to create a reference + + // TODO: can we validate the response here? + // TODO: otherwise, fire off a GetAll and validate it's not in the list + + await _fixture.Delete("owner", "repo", "heads/develop"); + } + + public void Dispose() + { + Helper.DeleteRepo(_repository); + } +} diff --git a/Octokit.Tests.Integration/ReleasesClientTests.cs b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/ReleasesClientTests.cs rename to Octokit.Tests.Integration/Clients/ReleasesClientTests.cs diff --git a/Octokit.Tests.Integration/RepositoriesClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/RepositoriesClientTests.cs rename to Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs diff --git a/Octokit.Tests.Integration/Clients/TreeClientTests.cs b/Octokit.Tests.Integration/Clients/TreeClientTests.cs new file mode 100644 index 00000000..1c18a4d3 --- /dev/null +++ b/Octokit.Tests.Integration/Clients/TreeClientTests.cs @@ -0,0 +1,92 @@ +using System; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Octokit; +using Octokit.Tests.Integration; +using Xunit; + +public class TreeClientTests : IDisposable +{ + readonly ITreesClient _fixture; + readonly Repository _repository; + readonly string _owner; + readonly GitHubClient _client; + + public TreeClientTests() + { + _client = new GitHubClient(new ProductHeaderValue("OctokitTests")) + { + Credentials = Helper.Credentials + }; + _fixture = _client.GitDatabase.Tree; + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + _repository = _client.Repository.Create(new NewRepository { Name = repoName, AutoInit = true }).Result; + _owner = _repository.Owner.Login; + } + + [IntegrationTest] + public async Task CanCreateATree() + { + var blob = new NewBlob + { + Content = "Hello World!", + Encoding = EncodingType.Utf8 + }; + + var createdBlob = await _client.GitDatabase.Blob.Create(_owner, _repository.Name, blob); + + var newTree = new NewTree(); + newTree.Tree.Add(new NewTreeItem + { + Type = TreeType.Blob, + Path = "README.md", + Sha = createdBlob.Sha + }); + + var result = await _fixture.Create(_owner, _repository.Name, newTree); + + Assert.NotNull(result); + } + + [IntegrationTest] + public async Task CanGetATree() + { + var result = await _fixture.Get("octokit", "octokit.net", "master"); + + Assert.NotNull(result); + Assert.NotEmpty(result.Tree); + } + + [IntegrationTest] + public async Task CanGetACreatedTree() + { + var blob = new NewBlob + { + Content = "Hello World!", + Encoding = EncodingType.Utf8 + }; + + var blobResult = await _client.GitDatabase.Blob.Create(_owner, _repository.Name, blob); + + var newTree = new NewTree(); + newTree.Tree.Add(new NewTreeItem + { + Type = TreeType.Blob, + Path = "README.md", + Sha = blobResult.Sha + }); + + var tree = await _fixture.Create(_owner, _repository.Name, newTree); + + var result = await _fixture.Get(_owner, _repository.Name, tree.Sha); + + Assert.NotNull(result); + Assert.Equal(1, result.Tree.Count); + } + + public void Dispose() + { + Helper.DeleteRepo(_repository); + } +} diff --git a/Octokit.Tests.Integration/UsersClientTests.cs b/Octokit.Tests.Integration/Clients/UsersClientTests.cs similarity index 100% rename from Octokit.Tests.Integration/UsersClientTests.cs rename to Octokit.Tests.Integration/Clients/UsersClientTests.cs diff --git a/Octokit.Tests.Integration/CommitsClientTests.cs b/Octokit.Tests.Integration/CommitsClientTests.cs deleted file mode 100644 index 9e89a608..00000000 --- a/Octokit.Tests.Integration/CommitsClientTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Linq; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Xunit; - -namespace Octokit.Tests.Integration -{ - public class CommitsClientTests : IDisposable - { - readonly IGitHubClient _gitHubClient; - readonly Repository _repository; - readonly ICommitsClient _commitsClient; - - public CommitsClientTests() - { - this._gitHubClient = new GitHubClient(new ProductHeaderValue("OctokitTests")) - { - Credentials = Helper.Credentials - }; - - var repoName = Helper.MakeNameWithTimestamp("public-repo"); - this._commitsClient = this._gitHubClient.GitDatabase.Commit; - this._repository = this._gitHubClient.Repository.Create(new NewRepository { Name = repoName, AutoInit = true }).Result; - } - - [IntegrationTest(Skip = "Requires Tree Api implementation to create a commit")] - public async Task CanCreateAndRetrieveCommit() - { - string owner = this._repository.Owner.Login; - - var author = new Signature { Name = "author", Email = "test-author@example.com", Date = DateTime.UtcNow }; - var commiter = new Signature { Name = "commiter", Email = "test-commiter@example.com", Date = DateTime.Today }; - - var newCommit = new NewCommit("test-commit", "[Change this to tree sha]", Enumerable.Empty()) - { - Author = author, - Committer = commiter - }; - - var commit = await this._commitsClient.Create(owner, this._repository.Name, newCommit); - - Assert.NotNull(commit); - var retrieved = await this._commitsClient.Get(owner, this._repository.Name, commit.Sha); - Assert.NotNull(retrieved); - } - - - public void Dispose() - { - Helper.DeleteRepo(this._repository); - } - } -} \ No newline at end of file diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 4eb79e2f..1fa54095 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -57,23 +57,32 @@ - - - - - + + + + + + + + + +<<<<<<< HEAD +======= + + +>>>>>>> master - - + + - + diff --git a/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs index ab7f232d..2eedd3b1 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs @@ -2,7 +2,7 @@ using System.Net.Http.Headers; using System.Reactive.Linq; using System.Threading.Tasks; -using Octokit.Reactive.Clients; +using Octokit.Reactive; using Xunit; namespace Octokit.Tests.Integration diff --git a/Octokit.Tests/Clients/AssigneesClientTests.cs b/Octokit.Tests/Clients/AssigneesClientTests.cs index 443a059b..6a422c34 100644 --- a/Octokit.Tests/Clients/AssigneesClientTests.cs +++ b/Octokit.Tests/Clients/AssigneesClientTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Net; using System.Threading.Tasks; using NSubstitute; -using Octokit; using Octokit.Internal; using Octokit.Tests.Helpers; using Xunit; @@ -97,4 +96,4 @@ namespace Octokit.Tests.Clients } } } -} \ No newline at end of file +} diff --git a/Octokit.Tests/Clients/CommitsClientTests.cs b/Octokit.Tests/Clients/CommitsClientTests.cs index c36cb9a4..1901322a 100644 --- a/Octokit.Tests/Clients/CommitsClientTests.cs +++ b/Octokit.Tests/Clients/CommitsClientTests.cs @@ -75,4 +75,4 @@ public class CommitsClientTests Assert.Throws(() => new CommitsClient(null)); } } -} \ No newline at end of file +} diff --git a/Octokit.Tests/Clients/GistCommentsClientTests.cs b/Octokit.Tests/Clients/GistCommentsClientTests.cs new file mode 100644 index 00000000..8ca77c6e --- /dev/null +++ b/Octokit.Tests/Clients/GistCommentsClientTests.cs @@ -0,0 +1,108 @@ +using System; +using System.Threading.Tasks; +using NSubstitute; +using Octokit; +using Octokit.Tests.Helpers; +using Xunit; + +public class GistCommentsClientTests +{ + public class TheCtor + { + [Fact] + public void EnsuresArgument() + { + Assert.Throws(() => new GistCommentsClient(null)); + } + } + + public class TheGetMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistCommentsClient(connection); + + await client.Get(24, 1337); + + connection.Received().Get(Arg.Is(u => u.ToString() == "gists/24/comments/1337"), null); + } + } + + public class TheGetForGistMethod + { + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistCommentsClient(connection); + + await client.GetForGist(24); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "gists/24/comments")); + } + } + + public class TheCreateMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new GistCommentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Create(24, null)); + await AssertEx.Throws(async () => await client.Create(24, "")); + } + + [Fact] + public async Task PostsToCorrectUrl() + { + var comment = "This is a comment."; + var connection = Substitute.For(); + var client = new GistCommentsClient(connection); + + await client.Create(24, comment); + + connection.Received().Post(Arg.Is(u => u.ToString() == "gists/24/comments"), Arg.Is(x => x.Body == comment)); + } + } + + public class TheUpdateMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new GistCommentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Update(24, 1337, null)); + await AssertEx.Throws(async () => await client.Update(24, 1337, "")); + } + + [Fact] + public async Task PostsToCorrectUrl() + { + var comment = "This is a comment."; + var connection = Substitute.For(); + var client = new GistCommentsClient(connection); + + await client.Update(24, 1337, comment); + + connection.Received().Patch(Arg.Is(u => u.ToString() == "gists/24/comments/1337"), Arg.Is(x => x.Body == comment)); + } + } + + public class TheDeleteMethod + { + [Fact] + public async Task PostsToCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistCommentsClient(connection); + + await client.Delete(24, 1337); + + connection.Received().Delete(Arg.Is(u => u.ToString() == "gists/24/comments/1337")); + } + } +} \ No newline at end of file diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs new file mode 100644 index 00000000..ad3f6d76 --- /dev/null +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -0,0 +1,38 @@ +using System; +using NSubstitute; +using Octokit; +using Xunit; + +public class GistsClientTests +{ + public class TheGetMethod + { + [Fact] + public void RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new GistsClient(connection); + + client.Get("1"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "gists/1"), null); + } + } + + public class TheCtor + { + [Fact] + public void EnsuresArgument() + { + Assert.Throws(() => new GistsClient(null)); + } + + [Fact] + public void SetCommentsClient() + { + var apiConnection = Substitute.For(); + var client = new GistsClient(apiConnection); + Assert.NotNull(client.Comment); + } + } +} diff --git a/Octokit.Tests/Clients/GitDatabaseClientTests.cs b/Octokit.Tests/Clients/GitDatabaseClientTests.cs index 93ee03bb..7c417981 100644 --- a/Octokit.Tests/Clients/GitDatabaseClientTests.cs +++ b/Octokit.Tests/Clients/GitDatabaseClientTests.cs @@ -28,5 +28,13 @@ public class GitDatabaseClientTests var gitDatabaseClient = new GitDatabaseClient(apiConnection); Assert.NotNull(gitDatabaseClient.Commit); } + + [Fact] + public void SetReferencesClient() + { + var apiConnection = Substitute.For(); + var gitDatabaseClient = new GitDatabaseClient(apiConnection); + Assert.NotNull(gitDatabaseClient.Reference); + } } -} \ No newline at end of file +} diff --git a/Octokit.Tests/Clients/IssuesClientTests.cs b/Octokit.Tests/Clients/IssuesClientTests.cs index da402574..632b37f8 100644 --- a/Octokit.Tests/Clients/IssuesClientTests.cs +++ b/Octokit.Tests/Clients/IssuesClientTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using NSubstitute; -using Octokit; using Octokit.Internal; using Octokit.Tests; using Octokit.Tests.Helpers; @@ -254,4 +253,4 @@ namespace Octokit.Tests.Clients Assert.Equal(new Uri("https://github.com/octokit-net-test/public-repo-20131022050247078/issues/1"), response.BodyAsObject.HtmlUrl); } } -} \ No newline at end of file +} diff --git a/Octokit.Tests/Clients/MilestonesClientTests.cs b/Octokit.Tests/Clients/MilestonesClientTests.cs index 9b27b715..8897e77d 100644 --- a/Octokit.Tests/Clients/MilestonesClientTests.cs +++ b/Octokit.Tests/Clients/MilestonesClientTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using NSubstitute; -using Octokit; using Octokit.Tests.Helpers; using Xunit; diff --git a/Octokit.Tests/Clients/ReferencesClientTests.cs b/Octokit.Tests/Clients/ReferencesClientTests.cs new file mode 100644 index 00000000..5ca39024 --- /dev/null +++ b/Octokit.Tests/Clients/ReferencesClientTests.cs @@ -0,0 +1,180 @@ +using System; +using System.Threading.Tasks; +using NSubstitute; +using Octokit.Tests.Helpers; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class ReferencesClientTests + { + public class TheCtor + { + [Fact] + public void EnsuresArgument() + { + Assert.Throws(() => new ReferencesClient(null)); + } + } + + public class TheGetMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ReferencesClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Get(null, "name", "heads/develop")); + await AssertEx.Throws(async () => await client.Get("owner", null, "heads/develop")); + await AssertEx.Throws(async () => await client.Get("owner", "name", null)); + await AssertEx.Throws(async () => await client.Get("", "name", "heads/develop")); + await AssertEx.Throws(async () => await client.Get("owner", "", "heads/develop")); + await AssertEx.Throws(async () => await client.Get("owner", "name", "")); + } + + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new ReferencesClient(connection); + + await client.Get("owner", "repo", "heads/develop"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "repos/owner/repo/git/refs/heads/develop"), null); + } + } + + public class TheGetAllMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ReferencesClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAll(null, "name")); + await AssertEx.Throws(async () => await client.GetAll("owner", null)); + await AssertEx.Throws(async () => await client.GetAll("", "name")); + await AssertEx.Throws(async () => await client.GetAll("owner", "")); + } + + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new ReferencesClient(connection); + + await client.GetAll("owner", "repo"); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/owner/repo/git/refs")); + } + } + + public class TheGetAllForSubNamespaceMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ReferencesClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAllForSubNamespace(null, "name", "heads")); + await AssertEx.Throws(async () => await client.GetAllForSubNamespace("owner", null, "heads")); + await AssertEx.Throws(async () => await client.GetAllForSubNamespace("", "name", "heads")); + await AssertEx.Throws(async () => await client.GetAllForSubNamespace("owner", "", "heads")); + } + + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new ReferencesClient(connection); + + await client.GetAllForSubNamespace("owner", "repo", "heads"); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/owner/repo/git/refs/heads")); + } + } + + public class TheCreateMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ReferencesClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Create(null, "name", new NewReference("heads/develop", "sha"))); + await AssertEx.Throws(async () => await client.Create("owner", null, new NewReference("heads/develop", "sha"))); + await AssertEx.Throws(async () => await client.Create("owner", "name", null)); + await AssertEx.Throws(async () => await client.Create("", "name", new NewReference("heads/develop", "sha"))); + await AssertEx.Throws(async () => await client.Create("owner", "", new NewReference("heads/develop", "sha"))); + } + + [Fact] + public async Task PostsToCorrectUrl() + { + var newReference = new NewReference("heads/develop", "sha"); + var connection = Substitute.For(); + var client = new ReferencesClient(connection); + + await client.Create("owner", "repo", newReference); + + connection.Received().Post(Arg.Is(u => u.ToString() == "repos/owner/repo/git/refs"), newReference); + } + } + + public class TheUpdateMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ReferencesClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Update(null, "name", "heads/develop", new ReferenceUpdate("sha"))); + await AssertEx.Throws(async () => await client.Update("owner", null, "heads/develop", new ReferenceUpdate("sha"))); + await AssertEx.Throws(async () => await client.Update("owner", "name", null, new ReferenceUpdate("sha"))); + await AssertEx.Throws(async () => await client.Update("owner", "name", "heads/develop", null)); + await AssertEx.Throws(async () => await client.Update("", "name", "heads/develop", new ReferenceUpdate("sha"))); + await AssertEx.Throws(async () => await client.Update("owner", "", "heads/develop", new ReferenceUpdate("sha"))); + await AssertEx.Throws(async () => await client.Update("owner", "name", "", new ReferenceUpdate("sha"))); + } + + [Fact] + public async Task PostsToCorrectUrl() + { + var referenceUpdate = new ReferenceUpdate("sha"); + var connection = Substitute.For(); + var client = new ReferencesClient(connection); + + await client.Update("owner", "repo", "heads/develop", referenceUpdate); + + connection.Received().Patch(Arg.Is(u => u.ToString() == "repos/owner/repo/git/refs/heads/develop"), referenceUpdate); + } + } + + public class TheDeleteMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var client = new ReferencesClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Delete(null, "name", "heads/develop")); + await AssertEx.Throws(async () => await client.Delete("owner", null, "heads/develop")); + await AssertEx.Throws(async () => await client.Delete("owner", "name", null)); + await AssertEx.Throws(async () => await client.Delete("", "name", "heads/develop")); + await AssertEx.Throws(async () => await client.Delete("owner", "", "heads/develop")); + await AssertEx.Throws(async () => await client.Delete("owner", "name", "")); + } + + [Fact] + public async Task RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new ReferencesClient(connection); + + await client.Delete("owner", "repo", "heads/develop"); + + connection.Received().Delete(Arg.Is(u => u.ToString() == "repos/owner/repo/git/refs/heads/develop")); + } + } + } +} \ No newline at end of file diff --git a/Octokit.Tests/Clients/TreesClientTests.cs b/Octokit.Tests/Clients/TreesClientTests.cs index 60a18e2a..28bcc1b4 100644 --- a/Octokit.Tests/Clients/TreesClientTests.cs +++ b/Octokit.Tests/Clients/TreesClientTests.cs @@ -62,6 +62,19 @@ namespace Octokit.Tests await AssertEx.Throws(async () => await client.Create("owner", null, new NewTree())); await AssertEx.Throws(async () => await client.Create("owner", "", new NewTree())); } + + [Fact] + public async Task EnsureExceptionIsThrownWhenModeIsNotProvided() + { + var newTree = new NewTree(); + newTree.Tree.Add(new NewTreeItem { Path = "README.md", Type = TreeType.Blob, Sha = "2e1a73d60f004fd842d4bad28aa42392d4f35d28" }); + + var connection = Substitute.For(); + var client = new TreesClient(connection); + + await AssertEx.Throws( + async () => await client.Create("fake", "repo", newTree)); + } } public class TheCtor diff --git a/Octokit.Tests/Models/NewReferenceTests.cs b/Octokit.Tests/Models/NewReferenceTests.cs new file mode 100644 index 00000000..48cc90ca --- /dev/null +++ b/Octokit.Tests/Models/NewReferenceTests.cs @@ -0,0 +1,23 @@ +using System; +using Octokit; +using Xunit; + +public class NewReferenceTests +{ + public class TheCtor + { + [Fact] + public void EnforcesRefsPrefix() + { + var create = new NewReference("heads/develop", "sha"); + + Assert.Equal(create.Ref, "refs/heads/develop"); + } + + [Fact] + public void ThrowsExceptionIfRefHasLessThanTwoSlashes() + { + Assert.Throws(() => new NewReference("refs/develop", "sha")); + } + } +} \ No newline at end of file diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index c61f5c7d..cf0c19d4 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -62,7 +62,10 @@ + + + @@ -111,6 +114,7 @@ + @@ -129,6 +133,7 @@ + diff --git a/Octokit.Tests/Reactive/ObservableMilestonesClientTests.cs b/Octokit.Tests/Reactive/ObservableMilestonesClientTests.cs index d0216d85..35b1666d 100644 --- a/Octokit.Tests/Reactive/ObservableMilestonesClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableMilestonesClientTests.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using NSubstitute; using Octokit; using Octokit.Internal; -using Octokit.Reactive.Clients; +using Octokit.Reactive; using Octokit.Tests.Helpers; using Xunit; diff --git a/Octokit.Tests/Reactive/ObservableStarredClientTests.cs b/Octokit.Tests/Reactive/ObservableStarredClientTests.cs new file mode 100644 index 00000000..f8797c2f --- /dev/null +++ b/Octokit.Tests/Reactive/ObservableStarredClientTests.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Reactive.Linq; +using System.Threading.Tasks; +using NSubstitute; +using Octokit; +using Octokit.Internal; +using Octokit.Reactive; +using Octokit.Reactive.Internal; +using Octokit.Tests.Helpers; +using Xunit; +using Xunit.Extensions; + +namespace Octokit.Tests.Reactive +{ + public class ObservableStarredClientTests + { + public class TheGetAllStargazersMethod + { + [Fact] + public async Task EnsuresArguments() + { + var client = new ObservableStarredClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAllStargazers(null, "name")); + await AssertEx.Throws(async () => await client.GetAllStargazers("owner", null)); + } + + [Fact] + public void GetsStargazersFromClient() + { + var connection = Substitute.For(); + var gitHubClient = Substitute.For(); + gitHubClient.Connection.Returns(connection); + var client = new ObservableStarredClient(gitHubClient); + + client.GetAllStargazers("jugglingnutcase", "katiejamie"); + connection.Received().GetAsync>(ApiUrls.Stargazers("jugglingnutcase", "katiejamie"), null, null); + } + } + + public class TheGetAllForCurrentMethod + { + [Fact] + public void GetsStarsForCurrent() + { + var connection = Substitute.For(); + var gitHubClient = Substitute.For(); + gitHubClient.Connection.Returns(connection); + var client = new ObservableStarredClient(gitHubClient); + + client.GetAllForCurrent(); + connection.Received().GetAsync>(ApiUrls.Starred(), null, null); + } + } + + public class TheGetAllForUserMethod + { + [Fact] + public async Task EnsuresArguments() + { + var client = new ObservableStarredClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAllForUser(null)); + } + + [Fact] + public void GetsStarsForUser() + { + var connection = Substitute.For(); + var gitHubClient = Substitute.For(); + gitHubClient.Connection.Returns(connection); + var client = new ObservableStarredClient(gitHubClient); + + client.GetAllForUser("jugglingnutcase"); + connection.Received().GetAsync>(ApiUrls.StarredByUser("jugglingnutcase"), null, null); + } + } + + public class TheCheckStarredMethod + { + [Fact] + public async Task EnsuresArguments() + { + var client = new ObservableStarredClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.CheckStarred(null, "james")); + await AssertEx.Throws(async () => await client.CheckStarred("james", null)); + } + + [Fact] + public async Task ChecksStarredForUser() + { + var gitHubClient = Substitute.For(); + var client = new ObservableStarredClient(gitHubClient); + + client.CheckStarred("jugglingnutcase", "katiejamie"); + gitHubClient.Activity.Starring.Received().CheckStarred("jugglingnutcase", "katiejamie"); + } + } + + public class TheStarRepoMethod + { + [Fact] + public async Task EnsuresArguments() + { + var client = new ObservableStarredClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.StarRepo(null, "james")); + await AssertEx.Throws(async () => await client.StarRepo("james", null)); + } + + [Fact] + public async Task ChecksStarredForUser() + { + var gitHubClient = Substitute.For(); + var client = new ObservableStarredClient(gitHubClient); + + client.StarRepo("jugglingnutcase", "katiejamie"); + gitHubClient.Activity.Starring.Received().StarRepo("jugglingnutcase", "katiejamie"); + } + } + + public class TheRemoveStarFromRepoMethod + { + [Fact] + public async Task EnsuresArguments() + { + var client = new ObservableStarredClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.RemoveStarFromRepo(null, "james")); + await AssertEx.Throws(async () => await client.RemoveStarFromRepo("james", null)); + } + + [Fact] + public async Task ChecksStarredForUser() + { + var gitHubClient = Substitute.For(); + var client = new ObservableStarredClient(gitHubClient); + + client.RemoveStarFromRepo("jugglingnutcase", "katiejamie"); + gitHubClient.Activity.Starring.Received().RemoveStarFromRepo("jugglingnutcase", "katiejamie"); + } + } + } +} \ No newline at end of file diff --git a/Octokit.sln.DotSettings b/Octokit.sln.DotSettings index 36aa1792..202116c9 100644 --- a/Octokit.sln.DotSettings +++ b/Octokit.sln.DotSettings @@ -262,4 +262,5 @@ II.2.12 <HandlesEvent /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + True \ No newline at end of file diff --git a/Octokit/Clients/GistCommentsClient.cs b/Octokit/Clients/GistCommentsClient.cs new file mode 100644 index 00000000..1b708e43 --- /dev/null +++ b/Octokit/Clients/GistCommentsClient.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Octokit +{ + public class GistCommentsClient : ApiClient, IGistCommentsClient + { + public GistCommentsClient(IApiConnection apiConnection) : base(apiConnection) + { + } + + /// + /// Gets a single comment by gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#get-a-single-comment + /// The id of the gist + /// The id of the comment + /// Task{GistComment}. + public Task Get(int gistId, int commentId) + { + return ApiConnection.Get(ApiUrls.GistComment(gistId, commentId)); + } + + /// + /// Gets all comments for the gist with the specified id. + /// + /// http://developer.github.com/v3/gists/comments/#list-comments-on-a-gist + /// The id of the gist + /// Task{IReadOnlyList{GistComment}}. + public Task> GetForGist(int gistId) + { + return ApiConnection.GetAll(ApiUrls.GistComments(gistId)); + } + + /// + /// Creates a comment for the gist with the specified id. + /// + /// http://developer.github.com/v3/gists/comments/#create-a-comment + /// The id of the gist + /// The body of the comment + /// Task{GistComment}. + public Task Create(int gistId, string comment) + { + Ensure.ArgumentNotNullOrEmptyString(comment, "comment"); + + return ApiConnection.Post(ApiUrls.GistComments(gistId), new BodyWrapper(comment)); + } + + /// + /// Updates the comment with the specified gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#edit-a-comment + /// The id of the gist + /// The id of the comment + /// The updated body of the comment + /// Task{GistComment}. + public Task Update(int gistId, int commentId, string comment) + { + Ensure.ArgumentNotNullOrEmptyString(comment, "comment"); + + return ApiConnection.Patch(ApiUrls.GistComment(gistId, commentId), new BodyWrapper(comment)); + } + + /// + /// Deletes the comment with the specified gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#delete-a-comment + /// The id of the gist + /// The id of the comment + /// Task. + public Task Delete(int gistId, int commentId) + { + return ApiConnection.Delete(ApiUrls.GistComment(gistId, commentId)); + } + } +} \ No newline at end of file diff --git a/Octokit/Clients/GistsClient.cs b/Octokit/Clients/GistsClient.cs new file mode 100644 index 00000000..0a08b80f --- /dev/null +++ b/Octokit/Clients/GistsClient.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + public class GistsClient : ApiClient, IGistsClient + { + public GistsClient(IApiConnection apiConnection) : + base(apiConnection) + { + Comment = new GistCommentsClient(apiConnection); + } + + public IGistCommentsClient Comment { get; set; } + + /// + /// Gets a gist + /// + /// + /// http://developer.github.com/v3/gists/#get-a-single-gist + /// + /// The id of the gist + public Task Get(string id) + { + return ApiConnection.Get(ApiUrls.Gist(id)); + } + } +} \ No newline at end of file diff --git a/Octokit/Clients/GitDatabaseClient.cs b/Octokit/Clients/GitDatabaseClient.cs index 908f1ca0..0b50317f 100644 --- a/Octokit/Clients/GitDatabaseClient.cs +++ b/Octokit/Clients/GitDatabaseClient.cs @@ -5,11 +5,17 @@ public GitDatabaseClient(IApiConnection apiConnection) : base(apiConnection) { + Blob = new BlobsClient(apiConnection); + Tree = new TreesClient(apiConnection); Tag = new TagsClient(apiConnection); Commit = new CommitsClient(apiConnection); + Reference = new ReferencesClient(apiConnection); } + public IBlobsClient Blob { get; set; } + public ITreesClient Tree { get; set; } public ITagsClient Tag { get; set; } public ICommitsClient Commit { get; set; } + public IReferencesClient Reference { get; set; } } } \ No newline at end of file diff --git a/Octokit/Clients/IGistCommentsClient.cs b/Octokit/Clients/IGistCommentsClient.cs new file mode 100644 index 00000000..a9a5aeb8 --- /dev/null +++ b/Octokit/Clients/IGistCommentsClient.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IGistCommentsClient + { + /// + /// Gets a single comment by gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#get-a-single-comment + /// The id of the gist + /// The id of the comment + /// Task{GistComment}. + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + Task Get(int gistId, int commentId); + + /// + /// Gets all comments for the gist with the specified id. + /// + /// http://developer.github.com/v3/gists/comments/#list-comments-on-a-gist + /// The id of the gist + /// Task{IReadOnlyList{GistComment}}. + Task> GetForGist(int gistId); + + /// + /// Creates a comment for the gist with the specified id. + /// + /// http://developer.github.com/v3/gists/comments/#create-a-comment + /// The id of the gist + /// The body of the comment + /// Task{GistComment}. + Task Create(int gistId, string comment); + + /// + /// Updates the comment with the specified gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#edit-a-comment + /// The id of the gist + /// The id of the comment + /// The updated body of the comment + /// Task{GistComment}. + Task Update(int gistId, int commentId, string comment); + + /// + /// Deletes the comment with the specified gist- and comment id. + /// + /// http://developer.github.com/v3/gists/comments/#delete-a-comment + /// The id of the gist + /// The id of the comment + /// Task. + Task Delete(int gistId, int commentId); + } +} diff --git a/Octokit/Clients/IGistsClient.cs b/Octokit/Clients/IGistsClient.cs new file mode 100644 index 00000000..a8a90fdb --- /dev/null +++ b/Octokit/Clients/IGistsClient.cs @@ -0,0 +1,21 @@ +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IGistsClient + { + IGistCommentsClient Comment { get; set; } + + /// + /// Gets a gist + /// + /// + /// http://developer.github.com/v3/gists/#get-a-single-gist + /// + /// The id of the gist + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + Task Get(string id); + } +} \ No newline at end of file diff --git a/Octokit/Clients/IGitDatabaseClient.cs b/Octokit/Clients/IGitDatabaseClient.cs index 8c36b6bb..0516b36a 100644 --- a/Octokit/Clients/IGitDatabaseClient.cs +++ b/Octokit/Clients/IGitDatabaseClient.cs @@ -5,7 +5,10 @@ /// public interface IGitDatabaseClient { + IBlobsClient Blob { get; set; } ITagsClient Tag { get; set; } + ITreesClient Tree { get; set; } ICommitsClient Commit { get; set; } + IReferencesClient Reference { get; set; } } } \ No newline at end of file diff --git a/Octokit/Clients/IReferencesClient.cs b/Octokit/Clients/IReferencesClient.cs new file mode 100644 index 00000000..06aecfb8 --- /dev/null +++ b/Octokit/Clients/IReferencesClient.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IReferencesClient + { + /// + /// Gets a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#get-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + Task Get(string owner, string name, string reference); + + /// + /// Gets all references for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// + Task> GetAll(string owner, string name); + + /// + /// Gets references for a given repository by sub-namespace, i.e. "tags" or "heads" + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// The sub-namespace to get references for + /// + Task> GetAllForSubNamespace(string owner, string name, string subNamespace); + + /// + /// Creates a reference for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#create-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The reference to create + /// + Task Create(string owner, string name, NewReference reference); + + /// + /// Updates a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#update-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// The updated reference data + /// + Task Update(string owner, string name, string reference, ReferenceUpdate referenceUpdate); + + /// + /// Deletes a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#delete-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + Task Delete(string owner, string name, string reference); + } +} \ No newline at end of file diff --git a/Octokit/Clients/IRepoCollaboratorsClient.cs b/Octokit/Clients/IRepoCollaboratorsClient.cs index f94b0fe1..3c379ba0 100644 --- a/Octokit/Clients/IRepoCollaboratorsClient.cs +++ b/Octokit/Clients/IRepoCollaboratorsClient.cs @@ -31,7 +31,7 @@ namespace Octokit /// See the API documentation for more information. /// /// Thrown when a general API error occurs. - /// True if user is a collaborator else false + /// True if user is a collaborator else false Task IsCollaborator(string owner, string repo, string user); /// diff --git a/Octokit/Clients/IStarredClient.cs b/Octokit/Clients/IStarredClient.cs index ffb8695c..5dcbebfb 100644 --- a/Octokit/Clients/IStarredClient.cs +++ b/Octokit/Clients/IStarredClient.cs @@ -11,14 +11,16 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// Thrown if the client is not authenticated. - /// A of . + /// A of s starring the passed repository. Task> GetAllStargazers(string owner, string name); /// /// Retrieves all of the starred (ies) for the current user. /// /// Thrown if the client is not authenticated. - /// A of . + /// + /// A of (ies) starred by the current authenticated user. + /// Task> GetAllForCurrent(); /// @@ -26,7 +28,10 @@ namespace Octokit /// /// Star-specific request parameters that sort the results /// Thrown if the client is not authenticated. - /// A of . + /// + /// A of (ies) starred by the current user, + /// sorted according to the passed request parameters. + /// Task> GetAllForCurrent(StarredRequest request); /// @@ -34,7 +39,9 @@ namespace Octokit /// /// The login of the user /// Thrown if the client is not authenticated. - /// A starred by the specified user. + /// + /// A (ies) starred by the specified user. + /// Task> GetAllForUser(string user); /// diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 06554128..31c02b70 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -18,7 +18,7 @@ namespace Octokit /// Returns all s for the current org. /// /// Thrown when a general API error occurs. - /// A list of the orgs's teams s. + /// A list of the orgs's teams s. Task> GetAllTeams(string org); /// diff --git a/Octokit/Clients/ReferencesClient.cs b/Octokit/Clients/ReferencesClient.cs new file mode 100644 index 00000000..9ba48437 --- /dev/null +++ b/Octokit/Clients/ReferencesClient.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Octokit +{ + public class ReferencesClient : ApiClient, IReferencesClient + { + public ReferencesClient(IApiConnection apiConnection) : + base(apiConnection) + { + } + + /// + /// Gets a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#get-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + public Task Get(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + + return ApiConnection.Get(ApiUrls.Reference(owner, name, reference)); + } + + /// + /// Gets all references for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// + public Task> GetAll(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return ApiConnection.GetAll(ApiUrls.Reference(owner, name)); + } + + /// + /// Gets references for a given repository by sub-namespace, i.e. "tags" or "heads" + /// + /// + /// http://developer.github.com/v3/git/refs/#get-all-references + /// + /// The owner of the repository + /// The name of the repository + /// The sub-namespace to get references for + /// + public Task> GetAllForSubNamespace(string owner, string name, string subNamespace) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(subNamespace, "subNamespace"); + + // TODO: Handle 404 when subNamespace cannot be found + + return ApiConnection.GetAll(ApiUrls.Reference(owner, name, subNamespace)); + } + + /// + /// Creates a reference for a given repository + /// + /// + /// http://developer.github.com/v3/git/refs/#create-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The reference to create + /// + public Task Create(string owner, string name, NewReference reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNull(reference, "reference"); + + return ApiConnection.Post(ApiUrls.Reference(owner, name), reference); + } + + /// + /// Updates a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#update-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// The updated reference data + /// + public Task Update(string owner, string name, string reference, ReferenceUpdate referenceUpdate) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + Ensure.ArgumentNotNull(referenceUpdate, "update"); + + return ApiConnection.Patch(ApiUrls.Reference(owner, name, reference), referenceUpdate); + } + + /// + /// Deletes a reference for a given repository by reference name + /// + /// + /// http://developer.github.com/v3/git/refs/#delete-a-reference + /// + /// The owner of the repository + /// The name of the repository + /// The name of the reference + /// + public Task Delete(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + + return ApiConnection.Delete(ApiUrls.Reference(owner, name, reference)); + } + } +} diff --git a/Octokit/Clients/RepoCollaboratorsClient.cs b/Octokit/Clients/RepoCollaboratorsClient.cs index 6fc52ca4..6b508b98 100644 --- a/Octokit/Clients/RepoCollaboratorsClient.cs +++ b/Octokit/Clients/RepoCollaboratorsClient.cs @@ -48,7 +48,7 @@ namespace Octokit /// See the API documentation for more information. /// /// Thrown when a general API error occurs. - /// True if user is a collaborator else false + /// True if user is a collaborator else false public async Task IsCollaborator(string owner, string repo, string user) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); diff --git a/Octokit/Clients/StarredClient.cs b/Octokit/Clients/StarredClient.cs index 06e46c53..94ff2849 100644 --- a/Octokit/Clients/StarredClient.cs +++ b/Octokit/Clients/StarredClient.cs @@ -12,12 +12,12 @@ namespace Octokit } /// - /// Retrieves all of the stargazers for the passed repository. + /// Retrieves all of the stargazers for the passed repository /// /// The owner of the repository /// The name of the repository - /// Thrown if the client is not authenticated. - /// A of . + /// Thrown if the client is not authenticated + /// A of s starring the passed repository public Task> GetAllStargazers(string owner, string name) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -27,21 +27,26 @@ namespace Octokit } /// - /// Retrieves all of the starred (ies) for the current user. + /// Retrieves all of the starred (ies) for the current user /// - /// Thrown if the client is not authenticated. - /// A of . + /// Thrown if the client is not authenticated + /// + /// A of (ies) starred by the current user + /// public Task> GetAllForCurrent() { return ApiConnection.GetAll(ApiUrls.Starred()); } /// - /// Retrieves all of the starred (ies) for the current user. + /// Retrieves all of the starred (ies) for the current user /// /// Star-specific request parameters that sort the results - /// Thrown if the client is not authenticated. - /// A of . + /// Thrown if the client is not authenticated + /// + /// A of (ies) starred by the current user, + /// sorted according to the passed request parameters + /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "But i think i do need star-specific request parameters")] public Task> GetAllForCurrent(StarredRequest request) @@ -52,11 +57,11 @@ namespace Octokit } /// - /// Retrieves all of the (ies) starred by the specified user. + /// Retrieves all of the (ies) starred by the specified user /// /// The login of the user - /// Thrown if the client is not authenticated. - /// A starred by the specified user. + /// Thrown if the client is not authenticated + /// A starred by the specified user public Task> GetAllForUser(string user) { Ensure.ArgumentNotNullOrEmptyString(user, "user"); @@ -65,12 +70,12 @@ namespace Octokit } /// - /// Retrieves all of the (ies) starred by the specified user. + /// Retrieves all of the (ies) starred by the specified user /// /// The login of the user /// Star-specific request parameters that sort the results - /// Thrown if the client is not authenticated. - /// A starred by the specified user. + /// Thrown if the client is not authenticated + /// A starred by the specified user [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] public Task> GetAllForUser(string user, StarredRequest request) { @@ -81,11 +86,11 @@ namespace Octokit } /// - /// Check if a repository is starred by the current authenticated user. + /// Check if a repository is starred by the current authenticated user /// /// The owner of the repository /// The name of the repository - /// Thrown if the client is not authenticated. + /// Thrown if the client is not authenticated /// A bool representing the success of the operation public async Task CheckStarred(string owner, string name) { @@ -106,11 +111,11 @@ namespace Octokit } /// - /// Stars a repository for the authenticated user. + /// Stars a repository for the authenticated user /// /// The owner of the repository to star /// The name of the repository to star - /// A bool representing the success of starring the repository. + /// A bool representing the success of starring the repository public async Task StarRepo(string owner, string name) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -130,11 +135,11 @@ namespace Octokit } /// - /// Unstars a repository for the authenticated user. + /// Unstars a repository for the authenticated user /// /// The owner of the repository to unstar /// The name of the repository to unstar - /// A bool representing the success of unstarring the repository. + /// A bool representing the success of unstarring the repository public async Task RemoveStarFromRepo(string owner, string name) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); diff --git a/Octokit/Clients/TreesClient.cs b/Octokit/Clients/TreesClient.cs index 085ee05a..3d109fa9 100644 --- a/Octokit/Clients/TreesClient.cs +++ b/Octokit/Clients/TreesClient.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System; +using System.Linq; +using System.Threading.Tasks; namespace Octokit { @@ -44,6 +46,11 @@ namespace Octokit Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNull(newTree, "newTree"); + if (newTree.Tree.Any(t => String.IsNullOrWhiteSpace(t.Mode))) + { + throw new ArgumentException("You have specified items in the tree which do not have a Mode value set."); + } + return ApiConnection.Post(ApiUrls.Tree(owner, name), newTree); } } diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs index 24a5c765..3692eebf 100644 --- a/Octokit/GitHubClient.cs +++ b/Octokit/GitHubClient.cs @@ -88,6 +88,7 @@ namespace Octokit Organization = new OrganizationsClient(apiConnection); PullRequest = new PullRequestsClient(apiConnection); Repository = new RepositoriesClient(apiConnection); + Gist = new GistsClient(apiConnection); Release = new ReleasesClient(apiConnection); User = new UsersClient(apiConnection); SshKey = new SshKeysClient(apiConnection); @@ -137,6 +138,7 @@ namespace Octokit public IOrganizationsClient Organization { get; private set; } public IPullRequestsClient PullRequest { get; private set; } public IRepositoriesClient Repository { get; private set; } + public IGistsClient Gist { get; private set; } public IReleasesClient Release { get; private set; } public ISshKeysClient SshKey { get; private set; } public IUsersClient User { get; private set; } diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index a082c057..2b0e9dfe 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -381,9 +381,11 @@ namespace Octokit /// /// Returns the that lists the starred repositories for the authenticated user. /// - public static Uri Stargazers(string owner, string repo) + /// The owner of the repository + /// The name of the repository + public static Uri Stargazers(string owner, string name) { - return "repos/{0}/{1}/stargazers".FormatUri(owner, repo); + return "repos/{0}/{1}/stargazers".FormatUri(owner, name); } /// @@ -407,11 +409,11 @@ namespace Octokit /// Returns the that shows whether the repo is starred by the current user. /// /// The owner of the repository - /// The name of the repository + /// The name of the repository /// - public static Uri Starred(string owner, string repo) + public static Uri Starred(string owner, string name) { - return "user/starred/{0}/{1}".FormatUri(owner, repo); + return "user/starred/{0}/{1}".FormatUri(owner, name); } /// @@ -446,6 +448,34 @@ namespace Octokit return "events".FormatUri(); } + /// + /// Returns the for the specified commit. + /// + /// The id of the gist + public static Uri Gist(string id) + { + return "gists/{0}".FormatUri(id); + } + + /// + /// Returns the for the comments for the specified gist. + /// + /// The id of the gist + public static Uri GistComments(int gistId) + { + return "gists/{0}/comments".FormatUri(gistId); + } + + /// + /// Returns the for a spesific comment for the specified commit. + /// + /// The id of the gist + /// The id of the comment + public static Uri GistComment(int gistId, int commentId) + { + return "gists/{0}/comments/{1}".FormatUri(gistId, commentId); + } + /// /// Returns the for the specified commit. /// @@ -458,6 +488,29 @@ namespace Octokit return "repos/{0}/{1}/git/commits/{2}".FormatUri(owner, name, reference); } + /// + /// Returns the for the specified reference. + /// + /// The owner of the repository + /// The name of the repository + /// + public static Uri Reference(string owner, string name) + { + return "repos/{0}/{1}/git/refs".FormatUri(owner, name); + } + + /// + /// Returns the for the specified reference. + /// + /// The owner of the repository + /// The name of the repository + /// The reference name + /// + public static Uri Reference(string owner, string name, string referenceName) + { + return "repos/{0}/{1}/git/refs/{2}".FormatUri(owner, name, referenceName); + } + /// /// Returns the for creating a commit object. /// diff --git a/Octokit/Http/IHttpClient.cs b/Octokit/Http/IHttpClient.cs index 75c87a0c..4e699d31 100644 --- a/Octokit/Http/IHttpClient.cs +++ b/Octokit/Http/IHttpClient.cs @@ -15,7 +15,7 @@ namespace Octokit.Internal /// /// The type of data to send /// A that represents the HTTP request - /// A + /// A of Task> Send(IRequest request); } } diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs index 8a0cc93d..9fae5938 100644 --- a/Octokit/IGitHubClient.cs +++ b/Octokit/IGitHubClient.cs @@ -14,6 +14,7 @@ namespace Octokit IOrganizationsClient Organization { get; } IPullRequestsClient PullRequest { get; } IRepositoriesClient Repository { get; } + IGistsClient Gist { get; } IReleasesClient Release { get; } ISshKeysClient SshKey { get; } IUsersClient User { get; } diff --git a/Octokit/Models/Request/BodyWrapper.cs b/Octokit/Models/Request/BodyWrapper.cs new file mode 100644 index 00000000..2c1d332f --- /dev/null +++ b/Octokit/Models/Request/BodyWrapper.cs @@ -0,0 +1,12 @@ +namespace Octokit +{ + public class BodyWrapper + { + public BodyWrapper(string body) + { + Body = body; + } + + public string Body { get; private set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Request/NewAuthorization.cs b/Octokit/Models/Request/NewAuthorization.cs index 19a48e49..135e018c 100644 --- a/Octokit/Models/Request/NewAuthorization.cs +++ b/Octokit/Models/Request/NewAuthorization.cs @@ -18,8 +18,8 @@ namespace Octokit public string Note { get; set; } /// - // An optional URL to remind you what app the OAuth token is for. + /// An optional URL to remind you what app the OAuth token is for. /// public string NoteUrl { get; set; } } -} \ No newline at end of file +} diff --git a/Octokit/Models/Request/NewReference.cs b/Octokit/Models/Request/NewReference.cs new file mode 100644 index 00000000..47288583 --- /dev/null +++ b/Octokit/Models/Request/NewReference.cs @@ -0,0 +1,40 @@ +using System; +using System.Linq; + +namespace Octokit +{ + public class NewReference + { + const string _refsPrefix = "refs"; + + public NewReference(string reference, string sha) + { + Ensure.ArgumentNotNullOrEmptyString(reference, "ref"); + Ensure.ArgumentNotNullOrEmptyString(sha, "sha"); + + Ref = GetReference(reference); + Sha = sha; + } + + public string Ref { get; private set; } + public string Sha { get; private set; } + + static string GetReference(string reference) + { + var parts = reference.Split('/').ToList(); + + var refsPart = parts.FirstOrDefault(); + if (refsPart != null && refsPart != _refsPrefix) + { + parts.Insert(0, _refsPrefix); + } + + if (parts.Count < 3) + { + throw new FormatException("Reference must start with 'refs' and have at least two slashes."); + } + + return string.Join("/", parts); + } + } +} \ No newline at end of file diff --git a/Octokit/Models/Request/NewTree.cs b/Octokit/Models/Request/NewTree.cs index 35e6c400..78e18588 100644 --- a/Octokit/Models/Request/NewTree.cs +++ b/Octokit/Models/Request/NewTree.cs @@ -1,10 +1,16 @@ using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; namespace Octokit { public class NewTree { + public NewTree() + { + Tree = new Collection(); + } + /// /// The SHA1 of the tree you want to update with new data. /// diff --git a/Octokit/Models/Request/ReferenceUpdate.cs b/Octokit/Models/Request/ReferenceUpdate.cs new file mode 100644 index 00000000..0b187397 --- /dev/null +++ b/Octokit/Models/Request/ReferenceUpdate.cs @@ -0,0 +1,20 @@ +namespace Octokit +{ + public class ReferenceUpdate + { + public ReferenceUpdate(string sha) : this(sha, false) + { + } + + public ReferenceUpdate(string sha, bool force) + { + Ensure.ArgumentNotNullOrEmptyString(sha, "sha"); + + Sha = sha; + Force = force; + } + + public string Sha { get; private set; } + public bool Force { get; private set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/Gist.cs b/Octokit/Models/Response/Gist.cs new file mode 100644 index 00000000..9224b6c7 --- /dev/null +++ b/Octokit/Models/Response/Gist.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Octokit +{ + public class Gist + { + /// + /// The API URL for this . + /// + public string Url { get; set; } + + /// + /// The Id of this . + /// + /// + /// Given a gist url of https://gist.github.com/UserName/1234 the Id would be '1234'. + /// + public string Id { get; set; } + + /// + /// A description of the . + /// + public string Description { get; set; } + + /// + /// Indicates if the is private or public. + /// + public bool Public { get; set; } + + /// + /// The who owns this . + /// + /// + /// Given a gist url of https://gist.github.com/UserName/1234 the Owner would be 'UserName'. + /// + public User Owner { get; set; } + + /// + /// A containing all s in this . + /// + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public IDictionary Files { get; set; } + + /// + /// The number of comments on this . + /// + public int Comments { get; set; } + + /// + /// A url to retrieve the comments for this . + /// + public string CommentsUrl { get; set; } + + public string HtmlUrl { get; set; } + + /// + /// The git url to pull from to retrieve the contents for this . + /// + public string GitPullUrl { get; set; } + + /// + /// The git url to push to when changing this . + /// + public string GitPushUrl { get; set; } + + /// + /// The for when this was created. + /// + public DateTimeOffset CreatedAt { get; set; } + + /// + /// The for when this was last updated. + /// + public DateTimeOffset UpdatedAt { get; set; } + + /// + /// A of all that exist for this . + /// + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public IList Forks { get; set; } + + /// + /// A of all containing the full history for this . + /// + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public IList History { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/GistChangeStatus.cs b/Octokit/Models/Response/GistChangeStatus.cs new file mode 100644 index 00000000..4b790347 --- /dev/null +++ b/Octokit/Models/Response/GistChangeStatus.cs @@ -0,0 +1,23 @@ +namespace Octokit +{ + /// + /// User by to indicate the level of change. + /// + public class GistChangeStatus + { + /// + /// The number of deletions that occurred as part of this change. + /// + public int Deletions { get; set; } + + /// + /// The number of additions that occurred as part of this change. + /// + public int Additions { get; set; } + + /// + /// The total number of changes. + /// + public int Total { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/GistComment.cs b/Octokit/Models/Response/GistComment.cs new file mode 100644 index 00000000..f37023e0 --- /dev/null +++ b/Octokit/Models/Response/GistComment.cs @@ -0,0 +1,37 @@ +using System; + +namespace Octokit +{ + public class GistComment + { + /// + /// The gist comment id. + /// + public int Id { get; set; } + + /// + /// The URL for this gist comment. + /// + public Uri Url { get; set; } + + /// + /// The body of this gist comment. + /// + public string Body { get; set; } + + /// + /// The user that created this gist comment. + /// + public User User { get; set; } + + /// + /// The date this comment was created. + /// + public DateTimeOffset CreatedAt { get; set; } + + /// + /// The date this comment was last updated. + /// + public DateTimeOffset? UpdatedAt { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/GistFile.cs b/Octokit/Models/Response/GistFile.cs new file mode 100644 index 00000000..64aad8b0 --- /dev/null +++ b/Octokit/Models/Response/GistFile.cs @@ -0,0 +1,39 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Octokit +{ + public class GistFile + { + /// + /// The size in bytes of the file. + /// + public int Size { get; set; } + + /// + /// The name of the file + /// + [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly")] + public string Filename { get; set; } + + /// + /// The mime type of the file + /// + [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")] + public string Type { get; set; } + + /// + /// The programming language of the file, if any. + /// + public string Language { get; set; } + + /// + /// The text content of the file. + /// + public string Content { get; set; } + + /// + /// The url to download the file. + /// + public string RawUrl { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/GistFork.cs b/Octokit/Models/Response/GistFork.cs new file mode 100644 index 00000000..b6c3662c --- /dev/null +++ b/Octokit/Models/Response/GistFork.cs @@ -0,0 +1,22 @@ +using System; + +namespace Octokit +{ + public class GistFork + { + /// + /// The that created this + /// + public User User { get; set; } + + /// + /// The API URL for this . + /// + public string Url { get; set; } + + /// + /// The for when this was created. + /// + public DateTimeOffset CreatedAt { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/GistHistory.cs b/Octokit/Models/Response/GistHistory.cs new file mode 100644 index 00000000..0ea5fe32 --- /dev/null +++ b/Octokit/Models/Response/GistHistory.cs @@ -0,0 +1,35 @@ +using System; + +namespace Octokit +{ + /// + /// A historical version of a + /// + public class GistHistory + { + /// + /// The url that can be used by the API to retrieve this version of the . + /// + public string Url { get; set; } + + /// + /// A git sha representing the version. + /// + public string Version { get; set; } + + /// + /// The who create this version. + /// + public User User { get; set; } + + /// + /// A that represents the level of change for this . + /// + public GistChangeStatus ChangeStatus { get; set; } + + /// + /// The the version was created. + /// + public DateTimeOffset CommittedAt { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/Reference.cs b/Octokit/Models/Response/Reference.cs new file mode 100644 index 00000000..1fd8d08b --- /dev/null +++ b/Octokit/Models/Response/Reference.cs @@ -0,0 +1,9 @@ +namespace Octokit +{ + public class Reference + { + public string Ref { get; set; } + public string Url { get; set; } + public TagObject Object { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Models/Response/TagObject.cs b/Octokit/Models/Response/TagObject.cs index b9c4b7cf..183f754f 100644 --- a/Octokit/Models/Response/TagObject.cs +++ b/Octokit/Models/Response/TagObject.cs @@ -14,6 +14,7 @@ { Commit, Blob, - Tree + Tree, + Tag } } \ No newline at end of file diff --git a/Octokit/Models/Response/TreeItem.cs b/Octokit/Models/Response/TreeItem.cs index 96a118a8..0fff7f60 100644 --- a/Octokit/Models/Response/TreeItem.cs +++ b/Octokit/Models/Response/TreeItem.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; namespace Octokit { @@ -42,4 +43,33 @@ namespace Octokit Tree, Commit } + + /// + /// The file mode to associate with a tree item + /// + public static class FileMode + { + /// + /// Mark the tree item as a file (applicable to blobs only) + /// + public const string File = "100644"; + /// + /// Mark the tree item as an executable (applicable to blobs only) + /// + public const string Executable = "100755"; + /// + /// Mark the tree item as a subdirectory (applicable to trees only) + /// + public const string Subdirectory = "040000"; + /// + /// Mark the tree item as a submodule (applicable to commits only) + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Submodule")] + public const string Submodule = "160000"; + /// + /// Mark the tree item as a symlink (applicable to blobs only) + /// + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Symlink")] + public const string Symlink = "120000"; + } } \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index a643db9b..959cc18f 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -46,16 +46,19 @@ + + + @@ -65,6 +68,7 @@ + @@ -80,11 +84,13 @@ + + @@ -93,6 +99,11 @@ + + + + + @@ -108,6 +119,7 @@ + @@ -226,6 +238,10 @@ + + + + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index de9ae97a..463cfea6 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -236,6 +236,22 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 6bf347b9..50c581f1 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -231,6 +231,22 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index ccc85f2b..65c7fd11 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -57,6 +57,7 @@ + @@ -69,6 +70,7 @@ + @@ -78,6 +80,7 @@ + @@ -94,6 +97,7 @@ + @@ -163,12 +167,14 @@ + + @@ -186,6 +192,11 @@ + + + + + @@ -201,6 +212,7 @@ + @@ -224,6 +236,10 @@ + + + + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 5fa3f190..d30d21ab 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -61,6 +61,16 @@ + + + + + + + + + + @@ -75,6 +85,8 @@ + + @@ -117,6 +129,11 @@ + + + + + diff --git a/README.md b/README.md index b4652e84..e5f1dc0c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ To clone it locally click the "Clone in Windows" button above or run the following git commands. ``` -git clone git@github.com:github/Octokit.net.git Octokit +git clone git@github.com:octokit/Octokit.net.git Octokit cd Octokit .\build.cmd ``` @@ -81,6 +81,18 @@ problem. Visit the [Contributor Guidelines](https://github.com/octokit/octokit.net/blob/master/CONTRIBUTING.md) for more details. +### A Note about project structure + +There are two primary projects in the solution: `Octokit.csproj` and `Octokit.Reactive.csproj`. + +The first is the task-based library. The second is a wrapper that provides an Reactive Extensions (Rx) based library. + +The clients within a project are organized similarly to the endpoints in the [GitHub API documentation](http://developer.github.com/v3/) + +Some clients are "sub-clients". For example, when you navigate to the [Issues API](http://developer.github.com/v3/issues/) you'll notice there's an endpoint for issues. But in the right navbar, there are other APIs such as [Assignees](http://developer.github.com/v3/issues/assignees/) and [Milestones](http://developer.github.com/v3/issues/milestones/). + +We've tried to mirror this structure. So the `IObservableMilestoneClient` isn't a direct property of `IObservableGitHubClient`. Instead, it's a property of the `IObservableIssuesClient`. And thus you can get to it by going to `client.Issues.Milestones`. + ## Copyright and License Copyright 2013 GitHub, Inc. diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 0ab42142..33c8b71c 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,11 @@ +### New in 0.1.5 (Released 2013/11/19) +* New client for starring repositories +* New client for retrieving commits +* New client for managing an organization's teams and members +* New client for managing blobs +* New client for retrieving and creating trees +* New client for managing collaborators of a repository + ### New in 0.1.4 (Released 2013/11/6) * New client for retrieving activity events * Fixed bug where concealing an org's member actually shows the member diff --git a/SolutionInfo.cs b/SolutionInfo.cs index 65f27551..358bd08a 100644 --- a/SolutionInfo.cs +++ b/SolutionInfo.cs @@ -3,11 +3,11 @@ using System.Reflection; using System.Runtime.InteropServices; [assembly: AssemblyProductAttribute("Octokit")] -[assembly: AssemblyVersionAttribute("0.1.4")] -[assembly: AssemblyFileVersionAttribute("0.1.4")] +[assembly: AssemblyVersionAttribute("0.1.5")] +[assembly: AssemblyFileVersionAttribute("0.1.5")] [assembly: ComVisibleAttribute(false)] namespace System { internal static class AssemblyVersionInformation { - internal const string Version = "0.1.4"; + internal const string Version = "0.1.5"; } } diff --git a/build.cmd b/build.cmd index 431be99c..f3c0c6a8 100644 --- a/build.cmd +++ b/build.cmd @@ -1,17 +1,6 @@ @echo off -SET MinimalFAKEVersion=639 -SET FAKEVersion=1 -cls - -if exist tools\FAKE.Core\tools\PatchVersion.txt ( - FOR /F "tokens=*" %%i in (tools\FAKE.Core\tools\PatchVersion.txt) DO (SET FAKEVersion=%%i) -) - -if %MinimalFAKEVersion% lss %FAKEVersion% goto Build -if %MinimalFAKEVersion%==%FAKEVersion% goto Build - -"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-Prerelease" +"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.2.0" :Build cls @@ -23,6 +12,19 @@ IF NOT [%1]==[] (set TARGET="%1") SET BUILDMODE="Release" IF NOT [%2]==[] (set BUILDMODE="%2") +:: because we want to run specific steps inline on qed +:: we need to break the dependency chain +:: this ensures we do a build before running any tests + +if TARGET=="Default" (SET RunBuild=1) +if TARGET=="RunUnitTests" (SET RunBuild=1) +if TARGET=="RunIntegrationTests" (SET RunBuild=1) +if TARGET=="CreatePackages" (SET RunBuild=1) + +if NOT "%RunBuild%"=="" ( +"tools\FAKE.Core\tools\Fake.exe" "build.fsx" "target=BuildApp" "buildMode=%BUILDMODE%" +) + "tools\FAKE.Core\tools\Fake.exe" "build.fsx" "target=%TARGET%" "buildMode=%BUILDMODE%" rem Bail if we're running a TeamCity build. @@ -31,13 +33,5 @@ if defined TEAMCITY_PROJECT_NAME goto Quit rem Bail if we're running a MyGet build. if /i "%BuildRunner%"=="MyGet" goto Quit -rem Loop the build script. -set CHOICE=nothing -echo (Q)uit, (Enter) runs the build again -set /P CHOICE= -if /i "%CHOICE%"=="Q" goto :Quit - -GOTO Build - :Quit exit /b %errorlevel% diff --git a/build.fsx b/build.fsx index 009dc883..a9419026 100644 --- a/build.fsx +++ b/build.fsx @@ -75,6 +75,7 @@ Target "IntegrationTests" (fun _ -> |> xUnit (fun p -> {p with XmlOutput = true + Verbose = false OutputDir = testResultsDir }) else "The integration tests were skipped because the OCTOKIT_GITHUBUSERNAME and OCTOKIT_GITHUBPASSWORD environment variables are not set. " + @@ -131,14 +132,21 @@ Target "CreateOctokitReactivePackage" (fun _ -> Target "Default" DoNothing +Target "CreatePackages" DoNothing + "Clean" ==> "AssemblyInfo" ==> "CheckProjects" - ==> "BuildApp" - ==> "UnitTests" - ==> "IntegrationTests" - ==> "CreateOctokitPackage" - ==> "CreateOctokitReactivePackage" + ==> "BuildApp" + +"UnitTests" ==> "Default" +"IntegrationTests" + ==> "Default" + +"CreateOctokitPackage" +"CreateOctokitReactivePackage" + ==> "CreatePackages" + RunTargetOrDefault "Default" \ No newline at end of file diff --git a/script/cibuild.ps1 b/script/cibuild.ps1 index bddfe95a..62568b95 100644 --- a/script/cibuild.ps1 +++ b/script/cibuild.ps1 @@ -35,6 +35,17 @@ function Die-WithOutput($exitCode, $output) { exit $exitCode } +function Dump-Error($output) { + $exitCode = $LastExitCode + + $errors = $output | Select-String ": error" + if ($errors) { + $output = "Likely errors:", $errors, "", "Full output:", $output + } + + Die-WithOutput $exitCode $output +} + function Run-Command([scriptblock]$Command, [switch]$Fatal, [switch]$Quiet) { $output = "" if ($Quiet) { @@ -76,21 +87,35 @@ if (Test-Path tools\FAKE.Core\tools\Fake.exe) { else { Write-Output "Installing FAKE..." Write-Output "" - .\tools\nuget\nuget.exe "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-Prerelease" + .\tools\nuget\nuget.exe "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-Version" "2.2.1" } Write-Output "Building Octokit..." Write-Output "" -$output = .\tools\FAKE.Core\tools\Fake.exe "build.fsx" "target=Default" "buildMode=Release" +$output = & .\tools\FAKE.Core\tools\Fake.exe "build.fsx" "target=BuildApp" "buildMode=Release" if ($LastExitCode -ne 0) { - $exitCode = $LastExitCode + Dump-Error($output) +} - $errors = $output | Select-String ": error" - if ($errors) { - $output = "Likely errors:", $errors, "", "Full output:", $output - } +Write-Output "Running unit tests..." +Write-Output "" +$output = & .\tools\FAKE.Core\tools\Fake.exe "build.fsx" "target=UnitTests" "buildMode=Release" +if ($LastExitCode -ne 0) { + Dump-Error($output) +} - Die-WithOutput $exitCode $output +Write-Output "Running integration tests..." +Write-Output "" +$output = & .\tools\FAKE.Core\tools\Fake.exe "build.fsx" "target=IntegrationTests" "buildMode=Release" +if ($LastExitCode -ne 0) { + Dump-Error($output) +} + +Write-Output "Creating NuGet packages..." +Write-Output "" +$output = & .\tools\FAKE.Core\tools\Fake.exe "build.fsx" "target=CreatePackages" "buildMode=Release" +if ($LastExitCode -ne 0) { + Dump-Error($output) } $exitCode = 0