Compare commits

...

14 Commits

Author SHA1 Message Date
Jose Diaz-Gonzalez
031a984434 Release version 0.36.0 2020-08-29 02:37:48 -04:00
Jose Diaz-Gonzalez
9e16f39e3e Merge pull request #157 from albertyw/lint 2020-08-29 02:37:19 -04:00
Albert Wang
2de96390be Add flake8 instructions to readme 2020-08-28 23:13:24 -07:00
Albert Wang
78cff47a91 Fix regex string 2020-08-28 23:13:24 -07:00
Albert Wang
fa27988c1c Update boolean check 2020-08-28 23:13:23 -07:00
Albert Wang
bb2e2b8c6f Fix whitespace issues 2020-08-28 23:13:23 -07:00
Albert Wang
8fd0f2b64f Do not use bare excepts 2020-08-28 23:13:23 -07:00
Jose Diaz-Gonzalez
753a551961 Merge pull request #161 from albertyw/circleci-project-setup
Add circleci config
2020-08-29 01:48:49 -04:00
Albert Wang
607b6ca69b Add .circleci/config.yml 2020-08-28 02:33:51 -07:00
Jose Diaz-Gonzalez
ef71655b01 Merge pull request #160 from wbolster/patch-1
Include --private flag in example
2020-08-27 13:23:28 -04:00
wouter bolsterlee
d8bcbfa644 Include --private flag in example
By default, private repositories are not included. This is surprising.
It took me a while to figure this out, and making that clear in the
example can help others to be aware of that.
2020-08-27 17:01:56 +02:00
Jose Diaz-Gonzalez
751b0d6e82 Release version 0.35.0 2020-08-05 12:02:21 -04:00
Jose Diaz-Gonzalez
ea633ca2bb Merge pull request #156 from samanthaq/restore-optional-throttling
Make API request throttling optional
2020-08-05 12:01:56 -04:00
Samantha Baldwin
a2115ce3e5 Make API request throttling optional 2020-08-05 11:53:17 -04:00
5 changed files with 74 additions and 15 deletions

23
.circleci/config.yml Normal file
View File

@@ -0,0 +1,23 @@
version: 2.1
orbs:
python: circleci/python@0.3.2
jobs:
build-and-test:
executor: python/default
steps:
- checkout
- python/load-cache
- run:
command: pip install flake8
name: Install dependencies
- python/save-cache
- run:
command: flake8 --ignore=E501
name: Lint
workflows:
main:
jobs:
- build-and-test

View File

@@ -1,9 +1,28 @@
Changelog Changelog
========= =========
0.34.0 (2020-07-24) 0.36.0 (2020-08-29)
------------------- -------------------
------------------------ ------------------------
- Add flake8 instructions to readme. [Albert Wang]
- Fix regex string. [Albert Wang]
- Fix whitespace issues. [Albert Wang]
- Do not use bare excepts. [Albert Wang]
- Add .circleci/config.yml. [Albert Wang]
- Include --private flag in example. [wouter bolsterlee]
By default, private repositories are not included. This is surprising.
It took me a while to figure this out, and making that clear in the
example can help others to be aware of that.
0.35.0 (2020-08-05)
-------------------
- Make API request throttling optional. [Samantha Baldwin]
0.34.0 (2020-07-24)
-------------------
- Add logic for transforming gist repository urls to ssh. [Matt Fields] - Add logic for transforming gist repository urls to ssh. [Matt Fields]

View File

@@ -153,10 +153,10 @@ Instructions on how to do this can be found on https://git-lfs.github.com.
Examples Examples
======== ========
Backup all repositories:: Backup all repositories, including private ones::
export ACCESS_TOKEN=SOME-GITHUB-TOKEN export ACCESS_TOKEN=SOME-GITHUB-TOKEN
github-backup WhiteHouse --token $ACCESS_TOKEN --organization --output-directory /tmp/white-house --repositories github-backup WhiteHouse --token $ACCESS_TOKEN --organization --output-directory /tmp/white-house --repositories --private
Backup a single organization repository with everything else (wiki, pull requests, comments, issues etc):: Backup a single organization repository with everything else (wiki, pull requests, comments, issues etc)::
@@ -166,6 +166,15 @@ Backup a single organization repository with everything else (wiki, pull request
# e.g. git@github.com:docker/cli.git # e.g. git@github.com:docker/cli.git
github-backup $ORGANIZATION -P -t $ACCESS_TOKEN -o . --all -O -R $REPO github-backup $ORGANIZATION -P -t $ACCESS_TOKEN -o . --all -O -R $REPO
Testing
=======
This project currently contains no unit tests. To run linting::
pip install flake8
flake8 --ignore=E501
.. |PyPI| image:: https://img.shields.io/pypi/v/github-backup.svg .. |PyPI| image:: https://img.shields.io/pypi/v/github-backup.svg
:target: https://pypi.python.org/pypi/github-backup/ :target: https://pypi.python.org/pypi/github-backup/
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/github-backup.svg .. |Python Versions| image:: https://img.shields.io/pypi/pyversions/github-backup.svg

View File

@@ -1 +1 @@
__version__ = '0.34.0' __version__ = '0.36.0'

View File

@@ -30,9 +30,11 @@ try:
from urllib.request import Request from urllib.request import Request
from urllib.request import HTTPRedirectHandler from urllib.request import HTTPRedirectHandler
from urllib.request import build_opener from urllib.request import build_opener
from subprocess import SubprocessError
except ImportError: except ImportError:
# python 2 # python 2
PY2 = True PY2 = True
from subprocess import CalledProcessError as SubprocessError
from urlparse import urlparse from urlparse import urlparse
from urllib import quote as urlquote from urllib import quote as urlquote
from urllib import urlencode from urllib import urlencode
@@ -363,7 +365,7 @@ def get_auth(args, encode=True, for_git_cli=False):
if not PY2: if not PY2:
token = token.decode('utf-8') token = token.decode('utf-8')
auth = token + ':' + 'x-oauth-basic' auth = token + ':' + 'x-oauth-basic'
except: except SubprocessError:
log_error('No password item matching the provided name and account could be found in the osx keychain.') log_error('No password item matching the provided name and account could be found in the osx keychain.')
elif args.osx_keychain_item_account: elif args.osx_keychain_item_account:
log_error('You must specify both name and account fields for osx keychain password items') log_error('You must specify both name and account fields for osx keychain password items')
@@ -421,8 +423,8 @@ def get_github_repo_url(args, repository):
if repository.get('is_gist'): if repository.get('is_gist'):
if args.prefer_ssh: if args.prefer_ssh:
# The git_pull_url value is always https for gists, so we need to transform it to ssh form # The git_pull_url value is always https for gists, so we need to transform it to ssh form
repo_url = re.sub('^https?:\/\/(.+)\/(.+)\.git$', r'git@\1:\2.git', repository['git_pull_url']) repo_url = re.sub(r'^https?:\/\/(.+)\/(.+)\.git$', r'git@\1:\2.git', repository['git_pull_url'])
repo_url = re.sub('^git@gist\.', 'git@', repo_url) # strip gist subdomain for better hostkey compatibility repo_url = re.sub(r'^git@gist\.', 'git@', repo_url) # strip gist subdomain for better hostkey compatibility
else: else:
repo_url = repository['git_pull_url'] repo_url = repository['git_pull_url']
return repo_url return repo_url
@@ -431,7 +433,7 @@ def get_github_repo_url(args, repository):
return repository['ssh_url'] return repository['ssh_url']
auth = get_auth(args, encode=False, for_git_cli=True) auth = get_auth(args, encode=False, for_git_cli=True)
if auth and repository['private'] == True: if auth and repository['private'] is True:
repo_url = 'https://{0}@{1}/{2}/{3}.git'.format( repo_url = 'https://{0}@{1}/{2}/{3}.git'.format(
auth, auth,
get_github_host(args), get_github_host(args),
@@ -457,7 +459,7 @@ def retrieve_data_gen(args, template, query_args=None, single_request=False):
status_code = int(r.getcode()) status_code = int(r.getcode())
# be gentle with API request limit and throttle requests if remaining requests getting low # be gentle with API request limit and throttle requests if remaining requests getting low
limit_remaining = int(r.headers.get('x-ratelimit-remaining', 0)) limit_remaining = int(r.headers.get('x-ratelimit-remaining', 0))
if limit_remaining <= args.throttle_limit: if args.throttle_limit and limit_remaining <= args.throttle_limit:
log_info( log_info(
'API request limit hit: {} requests left, pausing further requests for {}s'.format( 'API request limit hit: {} requests left, pausing further requests for {}s'.format(
limit_remaining, limit_remaining,
@@ -495,9 +497,11 @@ def retrieve_data_gen(args, template, query_args=None, single_request=False):
if single_request: if single_request:
break break
def retrieve_data(args, template, query_args=None, single_request=False): def retrieve_data(args, template, query_args=None, single_request=False):
return list(retrieve_data_gen(args, template, query_args, single_request)) return list(retrieve_data_gen(args, template, query_args, single_request))
def get_query_args(query_args=None): def get_query_args(query_args=None):
if not query_args: if not query_args:
query_args = {} query_args = {}
@@ -901,18 +905,22 @@ def backup_pulls(args, repo_cwd, repository, repos_template):
pull_states = ['open', 'closed'] pull_states = ['open', 'closed']
for pull_state in pull_states: for pull_state in pull_states:
query_args['state'] = pull_state query_args['state'] = pull_state
_pulls = retrieve_data_gen(args, _pulls = retrieve_data_gen(
args,
_pulls_template, _pulls_template,
query_args=query_args) query_args=query_args
)
for pull in _pulls: for pull in _pulls:
if args.since and pull['updated_at'] < args.since: if args.since and pull['updated_at'] < args.since:
break break
if not args.since or pull['updated_at'] >= args.since: if not args.since or pull['updated_at'] >= args.since:
pulls[pull['number']] = pull pulls[pull['number']] = pull
else: else:
_pulls = retrieve_data_gen(args, _pulls = retrieve_data_gen(
args,
_pulls_template, _pulls_template,
query_args=query_args) query_args=query_args
)
for pull in _pulls: for pull in _pulls:
if args.since and pull['updated_at'] < args.since: if args.since and pull['updated_at'] < args.since:
break break