使用特定的提交哈希从 Github 获取许可证 link

Get license link from Github with specific commit hash

我有一个 table(作为 Pandas DF)(主要是)github 回购,我需要自动提取许可证 link。但是,要求 link 不只是简单地转到 /blob/master/,而是实际指向特定的提交,因为主 link 可能会在某个时候更新。我组装了一个 Python 脚本来通过 github API 执行此操作,但是使用 API 我只能使用 master 标签检索 link 。

即而不是
https://github.com/jsdom/abab/blob/master/LICENSE.md
我要
https://github.com/jsdom/abab/blob/8abc2aa5b1378e59d61dee1face7341a155d5805/LICENSE.md

知道是否有办法自动获取 link 文件的最新提交,在本例中为 LICENSE 文件?

这是我到目前为止编写的代码:

def githubcrawl(repo_url, session, headers):
    parts = repo_url.split("/")[3:]
    url_tmpl = "http://api.github.com/repos/{}/license"
    url = url_tmpl.format("/".join(parts))
    try:
        response = session.get(url, headers=headers)
        if response.status_code in [404]:
            return(f"404: {repo_url}")
        else:
            data = json.loads(response.text)
            return(data["html_url"]) # Returns the html URL to LICENSE file
    except urllib.error.HTTPError as e:
        print(repo_url, "-", e)
        return f"http_error: {repo_url}"

token="mytoken" # Token for github authentication to get more requests per hour
headers={"Authorization": "token %s" % token}

session = requests.Session()
lizlinks = [] # List to store the links of the LICENSE files in

# iterate over DataFrame of applications/deps
for idx, row in df.iterrows():
#    if idx < 5:
        if type(row["Homepage"]) == type("str"):
            repo_url = re.sub(r"\#readme", "", row["Homepage"])
            response = session.get(repo_url, headers=headers) 
            repo_url = response.url # Some URLs are just redirects, so I get the actual repo url here
            if "github" in repo_url and len(repo_url.split("/")) >= 3:
                link = githubcrawl(repo_url, session, headers)
                print(link)
                lizlinks.append(link)
            else:
                print(row["Homepage"], "Not a github Repo")
                lizlinks.append("Not a github repo")
        else:
            print(row["Homepage"], "Not a github Repo")
            lizlinks.append("Not a github repo")

奖金问题:并行化此任务是否与 Github-API 一起工作? IE。我可以一次发送多个请求而不会被锁定 (DoS) 还是 for-loop 是避免这种情况的好方法?浏览我在该列表中的 1000 个回购协议需要相当长的时间。

好的,我找到了一种获取当前提交的唯一 SHA 哈希的方法。我相信应该总是 link 到那个时间点的许可证文件。

使用 python git 库,我只需 运行 ls_remote git 命令和 return HEAD sha

def lsremote_HEAD(url):
    g = git.cmd.Git()
    HEAD_sha = g.ls_remote(url).split()[0]
    return HEAD_sha

然后我可以替换我的 github_crawl 函数中的“master”、“main”或任何标签:

token="token_string"
headers={"Authorization": "token %s" % token}
session = requests.Session()
def githubcrawl(repo_url, session, headers):
    parts = repo_url.split("/")[3:]
    api_url_tmpl = "http://api.github.com/repos/{}/license"
    api_url = api_url_tmpl.format("/".join(parts))
    try:
        print(api_url)
        response = session.get(api_url, headers=headers)
        if response.status_code in [404]:
            return(f"404: {repo_url}")
        else:
            data = json.loads(response.text)
            commit_link = re.sub(r"/blob/.+?/",rf"/blob/{lsremote_HEAD(repo_url)}/", data["html_url"])
            return(commit_link)
    except urllib.error.HTTPError as e:
        print(repo_url, "-", e)
        return f"http_error: {repo_url}"

也许这对某人有帮助,所以我在这里发布这个答案。

此答案使用以下库:

import re
import git
import urllib
import json
import requests