# 使用说明:# 使用 SSH 协议前,确保已将 SSH 公钥添加到 Gitee 账户# ssh 方式: python gitall.py --token YOUR_TOKEN --user YOUR_USER_NAME# https 方式: python gitall.py --token YOUR_TOKEN --user YOUR_USER_NAME --protocol httpsimport osimport jsonimport requestsimport subprocessimport argparsefrom urllib.parse import urlparsedef main():# 参数解析parser = argparse.ArgumentParser(description='批量下载 Gitee 所有仓库')parser.add_argument('--token', required=True, help='Gitee 访问令牌')parser.add_argument('--user', required=True, help='Gitee 用户名')parser.add_argument('--output', default='./', help='保存目录(默认为当前目录)')parser.add_argument('--protocol', choices=['ssh', 'https'], default='ssh', help='克隆协议(默认ssh)')parser.add_argument('--depth', type=int, default=0, help='克隆深度(0表示完整克隆)')args = parser.parse_args()# 创建保存目录save_dir = os.path.abspath(args.output)os.makedirs(save_dir, exist_ok=True)print(f"仓库将保存到: {save_dir}")# API 配置base_url = "https://gitee.com/api/v5"headers = {"Authorization": f"token {args.token}"}page = 1per_page = 100 # 每页最大100条total_repos = 0cloned_count = 0skipped_count = 0failed_repos = []print(f"\n开始获取 {args.user} 的仓库列表...")try:while True:# 获取仓库数据url = f"{base_url}/users/{args.user}/repos?page={page}&per_page={per_page}"response = requests.get(url, headers=headers)# 检查响应状态if response.status_code != 200:print(f"错误: API 请求失败 (状态码 {response.status_code})")print(f"响应内容: {response.text[:200]}...")breakrepos = response.json()# 检查是否为空响应if not repos:print("\n已获取所有仓库列表")breaktotal_repos += len(repos)print(f"第 {page} 页: 获取到 {len(repos)} 个仓库")# 处理每个仓库for repo in repos:repo_name = repo['name']owner_name = repo['owner']['login']repo_path = os.path.join(save_dir, owner_name, repo_name)# 选择克隆URLif args.protocol == 'https':clone_url = repo['clone_url']# 在HTTPS URL中嵌入token用于认证parsed = urlparse(clone_url)clone_url = f"{parsed.scheme}://{args.user}:{args.token}@{parsed.netloc}{parsed.path}"else:clone_url = repo['ssh_url']# 检查仓库是否存在if os.path.exists(os.path.join(repo_path, '.git')):print(f"✓ {repo_name} 已存在,跳过")skipped_count += 1continue# 创建目录os.makedirs(os.path.dirname(repo_path), exist_ok=True)# 构建克隆命令cmd = ['git', 'clone']if args.depth > 0:cmd.extend(['--depth', str(args.depth)])cmd.extend([clone_url, repo_path])print(f"\n▶ 正在克隆: {repo_name} ({clone_url})")# 执行克隆try:result = subprocess.run(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True,check=True)print(result.stdout)cloned_count += 1except subprocess.CalledProcessError as e:print(f"克隆失败: {e.output}")failed_repos.append({'name': repo_name,'url': clone_url,'error': e.output.strip()[:100]})page += 1# 输出总结print("\n" + "="*50)print(f"操作完成! 共处理 {total_repos} 个仓库")print(f"✓ 成功克隆: {cloned_count}")print(f"↻ 跳过已存在: {skipped_count}")print(f"✗ 失败: {len(failed_repos)}")if failed_repos:print("\n失败的仓库:")for repo in failed_repos:print(f" - {repo['name']}: {repo['error']}")print(f"\n所有仓库已保存到: {save_dir}")except KeyboardInterrupt:print("\n操作已取消")except Exception as e:print(f"\n发生未预期错误: {str(e)}")if __name__ == "__main__":main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。