git » repo-mgmt.git » main » tree

[main] / publish-pkg.py

#!/usr/bin/env python3

import os
import sys
import subprocess
from subprocess import DEVNULL, PIPE, STDOUT

class Return:
    def __init__(self, rv, out=None):
        self.rv = rv
        self.out = out
    def __bool__(self):
        return self.rv == 0
    def __int__(self):
        return self.rv
    def __str__(self):
        if self.out:
            return self.out
        return str(self.rv)

def sub(*args, **kwargs):
    c = subprocess.run(*args, **kwargs)
    return Return(c.returncode, c.stdout)

def subc(*args, **kwargs):
    c = subprocess.run(*args, **kwargs)
    if c.returncode != 0:
        print("subprocess failed: ", args)
        print("code:", c.returncode)
        sys.exit(1)
    return Return(c.returncode, c.stdout)


releasepkg="/mnt/nfs/pkg"

os.chdir("/sources")
subc("mountpoint -q pkg && umount pkg || true", shell=True)
os.chdir("pkg-untested")

bases={}
count=0

# this is os.walk, simplified, but yielding DirEntries, and only for non-dirs,
# one by one.
def filewalk(top):
	stack = [top]
	while stack:
		top = stack.pop()
		dirs = []
		with os.scandir(top) as entries:
			for entry in entries:
				if entry.is_dir():
					dirs.append(entry.name)
				else:
					yield top, entry
		for dirname in reversed(dirs):
			new_path = os.path.join(top, dirname)
			stack.append(new_path)

for root, entry in filewalk('.'):
	if entry.name.endswith('.pkg.tar.xz'):
		if not entry.is_file():
			continue
		if root not in bases.keys():
			bases[root] = []
		bases[root].append(entry.name)
		count+=1
		#print(os.path.join(root, entry.name))


if count == 0:
	print("Nothing to do (?)")
	subc(["mount", "/sources/pkg"])
	sys.exit(0)

print(f"Found {count} packages in these repos:")
for k in bases.keys():
    _,arch,repo = k.split('/')
    print(f"{arch}:{repo}:")
    for f in sorted(bases[k]):
        print(f"\t{f}")
try:
    input("Press enter to continue.")
except KeyboardInterrupt:
    print("\nBailing out.")
    subc(["mount", "/sources/pkg"])
    sys.exit(1)

bp=os.getcwd()
print("Moving packages to release directory",end="")
for k in bases.keys():
	print(f"\nFrom {k}:.",end='',flush=True)
	os.chdir(os.path.join(bp, k))
	to=os.path.join(releasepkg, k)
	for f in bases[k]:
		c = ["mv", f, os.path.join(to, f)]
		#print(c)
		subc(c)
		print(".",end='',flush=True)

print("\nDone")

signifycmd=["asignify", "sign", "-Nn", "-S", ".sig", "/etc/pacman.d/keys/armlfs-release-key"]
for k in bases.keys():
	for f in bases[k]:
		signifycmd.append(os.path.join(k,f))


print("Signing packages (prepare for password entry)")
os.chdir(releasepkg)
subc(signifycmd)

print("Adding packages to repos")
for k in bases.keys():
	_,arch,repo = k.split('/')
	# Do not use "-R": we will cleanup the release repo
	# with other methods when that becomes relevant, later.
	# - the point is _not_ to hit users with a 404 if they have not synced lately.
	# (that is one of the _big_ "i hate living here" moments for me on Arch, so i'd rather not replicate it.)
	repocmd = ["repo-add", repo + '.db.tar.gz' ]
	for f in bases[k]:
		repocmd.append(f)
	os.chdir(os.path.join(releasepkg, k))
	#print(arch,repo, len(repocmd))
	print(f"{arch}:{repo}")
	subc(repocmd)



os.chdir("/sources/pkg-untested")
subc(["find", "-type", "l", "-delete"])
subc(["find", "-type", "c", "-delete"])
subc(["find", "-type", "f", "-delete"])
subc(["mount", "/sources/pkg"])