Skip to content

Commit

Permalink
Add repository topics support (octokit#2246)
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanKilleen authored Feb 25, 2021
1 parent 2e5fb68 commit 57fe2ce
Show file tree
Hide file tree
Showing 16 changed files with 757 additions and 1 deletion.
74 changes: 74 additions & 0 deletions Octokit.Reactive/Clients/IObservableRepositoriesClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reactive;
using System.Threading.Tasks;

namespace Octokit.Reactive
{
Expand Down Expand Up @@ -556,5 +558,77 @@ public interface IObservableRepositoriesClient
/// Refer to the API documentation for more information: https://developer.github.com/v3/repos/projects/
/// </remarks>
IObservableProjectsClient Project { get; }

/// <summary>
/// Gets all topics for the specified owner and repository name.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All topics associated with the repository.</returns>
IObservable<RepositoryTopics> GetAllTopics(string owner, string name, ApiOptions options);

/// <summary>
/// Gets all topics for the specified owner and repository name.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <returns>All topics associated with the repository.</returns>
IObservable<RepositoryTopics> GetAllTopics(string owner, string name);

/// <summary>
/// Gets all topics for the specified repository ID.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All topics associated with the repository.</returns>
IObservable<RepositoryTopics> GetAllTopics(long repositoryId, ApiOptions options);

/// <summary>
/// Gets all topics for the specified repository ID.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <returns>All topics associated with the repository.</returns>
IObservable<RepositoryTopics> GetAllTopics(long repositoryId);

/// <summary>
/// Replaces all topics for the specified repository.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#replace-all-repository-topics">API documentation</a> for more details
///
/// This is a replacement operation; it is not additive. To clear repository topics, for example, you could specify an empty list of topics here.
/// </remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="topics">The list of topics to associate with the repository</param>
/// <returns>All topics now associated with the repository.</returns>
IObservable<RepositoryTopics> ReplaceAllTopics(long repositoryId, RepositoryTopics topics);

/// <summary>
/// Replaces all topics for the specified repository.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#replace-all-repository-topics">API documentation</a> for more details
///
/// This is a replacement operation; it is not additive. To clear repository topics, for example, you could specify an empty list of topics here.
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="topics">The list of topics to associate with the repository</param>
/// <returns>All topics now associated with the repository.</returns>
IObservable<RepositoryTopics> ReplaceAllTopics(string owner, string name, RepositoryTopics topics);

}
}
91 changes: 91 additions & 0 deletions Octokit.Reactive/Clients/ObservableRepositoriesClient.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;
using Octokit.Reactive.Clients;
using Octokit.Reactive.Internal;

Expand Down Expand Up @@ -821,5 +823,94 @@ public IObservable<CompareResult> Compare(string owner, string name, string @bas
/// Refer to the API documentation for more information: https://developer.github.com/v3/repos/projects/
/// </remarks>
public IObservableProjectsClient Project { get; private set; }

/// <summary>
/// Gets all topics for the specified owner and repository name.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All topics associated with the repository.</returns>
public IObservable<RepositoryTopics> GetAllTopics(string owner, string name, ApiOptions options)
{
return _client.GetAllTopics(owner, name, options).ToObservable();
}

/// <summary>
/// Gets all topics for the specified owner and repository name.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <returns>All topics associated with the repository.</returns>
public IObservable<RepositoryTopics> GetAllTopics(string owner, string name)
{
return GetAllTopics(owner, name, ApiOptions.None);
}

/// <summary>
/// Gets all topics for the specified repository ID.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All topics associated with the repository.</returns>
public IObservable<RepositoryTopics> GetAllTopics(long repositoryId, ApiOptions options)
{
return _client.GetAllTopics(repositoryId, options).ToObservable();
}

/// <summary>
/// Gets all topics for the specified repository ID.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#get-all-repository-topics">API documentation</a> for more details
/// </remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <returns>All topics associated with the repository.</returns>
public IObservable<RepositoryTopics> GetAllTopics(long repositoryId)
{
return GetAllTopics(repositoryId, ApiOptions.None);
}

/// <summary>
/// Replaces all topics for the specified repository.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#replace-all-repository-topics">API documentation</a> for more details
///
/// This is a replacement operation; it is not additive. To clear repository topics, for example, you could specify an empty list of topics here.
/// </remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="topics">The list of topics to associate with the repository</param>
/// <returns>All topics now associated with the repository.</returns>
public IObservable<RepositoryTopics> ReplaceAllTopics(long repositoryId, RepositoryTopics topics)
{
return _client.ReplaceAllTopics(repositoryId, topics).ToObservable();
}

/// <summary>
/// Replaces all topics for the specified repository.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/reference/repos#replace-all-repository-topics">API documentation</a> for more details
///
/// This is a replacement operation; it is not additive. To clear repository topics, for example, you could specify an empty list of topics here.
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="topics">The list of topics to associate with the repository</param>
/// <returns>All topics now associated with the repository.</returns>
public IObservable<RepositoryTopics> ReplaceAllTopics(string owner, string name, RepositoryTopics topics)
{
return _client.ReplaceAllTopics(owner, name, topics).ToObservable();
}
}
}
98 changes: 98 additions & 0 deletions Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,104 @@ public async Task GetsEmptyLanguagesWhenNoneWithRepositoryId()
}
}

public class TheReplaceAllTopicsMethod : IDisposable
{
readonly IGitHubClient _github = Helper.GetAuthenticatedClient();
private readonly RepositoryTopics _defaultTopics = new RepositoryTopics(new List<string> { "blog", "ruby", "jekyll" });
private readonly RepositoryContext _context;
private readonly string _theRepository;
private readonly string _theRepoOwner;

public TheReplaceAllTopicsMethod()
{
_theRepoOwner = Helper.Organization;
_theRepository = Helper.MakeNameWithTimestamp("topics");
_context = _github.CreateRepositoryContext(_theRepoOwner, new NewRepository(_theRepository)).Result;
var defaultTopicAssignmentResult = _github.Repository.ReplaceAllTopics(_context.RepositoryId, _defaultTopics).Result;
}

[IntegrationTest]
public async Task ClearsTopicsWithAnEmptyList()
{
var result = await _github.Repository.ReplaceAllTopics(_theRepoOwner, _theRepository, new RepositoryTopics());
Assert.Empty(result.Names);

var doubleCheck = await _github.Repository.GetAllTopics(_theRepoOwner, _theRepository);
Assert.Empty((doubleCheck.Names));
}

[IntegrationTest]
public async Task ClearsTopicsWithAnEmptyListWhenUsingRepoId()
{
var repo = await _github.Repository.Get(_theRepoOwner, _theRepository);
var result = await _github.Repository.ReplaceAllTopics(repo.Id, new RepositoryTopics());
Assert.Empty(result.Names);

var doubleCheck = await _github.Repository.GetAllTopics(_theRepoOwner, _theRepository);
Assert.Empty((doubleCheck.Names));
}

[IntegrationTest]
public async Task ReplacesTopicsWithAList()
{
var defaultTopicsList = new RepositoryTopics(_defaultTopics.Names);
var result = await _github.Repository.ReplaceAllTopics(_theRepoOwner, _theRepository, defaultTopicsList);

Assert.NotEmpty(result.Names);
Assert.Contains(result.Names, item => _defaultTopics.Names.Contains(item, StringComparer.InvariantCultureIgnoreCase));

var doubleCheck = await _github.Repository.GetAllTopics(_theRepoOwner, _theRepository);
Assert.Contains(doubleCheck.Names, item => _defaultTopics.Names.Contains(item, StringComparer.InvariantCultureIgnoreCase));
}

[IntegrationTest]
public async Task ReplacesTopicsWithAListWhenUsingRepoId()
{
var defaultTopicsList = new RepositoryTopics(_defaultTopics.Names);
var repo = await _github.Repository.Get(_theRepoOwner, _theRepository);
var result = await _github.Repository.ReplaceAllTopics(repo.Id, defaultTopicsList);

Assert.NotEmpty(result.Names);
Assert.Contains(result.Names, item => _defaultTopics.Names.Contains(item, StringComparer.InvariantCultureIgnoreCase));

var doubleCheck = await _github.Repository.GetAllTopics(_theRepoOwner, _theRepository);
Assert.Contains(doubleCheck.Names, item => _defaultTopics.Names.Contains(item, StringComparer.InvariantCultureIgnoreCase));
}

public void Dispose()
{
_context.Dispose();
}
}
public class TheGetAllTopicsMethod
{
private readonly string _repoOwner = "SeanKilleen";
private readonly string _repoName = "seankilleen.github.io";

[IntegrationTest]
public async Task GetsTopicsByOwnerAndName()
{
var github = Helper.GetAnonymousClient();
var result = await github.Repository.GetAllTopics(_repoOwner, _repoName);

Assert.Contains("blog", result.Names);
Assert.Contains("ruby", result.Names);
Assert.Contains("jekyll", result.Names);
}

[IntegrationTest]
public async Task GetsTopicsByRepoID()
{
var github = Helper.GetAnonymousClient();
var repo = await github.Repository.Get(_repoOwner, _repoName);
var result = await github.Repository.GetAllTopics(repo.Id);

Assert.Contains("blog", result.Names);
Assert.Contains("ruby", result.Names);
Assert.Contains("jekyll", result.Names);
}
}

public class TheGetAllTagsMethod
{
[IntegrationTest]
Expand Down
20 changes: 20 additions & 0 deletions Octokit.Tests.Integration/Clients/SearchClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ public async Task SearchForCSharpRepositories()
Assert.NotEmpty(repos.Items);
}

[IntegrationTest]
public async Task SearchForSingleTopic()
{
var request = new SearchRepositoriesRequest { Topic = "csharp" };

var repos = await _gitHubClient.Search.SearchRepo(request);

Assert.NotEmpty(repos.Items);
}

[IntegrationTest]
public async Task SearchForMoreThan2Topics()
{
var request = new SearchRepositoriesRequest { Topics = Octokit.Range.GreaterThanOrEquals(2) };

var repos = await _gitHubClient.Search.SearchRepo(request);

Assert.NotEmpty(repos.Items);
}

[IntegrationTest]
public async Task SearchForCSharpRepositoriesUpdatedIn2020()
{
Expand Down
Loading

0 comments on commit 57fe2ce

Please sign in to comment.