github-backup 0.65.0__tar.gz → 0.65.1__tar.gz
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-0.65.0 → github_backup-0.65.1}/CHANGES.rst +25 -1
- {github_backup-0.65.0/github_backup.egg-info → github_backup-0.65.1}/PKG-INFO +1 -1
- github_backup-0.65.1/github_backup/__init__.py +1 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup/github_backup.py +26 -16
- {github_backup-0.65.0 → github_backup-0.65.1/github_backup.egg-info}/PKG-INFO +1 -1
- {github_backup-0.65.0 → github_backup-0.65.1}/release-requirements.txt +1 -1
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_issue_timeline.py +31 -6
- github_backup-0.65.0/github_backup/__init__.py +0 -1
- {github_backup-0.65.0 → github_backup-0.65.1}/LICENSE.txt +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/MANIFEST.in +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/README +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/README.rst +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup/__main__.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup/cli.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup/graphql_queries.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup.egg-info/SOURCES.txt +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup.egg-info/dependency_links.txt +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup.egg-info/entry_points.txt +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup.egg-info/top_level.txt +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/github_backup.egg-info/zip-safe +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/requirements.txt +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/setup.cfg +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/setup.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_all_starred.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_attachments.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_auth.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_case_sensitivity.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_disabled_issues_pulls.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_discussions.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_gists.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_http_451.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_incremental_per_repository.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_json_dump_if_changed.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_logging_subprocess.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_pagination.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_pull_incremental_pagination.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_pull_reviews.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_releases.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_retrieve_data.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_skip_assets_on.py +0 -0
- {github_backup-0.65.0 → github_backup-0.65.1}/tests/test_starred_skip_size_over.py +0 -0
|
@@ -1,9 +1,33 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
0.65.
|
|
4
|
+
0.65.1 (2026-08-01)
|
|
5
5
|
-------------------
|
|
6
6
|
------------------------
|
|
7
|
+
- Fix timeline not being properly incremental. [Duncan Ogilvie]
|
|
8
|
+
- Chore(deps): bump twine from 6.2.0 to 7.0.0 in the python-packages
|
|
9
|
+
group. [dependabot[bot]]
|
|
10
|
+
|
|
11
|
+
Bumps the python-packages group with 1 update: [twine](https://github.com/pypa/twine).
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Updates `twine` from 6.2.0 to 7.0.0
|
|
15
|
+
- [Release notes](https://github.com/pypa/twine/releases)
|
|
16
|
+
- [Changelog](https://github.com/pypa/twine/blob/main/docs/changelog.rst)
|
|
17
|
+
- [Commits](https://github.com/pypa/twine/compare/6.2.0...7.0.0)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
updated-dependencies:
|
|
21
|
+
- dependency-name: twine
|
|
22
|
+
dependency-version: 7.0.0
|
|
23
|
+
dependency-type: direct:production
|
|
24
|
+
update-type: version-update:semver-major
|
|
25
|
+
dependency-group: python-packages
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
0.65.0 (2026-07-27)
|
|
30
|
+
-------------------
|
|
7
31
|
- Refresh issue timelines when cross-references change (#168) [Rodos]
|
|
8
32
|
|
|
9
33
|
Cross-references do not change an issue's updated_at, so an incremental
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.65.1"
|
|
@@ -2757,19 +2757,24 @@ def backup_issues(args, repo_cwd, repository, repos_template):
|
|
|
2757
2757
|
stale_timelines = find_stale_timeline_issues(
|
|
2758
2758
|
args, issue_cwd, repository, include_pulls=not should_include_pulls
|
|
2759
2759
|
)
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2760
|
+
|
|
2761
|
+
# Issues selected only by the cross-reference sweep have not otherwise
|
|
2762
|
+
# changed. Reuse their complete stored payload and refresh only timeline_data.
|
|
2763
|
+
# Fetching the issue, comments, events and attachments again turns the first
|
|
2764
|
+
# --issue-timeline run into a near-full backup and can discard optional data
|
|
2765
|
+
# when the corresponding flags are absent.
|
|
2766
|
+
timeline_only_issues = stale_timelines - set(issues)
|
|
2767
|
+
for number in sorted(timeline_only_issues):
|
|
2768
|
+
existing = read_json_file_if_exists(
|
|
2769
|
+
"{0}/{1}.json".format(issue_cwd, number)
|
|
2770
|
+
)
|
|
2771
|
+
if existing is None:
|
|
2772
|
+
logger.warning(
|
|
2773
|
+
"Unable to refresh cross-references for issue {0}: "
|
|
2774
|
+
"stored issue data is unreadable".format(number)
|
|
2775
|
+
)
|
|
2776
|
+
continue
|
|
2777
|
+
issues[number] = existing
|
|
2773
2778
|
|
|
2774
2779
|
if issues_skipped:
|
|
2775
2780
|
issues_skipped_message = " (skipped {0} pull requests)".format(issues_skipped)
|
|
@@ -2784,6 +2789,7 @@ def backup_issues(args, repo_cwd, repository, repos_template):
|
|
|
2784
2789
|
timeline_template = _issue_template + "/{0}/timeline"
|
|
2785
2790
|
for number, issue in list(issues.items()):
|
|
2786
2791
|
issue_file = "{0}/{1}.json".format(issue_cwd, number)
|
|
2792
|
+
timeline_only_refresh = number in timeline_only_issues
|
|
2787
2793
|
if (
|
|
2788
2794
|
args.incremental_by_files
|
|
2789
2795
|
and os.path.isfile(issue_file)
|
|
@@ -2799,10 +2805,14 @@ def backup_issues(args, repo_cwd, repository, repos_template):
|
|
|
2799
2805
|
)
|
|
2800
2806
|
continue
|
|
2801
2807
|
|
|
2802
|
-
if
|
|
2808
|
+
if not timeline_only_refresh and (
|
|
2809
|
+
args.include_issue_comments or args.include_everything
|
|
2810
|
+
):
|
|
2803
2811
|
template = comments_template.format(number)
|
|
2804
2812
|
issues[number]["comment_data"] = retrieve_data(args, template)
|
|
2805
|
-
if
|
|
2813
|
+
if not timeline_only_refresh and (
|
|
2814
|
+
args.include_issue_events or args.include_everything
|
|
2815
|
+
):
|
|
2806
2816
|
template = events_template.format(number)
|
|
2807
2817
|
issues[number]["event_data"] = retrieve_data(args, template)
|
|
2808
2818
|
if include_timeline:
|
|
@@ -2815,7 +2825,7 @@ def backup_issues(args, repo_cwd, repository, repos_template):
|
|
|
2815
2825
|
for item in retrieve_data(args, template)
|
|
2816
2826
|
if item.get("event") != "commented"
|
|
2817
2827
|
]
|
|
2818
|
-
if args.include_attachments:
|
|
2828
|
+
if args.include_attachments and not timeline_only_refresh:
|
|
2819
2829
|
download_attachments(
|
|
2820
2830
|
args, issue_cwd, issues[number], number, repository, item_type="issue"
|
|
2821
2831
|
)
|
|
@@ -274,12 +274,24 @@ def test_graphql_failure_warns_and_continues(
|
|
|
274
274
|
def test_stale_issue_backed_up_though_since_excludes_it(
|
|
275
275
|
create_args, tmp_path, monkeypatch
|
|
276
276
|
):
|
|
277
|
-
"""
|
|
278
|
-
|
|
277
|
+
"""A sweep-only issue refreshes just its timeline and preserves its data."""
|
|
278
|
+
issue_cwd = tmp_path / "issues"
|
|
279
|
+
issue_cwd.mkdir()
|
|
280
|
+
stored = _issue(
|
|
281
|
+
7,
|
|
282
|
+
body="stored body",
|
|
283
|
+
comment_data=[{"id": 1, "body": "stored comment"}],
|
|
284
|
+
event_data=[{"id": 2, "event": "referenced"}],
|
|
285
|
+
timeline_data=[],
|
|
286
|
+
)
|
|
287
|
+
(issue_cwd / "7.json").write_text(json.dumps(stored))
|
|
279
288
|
args = _sweep_args(
|
|
280
289
|
create_args,
|
|
281
290
|
include_issues=True,
|
|
291
|
+
include_issue_comments=True,
|
|
292
|
+
include_issue_events=True,
|
|
282
293
|
include_issue_timeline=True,
|
|
294
|
+
include_attachments=True,
|
|
283
295
|
since="2026-07-01T00:00:00Z",
|
|
284
296
|
)
|
|
285
297
|
timeline = [_xref("2026-07-20T00:00:00Z")]
|
|
@@ -287,22 +299,35 @@ def test_stale_issue_backed_up_though_since_excludes_it(
|
|
|
287
299
|
monkeypatch.setattr(
|
|
288
300
|
github_backup,
|
|
289
301
|
"retrieve_data",
|
|
290
|
-
_fake_retrieve(
|
|
291
|
-
{"/issues": [], "/issues/7": [_issue(7)], "/7/timeline": timeline}, calls
|
|
292
|
-
),
|
|
302
|
+
_fake_retrieve({"/issues": [], "/7/timeline": timeline}, calls),
|
|
293
303
|
)
|
|
294
304
|
monkeypatch.setattr(
|
|
295
305
|
github_backup,
|
|
296
306
|
"retrieve_graphql_data",
|
|
297
307
|
_graphql_state({7: (1, "2026-07-20T00:00:00Z")}),
|
|
298
308
|
)
|
|
309
|
+
attachment_calls = []
|
|
310
|
+
monkeypatch.setattr(
|
|
311
|
+
github_backup,
|
|
312
|
+
"download_attachments",
|
|
313
|
+
lambda *args, **kwargs: attachment_calls.append((args, kwargs)),
|
|
314
|
+
)
|
|
299
315
|
|
|
300
316
|
github_backup.backup_issues(
|
|
301
317
|
args, str(tmp_path), {"full_name": "owner/repo"}, "https://api.github.com/repos"
|
|
302
318
|
)
|
|
303
319
|
|
|
304
|
-
saved = json.loads((
|
|
320
|
+
saved = json.loads((issue_cwd / "7.json").read_text())
|
|
305
321
|
assert saved["timeline_data"] == timeline
|
|
322
|
+
assert saved["body"] == "stored body"
|
|
323
|
+
assert saved["comment_data"] == stored["comment_data"]
|
|
324
|
+
assert saved["event_data"] == stored["event_data"]
|
|
325
|
+
assert calls == [
|
|
326
|
+
"https://api.github.com/repos/owner/repo/issues",
|
|
327
|
+
"https://api.github.com/repos/owner/repo/issues",
|
|
328
|
+
"https://api.github.com/repos/owner/repo/issues/7/timeline",
|
|
329
|
+
]
|
|
330
|
+
assert attachment_calls == []
|
|
306
331
|
|
|
307
332
|
|
|
308
333
|
def test_sweep_follows_pagination_cursors(create_args, tmp_path, monkeypatch):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.65.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|