2013-01-19 30 views
9

我試圖使用GitHub v3 API獲取兩個SHA之間提交的完整列表,使用the comparison API/repos/:owner/:repo/compare/:base...:head),但它只返回前250個提交併且我需要得到他們所有人。GitHub v3 API:獲取完整的提交列表進行大量比較

我發現the API pagination docs,但比較API似乎並不支持任何的pageper_page參數,要麼計數或SHA值(編輯:在last_sha參數也不起作用)。與提交API不同,比較API似乎沒有返回Link HTTP標頭。

有沒有辦法增加比較API的提交計數限制或提取第二頁提交?

+3

我已經聯繫了GitHub支持。作爲一個API封裝的作者,我自己對此很好奇。如果他們不回答,我會回覆他們回答的問題。 –

+0

謝謝@ sigmavirus24! – etlovett

+1

是的,他們從來沒有回到我身邊......對不起 –

回答

0

嘗試使用last_sha參數。提交API似乎使用分頁而不是page

+0

不幸的是,提交比較API似乎忽略了last_sha參數;輸出是相同的,沒有它。 – etlovett

+0

不管用,現在'last_sha'已被廢棄。 – Nakedible

1

這是相對容易的。這裏有一個例子:

import requests 
next_url = 'https://api.github.com/repos/pydanny/django-admin2/commits' 
while next_url: 
    response = requests.get(next_url) 
    # DO something with response 
    # ... 
    # ... 
    if 'next' in response.links: 
     next_url = response.links['next']['url'] 
    else: 
     next_url = '' 

UPDATE:

takie記住,未來的URL比最初的前夫不一樣: 初始URL:

https://api.github.com/repos/pydanny/django-admin2/commits

下一個URL:

https://api.github.com/repositories/10054295/commits?top=develop&last_sha=eb204104bd40d2eaaf983a5a556e38dc9134f74e

所以它是全新的網址結構。

+2

感謝這個答案,Django Packages現在能夠恢復一堆在上次GitHub API更改後丟失的提交。謝謝@galuszkak! – pydanny

+0

謝謝@pydanny – galuszkak

+1

我會注意到這不是「相對容易」。關於如何工作,文檔還不太清楚。雖然實施「很簡單」,但在編程中遇到許多挑戰,但確定實施是很困難的。 – pydanny

0

來自:https://developer.github.com/v3/repos/commits/#working-with-large-comparisons

具有大的比較

響應工作將包括多達250所提交的比較。如果您正在使用更大的提交範圍,則可以使用提交列表API來枚舉範圍內的所有提交。

對於具有極大差異的比較,您可能會收到一個錯誤響應,指出差異花費太長的時間來生成。

https://api.github.com/repos/junit-team/junit/commits?sha=XXX,其中XXX是最後的SHA返回承諾在本輪查詢:您通常可以通過使用更小的承諾範圍

+1

實際上並沒有告訴你如何去做,因爲提交列表API的用法絕對不清楚! – Nakedible

2

嘗試使用參數sha,例如解決此錯誤。然後重複這個過程直到你到達結束SHA。

樣品Python代碼:

startSHA = '' 
endSHA = '' 
while True: 
    url = 'https://api.github.com/repos/junit-team/junit/commits?sha=' + startSHA 
    r = requests.get(url) 
    data = json.loads(r.text) 
    for i in range(len(data)): 
     commit = data[i]['sha'] 
     if commit == endSHA: 
      #reach the ending SHA, stop here 
     startSHA = commit 
+0

使用分頁更好。 Git歷史記錄可能包含只取最後一個sha只會跟隨合併的一個父代的合併。通過分頁,這不會發生,因爲所有父母的提交都會返回。 – Nakedible

1

我試圖再次解決這個。我的筆記:

  • 比較(或拉取請求提交)列表只顯示250個條目。對於拉取請求,您可以分頁,但無論您做什麼,您最多隻能獲得250次提交。

  • 提交列表API可以通過分頁遍歷整個提交鏈,直到存儲庫的開始。

  • 對於拉取請求,「基本」提交不一定在從拉取請求「頭」提交可到達的歷史記錄中。這是相同的比較,「base_commit」不一定是當前頭的歷史的一部分。

  • 然而,「merge_base_commit」是歷史的一部分,所以正確的方法是從「頭部」提交開始,迭代提交列表查詢,直到到達「merge_base_commit」。對於拉請求,這意味着必須分別在拉的「頭」和「底」之間進行比較。

  • 另一種方法是使用compare_by返回的「total_commits」,只是向後迭代,直到達到所需的提交數量。這似乎工作,但我並不是100%肯定,這是正確的所有角落案件與合併等。

所以,提交列表API,分頁和「merge_base_commit」解決了這個困境。

0

下面是一個示例來獲取所有提交對使用書面pull請求Octokit.NET(https://github.com/octokit/octokit.net

 var owner = "..."; 
     var repository = "..."; 
     var gitHubClient = new GitHubClient(
       new ProductHeaderValue("MyApp"), 
       new InMemoryCredentialStore(new Credentials("GitHubToken"))); 
     var pullRequest = await gitHubClient.PullRequest.Get(owner, repository, pullRequestNumber); 
     Console.WriteLine("Summarising Pull Request #{0} - {1}", pullRequest.Number, pullRequest.Title); 
     var commits = new List<GitHubCommit>(); 
     var moreToGet = true; 
     var headSha = pullRequest.Head.Sha; 
     while (moreToGet) 
     { 
      var comparison = 
       await 
       gitHubClient.Repository.Commits.Compare(
        owner, 
        repository, 
        pullRequest.Base.Sha, 
        headSha); 

      // Because we're working backwards from the head towards the base, but the oldest commits are at the start of the list 
      commits.InsertRange(0, comparison.Commits); 
      moreToGet = comparison.Commits.Count == 250; 
      if (moreToGet) 
      { 
       headSha = commits.First().Sha; 
      } 
     } 

我本來試圖使如果moreToGet設置爲true的與基地SHA犯被發現,但從未包括在提交的名單(不知道爲什麼),所以我只是承擔更多的得到,如果打的比較的250

0

極限/承諾?per_page = *您會得到所有提交

+0

這不起作用 – bert

0

這是我的解決方案使用Octokit.Net

private async Task<IReadOnlyList<GitHubCommit>> GetCommits(string branch, string baseBranch) 
{ 
    // compare branches and get all commits returned 
    var result = await this.gitHub.Repository.Commit.Compare(this.repoSettings.Owner, this.repoSettings.Name, baseBranch, branch); 
    var commits = result.Commits.ToList(); 

    // the commits property on the result only has the first 250 commits 
    if (result.TotalCommits > 250) 
    { 
     var baseCommitId = result.MergeBaseCommit.Sha; 
     var lastCommitLoadedId = commits.First().Sha; 
     var allCommitsLoaded = false; 
     var page = 1; 

     while (!allCommitsLoaded) 
     { 
      var missingCommits = await this.gitHub.Repository.Commit.GetAll(this.repoSettings.Owner, this.repoSettings.Name, new CommitRequest 
      { 
       Sha = lastCommitLoadedId // start from the oldest commit returned by compare 
      }, 
      new ApiOptions 
      { 
       PageCount = 1, 
       PageSize = 100, // arbitrary page size - not sure what the limit is here so set it to a reasonably large number 
       StartPage = page 
      }); 

      foreach (var missingCommit in missingCommits) 
      { 
       if (missingCommit.Sha == lastCommitLoadedId) 
       { 
        // this is the oldest commit in the compare result so we already have it 
        continue; 
       } 

       if (missingCommit.Sha == baseCommitId) 
       { 
        // we don't want to include this commit - its the most recent one on the base branch 
        // we've found all the commits now we can break out of both loops 
        allCommitsLoaded = true; 
        break; 
       } 

       commits.Add(missingCommit); 
      } 

      page++; 
     } 
    } 

    return commits; 
}