Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions lib/src/common/activity_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class ActivityService extends Service {
///
/// API docs: https://developer.github.com/v3/activity/notifications/#mark-as-read
Future<bool> markNotificationsRead({DateTime? lastRead}) {
final data = {};
final data = <String, dynamic>{};

if (lastRead != null) {
data['last_read_at'] = lastRead.toIso8601String();
Expand All @@ -167,7 +167,7 @@ class ActivityService extends Service {
RepositorySlug slug, {
DateTime? lastRead,
}) {
final data = {};
final data = <String, dynamic>{};

if (lastRead != null) {
data['last_read_at'] = lastRead.toIso8601String();
Expand All @@ -185,7 +185,7 @@ class ActivityService extends Service {
///
/// API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread
Future<Notification> getThread(String threadId) =>
github.getJSON('/notification/threads/$threadId',
github.getJSON('/notifications/threads/$threadId',
statusCode: StatusCodes.OK, convert: Notification.fromJson);

/// Mark the specified notification thread as read.
Expand Down Expand Up @@ -244,21 +244,17 @@ class ActivityService extends Service {
/// Stars the specified repository for the currently authenticated user.
///
/// API docs: https://developer.github.com/v3/activity/starring/#star-a-repository
Future star(RepositorySlug slug) {
return github.request('PUT', '/user/starred/${slug.fullName}',
headers: {'Content-Length': '0'}).then((response) {
return null;
});
Future<void> star(RepositorySlug slug) async {
await github.request('PUT', '/user/starred/${slug.fullName}',
statusCode: 204, headers: {'Content-Length': '0'});
}

/// Unstars the specified repository for the currently authenticated user.
///
/// API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository
Future unstar(RepositorySlug slug) {
return github.request('DELETE', '/user/starred/${slug.fullName}',
headers: {'Content-Length': '0'}).then((response) {
return null;
});
Future<void> unstar(RepositorySlug slug) async {
await github.request('DELETE', '/user/starred/${slug.fullName}',
statusCode: 204, headers: {'Content-Length': '0'});
}

/// Lists the watchers of the specified repository.
Expand Down Expand Up @@ -315,10 +311,10 @@ class ActivityService extends Service {
/// Deletes a Repository Subscription
///
/// API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription
Future deleteRepositorySubscription(RepositorySlug slug) {
Future<void> deleteRepositorySubscription(RepositorySlug slug) {
return github.request('DELETE', '/repos/${slug.fullName}/subscription',
headers: {'Content-Length': '0'}).then((response) {
return null;
return;
});
}
}
Expand Down Expand Up @@ -355,7 +351,8 @@ class EventPoller {

_lastFetched = response.headers['ETag'];

final json = List<Map<String, dynamic>>.from(jsonDecode(response.body));
final json = List<Map<String, dynamic>>.from(
jsonDecode(response.body) as Iterable<dynamic>);

if (!(onlyNew && _timer == null)) {
for (final item in json) {
Expand Down Expand Up @@ -399,7 +396,7 @@ class EventPoller {
return _controller!.stream;
}

Future stop() {
Future<void> stop() {
if (_timer == null) {
throw Exception('Polling not started.');
}
Expand Down
20 changes: 8 additions & 12 deletions lib/src/common/authorizations_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,27 @@ import 'dart:async';

import 'package:github/src/common.dart';

/// The [AuthorizationsService] handles communication with authorizations related methods
/// of the GitHub API.
/// The [AuthorizationsService] handles communication with legacy OAuth authorizations.
///
/// Note: You can only access this API via Basic Authentication using your
/// username and password, not tokens.
/// **Deprecated**: The OAuth Authorizations API was sunset by GitHub.
/// Use modern OAuth web application flows or GitHub Apps instead.
///
/// API docs: https://developer.github.com/v3/oauth_authorizations/
/// API docs: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#oauth-authorizations-api
@Deprecated(
'The OAuth Authorizations API has been sunset by GitHub. Use modern OAuth or GitHub Apps.')
class AuthorizationsService extends Service {
AuthorizationsService(super.github);

/// Lists all authorizations.
///
/// API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations
@Deprecated('The OAuth Authorizations API has been sunset by GitHub.')
Stream<Authorization> listAuthorizations() {
return PaginationHelper(github)
.objects('GET', '/authorizations', Authorization.fromJson);
}

/// Fetches an authorization specified by [id].
///
/// API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization
@Deprecated('The OAuth Authorizations API has been sunset by GitHub.')
Future<Authorization> getAuthorization(int id) =>
github.getJSON('/authorizations/$id',
statusCode: 200, convert: Authorization.fromJson);

// TODO: Implement remaining API methods of authorizations:
// See https://developer.github.com/v3/oauth_authorizations/
}
30 changes: 24 additions & 6 deletions lib/src/common/checks_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,18 @@ class CheckRunsService extends Service {
CheckRunOutput? output,
List<CheckRunAction>? actions,
}) async {
assert(conclusion != null ||
(completedAt == null && status != CheckRunStatus.completed));
assert(actions == null || actions.length <= 3);
if (status == CheckRunStatus.completed && conclusion == null) {
throw ArgumentError.value(
conclusion, 'conclusion', 'Required when status is completed');
}
if (completedAt != null && conclusion == null) {
throw ArgumentError.value(
conclusion, 'conclusion', 'Required when completedAt is provided');
}
if (actions != null && actions.length > 3) {
throw ArgumentError.value(
actions.length, 'actions', 'A maximum of 3 actions are accepted');
}
return github.postJSON<Map<String, dynamic>, CheckRun>(
'/repos/${slug.fullName}/check-runs',
statusCode: StatusCodes.CREATED,
Expand Down Expand Up @@ -109,9 +118,18 @@ class CheckRunsService extends Service {
CheckRunOutput? output,
List<CheckRunAction>? actions,
}) async {
assert(conclusion != null ||
(completedAt == null && status != CheckRunStatus.completed));
assert(actions == null || actions.length <= 3);
if (status == CheckRunStatus.completed && conclusion == null) {
throw ArgumentError.value(
conclusion, 'conclusion', 'Required when status is completed');
}
if (completedAt != null && conclusion == null) {
throw ArgumentError.value(
conclusion, 'conclusion', 'Required when completedAt is provided');
}
if (actions != null && actions.length > 3) {
throw ArgumentError.value(
actions.length, 'actions', 'A maximum of 3 actions are accepted');
}
return github.requestJson<Map<String, dynamic>, CheckRun>(
'PATCH',
'/repos/${slug.fullName}/check-runs/${checkRunToUpdate.id}',
Expand Down
15 changes: 10 additions & 5 deletions lib/src/common/gists_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ class GistsService extends Service {
String? description,
bool public = false,
}) {
final map = <String, dynamic>{'files': {}};
final map = <String, dynamic>{'files': <String, dynamic>{}};

if (description != null) {
map['description'] = description;
}

map['public'] = public;

final f = {};
final f = <String, dynamic>{};

for (final key in files.keys) {
f[key] = {'content': files[key]};
Expand Down Expand Up @@ -111,7 +111,8 @@ class GistsService extends Service {
map['files'] = f;
}

return github.postJSON(
return github.requestJson<Map<String, dynamic>, Gist>(
'PATCH',
'/gists/$id',
statusCode: 200,
body: GitHubJson.encode(map),
Expand All @@ -125,7 +126,9 @@ class GistsService extends Service {
///
/// API docs: https://developer.github.com/v3/gists/#star-a-gist
Future<bool> starGist(String id) {
return github.request('POST', '/gists/$id/star').then((response) {
return github
.request('PUT', '/gists/$id/star', statusCode: 204)
.then((response) {
return response.statusCode == 204;
});
}
Expand Down Expand Up @@ -176,7 +179,9 @@ class GistsService extends Service {
/// API docs: https://developer.github.com/v3/gists/comments/#create-a-comment
Future<GistComment> createComment(String gistId, CreateGistComment request) {
return github.postJSON('/gists/$gistId/comments',
body: GitHubJson.encode(request), convert: GistComment.fromJson);
body: GitHubJson.encode(request),
convert: GistComment.fromJson,
statusCode: 201);
}

// TODO: Implement editComment: https://developer.github.com/v3/gists/comments/#edit-a-comment
Expand Down
39 changes: 19 additions & 20 deletions lib/src/common/git_service.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'dart:async';
import 'dart:convert';

import 'package:github/src/common.dart';

Expand Down Expand Up @@ -77,10 +76,11 @@ class GitService extends Service {
/// API docs: https://developer.github.com/v3/git/refs/#create-a-reference
Future<GitReference> createReference(
RepositorySlug slug, String ref, String? sha) {
final formattedRef = ref.startsWith('refs/') ? ref : 'refs/$ref';
return github.postJSON('/repos/${slug.fullName}/git/refs',
convert: GitReference.fromJson,
statusCode: StatusCodes.CREATED,
body: GitHubJson.encode({'ref': ref, 'sha': sha}));
body: GitHubJson.encode({'ref': formattedRef, 'sha': sha}));
}

/// Updates a reference in a repository.
Expand All @@ -92,25 +92,25 @@ class GitService extends Service {
String? sha, {
bool force = false,
}) {
final formattedRef = ref.startsWith('refs/') ? ref.substring(5) : ref;
final body = GitHubJson.encode({'sha': sha, 'force': force});
// Somehow the reference updates PATCH request needs a valid content-length.
final headers = {'content-length': body.length.toString()};

return github
.request('PATCH', '/repos/${slug.fullName}/git/refs/$ref',
body: body, headers: headers)
.then((response) {
return GitReference.fromJson(
jsonDecode(response.body) as Map<String, dynamic>);
});
return github.requestJson<Map<String, dynamic>, GitReference>(
'PATCH',
'/repos/${slug.fullName}/git/refs/$formattedRef',
statusCode: StatusCodes.OK,
body: body,
convert: GitReference.fromJson,
);
}

/// Deletes a reference.
///
/// API docs: https://developer.github.com/v3/git/refs/#delete-a-reference
Future<bool> deleteReference(RepositorySlug slug, String ref) {
final formattedRef = ref.startsWith('refs/') ? ref.substring(5) : ref;
return github
.request('DELETE', '/repos/${slug.fullName}/git/refs/$ref')
.request('DELETE', '/repos/${slug.fullName}/git/refs/$formattedRef',
statusCode: StatusCodes.NO_CONTENT)
.then((response) => response.statusCode == StatusCodes.NO_CONTENT);
}

Expand Down Expand Up @@ -138,13 +138,12 @@ class GitService extends Service {
/// and https://developer.github.com/v3/git/trees/#get-a-tree-recursively
Future<GitTree> getTree(RepositorySlug slug, String? sha,
{bool recursive = false}) {
var path = '/repos/${slug.fullName}/git/trees/$sha';
if (recursive) {
path += '?recursive=1';
}

return github.getJSON(path,
convert: GitTree.fromJson, statusCode: StatusCodes.OK);
return github.getJSON(
'/repos/${slug.fullName}/git/trees/$sha',
params: recursive ? {'recursive': '1'} : const {},
convert: GitTree.fromJson,
statusCode: StatusCodes.OK,
);
}

/// Creates a new tree in a repository.
Expand Down
40 changes: 20 additions & 20 deletions lib/src/common/issues_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,19 +174,13 @@ class IssuesService extends Service {
/// Create an issue.
///
/// API docs: https://developer.github.com/v3/issues/#create-an-issue
Future<Issue> create(RepositorySlug slug, IssueRequest issue) async {
final response = await github.request(
'POST',
Future<Issue> create(RepositorySlug slug, IssueRequest issue) {
return github.postJSON<Map<String, dynamic>, Issue>(
'/repos/${slug.fullName}/issues',
statusCode: StatusCodes.CREATED,
body: GitHubJson.encode(issue),
convert: Issue.fromJson,
);

if (StatusCodes.isClientError(response.statusCode)) {
//TODO: throw a more friendly error – better this than silent failure
throw GitHubError(github, response.body);
}

return Issue.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
}

/// Lists all available assignees (owners and collaborators) to which issues
Expand All @@ -201,9 +195,9 @@ class IssuesService extends Service {
/// Checks if a user is an assignee for the specified repository.
///
/// API docs: https://developer.github.com/v3/issues/assignees/#check-assignee
Future<bool> isAssignee(RepositorySlug slug, String repoName) {
Future<bool> isAssignee(RepositorySlug slug, String assignee) {
return github
.request('GET', '/repos/${slug.fullName}/assignees/$repoName')
.request('GET', '/repos/${slug.fullName}/assignees/$assignee')
.then((response) => response.statusCode == StatusCodes.NO_CONTENT);
}

Expand Down Expand Up @@ -373,12 +367,14 @@ class IssuesService extends Service {
/// API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue
Future<List<IssueLabel>> replaceLabelsForIssue(
RepositorySlug slug, int issueNumber, List<String> labels) {
return github
.request('PUT', '/repos/${slug.fullName}/issues/$issueNumber/labels',
body: GitHubJson.encode(labels))
.then((response) {
return jsonDecode(response.body).map(IssueLabel.fromJson);
});
return github.requestJson<List<dynamic>, List<IssueLabel>>(
'PUT',
'/repos/${slug.fullName}/issues/$issueNumber/labels',
statusCode: StatusCodes.OK,
body: GitHubJson.encode(labels),
convert: (input) =>
input.cast<Map<String, dynamic>>().map(IssueLabel.fromJson).toList(),
);
}

/// Removes a label for an issue.
Expand Down Expand Up @@ -457,8 +453,12 @@ class IssuesService extends Service {
} else {
body = '{}';
}
await github.postJSON('/repos/${slug.fullName}/issues/$number/lock',
body: body, statusCode: 204);
await github.request(
'PUT',
'/repos/${slug.fullName}/issues/$number/lock',
body: body,
statusCode: 204,
);
}

/// Unlock an issue.
Expand Down
Loading
Loading