【问题标题】:How can I get branch count on a repository via GitHub API?如何通过 GitHub API 获取存储库的分支计数?
【发布时间】:2019-12-26 05:27:14
【问题描述】:

我是working on a UI,它列出了给定用户或组织的所有存储库。这是使用树形格式,其中第一级是存储库,第二级层次结构(子节点)是每个分支,如果展开的话。

我正在使用一种机制,它故意不要求我提取给定 repo 的所有分支的列表,因为 API 对 API 调用有速率限制。相反,我所要做的就是指示它包含多少个子节点,而不是实际为它们分配值(直到用户展开它的那一刻)。我几乎可以肯定,获取 repos 列表会在结果中包含分支计数,但令我失望的是,我没有看到它。我只能看到分叉、观星者、观察者、问题等的计数。除了分支计数之外的所有内容。

UI 的目的是它会提前知道填充子节点的分支数量,但直到 用户展开父节点后才真正获取它们 - 因此立即显示 每个分支的空占位符,然后异步加载要填充的实际分支。同样,因为我需要避免过多的 API 调用。当用户滚动时,它将使用分页只获取它需要向用户显示的页面,并保持缓存以供以后显示。

具体来说,我使用的是 Delphi 的 Virtual TreeView:

procedure TfrmMain.LstInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
  var ChildCount: Cardinal);
var
  L: Integer;
  R: TGitHubRepo;
begin
  L:= Lst.GetNodeLevel(Node);
  case L of
    0: begin
      //TODO: Return number of branches...
      R:= TGitHubRepo(Lst.GetNodeData(Node));
      ChildCount:= R.I['branch_count']; //TODO: There is no such thing!!!
    end;
    1: ChildCount:= 0; //Branches have no further child nodes
  end;
end;

我是否缺少某些东西,可以让我获得 repo 分支计数,而无需预先获取所有这些分支的完整列表?

【问题讨论】:

  • 如果您在速率限制方面遇到问题,请考虑实施Conditional Requests,这样重复查询就不会计入您的限制。
  • 我从未想过要考虑的一件事是,实际上每个存储库都至少有一个分支。因此,我总是可以显示 [+] 来扩展任何 repo,只有这样它才会关心获取任何东西。那时,我可以使用分页来加载所有分支,甚至可能一次加载所有分支。扩展一个的成本可能很高,但至少我不需要提前知道总数。我首先需要知道的原因是我知道是否要在任何东西上加上 [+] 扩展器。但是因为所有的都会有一个默认的分支,所以他们都会有一个。

标签: github github-api


【解决方案1】:

您可以改用新的GraphQL API。这使您可以根据需要定制查询和结果。您可以在一个查询中完成这两项操作,而不是先获取计数然后再填写分支。

试试Query Explorer

query {
  repository(owner: "octocat", name: "Hello-World") {
    refs(first: 100, refPrefix:"refs/heads/") {
      totalCount
      nodes {
        name
      }
    },
    pullRequests(states:[OPEN]) {
        totalCount
    }
  }
}
{
  "data": {
    "repository": {
      "refs": {
        "totalCount": 3,
        "nodes": [
          {
            "name": "master"
          },
          {
            "name": "octocat-patch-1"
          },
          {
            "name": "test"
          }
        ]
      },
      "pullRequests": {
        "totalCount": 192
      }
    }
  }
}

Pagination 使用游标完成。首先你得到第一页,一次最多 100 页,但为了简洁起见,我们在这里只使用 2 页。响应将包含一个唯一的光标。

{
  repository(owner: "octocat", name: "Hello-World") {
    pullRequests(first:2, states: [OPEN]) {
      edges {
        node {
          title
        }
        cursor
      }
    }
  }
}
{
  "data": {
    "repository": {
      "pullRequests": {
        "edges": [
          {
            "node": {
              "title": "Update README"
            },
            "cursor": "Y3Vyc29yOnYyOpHOABRYHg=="
          },
          {
            "node": {
              "title": "Just a pull request test"
            },
            "cursor": "Y3Vyc29yOnYyOpHOABR2bQ=="
          }
        ]
      }
    }
  }
}

然后您可以在光标后请求更多元素。这将获得接下来的 2 个元素。

{
  repository(owner: "octocat", name: "Hello-World") {
    pullRequests(first:2, after: "Y3Vyc29yOnYyOpHOABR2bQ==", states: [OPEN]) {
      edges {
        node {
          title
        }
        cursor
      }
    }
  }
}

Queries can be written like functions and passed arguments。参数以单独的 JSON 格式发送。这允许查询是一个简单的不变字符串。

这个查询和以前做的一样。

query NextPullRequestPage($pullRequestCursor:String) {
  repository(owner: "octocat", name: "Hello-World") {
    pullRequests(first:2, after: $pullRequestCursor, states: [OPEN]) {
      edges {
        node {
          title
        }
        cursor
      }
    }
  }
}

{
  "pullRequestCursor": "Y3Vyc29yOnYyOpHOABR2bQ=="
}

{ "pullRequestCursor": null } 将获取第一页。


它的rate limit calculations 比 REST API 更复杂。您每小时可获得 5000 积分,而不是每小时通话。每个查询花费一定数量的点数,大致对应于 Github 计算结果的成本。您可以通过询问其rateLimit 信息来了解查询的成本。如果你通过 dryRun: true 它只会告诉你成本而不运行查询。

{
  rateLimit(dryRun:true) {
    limit
    cost
    remaining
    resetAt
  }
  repository(owner: "octocat", name: "Hello-World") {
    refs(first: 100, refPrefix: "refs/heads/") {
      totalCount
      nodes {
        name
      }
    }
    pullRequests(states: [OPEN]) {
      totalCount
    }
  }
}
{
  "data": {
    "rateLimit": {
      "limit": 5000,
      "cost": 1,
      "remaining": 4979,
      "resetAt": "2019-08-21T05:13:56Z"
    }
  }
}

这个查询只需要一分。我还剩 4979 点,我将在 05:13 UTC 重置我的速率限制。

GraphQL API 非常灵活。您应该能够使用更少的 Github 资源和更少的编程来解决速率限制。

【讨论】:

  • 如果我以后能够对速率限制进行编辑,我会再给它第二次投票。不幸的是,我已经在晚上喝了 6 号啤酒,明天晚上可能会再喝。我以前见过并使用过 GraphQL,但从未真正使用过它,也从未在 Delphi 中使用过它。但这似乎很简单,可以融入我正在做的事情中。尤其是为了摆脱我永远不需要的 90% 的 repo URL 垃圾。
  • 顺便说一句,我很好奇分页是如何使用 GraphQL 工作的。我见过一些包含数百个分支的存储库,但 GitHub 将每个页面的最大资源限制为 100 个,显然即使在使用 GraphQL 时也是如此......
  • @JerryDodge 我在同一条船上......啤酒少了。这是我第一次真正玩它。我添加了关于分页等的信息。
  • 您的示例正在使用拉取请求,但这不是我感兴趣的。我正在使用分支,它的工作方式似乎完全不同。我尝试将cursor 添加到请求中的不同相关级别,但无济于事。现在我变成了一个“光标”……
  • @JerryDodge 它的工作原理与 pullRequests 相同。 refs(first: 2, refPrefix:"refs/heads/") { edges { cursor { node { name } } } }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多