2013-04-10 66 views
12

据我了解,消息与提交相关联。但是当你在GitHub上查看回购时,它会按照每个文件有助于列出消息,因为它最后一次被更改。在GitHub API上 - 获取与每个文件关联的上次提交消息的最佳方式是什么?

我想复制在回购我有一个Web视图。纵观GitHub的API,它看起来我得到这些信息的唯一途径是从最近期的分配承诺在您的本地缓存中的信息,将文件下载(可分页)所有的提交,工作,去更进一步,直到你得到每个文件的消息,可能是第一次提交,如果从最初提交以来没有任何文件被改变

问题是,是否是正确的方法来做到这一点?即使5000 /小时的配额也不会杀死吗?

+0

我不知道我完全理解你想达到什么。你想得到(1)一个文件的最新评论,不管这个评论与哪个提交相关联?或者你想获得(2)最新的评论文件的最新提交?不同之处在于文件可能在多次提交中都有关联的注释,并且最新的注释可能不在最新的提交中,因为有人可能会在之前的提交中对文件发表评论。那么,这些选项中的哪一个就是你想要的? – 2013-04-10 09:37:54

+0

我想要选项1,请:)正如它在GitHub本身的Web视图中显示的那样。 – 2013-04-10 15:11:15

+0

它在GitHub的Web视图中向您显示的内容?你能给我一个确切的URL作为例子吗?当你去GitHub上的一个项目站点时,它向你显示了这些文件的提交信息(例如,当你访问https://github.com/github/developer.github.com时的文件列表),而不是提交评论。提交消息和提交注释是两个不同的事情。如果我误解了你,我很抱歉,只是想澄清你确切需要什么。 :) – 2013-04-10 15:29:07

回答

26

好吧,搞清楚你需要的是最新的提交信息中的每个文件,这里是你可以做什么了。

首先,获取存储库中的文件列表。要做到这一点,你需要:

1)分支的要列出文件fetch the reference object

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)fetch the commit object的参考点,使用您在上一步中接收到的响应的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)在上一步中提取的提交对象的fetch the tree object。您将按照在上一步的响应中提供的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请求:

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

另一种方法是只有一个请求得到所有文件列表(所有文件夹中),使用recursive=1参数如here所述。我建议你使用这种方法,因为它只需要一个HTTP请求。

接下来,现在您已拥有回购库中的文件和文件夹列表,您将更改每个文件/文件夹get the last commit。要做到这一点,提出这一要求

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请求。好消息是,您可以缓存响应,以便在没有任何更改时无需发出请求(有关更多信息,请参阅here)。此外,您不会一次提取所有提交消息,您将在用户浏览文件夹时获取它们(就像在GitHub上单击文件夹一样)。因此,您应该能够轻松保持5000个请求的限制。

希望这会有所帮助!并让我知道如果你找到一个更简单的方法来做到这一点:)。我不知道是否只有1-2个请求才能实现这一点,这可能是您的预期。

+1

作为答案,因为它非常全面,谢谢。然而,这是对我希望避免的每个文件都进行最后一次提交的调用。我认为我要做的是做一个背景cron工作,每隔一段时间就会获得一些cron作业,限制它的速度。这不是关键信息,但它是有用的,我认为 – 2013-04-11 12:34:11

+0

@MarcosScriven谢谢!是的,我明白为什么这是你的问题。尽管如此,cron的工作理念听起来很酷。太好了! – 2013-04-11 13:09:26

+4

不错!如果你只是想要影响文件的最新提交,你可以使用分页来为你工作,就像'GET https://api.github.com/repos/izuzak/pmrpc/commits?path = examples&page = 1&per_page = 1' – novemberkilo 2013-11-29 16:43:17

2

我列出提交的库比抓住了第一个和阅读它的SHA和它的伟大工程:

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

在去它看起来是这样的:

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 
} 
0

为了寻找构建永久链接,我发现检索commit sha最简单的方法之一是实际解析html页面。

优点:

  • 在一个库中的所有文件/文件夹页有它,甚至根本
  • 单一HTTP调用
  • 没有身份验证的登录需要
  • 会使用正确的分支(一些别“T使用主默认)
  • 作品在树枝太

每个文件页面上都有一个叫做Permalink的链接。 如果您正在寻找方法来确定该链接 有类.js-permalink-shortcutdata-hotkey="y"属性,如Getting permanent links to files - 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)。

相关问题