Skip to content

Instantly share code, notes, and snippets.

@yunazuno
Last active December 22, 2015 04:49
Show Gist options
  • Save yunazuno/6419552 to your computer and use it in GitHub Desktop.
Save yunazuno/6419552 to your computer and use it in GitHub Desktop.
Backup own bitbucket repositories to the specific directory
#!/usr/bin/env python3
"""
Backup own bitbucket repositories to the specific directory
Usage: backup-bitbucket-repository.py USERNAME BACKUP_TARGET_DIR
"""
import urllib.request
import keyring
import json
import os
import subprocess
AUTH_USERNAME = ""
BACKUP_BASE = ""
API_BASE_URI = "https://api.bitbucket.org"
AUTH_REALM = "Bitbucket.org API"
def build_opener(realm: str, uri: str, user: str, passwd: str) -> urllib.request.OpenerDirector:
"""
Build a opener for BASIC auth on urllib.request
:param realm: Realm on BASIC auth
:param uri: URI for auth
:param user: Username
:param passwd: Password
:return: Opener for BASIC auth
"""
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm, uri, user, passwd)
opener = urllib.request.build_opener(auth_handler)
return opener
def request_rest_api(path: str, urlopen: "Function for opening a uri"=urllib.request.urlopen) -> "Response in dict":
"""
Request to the REST API and return the JSON response in dict
:param path: API path
:param urlopen: Function for opening a URI. urllib.request.urlopen or its compatible function is needed.
:return: Response from REST API in dict
"""
response = urlopen("{0}{1}".format(API_BASE_URI, path))
charset = response.info().get_content_charset()
response_str = response.readall().decode(charset)
response_dict = json.loads(response_str)
return response_dict
def backup_bitbucket_git_repository(slug: str, user: str, dst_dir: str):
"""
Backup the specified repository
:param slug: "slug" on repository
:param user: Username
:param dst_dir: Where to backup the repository
"""
repository_name = "{slug}.git".format(slug=slug)
remote_uri = "[email protected]:{user}/{repository_name}".format(
user=user,
repository_name=repository_name)
local_path = os.path.join(dst_dir, repository_name)
os.chdir(dst_dir)
if os.path.exists(local_path):
# Fetch update from remote repository
subprocess.call(["git", "--git-dir", repository_name, "fetch", "--all"])
else:
# Clone as a mirror from remote repository
subprocess.call(["git", "clone", "--mirror", remote_uri])
return
def main():
passwd = keyring.get_password(API_BASE_URI, AUTH_USERNAME)
opener = build_opener(AUTH_REALM, API_BASE_URI, AUTH_USERNAME, passwd)
repositories = request_rest_api("/1.0/user/repositories/", opener.open)
for repository in repositories:
slug = repository["slug"]
backup_bitbucket_git_repository(slug, AUTH_USERNAME, BACKUP_BASE)
if __name__ == '__main__':
import sys
if len(sys.argv) == 3:
# FIXME: should use the argparse
AUTH_USERNAME = sys.argv[1]
BACKUP_BASE = sys.argv[2]
else:
print("Usage: {0} USERNAME BACKUP_TARGET_DIR".format(sys.argv[0]),
file=sys.stderr)
sys.exit()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment