-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrgog.py
More file actions
127 lines (107 loc) · 5.9 KB
/
rgog.py
File metadata and controls
127 lines (107 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python3
"""
RGOG - Reproducible GOG Archive Tool
A command-line tool for creating, listing, extracting, and verifying
RGOG (Reproducible GOG) archives following the RGOG Format Specification v2.0.
Usage:
rgog.py pack <input_dir> -o <output.rgog> [--max-part-size SIZE]
rgog.py unpack <archive.rgog> -o <output_dir> [--debug] [--chunks-only]
rgog.py list <archive.rgog> [--detailed] [--build BUILD_ID]
rgog.py extract <archive.rgog> -o <output_dir> [--build BUILD_ID] [--chunks-only]
rgog.py verify <archive.rgog> [--build BUILD_ID]
rgog.py info <archive.rgog>
Commands:
pack Create an RGOG archive from a GOG v2 directory structure
unpack Unpack an RGOG archive to recreate the original GOG v2 directory structure
list List contents of an RGOG archive
extract Extract builds and/or chunks from an RGOG archive
verify Verify MD5 checksums of all data in an RGOG archive
info Display statistics and information about an RGOG archive
"""
import argparse
import sys
from pathlib import Path
# Import subcommands
from rgog import pack, unpack, list as list_cmd, extract, verify, info
def main():
"""Main CLI entry point."""
parser = argparse.ArgumentParser(
description="RGOG - Reproducible GOG Archive Tool",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
subparsers = parser.add_subparsers(dest='command', help='Command to execute')
# Pack command
pack_parser = subparsers.add_parser('pack', help='Create an RGOG archive')
pack_parser.add_argument('input_dir', type=Path, help='Input directory (GOG v2 structure)')
pack_parser.add_argument('-o', '--output', type=Path, required=True, help='Output RGOG file')
pack_parser.add_argument('--max-part-size', type=str, default='2GB',
help='Maximum size per part (e.g., 2GB, 4GB, 10GB). Default: 2GB')
pack_parser.add_argument('--type', type=str, choices=['base', 'patch'], default='base',
help='Archive type. Default: base')
pack_parser.add_argument('--build', type=int, help='Pack only specific build ID')
# Unpack command
unpack_parser = subparsers.add_parser('unpack', help='Unpack RGOG archive to original structure')
unpack_parser.add_argument('archive', type=Path, help='RGOG archive file')
unpack_parser.add_argument('-o', '--output', type=Path, required=True, help='Output directory')
unpack_parser.add_argument('--debug', action='store_true',
help='Create human-readable JSON debug copies of build records')
unpack_parser.add_argument('--chunks-only', action='store_true',
help='Unpack only chunk files (skip build metadata)')
unpack_parser.add_argument('--threads', type=int, default=0,
help='Number of threads for extraction (0=auto, default: CPU count)')
# List command
list_parser = subparsers.add_parser('list', help='List archive contents')
list_parser.add_argument('archive', type=Path, help='RGOG archive file')
list_parser.add_argument('--detailed', action='store_true',
help='Show detailed build information (decompresses repositories)')
list_parser.add_argument('--build', type=int, help='Show specific build details')
# Extract command
extract_parser = subparsers.add_parser('extract', help='Extract from archive')
extract_parser.add_argument('archive', type=Path, help='RGOG archive file')
extract_parser.add_argument('-o', '--output', type=Path, required=True, help='Output directory')
extract_parser.add_argument('--build', type=int, help='Extract specific build only')
extract_parser.add_argument('--chunks-only', action='store_true',
help='Extract only chunk files')
extract_parser.add_argument('--reassemble', action='store_true',
help='Reassemble chunks into final files (requires manifest data)')
# Verify command
verify_parser = subparsers.add_parser('verify', help='Verify archive integrity')
verify_parser.add_argument('archive', type=Path, help='RGOG archive file')
verify_parser.add_argument('--build', type=int, help='Verify specific build only')
verify_parser.add_argument('--quick', action='store_true',
help='Quick verify (check structure only, skip MD5)')
verify_parser.add_argument('--detailed', action='store_true',
help='Show detailed verification of each file')
verify_parser.add_argument('--full', action='store_true',
help='Full verify (decompress chunks and verify both compressed and decompressed MD5)')
verify_parser.add_argument('--threads', type=int, default=0,
help='Number of threads for verification (0=auto, default: CPU count)')
# Info command
info_parser = subparsers.add_parser('info', help='Show archive information')
info_parser.add_argument('archive', type=Path, help='RGOG archive file')
info_parser.add_argument('--stats', action='store_true',
help='Show detailed statistics')
args = parser.parse_args()
if not args.command:
parser.print_help()
return 1
# Execute command
try:
if args.command == 'pack':
return pack.execute(args)
elif args.command == 'unpack':
return unpack.execute(args)
elif args.command == 'list':
return list_cmd.execute(args)
elif args.command == 'extract':
return extract.execute(args)
elif args.command == 'verify':
return verify.execute(args)
elif args.command == 'info':
return info.execute(args)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return 1
return 0
if __name__ == '__main__':
sys.exit(main())