blob: b1622724efa7531ec5f71ad6b20e85b5c14fa0d5 [file] [log] [blame]
// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert' show json;
import 'package:github/github.dart';
import 'package:http/http.dart';
class GithubService {
const GithubService(this.github);
final GitHub github;
/// Lists commits of the provided repository [slug] and [branch]. When
/// [lastCommitTimestampMills] equals 0, it means a new release branch is
/// found and only the branched commit will be returned for now, though the
/// rare case that multiple commits exist. For other cases, it returns all
/// newer commits since [lastCommitTimestampMills].
Future<List<RepositoryCommit>> listCommits(
RepositorySlug slug, String branch, int lastCommitTimestampMills) async {
ArgumentError.checkNotNull(slug);
final PaginationHelper paginationHelper = PaginationHelper(github);
/// The [pages] defines the number of pages of returned http request
/// results. Return only one page when this is a new branch. Otherwise
/// it will return all commits prior to this release branch commit,
/// leading to heavy workload.
int pages;
if (lastCommitTimestampMills == 0) {
pages = 1;
}
List<Map<String, dynamic>> commits = <Map<String, dynamic>>[];
/// [lastCommitTimestamp+1] excludes last commit itself.
/// Github api url: https://developer.github.com/v3/repos/commits/#list-commits
await for (Response response in paginationHelper.fetchStreamed(
'GET',
'/repos/${slug.fullName}/commits',
params: <String, dynamic>{
'sha': branch,
'since':
DateTime.fromMillisecondsSinceEpoch(lastCommitTimestampMills + 1)
.toUtc()
.toIso8601String(),
},
pages: pages,
)) {
commits.addAll((json.decode(response.body) as List<dynamic>)
.cast<Map<String, dynamic>>());
}
/// When a release branch is first detected only the most recent commit would be needed.
///
/// If for the worst case, a new release branch consists of a useful cherry pick commit
/// which should be considered as well, here is the todo.
// TODO(keyonghan): https://github.com/flutter/flutter/issues/59275
if (lastCommitTimestampMills == 0) {
commits = commits.take(1).toList();
}
return commits.map((dynamic commit) {
return RepositoryCommit()
..sha = commit['sha'] as String
..author = (User()
..login = commit['author']['login'] as String
..avatarUrl = commit['author']['avatar_url'] as String)
..commit = (GitCommit()
..committer = (GitCommitUser(
commit['commit']['author']['name'] as String,
commit['commit']['author']['email'] as String,
DateTime.parse(commit['commit']['author']['date'] as String))));
}).toList();
}
Future<List<PullRequest>> listPullRequests(
RepositorySlug slug, String branch) async {
ArgumentError.checkNotNull(slug);
final PaginationHelper paginationHelper = PaginationHelper(github);
final List<Map<String, dynamic>> pullRequests = <Map<String, dynamic>>[];
await for (Response response in paginationHelper.fetchStreamed(
'GET',
'/repos/${slug.fullName}/pulls',
params: <String, dynamic>{
'base': branch,
'direction': 'desc',
'sort': 'created',
'state': 'open',
},
)) {
pullRequests.addAll((json.decode(response.body) as List<dynamic>)
.cast<Map<String, dynamic>>());
}
return pullRequests.map((dynamic commit) {
return PullRequest()
..number = commit['number'] as int
..head = (PullRequestHead()..sha = commit['head']['sha'] as String);
}).toList();
}
}