github-backup 0.64.0__py3-none-any.whl → 0.64.2__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.64.0"
1
+ __version__ = "0.64.2"
@@ -1789,7 +1789,39 @@ def check_git_lfs_install():
1789
1789
  )
1790
1790
 
1791
1791
 
1792
+ # Resources fetched from their own endpoints, not from the repository listing
1793
+ # (gists and account-level data). Every other include_* flag needs the listing.
1794
+ NON_REPOSITORY_RESOURCES = frozenset(
1795
+ {
1796
+ "include_gists",
1797
+ "include_starred_gists",
1798
+ "include_starred",
1799
+ "include_watched",
1800
+ "include_followers",
1801
+ "include_following",
1802
+ }
1803
+ )
1804
+
1805
+
1806
+ def repository_list_needed(args):
1807
+ """The base repository listing is only needed when a per-repository
1808
+ resource was requested; e.g. a gists-only backup can skip it entirely.
1809
+ Flags not listed in NON_REPOSITORY_RESOURCES default to needing it, so a
1810
+ newly added resource can never be silently skipped."""
1811
+ if args.repository:
1812
+ return True
1813
+ return any(
1814
+ value
1815
+ for name, value in vars(args).items()
1816
+ if name.startswith("include_") and name not in NON_REPOSITORY_RESOURCES
1817
+ )
1818
+
1819
+
1792
1820
  def retrieve_repositories(args, authenticated_user):
1821
+ if not repository_list_needed(args):
1822
+ repos = []
1823
+ return retrieve_additional_repositories(args, authenticated_user, repos)
1824
+
1793
1825
  logger.info("Retrieving repositories")
1794
1826
  paginated = True
1795
1827
  if args.user == authenticated_user["login"]:
@@ -1825,6 +1857,12 @@ def retrieve_repositories(args, authenticated_user):
1825
1857
  logger.warning(f"Legal notice: {e.legal_url}")
1826
1858
  return []
1827
1859
 
1860
+ return retrieve_additional_repositories(args, authenticated_user, repos)
1861
+
1862
+
1863
+ def retrieve_additional_repositories(args, authenticated_user, repos):
1864
+ """Append starred repositories, gists and starred gists to the base
1865
+ repository list when requested."""
1828
1866
  if args.all_starred:
1829
1867
  starred_template = "https://{0}/users/{1}/starred".format(
1830
1868
  get_github_api_host(args), args.user
@@ -2058,6 +2096,24 @@ def remove_legacy_last_update_if_migrated(
2058
2096
  )
2059
2097
 
2060
2098
 
2099
+ def gist_backup_is_current(repository, repo_cwd, repo_dir):
2100
+ """Whether fetching a gist can be skipped because a clone exists and the
2101
+ stored gist.json matches the listing's updated_at. Any edit to a gist —
2102
+ including a git push — bumps updated_at, so this can never miss a content
2103
+ change; at worst a comment bumps it and causes a harmless refetch."""
2104
+ if not os.path.exists(repo_dir):
2105
+ return False
2106
+ updated_at = repository.get("updated_at")
2107
+ if not updated_at:
2108
+ return False
2109
+ try:
2110
+ with codecs.open(os.path.join(repo_cwd, "gist.json"), encoding="utf-8") as f:
2111
+ stored = json.load(f)
2112
+ except (OSError, ValueError):
2113
+ return False
2114
+ return stored.get("updated_at") == updated_at
2115
+
2116
+
2061
2117
  def backup_repositories(args, output_directory, repositories):
2062
2118
  logger.info("Backing up repositories")
2063
2119
  repos_template = "https://{0}/repos".format(get_github_api_host(args))
@@ -2065,6 +2121,7 @@ def backup_repositories(args, output_directory, repositories):
2065
2121
  args, output_directory
2066
2122
  )
2067
2123
  incremental_resource_work_attempted = False
2124
+ skipped_unchanged_gists = 0
2068
2125
 
2069
2126
  for repository in repositories:
2070
2127
  if repository.get("is_gist"):
@@ -2098,18 +2155,30 @@ def backup_repositories(args, output_directory, repositories):
2098
2155
  if not repository.get("is_gist")
2099
2156
  else repository.get("id")
2100
2157
  )
2101
- fetch_repository(
2102
- repo_name,
2103
- repo_url,
2104
- repo_dir,
2105
- skip_existing=args.skip_existing,
2106
- bare_clone=args.bare_clone,
2107
- lfs_clone=args.lfs_clone,
2108
- no_prune=args.no_prune,
2109
- )
2158
+ if repository.get("is_gist") and gist_backup_is_current(
2159
+ repository, repo_cwd, repo_dir
2160
+ ):
2161
+ logger.debug(
2162
+ "Skipping gist {0} (unchanged since last backup)".format(repo_name)
2163
+ )
2164
+ skipped_unchanged_gists += 1
2165
+ else:
2166
+ fetch_repository(
2167
+ repo_name,
2168
+ repo_url,
2169
+ repo_dir,
2170
+ skip_existing=args.skip_existing,
2171
+ bare_clone=args.bare_clone,
2172
+ lfs_clone=args.lfs_clone,
2173
+ no_prune=args.no_prune,
2174
+ )
2110
2175
 
2111
2176
  if repository.get("is_gist"):
2112
- # dump gist information to a file as well
2177
+ # dump gist information to a file as well, even when the fetch
2178
+ # was skipped, so listing metadata (fork counts etc.) stays
2179
+ # fresh; the clone may also have been skipped entirely (e.g.
2180
+ # DMCA-blocked or empty gist), so make sure the directory exists
2181
+ mkdir_p(repo_cwd)
2113
2182
  output_file = "{0}/gist.json".format(repo_cwd)
2114
2183
  with codecs.open(output_file, "w", encoding="utf-8") as f:
2115
2184
  json_dump(repository, f)
@@ -2178,6 +2247,9 @@ def backup_repositories(args, output_directory, repositories):
2178
2247
  logger.info(f"Skipping remaining resources for {repository['full_name']}")
2179
2248
  continue
2180
2249
 
2250
+ if skipped_unchanged_gists:
2251
+ logger.info("Skipped {0} unchanged gists".format(skipped_unchanged_gists))
2252
+
2181
2253
  if incremental_resource_work_attempted:
2182
2254
  remove_legacy_last_update_if_migrated(
2183
2255
  args, output_directory, legacy_last_update_path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-backup
3
- Version: 0.64.0
3
+ Version: 0.64.2
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
@@ -0,0 +1,12 @@
1
+ github_backup/__init__.py,sha256=HaA1w46nhUOTnwyEmiDmwgxgpts5fYS0-7T_j-jEoCs,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=N71PvIZjPedFMcuFxnirHPtnlOhx9FsMJKDJcLMirMc,119503
5
+ github_backup/graphql_queries.py,sha256=QBIXcGzGunilMpHfL32cTO_AAzxuQD27QII1V9K_Yw4,4883
6
+ github_backup-0.64.2.dist-info/licenses/LICENSE.txt,sha256=ML-pLyn1qtAKo_DHMcQ8-p7k3f8cp-IR-mf5B49R2rk,1085
7
+ github_backup-0.64.2.dist-info/METADATA,sha256=86x3tJ_aA1ktrSimtDh6eqgZYRVvJinaXYTLOICZETY,32426
8
+ github_backup-0.64.2.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
9
+ github_backup-0.64.2.dist-info/entry_points.txt,sha256=cLPKK7MqC77QVb6HnT2mnyL_f-ciavJG_Y9vVHlCF68,57
10
+ github_backup-0.64.2.dist-info/top_level.txt,sha256=Za6fKRAlxZ0b3ZBH_osPqklLe14LetdNAkvAQANT2AA,14
11
+ github_backup-0.64.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
12
+ github_backup-0.64.2.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- github_backup/__init__.py,sha256=4aEOIqCiMfp1lfhnZ0isYinRITBjjNflprA4nXib3RQ,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=S5uxqZsYMnOGBYuEX9Dy1sipyUDyaeU7qXoLjkz3nLk,116637
5
- github_backup/graphql_queries.py,sha256=QBIXcGzGunilMpHfL32cTO_AAzxuQD27QII1V9K_Yw4,4883
6
- github_backup-0.64.0.dist-info/licenses/LICENSE.txt,sha256=ML-pLyn1qtAKo_DHMcQ8-p7k3f8cp-IR-mf5B49R2rk,1085
7
- github_backup-0.64.0.dist-info/METADATA,sha256=XSm6FyyldS86S0nFxbOMcS1lNkP0vVb8nTNLAMdF0J4,32426
8
- github_backup-0.64.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
9
- github_backup-0.64.0.dist-info/entry_points.txt,sha256=cLPKK7MqC77QVb6HnT2mnyL_f-ciavJG_Y9vVHlCF68,57
10
- github_backup-0.64.0.dist-info/top_level.txt,sha256=Za6fKRAlxZ0b3ZBH_osPqklLe14LetdNAkvAQANT2AA,14
11
- github_backup-0.64.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
12
- github_backup-0.64.0.dist-info/RECORD,,