【问题标题】:Bitbucket clone all team repositoriesBitbucket 克隆所有团队存储库
【发布时间】:2017-03-18 16:43:39
【问题描述】:

我想使用 bash 脚本和 http 克隆我的所有 bitbucket 团队存储库。我发现了一些使用 Bitbucket api 的示例,但是它们似乎都没有返回任何存储库。有任何想法吗?使用 mac。

【问题讨论】:

  • 您是否通过了身份验证?您认证的用户是否有权访问团队存储库?如果不是,我建议您设置一个具有足够权限的应用程序密码(bitbucket.org/account/user/<YOUR_USERNAME>/app-passwords)(对帐户/团队成员/项目/存储库的读取权限应该涵盖您需要的大部分内容)。

标签: git macos bitbucket


【解决方案1】:

这是我的简单解决方案。制作文件downloader.sh

#!/bin/bash

USER=${1}
TEAM=${2}

rm -rf "$TEAM" && mkdir "$TEAM" && cd $TEAM

NEXT_URL="https://api.bitbucket.org/2.0/repositories/${TEAM}?pagelen=100"

while [ ! -z $NEXT_URL ] && [ $NEXT_URL != "null" ]
do
    curl -u $USER $NEXT_URL > repoinfo.json
    jq -r '.values[] | .links.clone[1].href' repoinfo.json > ../repos.txt
    NEXT_URL=`jq -r '.next' repoinfo.json`

    for repo in `cat ../repos.txt`
    do
        echo "Cloning" $repo
        if echo "$repo" | grep -q ".git"; then
            command="git"
        else
            command="hg"
        fi
        $command clone $repo
    done
done

cd ..

您可以通过以下方式运行它:

sh downloader.sh username teamname # or username instead team name

【讨论】:

  • 警告:每 100 个 repos 会要求你输入密码
  • @chillappreciator 不使用 http 协议。使用 git@ 协议和 ssh 密钥。
  • 这很好用,但是当 bitbucket 的 repos 少于 100 个时,在下载所有 repos 后,比如只有 6 个,脚本再次要求我输入密码,如果我输入密码,脚本将 删除所有以前下载的文件夹(当然我可以按Ctrl-C,一切都会好起来的)。我尝试设置 pagelen=2 并且此行为不再发生。
  • 我上面评论的解决方案:更改 while 循环以检查 $NEXT_URL != "null" ...... while [ ! -z $NEXT_URL ] && [ $NEXT_URL != "null" ]
【解决方案2】:

确保您在 bitbucket 中设置了 ssh 密钥,并通过手动克隆一个 repo 来安装 git:

这将克隆您拥有的所有存储库:

USER=bitbucket_username; curl --user ${USER} https://api.bitbucket.org/2.0/repositories/${USER} | grep -o '"ssh:[^ ,]\+' | xargs -L1 git clone

要备份您的团队存储库,请使用相同的脚本,但硬编码您的 bitbucket 团队名称,如下所示:

USER=bitbucket_username; curl --user ${USER} https://api.bitbucket.org/2.0/repositories/TEAMNAME | grep -o '"ssh:[^ ,]\+' | xargs -L1 git clone

这是better way

curl -u ${1} https://api.bitbucket.org/1.0/users/TEAMNAME > repoinfo

for repo_name in `cat repoinfo | sed -r 's/("name": )/\n\1/g' | sed -r 's/"name": "(.*)"/\1/' | sed -e 's/{//' | cut -f1 -d\" | tr '\n' ' '`
do
    echo "Cloning " $repo_name
    git clone git@bitbucket.org:TEAMNAME/$repo_name.git
    echo "---"
done

【讨论】:

  • 仅适用于那些可能试图使用它的人。确保ssh: 是您存储库的正确签名。对我来说是git:。像这样看:USER=myUserName; curl --user ${USER} https://api.bitbucket.org/2.0/repositories/THETEAM | grep -o '"git@[^ ,]\+' | xargs -L1 git clone
  • 在我的mac中我下载了gsed并在代码中用gsed替换了sed
【解决方案3】:

使用jq 的另一种选择。

#!/bin/bash

user=username:password

curl -u $user 'https://api.bitbucket.org/2.0/user/permissions/teams?pagelen=100' > teams.json

jq -r '.values[] | .team.username' teams.json > teams.txt

for team in `cat teams.txt`
do
  echo $team

  rm -rf "${team}"

  mkdir "${team}"

  cd "${team}"

  url="https://api.bitbucket.org/2.0/repositories/${team}?pagelen=100"

  echo $url

  curl -u $user $url > repoinfo.json

  jq -r '.values[] | .links.clone[0].href' repoinfo.json > repos.txt

  for repo in `cat repos.txt`
  do
    echo "Cloning" $repo
    git clone $repo
  done

  cd ..

done

【讨论】:

  • 我无法让它与 username:password 一起使用,但它与 --netrc-file 一起使用效果很好。不确定是否每次都删除整个团队目录...可能更好地引入新的更改,但为此更新脚本并非易事。
【解决方案4】:

如果您的存储库少于 100 个,您只能使用简单的命令并将“pagelen=100”添加到查询中,因为这是 bitbucket API 一次报告的最多次数。如果您有超过 100 个存储库,则需要处理返回的 JSON 中的“下一个”链接,以获取查询下一组存储库的 URL,使用脚本会更容易。

如果您使用 http 而不是 ssh 进行克隆,那么您需要输入受保护存储库的密码,或者获取 bitbucket 应用程序密码并修改 URL 以将其插入其中,因此它们看起来像:

https://bitbucketuserhere:apppasswordhere@bitbucket.org/teamorusername/repositoryname.git

此外,克隆不会获取所有版本的 git LFS 文件,因此请注意这一点。根据 bitbucket,使用 'git lfs fetch --all' 将所有 LFS 文件版本复制到本地。

要获取您的个人存储库列表,请使用如下 URL:

https://api.bitbucket.org/2.0/repositories/BITBUCKETUSERNAME?pagelen=100

要获取您的团队仓库列表,请使用这样的 URL 来获取您所属的所有仓库的列表:

https://api.bitbucket.org/2.0/repositories/TEAMNAME?pagelen=100&role=member

以下是一个示例 perl 脚本,您可以使用它来克隆并维护存储库的副本,使用 http 而不是 ssh 来获取。它使 --mirror 克隆而不是完全填充的工作副本(非常适合移动或灾难恢复)。它备份所有 LFS 文件。

#!/usr/bin/env perl

use warnings;
use strict;
use JSON::Parse 'parse_json';

# CONFIGURATION:
# Bitbucket team or user name to get list of repositories from
my $teamORuserName = "myteam";

# Bitbucket app password with access to query the API for the
# list of repositories. Format: "user-name:app-token"
my $appPassword= "frank-james:LAYDxtc8H6FGKUZeHEef";

#------------------------------------------------------------------------------

my $nextPageLink = "https://api.bitbucket.org/2.0/repositories/$teamORuserName?pagelen=100&role=member";
while (defined $nextPageLink)
{
    $nextPageLink =~ m/page=(\d+)/;
    print "Fetching page " . ($1 || 1). "\n";
    my $response = `curl -q --silent --request GET --user '$appPassword' '$nextPageLink'`;
    my $json = parse_json($response);
    my $values = $json->{values};

    foreach my $repo (@$values)
    {
        die "'$repo->{name}' is not a 'git' repo: $repo->{scm}" unless $repo->{scm} eq "git";
        my $links = $repo->{links} || die "no links data for '$repo->{name}'";
        my $clones = $links->{clone} || die "no clone data for '$repo->{name}'";
        my $url = $clones->[0]->{href} || die "no clone url found for $repo->{name}";

        # use uuid as directory name, to survive project name changes
        my $uuid = $repo->{uuid}; $uuid =~ s/[\{\}]//g;
        if (not -e $uuid)
        {
            print "cloning '$repo->{name}' into $uuid\n";
            # replace user name with token to avoid password prompts
            $url =~ s|(https?://).+(\@bitbucket.org)|$1$appPassword$2|;
            system("git clone --progress --mirror '$url' $uuid") == 0 or die "clone failed";
            # make a human friendly link to current repository name
            symlink $uuid, $repo->{slug} or warn "symlink failed: $!";
        }
        else
        {
            print "updating '$repo->{name}' in $uuid\n";
            system("cd $uuid && git fetch --all --tags --prune") == 0 or die "fetch failed";
        }
        print "\n";
    }

    $nextPageLink = $json->{next};
}
exit 0;

【讨论】:

    【解决方案5】:

    这是一个 python 脚本,用于在 bitbucket 中克隆所有团队或用户的存储库。由于团队存储库通常是私有的,因此我在使用 bitbucket API 时处理了这一点。因此,只需输入您的 bitbucket 用户名、密码和团队的用户名,它就会为您克隆所有团队存储库。

    import subprocess
    import json
    
    cmd = "curl -u <bitbucket_username>:<bitbucket_password>  https://api.bitbucket.org/2.0/repositories/<team_name_or_project_name>"
    cmd = cmd.split()
    
    while 1:
        from_api = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        from_api = from_api.communicate()
        json_from_api = json.loads(from_api[0])
        for unit_dict in json_from_api["values"]:
            clone_cmd = "git clone " + unit_dict["links"]["clone"][1]["href"]
            clone_cmd = clone_cmd.split()
            clone_out = subprocess.call(clone_cmd, shell=False)
        if "next" not in json_from_api:
            break
        else:
            cmd[-1] = json_from_api["next"]
    

    【讨论】:

      【解决方案6】:

      这是一个节点脚本,用于下载 bitbucket 帐户中的所有存储库。请不要忘记添加必要的 npm 包。

      const argv = require('yargs').argv
      const request = require('request');
      const nodegit = require('nodegit');
      
      let repos = [];
      let opts = {
          fetchOpts: {
              callbacks: {
                  credentials: function() {
                      return nodegit.Cred.userpassPlaintextNew(argv.username, argv.password);
                  },
                  certificateCheck: function() {
                      return 1;
                  }
              }
          }
      };
      
      function cloneRepository(index) {
          let repo = repos[index];
          console.log('Cloning ' + repo.full_name);
          nodegit.Clone(repo.links.clone[0].href, 'repositories/' + repo.full_name, opts)
          .then(function(repo) {
              if (repos.length - 1 == index) {
                  console.log("All repositories cloned");
              } else {
                  cloneRepository(index + 1);
              }
          })
          .catch(function(err) {
              if (err) {
                  console.log(err);
              }
          });
      }
      
      function loadRepositories(url) {
          request.get(url, {
              'auth': {
                  'user': argv.username,
                  'pass': argv.password
              }
          }, function (err, response, body) {
              if (err) return console.log(err);
              let data = JSON.parse(body);
              for (var i = 0; i < data.values.length; i++) {
                  repos.push(data.values[i]);
              }
              if (data.next){
                  loadRepositories(data.next);    
              } else if (repos.length > 0) {
                  console.log('Started cloning..');
                  cloneRepository(0);
              } else {
                  console.log("No repositories found");
              }
          });
      }
      
      if (argv.username && argv.password) {
          console.log('Loading all repositories..');
          loadRepositories('https://api.bitbucket.org/2.0/repositories/?role=member');
      } else {
          console.log('Please specify both the --username and --password options');
      }
      

      您还可以查看此 GitHub 存储库。 Bitbucket Repository Downloader

      【讨论】:

      • OP 要求 bash。这看起来不像 BASH 代码。
      • @StephenRauch,Eric 已经为 bash 脚本提供了答案。我的回答可能对其他一些正在寻找 nodejs 实现的人有用。
      【解决方案7】:

      在@eric-nord 的answer 的基础上,我将sed 替换为jq 以获取repo slug(考虑到bitbucket 输出json,我发现它更简单)。

      因此,如果您的存储库少于 100 个,并且您希望为特定项目克隆存储库,那么下面的 shell 脚本应该可以解决问题。

      #!/usr/bin/env sh
      
      if [ $# -eq 0 ] || [ "$1" == "-?" ] || [ "$1" == "--help" ] || [ "$1" == "-h" ]
        then
          echo "Usage: `basename $0` <URL> <USERNAME> <PROJECTNAME>"
          echo "e.g. `basename $0` bitbucket_url some_user some_project"
          exit 1
      fi
      
      curl -u ${2} https://${1}/rest/api/1.0/projects/${3}/repos?limit=100 > repos.json
      
      for repo_name in `cat repos.json | jq -r '.values[] .slug'`
      do
        echo "cloning" $repo_name
        git clone https://${2}@${1}/scm/${3}/$repo_name.git ./${3}/$repo_name
      done
      

      【讨论】:

        【解决方案8】:

        这在 Python 中对我有用:

        import subprocess
        import json
        import cookielib
        import urllib2
        import base64
        
        def _create_opener(proxy=None):
            cj = cookielib.LWPCookieJar()
            cookie_handler = urllib2.HTTPCookieProcessor(cj)
            if proxy:
                proxy_handler = urllib2.ProxyHandler(proxy)
                opener = urllib2.build_opener(cookie_handler, proxy_handler)
            else:
                opener = urllib2.build_opener(cookie_handler)
            return opener
        
        def get_repos(_opener, _auth, user, password, team_username, paging):
            query_url = 'https://bitbucket.org/!api/2.0/repositories/'+team_username+paging
            try:
                req = urllib2.Request(query_url, None, {"Authorization": _auth })
                handler = _opener.open(req)
            except urllib2.HTTPError, e:
                print e.headers
                raise e
            for unit_dict in json.load(handler)["values"]:
                clone_cmd = "git clone " + unit_dict["links"]["clone"][0]["href"].replace('https://'+user,'https://'+password+':'+password)
                clone_cmd = clone_cmd.split()
                clone_out = subprocess.call(clone_cmd, shell=False)
        encodedstring = base64.encodestring("%s:%s" % (user, password))[:-1]
        _auth = "Basic %s" % encodedstring
        _opener = _create_opener()
        get_repos(_opener,_auth,'bitbucket-user','bitbucket-password','team-username','pagelen=100&page=1')
        

        代码来源:thisthis

        【讨论】:

        • 您使用哪个 Python 版本?它在 Python3.7 中出现错误 - 我看到很多这些库都在 Python2 中,但此时 Python3 应该是未来使用的版本(只是我的看法)。
        【解决方案9】:

        我在 rust 中构建了一个 CLI,用于并发克隆和拉取 git 存储库(用户和项目)。 https://github.com/jensim/bitbucket_server_cli 它适用于交互模式或批处理模式,具有 shell 完成功能并能够记住交互模式下的选择,从而获得更快的用户体验。

        对于像你这样的 mac 用户:

        $> brew install jensim/bitbucket_server_cli/bitbucket_server_cli
        
        $> bitbucket_server_cli clone
        
        BitBucket server address: http://localhost
        BitBucket username: jensim
        ✔ BitBucket password · ********
        Clone/update all projects yes
        Fetching users [00:00:15] [########################################] 2011/2011 (eta:0s)
        Fetching projects [00:00:00] [########################################] 35/35 (eta:0s)
        Working repos [00:01:07] [########################################] 1337/1337 (eta:0s)
        

        免责声明: 这是相当实验性的,因此据我所知,目前它主要由 mac 人员使用。但是 Github Releases 上有可用的 windows 和 debian 二进制文件。此外,这同时工作,可配置数量的同时 http 请求/git 克隆,以免杀死您的 CI 管道

        【讨论】:

          【解决方案10】:

          这是一个通过 https 下载的 Bash 脚本。

          保存到文件download_bitbucket_repos.shchmod +x download_bitbucket_repos.sh 然后./download_bitbucket_repos.sh

          #!/bin/bash
          
          USER='yourBitBucketUsername' #not email
          PASS='yourPassword'
          TEAM='teamNameInBitbucket'
          
          curl -u $USER:$PASS https://api.bitbucket.org/1.0/users/$TEAM > repoinfo
          
          for repo_name in `cat repoinfo | sed -r 's/("name": )/\n\1/g' | sed -r 's/"name": "(.*)"/\1/' | sed -e 's/{//' | cut -f1 -d\" | tr '\n' ' '`
          do
              echo "Cloning " $repo_name
              git clone https://$USER@bitbucket.org/$TEAM/$repo_name.git
              echo "---"
          done
          

          【讨论】:

            【解决方案11】:

            我在这里提供了一个简单的脚本:https://github.com/mimo84/cloner 它的工作原理与 Nikolai 的答案类似,但是它使用 bitbucket 上的 api 来获取它们。它也有 jq 作为依赖项。

            用法: 下载它(也许正在做git clone https://github.com/mimo84/cloner.git) 那么

            chmod +x ./bitbucket.sh
            
            ./bitbucket.sh username:password
            

            它将在当前目录上方创建一个名为“bitbucket_repos”的新文件夹,并在其中克隆您的所有存储库。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-05-01
              • 2014-04-25
              • 1970-01-01
              • 2019-12-26
              • 1970-01-01
              • 2017-03-25
              • 1970-01-01
              • 2020-01-14
              相关资源
              最近更新 更多