2015-01-13 12 views
10

APIを使用して多くの大きなgithub reposのコミットをカウントしようとしていますので、コミットのリスト全体を取得しないようにしています(api.github.com/repos/jasonrudolph/keyboard/)。コミット)し、それらを数えます。GitHub V3 APIを使ってレポのコミット数を取得するには?

最初の(最初の)コミットのハッシュがあれば、私はuse this technique to compare the first commit to the latestとすることができ、その間にtotal_commitsを報告することができます(追加する必要があります)。残念ながら、APIを使用して優雅に最初のコミットを取得する方法はわかりません。

ベースrepoのURLは私にcreated_atを与えます(このurlはapi.github.com/repos/jasonrudolph/keyboardの例です)。そのため、作成するまでコミットを制限してコミットを減らすことができました日付(このURLは例です:api.github.com/repos/jasonrudolph/keyboard/commits?until=2013-03-30T16:01:43Z)、最も古いもの(常に最後にリストされていますか?空の親(forkされたプロジェクトに初期の親コミットがあるかどうか不明)

レポの最初のコミットハッシュを取得するには、より良い方法はありますか?

さらに、この全部が簡単な統計のために畳み込まれているように見えますが、私は何か不足しているのだろうかと思います。 APIを使用してレポ・コミット・カウントを得るためのより良いアイデアはありますか?

編集:somewhat similar questionは、特定のファイル(「特定のファイル内のファイル」)にフィルタをかけようとしています。そのため、別の回答があります。

+0

[github api:リポジトリのコミット数を効率的に見つける方法](http://stackoverflow.com/questions/15919539/github-api-how-to-efficiently-find)リポジトリコミット数) –

+0

実際には同じ質問ではありません。しかし、ありがとう! – SteveCoffman

答えて

4

aliasesを使用して、GraphQL API v4を使用して、同時に複数のリポジトリのコミット数を実行することができます。

{ 
    gson: repository(owner: "google", name: "gson") { 
    ...RepoFragment 
    } 
    martian: repository(owner: "google", name: "martian") { 
    ...RepoFragment 
    } 
    keyboard: repository(owner: "jasonrudolph", name: "keyboard") { 
    ...RepoFragment 
    } 
} 

fragment RepoFragment on Repository { 
    name 
    refs(first: 100, refPrefix: "refs/heads/") { 
    edges { 
     node { 
     name 
     target { 
      ... on Commit { 
      id 
      history(first: 0) { 
       totalCount 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Try it in the explorer

RepoFragmentは、これらのそれぞれについて、重複クエリフィールドを避けるのに役立ちますfragmentである:以下は(レポあたり100の支店まで)3つの異なるリポジトリのすべての支店のカウントをコミットフェッチしますレポ

あなただけのデフォルト枝に数をコミットする必要がある場合は、それがより簡単です:

{ 
    gson: repository(owner: "google", name: "gson") { 
    ...RepoFragment 
    } 
    martian: repository(owner: "google", name: "martian") { 
    ...RepoFragment 
    } 
    keyboard: repository(owner: "jasonrudolph", name: "keyboard") { 
    ...RepoFragment 
    } 
} 

fragment RepoFragment on Repository { 
    name 
    defaultBranchRef { 
    name 
    target { 
     ... on Commit { 
     id 
     history(first: 0) { 
      totalCount 
     } 
     } 
    } 
    } 
} 

Try it in the explorer

4

デフォルトのブランチでコミットの総数を調べる場合は、別の方法を検討することができます。

全ての貢献者のリストを取得するためにレポの貢献者APIを使用してください:

https://developer.github.com/v3/repos/#list-contributors

各項目をリストでは、デフォルトのブランチで作成、ユーザーをコミット何を説明しますcontributionsフィールドが含まれます。これらのフィールドをすべてのコントリビュータで合計し、デフォルトのブランチでコミットの総数を取得する必要があります。

寄稿者のリストは、しばしばコミットのリストよりもはるかに短いので、デフォルトのブランチのコミットの総数を計算する要求が少なくてすみます。

+0

ありがとうございます。私は[このようなリンク](https://api.github.com/repos/jquery/jquery/contributors?anon=true)を使用したとき、30項目に制限されているようでした。複数のアイテムを返すリクエストは、デフォルトで30個のアイテムにページ番号が付けられます。 '?page'パラメータでさらにページを指定することができます。だから、もしあなたが30を得るなら、あなたはもっと多くのページがあるかどうかをチェックして、それらを最初の結果に加える必要があります。 – SteveCoffman

+0

@SteveCoffmanええと、これは予想される動作です:https://developer.github.com/v3/#pagination –

+0

2つのアプローチ(あなたと私の)のどちらかが実行可能で、どちらも優雅でないようです。他の誰かが私たちが見落としてしまったことがない限り、私はあなたを答えとして受け入れます。ありがとう。 – SteveCoffman

3

これを行うためのスクリプトを作成しました。 GitHubのレート制限を処理しないため、大きなリポジトリでは機能しない可能性があります。また、Python requestsパッケージが必要です。

#!/bin/env python3.4 
import requests 

GITHUB_API_BRANCHES = 'https://%(token)[email protected]/repos/%(namespace)s/%(repository)s/branches' 
GUTHUB_API_COMMITS = 'https://%(token)[email protected]/repos/%(namespace)s/%(repository)s/commits?sha=%(sha)s&page=%(page)i' 


def github_commit_counter(namespace, repository, access_token=''): 
    commit_store = list() 

    branches = requests.get(GITHUB_API_BRANCHES % { 
     'token': access_token, 
     'namespace': namespace, 
     'repository': repository, 
    }).json() 

    print('Branch'.ljust(47), 'Commits') 
    print('-' * 55) 

    for branch in branches: 
     page = 1 
     branch_commits = 0 

     while True: 
      commits = requests.get(GUTHUB_API_COMMITS % { 
       'token': access_token, 
       'namespace': namespace, 
       'repository': repository, 
       'sha': branch['name'], 
       'page': page 
      }).json() 

      page_commits = len(commits) 

      for commit in commits: 
       commit_store.append(commit['sha']) 

      branch_commits += page_commits 

      if page_commits == 0: 
       break 

      page += 1 

     print(branch['name'].ljust(45), str(branch_commits).rjust(9)) 

    commit_store = set(commit_store) 
    print('-' * 55) 
    print('Total'.ljust(42), str(len(commit_store)).rjust(12)) 

# for private repositories, get your own token from 
# https://github.com/settings/tokens 
# github_commit_counter('github', 'gitignore', access_token='fnkr:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') 
github_commit_counter('github', 'gitignore') 
+0

何か変更されました。コードはgithub_commit_counterでエラー '行36を表示しています:commit_store.append(commit ['sha']) ' – Whitecat

+0

私は間違っていました。スクリプトは動作します。私はちょうど私のrate_limitに当たった。 – Whitecat

0

単純な解決策:ページ番号を見てください。 Githubはあなたのためにページを貼り付けます。そのため、リンクヘッダーから最後のページ番号を取得し、最後のページを手動で追加する必要があります)、ページサイズを掛けて、結果の最後のページを取得して、コミット数を簡単に計算できます。その配列のサイズを取得し、2つの数値を加算します。これは最大2つのAPI呼び出しです。ここで

はルビーでoctokit宝石を使用して組織全体のコミットの合計数をつかんで私の実装です:私はコードが汚れている知っている

@github = Octokit::Client.new access_token: key, auto_traversal: true, per_page: 100 

Octokit.auto_paginate = true 
repos = @github.org_repos('my_company', per_page: 100) 

# * take the pagination number 
# * get the last page 
# * see how many items are on it 
# * multiply the number of pages - 1 by the page size 
# * and add the two together. Boom. Commit count in 2 api calls 
def calc_total_commits(repos) 
    total_sum_commits = 0 

    repos.each do |e| 
     repo = Octokit::Repository.from_url(e.url) 
     number_of_commits_in_first_page = @github.commits(repo).size 
     repo_sum = 0 
     if number_of_commits_in_first_page >= 100 
      links = @github.last_response.rels 

      unless links.empty? 
       last_page_url = links[:last].href 

       /.*page=(?<page_num>\d+)/ =~ last_page_url 
       repo_sum += (page_num.to_i - 1) * 100 # we add the last page manually 
       repo_sum += links[:last].get.data.size 
      end 
     else 
      repo_sum += number_of_commits_in_first_page 
     end 
     puts "Commits for #{e.name} : #{repo_sum}" 
     total_sum_commits += repo_sum 
    end 
    puts "TOTAL COMMITS #{total_sum_commits}" 
end 

はい、これはほんの数で一緒に投げられました分。

関連する問題