通过Github API获取Github仓库中的所有文件名

59

是否可能使用GitHub API获取所有仓库中的文件名?

我目前尝试使用PyGithub来进行操作,但只要能够实现,我也完全可以手动进行请求。

我的算法如下:

  1. 获取用户仓库名称
  2. 获取符合特定描述的用户仓库
  3. ??? 获取仓库文件名?
5个回答

53
你可以使用 Github git trees https://api.github.com/repos/[USER]/[REPO]/git/trees/[BRANCH]?recursive=1 Repo https://github.com/deeja/bing-maps-loader Api Call https://api.github.com/repos/deeja/bing-maps-loader/git/trees/master?recursive=1 它会返回相应的结果
{
sha: "55382e87889ccb4c173bc99a42cc738358fc253a",
url: "https://api.github.com/repos/deeja/bing-maps-loader/git/trees/55382e87889ccb4c173bc99a42cc738358fc253a",
tree: [
{
path: "README.md",
mode: "100644",
type: "blob",
sha: "41ceefc1262bb80a25529342ee3ec2ec7add7063",
size: 3196,
url: "https://api.github.com/repos/deeja/bing-maps-loader/git/blobs/41ceefc1262bb80a25529342ee3ec2ec7add7063"
},
{
path: "index.js",
mode: "100644",
type: "blob",
sha: "a81c94f70d1ca2a0df02bae36eb2aa920c7fb20e",
size: 1581,
url: "https://api.github.com/repos/deeja/bing-maps-loader/git/blobs/a81c94f70d1ca2a0df02bae36eb2aa920c7fb20e"
},
{
path: "package.json",
mode: "100644",
type: "blob",
sha: "45f24dcb7a457b14fede4cb907e957600882b340",
size: 595,
url: "https://api.github.com/repos/deeja/bing-maps-loader/git/blobs/45f24dcb7a457b14fede4cb907e957600882b340"
}
],
truncated: false
}

52

这将需要相对于特定的提交,因为一些文件可能存在于某些提交中而不存在于其他提交中,因此在查看文件之前,您需要使用类似于列出存储库上的提交这样的内容:

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"
    }
  ]
}

正如您所看到的,我们有一些,它们对应于文件,以及一些额外的树,它们对应于子目录。您可能希望递归执行此操作


16
Repository Contents API也值得一看。它提供了熟悉的目录样式导航结构,展示目录和文件的树形结构。 - jasonrudolph
4
:sha 可以作为标签,就像 master 一样。 - Peter Krauss
似乎在列出拥有超过100,000个文件的目录时出现了问题;尝试下载整个存储库并在本地处理可能是一个选项:链接 - Xianxing

22

现在使用GraphQL API会更容易,您可以通过单个查询获取所有内容。

首先,获取您的代码库:

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

  }
}

然后获取它的defaultBranchRef以使操作更加简便

    defaultBranchRef{

    }

现在,分支引用实际上只是指向提交的指针,由于GraphQL是强类型的(而引用可能是不同的东西),因此我们需要让它知道这是一个提交。

   target{
      ...on Commit {

      }
   }

目标是我们引用指向的内容,如果它是一个提交(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
                                  }                                  
                                }
                              }
                            }   
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

10
如丹所提到的:Github trees
请参考以下的工作示例。
import requests

user = "grumbach"
repo = "ft_ping"

url = "https://api.github.com/repos/{}/{}/git/trees/master?recursive=1".format(user, repo)
r = requests.get(url)
res = r.json()

for file in res["tree"]:
    print(file["path"])

为了简单起见,我省略了错误处理,毕竟迅猛龙已经灭绝了...

有时候,你只需要一个简单的答案来解决问题。谢谢。 - Keet Sugathadasa

0

使用gh api进行身份验证的HTTP请求,访问GitHub API

一行代码实现
gh api -X GET /repos/octocat/Hello-World/commits | grep -E -o ".{0,0}\[{\"sha\":\".{0,40}" | sed 's/\[{\"sha\":\"//' | xargs -I {} gh api -X GET /repos/octocat/Hello-World/commits/{} | grep -E -o "\"filename\":\".*?\""

或者分为两步
获取提交的 SHA
gh api -X GET /repos/octocat/Hello-World/commits | grep -E -o ".{0,0}\[{\"sha\":\".{0,40}" | sed 's/\[{\"sha\":\"//' >> ~/commits
列出文件名
xargs < ~/commits -I {} gh api -X GET /repos/octocat/Hello-World/commits/{} | grep -E -o "\"filename\":\".*?\""

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接