2015-01-13 6 views
10

Ich versuche, commits für viele große Github Repos mit der API zu zählen, so möchte ich vermeiden, die gesamte Liste der Commits (auf diese Weise als Beispiel: api.github.com/repos/jashrudolph/keyboard/ commits) und zähle sie.Wie verwende ich GitHub V3 API, um Commit Count für ein Repo zu erhalten?

Wenn ich den Hash der ersten (Initial) Commit hätte, könnte ich use this technique to compare the first commit to the latest und es glücklich berichtet die total_commits dazwischen (so würde ich eine hinzufügen) auf diese Weise. Leider kann ich nicht sehen, wie man elegant das erste Festschreiben unter Verwendung der API erhält.

Die Base-Repo-URL gibt mir die created_at (diese URL ist ein Beispiel: api.github.com/repos/jashrudolph/keyboard), so dass ich einen reduzierten Commit-Satz erhalten konnte, indem ich die Commits bis zur Erstellung beschränkte Datum (diese URL ist ein Beispiel: api.github.com/repos/jasonrudolph/keyboard/commits?until=2013-03-30T16:01:43Z) und die früheste (die immer zuletzt?) oder vielleicht die mit ein leerer Elternteil (nicht sicher, ob gegabelte Projekte initiale Eltern-Commits haben).

Gibt es eine bessere Möglichkeit, den ersten Commit-Hash für ein Repo zu erhalten?

Besser noch, diese ganze Sache scheint für eine einfache Statistik verschachtelt, und ich frage mich, ob ich etwas verpasse. Gibt es bessere Ideen für die Verwendung der API zum Abrufen der Repo-Festschreibung?

Edit: Diese somewhat similar question versucht, nach bestimmten Dateien ("und in ihnen zu bestimmten Dateien.") Zu filtern, hat also eine andere Antwort.

+0

Mögliches Duplikat von [github api: Wie findet man effizient die Anzahl der Commits für ein Repository?] (Http://stackoverflow.com/questions/15919539/github-api-how-to-efficiently-find -die-commit-for-a-repository) –

+0

Nicht wirklich die gleiche Frage. Trotzdem danke! – SteveCoffman

Antwort

4

Sie können die Verwendung von GraphQL API v4 in Betracht ziehen, um die Anzahl von Festschreibungen für mehrere Repositorys gleichzeitig unter Verwendung von aliases durchzuführen. Im Folgenden wird Fetch Zählung für alle Zweige der 3 verschiedenen Repositories commit (bis zu 100 Filialen pro Repo):

{ 
    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 ein fragment ist, die die doppelten Abfragefelder für jeden von denen zu vermeiden hilft Repo

Wenn Sie nur Zählung auf dem Standard-Zweig verpflichten müssen, ist es einfacher:

{ 
    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

Wenn Sie nach der Gesamtzahl der Commits im Standardzweig suchen, sollten Sie einen anderen Ansatz in Betracht ziehen.

Mit dem Repo Teilnehmer API eine Liste aller Mitwirkenden holen:

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

Jedes Element in der Liste ein contributions Feld enthalten, die Ihnen sagt, wie viele der Benutzer im Default-Zweig Autor verpflichtet. Summiere diese Felder für alle Mitwirkenden und du solltest die Gesamtzahl der Commits in der Standard-Verzweigung erhalten.

Die Liste der Kontributoren ist oft viel kürzer als die Liste der Commits. Es sollten also weniger Requests benötigt werden, um die Gesamtzahl der Commits im Standardzweig zu berechnen.

+0

Danke. Als ich [einen solchen Link] (https://api.github.com/repos/jquery/jquery/contributors?anon=true) verwendete, schien es auf 30 Elemente beschränkt zu sein. Ich habe festgestellt, dass Anfragen, die mehrere Artikel zurückgeben, standardmäßig auf 30 Artikel paginiert werden. Sie können weitere Seiten mit dem Parameter '? Seite' angeben. Also, wenn Sie 30 bekommen, müssen Sie überprüfen, ob es mehr Seiten gibt, und sie zu den ersten Ergebnissen hinzufügen. – SteveCoffman

+0

@SteveCoffman Ja, das ist das erwartete Verhalten: https://developer.github.com/v3/#pagination –

+0

Es sieht aus wie einer der beiden Ansätze (deins und meins) sind lebensfähig, und keiner ist elegant. Ich werde deine als Antwort akzeptieren, es sei denn jemand anderes kommt auf etwas zurück, das wir beide übersehen haben. Vielen Dank. – SteveCoffman

3

Ich habe gerade ein kleines Skript dafür gemacht. Es funktioniert möglicherweise nicht mit großen Repositories, da es die Ratengrenzen von GitHub nicht behandelt. Außerdem benötigt es das Python requests Paket.

#!/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

Etwas geändert und jetzt zeigt der Code einen Fehler Zeile 36, in github_commit_counter: commit_store.append (commit ['sha']) ' – Whitecat

+0

Ich lag falsch. Das Skript funktioniert. Ich habe gerade meine Rate_limit getroffen. – Whitecat

0

Einfache Lösung: Schauen Sie sich die Seitenzahl an. Github paginiert für Sie. Sie können also einfach die Anzahl der Commits berechnen, indem Sie nur die letzte Seitennummer aus dem Link-Header abrufen, eine davon subtrahieren (Sie müssen die letzte Seite manuell addieren), die Seitengröße multiplizieren, die letzte Seite der Ergebnisse abrufen und die Größe dieses Arrays erhalten und die zwei Zahlen zusammenfügen. Es sind maximal zwei API-Aufrufe!

Hier ist meine Umsetzung der Gesamtzahl der Commits für eine gesamte Organisation packte den octokit Juwel in Ruby mit:

@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 

und ja, ich weiß, dass der Code verschmutzt ist, das nur zusammen in ein paar geworfen Protokoll.

Verwandte Themen