В GitHub API - какой лучший способ получить последнее сообщение фиксации, связанное с каждым файлом?

Насколько я понимаю, сообщения связаны с фиксациями. Но когда вы смотрите на репо на GitHub, это полезно перечисляет сообщение по каждому файлу, когда оно было изменено последним.

Я хотел бы воспроизвести это в веб-обзоре репо, которое у меня есть. Глядя на GitHub api, мне кажется, что единственный способ получить эту информацию - загрузить все коммиты (которые могут быть выгружены) и работать с самыми последними, которые назначают сообщения фиксации файлам в вашем локальном кеше, идя дальше и далее, пока вы не получите сообщение для каждого файла, возможно, до самого первого фиксации, если какой-либо из файлов не был изменен с момента первоначальной фиксации

Вопрос в том, что это правильный способ сделать это? Разве это не собирается убивать даже 5000/час квоты?

Ответ 1

Хорошо, выяснив, что вам нужно последнее сообщение о фиксации для каждого файла, вот что вы можете сделать.

Сначала получите список файлов в вашем репозитории. Для этого вам необходимо:

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. Итак, вы должны выполнить другой запрос GET на url, который предоставляется в папке:

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

Альтернативный подход состоит в том, чтобы получить список всех файлов (во всех папках) только с одним запросом, используя параметр recursive=1, как описано . Я предлагаю вам использовать этот подход, поскольку для него требуется только один HTTP-запрос.

Далее, теперь, когда у вас есть список файлов и папок в репо, вы получите последнюю фиксацию, которая изменила каждый из файлов/папки. Для этого сделайте этот запрос

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, и вы должны просто посмотреть на первый объект в этом списке (поскольку вас интересует последнее коммита для файла) и получить свойство 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 запроса, что, вероятно, вы ожидали.

Ответ 2

Я перечисляю коммиты в репозитории и захватываю первый и читая его 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
}

Ответ 3

В поисках построения постоянных ссылок я нашел один из самых простых способов получить команду commit sha - фактически проанализировать страницу html.

Преимущества:

  • все файлы/папки в репозитории имеют его, даже root
  • один HTTP-вызов
  • не требуется авторизация auth
  • будет использовать правильную ветвь (некоторые не используют мастер по умолчанию)
  • работает также с ветвями.

На каждой странице файла есть ссылка под названием Permalink. Если вы ищете способы идентифицировать эту ссылку существует класс .js-permalink-shortcut, а также атрибут data-hotkey="y", как описано в Получение постоянных ссылок на файлы - Github.

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

Итак, в этом примере sha - a6f4038336ff41463ad527b4ff4fda45642ebc6d.

Обратите внимание: он всегда будет отображаться, даже если вы уже на этом коммите.

В случае, если кому-то нравится строить постоянную ссылку от него, хеш URL (например, ссылки на строки, такие как #L437-L441) необходимо сохранить (прилагается) вручную.