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
|
#!/usr/bin/python3
# SPDX-FileCopyrightText: 2015-2025 Alexey Rochev
#
# SPDX-License-Identifier: CC0-1.0
import argparse
import gzip
import json
import logging
import shutil
import subprocess
import sys
import tarfile
from enum import Enum
from pathlib import Path, PurePath
from tempfile import TemporaryDirectory
def get_project_version() -> str:
cmakelists = "CMakeLists.txt"
if not Path(cmakelists).exists():
raise RuntimeError(f"{cmakelists} doesn't exist")
process = subprocess.run(["cmake", "--trace-format=json-v1", "--trace-expand", "-P", cmakelists],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
text=True)
for line in process.stderr.splitlines():
trace = json.loads(line)
if "cmd" in trace and trace["cmd"].lower() == "project":
args = trace["args"]
found_version = False
for arg in args:
if found_version:
return arg
if arg.lower() == "version":
found_version = True
raise RuntimeError("Failed to find version in CMake trace output")
def make_tar_archive(tempdir: PurePath, debian: bool) -> PurePath:
version = get_project_version()
root_directory = f"tremotesf-{version}"
if debian:
archive_filename = f"tremotesf_{version}.orig.tar"
else:
archive_filename = f"tremotesf-{version}.tar"
archive_path = tempdir / archive_filename
logging.info(f"Making tar archive {archive_path}")
files = subprocess.run(["git", "ls-files", "--recurse-submodules", "-z"],
check=True,
stdout=subprocess.PIPE,
text=True).stdout.split("\0")
# There is an empty string in the end for some reason
files = [f for f in files if f]
logging.info(f"Archiving {len(files)} files")
with tarfile.open(archive_path, mode="x") as tar:
for file in files:
tar.add(file, arcname=str(PurePath(root_directory, file)), recursive=False)
return archive_path
def compress_gzip(output_directory: PurePath, tar_path: PurePath) -> PurePath:
gzip_path = output_directory / tar_path.with_suffix(".tar.gz").name
logging.info(f"Compressing {tar_path} to {gzip_path}")
with open(tar_path, mode="rb") as tar_file, gzip.open(gzip_path, mode="xb") as gzip_file:
shutil.copyfileobj(tar_file, gzip_file)
return gzip_path
def compress_zstd(output_directory: PurePath, tar_path: PurePath) -> PurePath:
zstd_path = output_directory / tar_path.with_suffix(".tar.zst").name
logging.info(f"Compressing {tar_path} to {zstd_path}")
subprocess.run(["zstd", str(tar_path), "-o", str(zstd_path)], check=True, stdout=sys.stderr)
return zstd_path
class CompressionType(Enum):
GZIP = "gzip"
ZSTD = "zstd"
def main():
logging.basicConfig(level=logging.INFO, stream=sys.stderr)
parser = argparse.ArgumentParser()
parser.add_argument("compression_types",
nargs="+",
choices=[member.value for member in list(CompressionType)],
help="Compression type")
parser.add_argument("--output-directory",
help="Directory where to place archives. Defaults to current directory")
parser.add_argument("--debian",
action="store_true",
help="Make Debian upstream tarball")
args = parser.parse_args()
compression_types = [CompressionType(arg) for arg in args.compression_types]
if args.output_directory:
output_directory = PurePath(args.output_directory)
else:
output_directory = Path.cwd()
with TemporaryDirectory() as tempdir:
tar = make_tar_archive(PurePath(tempdir), args.debian)
for compression_type in compression_types:
match compression_type:
case CompressionType.GZIP:
print(compress_gzip(output_directory, tar))
case CompressionType.ZSTD:
print(compress_zstd(output_directory, tar))
if __name__ == "__main__":
main()
|