Получить все имена файлов из репозитория Github через API Github

Можно ли получить все имена файлов из репозитория с помощью API GitHub?

В настоящее время я пытаюсь исправить это с помощью PyGithub, но я полностью согласен с ручным выполнением запроса, пока он работает.

Мой алгоритм до сих пор:

  1. Получить имена пользователей репо
  2. Получите репозиторий пользователя, который соответствует определенному описанию
  3. ??? получить имена файлов репо?

Ответ 1

Это должно быть относительно конкретного коммита, так как некоторые файлы могут присутствовать в некоторых коммитах и ​​отсутствовать в других, поэтому, прежде чем вы сможете смотреть файлы, вам нужно использовать что-то вроде Список коммитов в репозитории:

GET /repos/:owner/:repo/commits

Если вас интересует последняя фиксация на ветке, вы можете установить для параметра sha имя ветки:

sha string SHA или ветка, чтобы начать перечисление коммитов из.

Как только у вас есть хеш фиксации, вы можете проверить, что зафиксировать

GET /repos/:owner/:repo/git/commits/:sha

который должен вернуть что-то вроде этого (усечен из документации GitHub):

{
  "sha": "...",
  "...",
  "tree": {
    "url": "https://api.github.com/repos/octocat/Hello-World/git/trees/691272480426f78a0138979dd3ce63b77f706feb",
    "sha": "691272480426f78a0138979dd3ce63b77f706feb"
  },
  "...": "..."
}

Посмотрите на хэш своего дерева, которое по сути является его содержимым каталога. В этом случае 691272480426f78a0138979dd3ce63b77f706feb. Теперь мы можем запросить содержимое этого дерева:

GET /repos/:owner/:repo/git/trees/:sha

Результат из примера GitHub -

{
  "sha": "9fb037999f264ba9a7fc6274d15fa3ae2ab98312",
  "url": "https://api.github.com/repos/octocat/Hello-World/trees/9fb037999f264ba9a7fc6274d15fa3ae2ab98312",
  "tree": [
    {
      "path": "file.rb",
      "mode": "100644",
      "type": "blob",
      "size": 30,
      "sha": "44b4fc6d56897b048c772eb4087f854f46256132",
      "url": "https://api.github.com/repos/octocat/Hello-World/git/blobs/44b4fc6d56897b048c772eb4087f854f46256132"
    },
    {
      "path": "subdir",
      "mode": "040000",
      "type": "tree",
      "sha": "f484d249c660418515fb01c2b9662073663c242e",
      "url": "https://api.github.com/repos/octocat/Hello-World/git/blobs/f484d249c660418515fb01c2b9662073663c242e"
    },
    {
      "path": "exec_file",
      "mode": "100755",
      "type": "blob",
      "size": 75,
      "sha": "45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
      "url": "https://api.github.com/repos/octocat/Hello-World/git/blobs/45b983be36b73c0788dc9cbcb76cbb80fc7bb057"
    }
  ]
}

Как вы можете видеть, у нас есть некоторые blob, которые соответствуют файлам и некоторым дополнительным деревьям, которые соответствуют подкаталогам. Вы можете сделать это рекурсивно.

Ответ 2

Теперь вы можете использовать API-интерфейс graphql, и все это можно получить одним запросом.

сначала вы получите репо:

query {
  repository(name: "MyRepo" owner: "mylogin"){

  }
}

тогда вы получите defaultBranchRef, чтобы упростить жизнь

    defaultBranchRef{

    }

Теперь все ссылки на ветки на самом деле - это просто указатель на коммит, и поскольку graphql строго типизирован (а ссылки могут быть разными), мы должны дать ему понять, что это коммит,

   target{
      ...on Commit {

      }
   }

поэтому цель - это то, на что указывает наш реф, и мы говорим: "если это коммит, сделайте это"

и что он должен делать? он должен получить самый последний коммит (так как он будет содержать самые последние файлы в репо)

так что для этого мы запрашиваем историю

        history(first: 1 until: "2019-10-08T00:00:00"){
            nodes{

            }
        }

теперь внутри nodes мы внутри нашего коммита и теперь мы можем видеть файлы, файлы в указателе коммитов на самом деле являются просто указателем на дерево, а в дереве есть только записи, которые могут быть объектами типа Tree или blob типа

.записи, представляющие файлы, называются BLOB-объектами, но поскольку мы ничего с ними не делаем, а перечисляем их имена, вам даже не нужно знать, что

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

       tree{
           entries {
             name
             object {
               ...on Tree{
                 entries{
                   name
                   object {
                      ...on Tree{
                        entries{
                          name
                        }
                      }
                   }
                 }
               }
             }
           } 
       }

теперь, чтобы сложить все вместе:

query{
  repository(owner: "MyLogin", name: "MyRepo") {
    defaultBranchRef {
      target {
        ... on Commit {
          history(first: 1 until: "2019-10-08T00:00:00") {
            nodes {
              tree {
                entries {
                  name
                  object {
                    ... on Tree {
                      entries {
                        name
                        object{
                          ...on Tree{
                            entries{
                              name
                              object{
                                ...on Tree{
                                  entries{
                                    name
                                  }                                  
                                }
                              }
                            }   
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}