如何提取Stash或Bitbucket中所有仓库的列表?

13

我需要提取Bitbucket中所有项目下的所有存储库列表。是否有相应的REST API可用?我找不到相关的API。

我同时使用本地和云上的Bitbucket。


请提供您使用的是Bitbucket Cloud还是自托管版本。 - Harmelodic
我有两个实例,一个在云端,另一个在本地。 - Jeel
@Jeel 这个答案解决了你的问题吗?https://dev59.com/F1oV5IYBdhLWcg3wkfe9#67988810 - jlo
7个回答

9

克隆给定stash url的所有项目和存储库

    #!/usr/bin/python
    # 
    # @author Jason LeMonier
    #
    # Clone ALL Projects & Repositories for a given stash url
    #
    # Loop through all projects: [P1, P2, ...]
    #    P1 > for each project make a directory with the key "P1"
    #    Then clone every repository inside of directory P1
    #    Backup a directory, create P2, ... 
    # 
    # Added ACTION_FLAG bit so the same logic can run fetch --all on every repository and/or clone.

    import sys
    import os
    import stashy

    ACTION_FLAG = 1     # Bit: +1=Clone, +2=fetch --all 

    url  = os.environ["STASH_URL"]  # "https://mystash.com/stash"
    user = os.environ["STASH_USER"] # joedoe"
    pwd  = os.environ["STASH_PWD"]  # Yay123

    stash = stashy.connect(url, user, pwd)

    def mkdir(xdir):
        if not os.path.exists(xdir):
            os.makedirs(xdir)

    def run_cmd(cmd):
        print ("Directory cwd: %s "%(os.getcwd() ))
        print ("Running Command: \n    %s " %(cmd))
        os.system(cmd)

    start_dir = os.getcwd()

    for project in stash.projects:
        pk = project_key = project["key"]
        mkdir(pk) 
        os.chdir(pk)

        for repo in stash.projects[project_key].repos.list():
            for url in repo["links"]["clone"]:
                href = url["href"]
                repo_dir = href.split("/")[-1].split(".")[0]

                if (url["name"] == "http"):
                    print ("        url.href: %s"% href)  # https://joedoe@mystash.com/stash/scm/app/ae.git
                    print ("Directory cwd: %s Project: %s"%(os.getcwd(), pk))

                    if ACTION_FLAG & 1 > 0:
                        if not os.path.exists(repo_dir):
                            run_cmd("git clone %s" % url["href"])
                        else:
                            print ("Directory: %s/%s exists already.  Skipping clone. "%(os.getcwd(), repo_dir))

                    if ACTION_FLAG & 2 > 0:
                        # chdir into directory "ae" based on url of this repo, fetch, chdir back
                        cur_dir = os.getcwd()
                        os.chdir(repo_dir)
                        run_cmd("git fetch --all ")
                        os.chdir(cur_dir)

                    break

        os.chdir(start_dir) # avoiding ".." in case of incorrect git directories

6
这很酷,将来我可能会使用它。但是它没有回答问题:“如何列出Bitbucket中的所有代码库?”克隆所有代码库以获取列表将是极其耗时且低效的空间占用。 - Br.Bill

7
一旦登录:在右上角点击您的个人头像,然后选择“查看个人资料”。

enter image description here

2. 注意你的用户(在下面的示例中为'YourEmail@domain.com',但请记住它是区分大小写的)

enter image description here

点击个人资料图片 > 管理账户 > 个人访问令牌 > 创建令牌(选择“读取”访问类型即可满足此功能)
对于所有项目:
打开命令行界面并使用以下命令(记得填写你的服务器域名!):
curl -u "YourEmail@domain.com" -X GET https://<my_server_domain>/rest/api/1.0/projects/?limit=1000

对于给定项目中的所有存储库:
4. 选择您想要获取存储库的项目。在我的情况下,项目URL是:<your_server_domain>/projects/TECH/,因此我的{projectKey}是'TECH',您需要在下面的命令中使用它。
5. 打开CLI并使用以下命令(记得填写您的服务器域和项目密钥!):
它会要求您提供个人访问令牌,您遵守并获得一个包含所有请求的存储库的JSON文件。
curl -u "YourEmail@domain.com" -X GET https://<my_server_domain>/rest/api/1.0/projects/{projectKey}/repos?limit=50

最后的修饰

  1. (可选) 如果你只想要所请求的仓库标题,并且你已经安装了jq(对于Windows系统,下载exe文件并将其添加到PATH路径应该就足够了,但你需要重新启动命令行界面才能检测到这个新的添加),你可以使用以下命令:
curl -u $BBUSER -X GET <my_server_domain>/rest/api/1.0/projects/TECH/repos?limit=50 | jq '.values|.[]|.name'

(在Data Center/Atlassian Bitbucket v7.9.0和powershell CLI上进行了测试)

我遇到了这个错误:Bitbucket Cloud 最近停止支持账户密码进行 API 认证。 请查看我们的社区帖子获取更多细节:https://atlassian.community/t5/x/x/ba-p/1948231 对于大多数使用情况,建议使用应用程序密码,并可在「个人设置」中创建: https://bitbucket.org/account/settings/app-passwords/ 有关 API 认证方法的更多详细信息,请参阅我们的文档: https://developer.atlassian.com/cloud/bitbucket/rest/intro/#authentication - Christopher Marlowe

4

对于Bitbucket Cloud

您可以使用他们的REST API来访问并查询您的服务器。

具体而言,您可以使用Atlassian提供的这个文档页面,了解如何列出您的存储库。


对于Bitbucket Server

编辑:在收到Dan Bennett的推文后,我了解到Bitbucket Server有一个API/plugin系统,可能适合您的需求。有关文档,请参见此处

编辑2:找到此参考资料,可用于列出个人存储库。

据我所知,除非您为自己构建一个与Bitbucket Server实例交互的小型API,否则您无法解决问题。

Atlassian文档确实指出,要列出所有当前配置的存储库,可以执行git remote -v。然而,我对此持怀疑态度,因为这不是git remote -v通常的用法;我认为更可能是Atlassian的文档不够清晰,而不是Atlassian在Bitbucket Server中构建了这个功能。


对于 BitBucket Server:我遇到了 404 错误,请求的 URL /rest/api/1.0/projects/ 在此服务器上未找到。以下是我的请求: http://<user>:<password>@BaseURL/rest/api/1.0/projects/ - Jeel
我也没有收到所声称的结果。当我使用这个API命令时,我会收到一个HTML文档的文本,这个文档实际上是一个通用的 Bitbucket 页面模板,里面只包含指向其他 Bitbucket 页面的链接,没有提到任何关于 repos 的信息或者其他有用信息。 - Br.Bill

1
我最终不得不自己使用Bitbucket的本地安装来完成此操作,似乎上述讨论的REST API无法访问,因此我想出了一个简短的脚本来从网页中抓取它。这种解决方法的优点是您无需安装任何东西,也不需要担心依赖项、证书或登录,只需登录您的Bitbucket服务器即可。如果您对脚本进行urlencode并在其前缀中添加javascript:,还可以将其设置为书签。
要使用此功能:
  1. 打开您的Bitbucket服务器项目页面,您应该会看到一个存储库列表。
  2. 打开浏览器的devtools控制台。这通常是F12ctrl-shift-i
  3. 将以下内容粘贴到命令提示符中。
JSON.stringify(Array.from(document.querySelectorAll('[data-repository-id]')).map(aTag => {
  const href = aTag.getAttribute('href');
  let projName = href.match(/\/projects\/(.+)\/repos/)[1].toLowerCase();
  let repoName = href.match(/\/repos\/(.+)\/browse/)[1];
  repoName = repoName.replace(' ', '-');
  const templ = `https://${location.host}/scm/${projName}/${repoName}.git`;
  return {
    href,
    name: aTag.innerText,
    clone: templ
  }
}));

结果是一个JSON字符串,其中包含一个由仓库URL、名称和克隆URL组成的数组。
[{
  "href": "/projects/FOO/repos/some-repo-here/browse",
  "name": "some-repo-here",
  "clone": "https://mybitbucket.company.com/scm/foo/some-repo-here.git"
}]

整洁的技巧,但似乎并没有获取到我所有的存储库... 可能是 HTML 稍微有所改变。 - Erik
我得到了一个空数组。你的代码需要改变。 - Christopher Marlowe

0
我解决这个问题的方法是获取HTML页面并设置一个荒谬的限制,例如在Python中:
 cmd = "curl -s  -k --user " +  username +  " https://URL/projects/<KEY_PROJECT_NAME>/?limit\=10000"

然后我用BeautifulSoup解析了它

make_list = str((subprocess.check_output(cmd, shell=True)).rstrip().decode("utf-8"))
  html = make_list 
  parsed_html = BeautifulSoup(html,'html.parser')
list1 = [] 
  for a in parsed_html.find_all("a", href=re.compile("/<projects>/<KEY_PROJECT_NAME>/repos/")):
    list1.append(a.string)
print(list1)

使用前请确保更改 <bitbucket_project> 和 <html_file>,这应该是您要定位的Bitbucket项目。我所做的只是解析一个HTML文件。


0

以下是我如何从Bitbucket Cloud中获取存储库列表的方法。

设置OAauth Consumer

进入您的工作区设置并设置OAuth Consumer,您可以直接使用此链接: https://bitbucket.org/{your_workspace}/workspace/settings/api

唯一重要的设置是回调URL,它可以是任何内容,但我选择了http://localhost

设置完成后,这将显示一个密钥和密钥对,用于您的OAuth Consumer,我将在下面称之为{oauth_key}{oauth_secret}

通过API进行身份验证

转到https://bitbucket.org/site/oauth2/authorize?client_id={oauth_key}&response_type=code,确保您替换{oauth_key}

这将重定向您到类似于http://localhost/?code=xxxxxxxxxxxxxxxxxx的页面,请记下该代码,我将在下面称之为{oauth_code}

在您的终端中输入以下命令:curl -X POST -u "{oauth_key}:{oauth_secret}" https://bitbucket.org/site/oauth2/access_token -d grant_type=authorization_code -d code={oauth_code},替换占位符。

这将返回包括access_token在内的json数据,我将称之为{oauth_token}

获取存储库列表

现在您可以运行以下命令来获取存储库列表。请注意,您的{oauth_token}默认有效期为2小时。

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/repositories/pageant?page=1' \
  --header 'Authorization: Bearer {oauth_token}' \
  --header 'Accept: application/json'

这个响应是分页的,所以您需要一页一页地浏览响应,每次浏览10个存储库。


欢迎来到Stack Overflow。我看到您在两个不同的位置发布了完全相同的答案(参考)。请注意这一点。如果完全相同的答案可以解决两个问题,您应该考虑这些问题是否彼此重复;如果是这样,那么较不有用的问题版本应被标记为更有用的版本的副本。或者,如果它们不是重复的,您应该自定义答案以解决每个问题的特定方面。 - Jeremy Caney

0

这个 Ruby 脚本并不是最好的代码,因为我也不是最好的程序员。但它很清晰、经过测试,并且能够正常工作。

该脚本过滤了 Bitbucket API 调用的输出,以创建一个完整的报告,其中包含 Bitbucket 服务器上所有存储库的项目、总计和子总计、每个存储库的链接以及存储库是公共的还是私人的。我本可以简化它以供一般使用,但它现在已经非常有用了。

没有命令行参数,只需运行即可。

#!/usr/bin/ruby
#
# @author Bill Cernansky
#
# List and count all repos on a Bitbucket server, arranged by project, to STDOUT.
#
require 'json'

bbserver   = 'http(s)://server.domain.com'
bbuser     = 'username'
bbpassword = 'password'
bbmaxrepos = 2000       # Increase if you have more than 2000 repos

reposRaw = JSON.parse(`curl -s -u '#{bbuser}':'#{bbpassword}' -X GET #{bbserver}/rest/api/1.0/repos?limit=#{bbmaxrepos}`)

projects = {}

repoCount = reposRaw['values'].count

reposRaw['values'].each do |r|
    projID = r['project']['key']
    if projects[projID].nil?
        projects[projID] = {}
        projects[projID]['name'] = r['project']['name']
        projects[projID]['repos'] = {}
    end
    repoName = r['name']
    projects[projID]['repos'][repoName] = r['links']['clone'][0]['href']
end

privateProjCount = projects.keys.grep(/^\~/).count
publicProjCount = projects.keys.count - privateProjCount

reportText = ''
privateRepoCount = 0
projects.keys.sort.each do |p|
    # Personal project slugs always start with tilde
    isPrivate = p[0] == '~'
    projRepoCount = projects[p]['repos'].keys.count
    privateRepoCount += projRepoCount if isPrivate
    reportText += "\nProject: #{p} : #{projects[p]['name']}\n  #{projRepoCount} #{isPrivate ? 'PERSONAL' : 'Public'} repositories\n"

    projects[p]['repos'].keys.each do |r|
        reportText += sprintf("    %-30s : %s\n", r, projects[p]['repos'][r])
    end
end

puts "BITBUCKET REPO REPORT\n\n"
puts sprintf("  Total Projects: %5d     Public: %5d    Personal: %5d", projects.keys.count, publicProjCount, privateProjCount)
puts sprintf("  Total Repos:    %5d     Public: %5d    Personal: %5d", repoCount, repoCount - privateRepoCount, privateRepoCount)
puts reportText

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