github-backup 0.66.0__py3-none-any.whl → 0.67.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- github_backup/__init__.py +1 -1
- github_backup/github_backup.py +26 -6
- {github_backup-0.66.0.dist-info → github_backup-0.67.0.dist-info}/METADATA +5 -8
- github_backup-0.67.0.dist-info/RECORD +12 -0
- github_backup-0.66.0.dist-info/RECORD +0 -12
- {github_backup-0.66.0.dist-info → github_backup-0.67.0.dist-info}/WHEEL +0 -0
- {github_backup-0.66.0.dist-info → github_backup-0.67.0.dist-info}/entry_points.txt +0 -0
- {github_backup-0.66.0.dist-info → github_backup-0.67.0.dist-info}/licenses/LICENSE.txt +0 -0
- {github_backup-0.66.0.dist-info → github_backup-0.67.0.dist-info}/top_level.txt +0 -0
- {github_backup-0.66.0.dist-info → github_backup-0.67.0.dist-info}/zip-safe +0 -0
github_backup/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.67.0"
|
github_backup/github_backup.py
CHANGED
|
@@ -20,7 +20,7 @@ import threading
|
|
|
20
20
|
import time
|
|
21
21
|
import traceback
|
|
22
22
|
from collections.abc import Generator
|
|
23
|
-
from datetime import datetime
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
24
|
from http.client import IncompleteRead
|
|
25
25
|
from urllib.error import HTTPError, URLError
|
|
26
26
|
from urllib.parse import urlencode, urlparse
|
|
@@ -2004,7 +2004,7 @@ def get_repository_checkpoint_time(repository):
|
|
|
2004
2004
|
if timestamps:
|
|
2005
2005
|
return max(timestamps)
|
|
2006
2006
|
|
|
2007
|
-
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.
|
|
2007
|
+
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
2008
2008
|
|
|
2009
2009
|
|
|
2010
2010
|
def resource_backup_exists(resource_cwd):
|
|
@@ -2525,7 +2525,9 @@ def backup_discussions(args, repo_cwd, repository):
|
|
|
2525
2525
|
|
|
2526
2526
|
if args.incremental_by_files and os.path.isfile(discussion_file):
|
|
2527
2527
|
modified = os.path.getmtime(discussion_file)
|
|
2528
|
-
modified = datetime.fromtimestamp(modified).strftime(
|
|
2528
|
+
modified = datetime.fromtimestamp(modified, timezone.utc).strftime(
|
|
2529
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
2530
|
+
)
|
|
2529
2531
|
if modified > summary["updatedAt"]:
|
|
2530
2532
|
logger.info(
|
|
2531
2533
|
"Skipping discussion {0} because it wasn't modified since last backup".format(
|
|
@@ -2805,7 +2807,9 @@ def backup_issues(args, repo_cwd, repository, repos_template):
|
|
|
2805
2807
|
and number not in stale_timelines
|
|
2806
2808
|
):
|
|
2807
2809
|
modified = os.path.getmtime(issue_file)
|
|
2808
|
-
modified = datetime.fromtimestamp(modified).strftime(
|
|
2810
|
+
modified = datetime.fromtimestamp(modified, timezone.utc).strftime(
|
|
2811
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
2812
|
+
)
|
|
2809
2813
|
if modified > issue["updated_at"]:
|
|
2810
2814
|
logger.info(
|
|
2811
2815
|
"Skipping issue {0} because it wasn't modified since last backup".format(
|
|
@@ -3006,7 +3010,9 @@ def backup_pulls(args, repo_cwd, repository, repos_template):
|
|
|
3006
3010
|
|
|
3007
3011
|
if args.incremental_by_files and os.path.isfile(pull_file):
|
|
3008
3012
|
modified = os.path.getmtime(pull_file)
|
|
3009
|
-
modified = datetime.fromtimestamp(modified).strftime(
|
|
3013
|
+
modified = datetime.fromtimestamp(modified, timezone.utc).strftime(
|
|
3014
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
3015
|
+
)
|
|
3010
3016
|
if modified > pull["updated_at"] and not needs_review_backfill:
|
|
3011
3017
|
logger.info(
|
|
3012
3018
|
"Skipping pull request {0} because it wasn't modified since last backup".format(
|
|
@@ -3155,6 +3161,15 @@ def backup_hooks(args, repo_cwd, repository, repos_template):
|
|
|
3155
3161
|
if not auth:
|
|
3156
3162
|
logger.info("Skipping hooks since no authentication provided")
|
|
3157
3163
|
return
|
|
3164
|
+
# Reading hooks needs admin access, and GitHub returns 404 without it.
|
|
3165
|
+
# Skip the request when the repository listing says we aren't an admin.
|
|
3166
|
+
if repository.get("permissions", {}).get("admin") is False:
|
|
3167
|
+
logger.info(
|
|
3168
|
+
"Skipping hooks for {0} since admin access is required".format(
|
|
3169
|
+
repository["full_name"]
|
|
3170
|
+
)
|
|
3171
|
+
)
|
|
3172
|
+
return
|
|
3158
3173
|
hook_cwd = os.path.join(repo_cwd, "hooks")
|
|
3159
3174
|
output_file = "{0}/hooks.json".format(hook_cwd)
|
|
3160
3175
|
template = "{0}/{1}/hooks".format(repos_template, repository["full_name"])
|
|
@@ -3162,7 +3177,12 @@ def backup_hooks(args, repo_cwd, repository, repos_template):
|
|
|
3162
3177
|
_backup_data(args, "hooks", template, output_file, hook_cwd)
|
|
3163
3178
|
except HTTPError as e:
|
|
3164
3179
|
if e.code == 404:
|
|
3165
|
-
logger.info(
|
|
3180
|
+
logger.info(
|
|
3181
|
+
"Unable to read hooks for {0}, skipping (requires admin access, "
|
|
3182
|
+
"or Webhooks read permission for fine-grained tokens)".format(
|
|
3183
|
+
repository["full_name"]
|
|
3184
|
+
)
|
|
3185
|
+
)
|
|
3166
3186
|
else:
|
|
3167
3187
|
raise e
|
|
3168
3188
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-backup
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.67.0
|
|
4
4
|
Summary: backup a github user or organization
|
|
5
5
|
Home-page: http://github.com/josegonzalez/python-github-backup
|
|
6
6
|
Author: Jose Diaz-Gonzalez
|
|
@@ -9,12 +9,11 @@ License: MIT
|
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Topic :: System :: Archiving :: Backup
|
|
11
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
-
Requires-Python: >=3.
|
|
16
|
+
Requires-Python: >=3.11
|
|
18
17
|
Description-Content-Type: text/x-rst
|
|
19
18
|
License-File: LICENSE.txt
|
|
20
19
|
Dynamic: author
|
|
@@ -39,7 +38,7 @@ The package can be used to backup an *entire* `Github <https://github.com/>`_ or
|
|
|
39
38
|
Requirements
|
|
40
39
|
============
|
|
41
40
|
|
|
42
|
-
- Python 3.
|
|
41
|
+
- Python 3.11 or higher
|
|
43
42
|
- GIT 1.9+
|
|
44
43
|
|
|
45
44
|
Installation
|
|
@@ -437,11 +436,9 @@ If the incremental argument is used, per-resource checkpoints are only advanced
|
|
|
437
436
|
|
|
438
437
|
It's therefore recommended to only use the incremental argument if the output/result is being actively monitored, or complimented with periodic full non-incremental runs, to avoid unexpected missing data in a regular backup runs.
|
|
439
438
|
|
|
440
|
-
**
|
|
439
|
+
**Hooks need admin access**
|
|
441
440
|
|
|
442
|
-
Since the ``--all`` argument includes ``--hooks``,
|
|
443
|
-
|
|
444
|
-
This is due to needing the correct permission for ``--hooks`` on public repos.
|
|
441
|
+
Reading a repository's hooks requires admin access to it, and fine-grained tokens also need the Webhooks read permission. Since the ``--all`` argument includes ``--hooks``, repositories you don't administer, such as starred repositories with ``--all-starred``, are skipped for hooks and the rest of the backup continues.
|
|
445
442
|
|
|
446
443
|
|
|
447
444
|
"bare" is actually "mirror"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
github_backup/__init__.py,sha256=DkegR91M-IkILN5EBv-0LVftxIGE60qyryEQ_lYCjdg,23
|
|
2
|
+
github_backup/__main__.py,sha256=3yorCiC63maaxbjdtaeAs-G-yAAxKSO3mprhGfa1Fho,271
|
|
3
|
+
github_backup/cli.py,sha256=JTiXPOvB8id8LopREOEd1W_FLvuf9SOZU5buMRPFd9U,2922
|
|
4
|
+
github_backup/github_backup.py,sha256=5OvANlDQv06qn3awp5rbOzP8ocV88l2o0O-9ng6RywI,127852
|
|
5
|
+
github_backup/graphql_queries.py,sha256=XcAQyp9nF7Ip9UzxsrXMkl2pO-W7SK8hhO2oE9HVcmA,6658
|
|
6
|
+
github_backup-0.67.0.dist-info/licenses/LICENSE.txt,sha256=ML-pLyn1qtAKo_DHMcQ8-p7k3f8cp-IR-mf5B49R2rk,1085
|
|
7
|
+
github_backup-0.67.0.dist-info/METADATA,sha256=redpeZKBK8eOJsG4nM7axcT7pz4v3jBDkeBV509NUfU,36164
|
|
8
|
+
github_backup-0.67.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
9
|
+
github_backup-0.67.0.dist-info/entry_points.txt,sha256=cLPKK7MqC77QVb6HnT2mnyL_f-ciavJG_Y9vVHlCF68,57
|
|
10
|
+
github_backup-0.67.0.dist-info/top_level.txt,sha256=Za6fKRAlxZ0b3ZBH_osPqklLe14LetdNAkvAQANT2AA,14
|
|
11
|
+
github_backup-0.67.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
12
|
+
github_backup-0.67.0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
github_backup/__init__.py,sha256=rdBd9Kj9DDCtQNzVZEbaE1YatB7HZXL9qX4Ge-gXzaM,23
|
|
2
|
-
github_backup/__main__.py,sha256=3yorCiC63maaxbjdtaeAs-G-yAAxKSO3mprhGfa1Fho,271
|
|
3
|
-
github_backup/cli.py,sha256=JTiXPOvB8id8LopREOEd1W_FLvuf9SOZU5buMRPFd9U,2922
|
|
4
|
-
github_backup/github_backup.py,sha256=zvWTp4_02ep-O7lE0fNuIBdMpN7wHKanboC4hydLXhA,127118
|
|
5
|
-
github_backup/graphql_queries.py,sha256=XcAQyp9nF7Ip9UzxsrXMkl2pO-W7SK8hhO2oE9HVcmA,6658
|
|
6
|
-
github_backup-0.66.0.dist-info/licenses/LICENSE.txt,sha256=ML-pLyn1qtAKo_DHMcQ8-p7k3f8cp-IR-mf5B49R2rk,1085
|
|
7
|
-
github_backup-0.66.0.dist-info/METADATA,sha256=x9vCzseh_H9lmtHA3Wb1O0iS1rlvAfrONsLMuco26eM,36196
|
|
8
|
-
github_backup-0.66.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
9
|
-
github_backup-0.66.0.dist-info/entry_points.txt,sha256=cLPKK7MqC77QVb6HnT2mnyL_f-ciavJG_Y9vVHlCF68,57
|
|
10
|
-
github_backup-0.66.0.dist-info/top_level.txt,sha256=Za6fKRAlxZ0b3ZBH_osPqklLe14LetdNAkvAQANT2AA,14
|
|
11
|
-
github_backup-0.66.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
12
|
-
github_backup-0.66.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|