web-dev-qa-db-ja.com

GitHub APIの場合-各ファイルに関連付けられている最後のコミットメッセージを取得するための最良の方法は何ですか?

私が理解している限り、メッセージはコミットに関連付けられています。ただし、GitHubのリポジトリを見ると、最後に変更された日時について、各ファイルごとにメッセージが表示されます。

私が持っているレポのウェブビューでそれを複製したいと思います。 GitHub APIを見ると、その情報を取得する唯一の方法は、コミット(ページング可能)をダウンロードすべてし、から作業することです。ローカルキャッシュ内のファイルにコミットメッセージを割り当てている最新のもの。最初のファイルのいずれかが変更されていない場合は、すべてのファイルのメッセージが表示されるまで、場合によっては最初のコミットまで、さらに遡ります。コミット

質問は、それを行う正しい方法ですか?それは5000 /時の割り当てさえ殺すつもりはありませんか?

17
Marcos Scriven

さて、必要なのは各ファイルの最新のコミットメッセージであることがわかった後、次のことができます。

まず、リポジトリ内のファイルのリストを取得します。これを行うには、次のことを行う必要があります。

1) 参照オブジェクトをフェッチする ファイルを一覧表示するブランチの:

GET https://api.github.com/repos/:owner/:repo/git/refs/heads/:branch

おそらくマスターブランチが必要なので、これはあなたが行うリクエストの例です:

https://api.github.com/repos/izuzak/pmrpc/git/refs/heads/master

取得する応答は次のようになります。

{
  "ref": "refs/heads/master",
  "url": "https://api.github.com/repos/izuzak/pmrpc/git/refs/heads/master",
  "object": {
    "sha": "fd6973f430a3367ad718ff049f1b075843913d6f",
    "type": "commit",
    "url": "https://api.github.com/repos/izuzak/pmrpc/git/commits/fd6973f430a3367ad718ff049f1b075843913d6f"
  }
}

2) コミットオブジェクトをフェッチ 前の手順で受け取った応答のobject.urlプロパティを使用して、参照が指す:

GET https://api.github.com/repos/izuzak/pmrpc/git/commits/fd6973f430a3367ad718ff049f1b075843913d6f

取得する応答は次のようになります。

{
  "sha": "fd6973f430a3367ad718ff049f1b075843913d6f",
  "url": "https://api.github.com/repos/izuzak/pmrpc/git/commits/fd6973f430a3367ad718ff049f1b075843913d6f",
  "html_url": "https://github.com/izuzak/pmrpc/commits/fd6973f430a3367ad718ff049f1b075843913d6f",
  "author": {
    "name": "Ivan Zuzak",
    "email": "[email protected]",
    "date": "2013-04-09T08:55:45Z"
  },
  "committer": {
    "name": "Ivan Zuzak",
    "email": "[email protected]",
    "date": "2013-04-09T08:55:45Z"
  },
  "tree": {
    "sha": "f5f5de80f67dd794ffbd4abb855fb7d1a573660e",
    "url": "https://api.github.com/repos/izuzak/pmrpc/git/trees/f5f5de80f67dd794ffbd4abb855fb7d1a573660e"
  },
  "message": "fix typos",
  "parents": [
    {
      "sha": "d3617ae56dda793131e743b2ff394984bbab6ca3",
      "url": "https://api.github.com/repos/izuzak/pmrpc/git/commits/d3617ae56dda793131e743b2ff394984bbab6ca3",
      "html_url": "https://github.com/izuzak/pmrpc/commits/d3617ae56dda793131e743b2ff394984bbab6ca3"
    }
  ]
}

3) ツリーオブジェクトをフェッチする 前のステップでフェッチされたコミットオブジェクトの。これを行うには、前の手順の応答で提供されたtree.urlリンクをたどります。

GET https://api.github.com/repos/izuzak/pmrpc/git/trees/f5f5de80f67dd794ffbd4abb855fb7d1a573660e

応答は次のようになります。

{
  "sha": "f5f5de80f67dd794ffbd4abb855fb7d1a573660e",
  "url": "https://api.github.com/repos/izuzak/pmrpc/git/trees/f5f5de80f67dd794ffbd4abb855fb7d1a573660e",
  "tree": [
    {
      "mode": "100644",
      "type": "blob",
      "sha": "726f21a4adec8c24c2fab6cf5b455d094a8b21bf",
      "path": "LICENSE.markdown",
      "size": 568,
      "url": "https://api.github.com/repos/izuzak/pmrpc/git/blobs/726f21a4adec8c24c2fab6cf5b455d094a8b21bf"
    },
    {
      "mode": "100644",
      "type": "blob",
      "sha": "eb94760b81441b34a73d1b085d9f153ae48b0e63",
      "path": "README.markdown",
      "size": 5772,
      "url": "https://api.github.com/repos/izuzak/pmrpc/git/blobs/eb94760b81441b34a73d1b085d9f153ae48b0e63"
    },
    {
      "mode": "040000",
      "type": "tree",
      "sha": "2e72b217b8644ce6874cda03387a7ab2d8eee55e",
      "path": "examples",
      "url": "https://api.github.com/repos/izuzak/pmrpc/git/trees/2e72b217b8644ce6874cda03387a7ab2d8eee55e"
    },
    {
      "mode": "100644",
      "type": "blob",
      "sha": "64b0dbe4981759c0f9640c8e882c97c7324fc798",
      "path": "pmrpc.js",
      "size": 24546,
      "url": "https://api.github.com/repos/izuzak/pmrpc/git/blobs/64b0dbe4981759c0f9640c8e882c97c7324fc798"
    }
  ]
}

これらは、リポジトリ内のすべてのファイルとフォルダです。ただし、フォルダの場合、フォルダ内のファイルのリストを取得するには、フォルダツリーオブジェクトを再帰的にフェッチする必要があることに注意してください。上記の応答では、examplesは、typeプロパティのツリー値で確認できるフォルダーです。したがって、フォルダで提供されているURLで別のGETリクエストを実行します。

  GET https://api.github.com/repos/izuzak/pmrpc/git/trees/2e72b217b8644ce6874cda03387a7ab2d8eee55e

別のアプローチは、説明されているように、recursive=1パラメーターを使用して、1つのリクエストですべてのファイル(すべてのフォルダー内)のリストを取得することです。 ここ 。必要なHTTPリクエストは1つだけなので、このアプローチを使用することをお勧めします。

次に、リポジトリにファイルとフォルダーのリストができたので、 最後のコミットを取得 各ファイル/フォルダーを変更します。これを行うには、このリクエストを行います

GET https://api.github.com/repos/:user/:repo/commits?path=FILE_OR_FOLDER_PATH

したがって、たとえば、これは上記のexamplesフォルダーのコミットをフェッチする要求です。

GET https://api.github.com/repos/izuzak/pmrpc/commits?path=examples

取得する応答はコミットオブジェクトのリストです。(ファイルの最後のコミットに関心があるため)そのリストの最初のオブジェクトを確認し、commit.messageプロパティを取得してメッセージを取得する必要があります。必要なもの:

[
  {
    "sha": "3437f015257683a86e3b973b3279754df9ac2b24",
    "commit": {
      "author": { ... },
      "committer": { ... },
      "message": "change mode",
      "tree": { ... },
      "url": "https://api.github.com/repos/izuzak/pmrpc/git/commits/3437f015257683a86e3b973b3279754df9ac2b24",
      "comment_count": 0
    },
    ...
  },
  {
    ...
  }
]

この場合、フォルダexamplesを変更した最新のコミットのメッセージは「変更モード」です。

したがって、基本的には、ファイルのリストをフェッチするために3つのHTTPリクエストを作成し、次にファイルとフォルダーごとに1つのHTTPリクエストを作成する必要があります。悪いニュースは、ファイルがたくさんある場合、HTTPリクエストをたくさん行うことになるということです。良いニュースは、何も変更されていない場合にリクエストを行う必要がないように、応答をキャッシュできることです(詳細については、 ここ を参照してください)。また、すべてのコミットメッセージを一度にフェッチするのではなく、ユーザーがフォルダーをナビゲートするときにそれらをフェッチします(GitHubでフォルダーをクリックするのと同じように)。したがって、5000リクエストの制限内に簡単にとどまることができるはずです。

お役に立てれば!そして、これを行うためのより簡単な方法を見つけたら私に知らせてください:)。たった1〜2回のリクエストでこれを達成する方法があるかどうかはわかりませんが、おそらくあなたが期待していたことです。

33
Ivan Zuzak

私はリポジトリにコミットをリストしていて、最初のコミットを取得してそれを読むよりもSHAで、うまく機能します:

https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository

Goでは、次のようになります。

func GetLatestCommit(owner, repo string, sgc *github.Client) (string, error) {
    commits, res, err := sgc.Repositories.ListCommits(owner, repo, &github.CommitsListOptions{})

    if err != nil {
        log.Printf("err: %s res: %s", err, res)
        return "", err
    }

    log.Printf("last commit: %s", *commits[0].SHA)

    return *commits[0].SHA, nil
}
2
tpiha

永続的なリンクを構築するために、コミットを取得する最も簡単な方法の1つは、実際にhtmlページを解析することです。

利点:

  • リポジトリ内のすべてのファイル/フォルダページには、ルートも含めてそれがあります
  • 単一のHTTP呼び出し
  • 認証ログインは必要ありません
  • 正しいブランチを使用します(デフォルトとしてマスターを使用しないものもあります)
  • 枝にも働きます

すべてのファイルページにPermalinkというリンクがあります。そのリンクを識別する方法を探している場合は、 ファイルへの永続的なリンクの取得-Github で説明されているように、クラス.js-permalink-shortcutdata-hotkey="y"属性があります。

<a href="/luckydonald/JavaPipBoyServer/blob/a6f4038336ff41463ad527b4ff4fda45642ebc6d/PROTOCOL.md" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a>

したがって、この例では、shaはa6f4038336ff41463ad527b4ff4fda45642ebc6dです。

すでにコミットしている場合でも、常にレンダリングされることに注意してください。

誰かがそれからパーマリンクを構築したい場合は、URLハッシュ(例: #L437-L441 などの行参照)を手動で保持(追加)する必要があります。

0
luckydonald