github-backup 0.65.0__py3-none-any.whl → 0.66.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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.65.0"
1
+ __version__ = "0.66.0"
@@ -1838,6 +1838,11 @@ def retrieve_repositories(args, authenticated_user):
1838
1838
  if args.user == authenticated_user["login"]:
1839
1839
  # we must use the /user/repos API to be able to access private repos
1840
1840
  template = "https://{0}/user/repos".format(get_github_api_host(args))
1841
+ elif args.as_app and not args.organization:
1842
+ # /users/{user}/repos is public-only; the installation sees private repos too
1843
+ template = "https://{0}/installation/repositories".format(
1844
+ get_github_api_host(args)
1845
+ )
1841
1846
  else:
1842
1847
  if args.private and not args.organization:
1843
1848
  logger.warning(
@@ -1868,6 +1873,10 @@ def retrieve_repositories(args, authenticated_user):
1868
1873
  logger.warning(f"Legal notice: {e.legal_url}")
1869
1874
  return []
1870
1875
 
1876
+ if template.endswith("/installation/repositories"):
1877
+ # Each page is {"total_count": ..., "repositories": [...]}
1878
+ repos = [repo for page in repos for repo in page["repositories"]]
1879
+
1871
1880
  return retrieve_additional_repositories(args, authenticated_user, repos)
1872
1881
 
1873
1882
 
@@ -2757,19 +2766,24 @@ def backup_issues(args, repo_cwd, repository, repos_template):
2757
2766
  stale_timelines = find_stale_timeline_issues(
2758
2767
  args, issue_cwd, repository, include_pulls=not should_include_pulls
2759
2768
  )
2760
- for number in sorted(stale_timelines - set(issues)):
2761
- try:
2762
- issues[number] = retrieve_data(
2763
- args, "{0}/{1}".format(_issue_template, number), paginated=False
2764
- )[0]
2765
- except (HTTPError, RepositoryUnavailableError, IndexError) as e:
2766
- # Deleted or transferred between the sweep and this fetch. The
2767
- # refresh is opportunistic, so skip rather than fail the run.
2768
- logger.warning(
2769
- "Unable to refresh cross-references for issue {0}: {1}".format(
2770
- number, e
2771
- )
2772
- )
2769
+
2770
+ # Issues selected only by the cross-reference sweep have not otherwise
2771
+ # changed. Reuse their complete stored payload and refresh only timeline_data.
2772
+ # Fetching the issue, comments, events and attachments again turns the first
2773
+ # --issue-timeline run into a near-full backup and can discard optional data
2774
+ # when the corresponding flags are absent.
2775
+ timeline_only_issues = stale_timelines - set(issues)
2776
+ for number in sorted(timeline_only_issues):
2777
+ existing = read_json_file_if_exists(
2778
+ "{0}/{1}.json".format(issue_cwd, number)
2779
+ )
2780
+ if existing is None:
2781
+ logger.warning(
2782
+ "Unable to refresh cross-references for issue {0}: "
2783
+ "stored issue data is unreadable".format(number)
2784
+ )
2785
+ continue
2786
+ issues[number] = existing
2773
2787
 
2774
2788
  if issues_skipped:
2775
2789
  issues_skipped_message = " (skipped {0} pull requests)".format(issues_skipped)
@@ -2784,6 +2798,7 @@ def backup_issues(args, repo_cwd, repository, repos_template):
2784
2798
  timeline_template = _issue_template + "/{0}/timeline"
2785
2799
  for number, issue in list(issues.items()):
2786
2800
  issue_file = "{0}/{1}.json".format(issue_cwd, number)
2801
+ timeline_only_refresh = number in timeline_only_issues
2787
2802
  if (
2788
2803
  args.incremental_by_files
2789
2804
  and os.path.isfile(issue_file)
@@ -2799,10 +2814,14 @@ def backup_issues(args, repo_cwd, repository, repos_template):
2799
2814
  )
2800
2815
  continue
2801
2816
 
2802
- if args.include_issue_comments or args.include_everything:
2817
+ if not timeline_only_refresh and (
2818
+ args.include_issue_comments or args.include_everything
2819
+ ):
2803
2820
  template = comments_template.format(number)
2804
2821
  issues[number]["comment_data"] = retrieve_data(args, template)
2805
- if args.include_issue_events or args.include_everything:
2822
+ if not timeline_only_refresh and (
2823
+ args.include_issue_events or args.include_everything
2824
+ ):
2806
2825
  template = events_template.format(number)
2807
2826
  issues[number]["event_data"] = retrieve_data(args, template)
2808
2827
  if include_timeline:
@@ -2815,7 +2834,7 @@ def backup_issues(args, repo_cwd, repository, repos_template):
2815
2834
  for item in retrieve_data(args, template)
2816
2835
  if item.get("event") != "commented"
2817
2836
  ]
2818
- if args.include_attachments:
2837
+ if args.include_attachments and not timeline_only_refresh:
2819
2838
  download_attachments(
2820
2839
  args, issue_cwd, issues[number], number, repository, item_type="issue"
2821
2840
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-backup
3
- Version: 0.65.0
3
+ Version: 0.66.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
@@ -229,6 +229,8 @@ GitHub Apps
229
229
 
230
230
  GitHub Apps are ideal for organization backups in CI/CD. Tokens are scoped to specific repositories and expire after 1 hour.
231
231
 
232
+ For a user account (no ``--organization``), ``--as-app`` lists the repositories the installation can access, so private repositories are included.
233
+
232
234
  **One-time setup:**
233
235
 
234
236
  1. Create a GitHub App at *Settings -> Developer Settings -> GitHub Apps -> New GitHub App*
@@ -0,0 +1,12 @@
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (83.0.0)
2
+ Generator: setuptools (84.2.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,12 +0,0 @@
1
- github_backup/__init__.py,sha256=eauVKKmGRrPjcW6OLz78zXL8jRoYaQPOL0tbet7E8Vo,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=jDGgAnhT_vn7QUmEJ95hwe8jfuVc3dETyLblGSQTZ0k,126285
5
- github_backup/graphql_queries.py,sha256=XcAQyp9nF7Ip9UzxsrXMkl2pO-W7SK8hhO2oE9HVcmA,6658
6
- github_backup-0.65.0.dist-info/licenses/LICENSE.txt,sha256=ML-pLyn1qtAKo_DHMcQ8-p7k3f8cp-IR-mf5B49R2rk,1085
7
- github_backup-0.65.0.dist-info/METADATA,sha256=lWXqgFoH_QhZEHy0fsp8cs_Iu8McBJZ4bUDrOL2VDp8,36048
8
- github_backup-0.65.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
9
- github_backup-0.65.0.dist-info/entry_points.txt,sha256=cLPKK7MqC77QVb6HnT2mnyL_f-ciavJG_Y9vVHlCF68,57
10
- github_backup-0.65.0.dist-info/top_level.txt,sha256=Za6fKRAlxZ0b3ZBH_osPqklLe14LetdNAkvAQANT2AA,14
11
- github_backup-0.65.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
12
- github_backup-0.65.0.dist-info/RECORD,,