From 77308a521f6f8f974c5e0e06d9803eaa7a0efa96 Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Fri, 21 Feb 2025 10:45:49 +0000 Subject: [PATCH 1/6] Fstrings and some other formatting --- deckdebuild | 16 ++++++++-------- libdeckdebuild/__init__.py | 38 ++++++++++++++++++++++---------------- libdeckdebuild/proctee.py | 2 +- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/deckdebuild b/deckdebuild index 443a1f4..974dd12 100755 --- a/deckdebuild +++ b/deckdebuild @@ -62,7 +62,7 @@ class Conf(dict): elif isinstance(value, str) and value.lower() == 'false': value = False if isinstance(value, bool): - action = "store_{}".format(str(not value).lower()) + action = f"store_{str(not value).lower()}" new_key = key+'_action' default[new_key] = action default[key] = value @@ -78,37 +78,37 @@ def main(): parser.add_argument("-r", "--root-cmd", help="command used to gain root_privileges" " env: DECKDEBUILD_ROOT_CMD" - " default: {}".format(conf.root_cmd), + f" default: {conf.root_cmd}", default=conf.root_cmd) parser.add_argument("-u", "--user", help="build username (created if it doesn't exist)" " env: DECKDEBUILD_USER" - " default: {}".format(conf.user), + f" default: {conf.user}", default=conf.user) parser.add_argument("-p", "--preserve-build", help="don't remove build deck after build" " env: DECKDEBUILD_PRESERVE_BUILD" - " default: {}".format(conf.preserve_build), + f" default: {conf.preserve_build}", action=conf.preserve_build_action) parser.add_argument("-f", "--faketime", help="use faketime (must be installed)" " env: DECKDEBUILD_FAKETIME" - " default: {}".format(conf.faketime), + f" default: {conf.faketime}", action=conf.faketime_action) parser.add_argument("--satisfydepends-cmd", help="program used to satisfy build dependencies" " env: DECKDEBUILD_SATISFYDEPENDS_CMD" - " default: {}".format(conf.satisfydepends_cmd), + f" default: {conf.satisfydepends_cmd}", default=conf.satisfydepends_cmd) parser.add_argument("--vardir", help="var data path" " env: DECKDEBUILD_VARDIR" - " default: {}".format(conf.vardir), + f" default: {conf.vardir}", default=conf.vardir) parser.add_argument("-b", "--build-source", help="Build source package too." " env: DECKDEBUILD_BUILD_SOURCE" - " default: {}".format(conf.build_source), + f" default: {conf.build_source}", action=conf.build_source_action) parser.add_argument("path_to_buildroot", help="Path to an exisiting buildroot") diff --git a/libdeckdebuild/__init__.py b/libdeckdebuild/__init__.py index 32d0803..b91f6df 100644 --- a/libdeckdebuild/__init__.py +++ b/libdeckdebuild/__init__.py @@ -73,7 +73,7 @@ def deckdebuild( path_builds = join(vardir, 'builds') if not isdir(buildroot): - raise DeckDebuildError("buildroot `%s' is not a directory" % buildroot) + raise DeckDebuildError(f"buildroot `{buildroot}' is not a directory") source_name = debsource.get_control_fields(path)['Source'] source_version = debsource.get_version(path) @@ -98,25 +98,33 @@ def deckdebuild( system([satisfydepends_cmd, "--chroot", chroot], prefix='satisfydepends') # create user if it doesn't already exist - user_exists = \ - get_returncode(["chroot", chroot, "getent", "passwd", user], - prefix='user-check') == 0 + user_exists = get_returncode( + ["chroot", chroot, "getent", "passwd", user], + prefix='user-check' + ) == 0 if not user_exists: - system(["chroot", chroot, "useradd", "-m", user], prefix='add-user') + system( + ["chroot", chroot, "useradd", "-m", user], + prefix='add-user') orig_cwd = os.getcwd() os.chdir(path) - user_home: str = get_output(["chroot", chroot, "su", user, "-l", "-c", - "pwd"], prefix='user-home') + user_home: str = get_output( + ["chroot", chroot, "su", user, "-l", "-c", "pwd"], + prefix='user-home') # transfer package over to chroot chr_source_dir = join(chroot, relpath(user_home, '/'), source_dir) shutil.copytree(path, chr_source_dir) # fix permissions for build - build_uid, build_gid = get_output(['chroot', chroot, 'su', user, '-l', '-c', - 'cat /etc/passwd | grep build | cut -d":" -f3,4'], prefix='get uid').rstrip().split(':') + build_uid, build_gid = get_output( + ['chroot', chroot, 'su', user, '-l', '-c', + 'cat /etc/passwd | grep build | cut -d":" -f3,4' + ], + prefix='get uid' + ).rstrip().split(':') build_uid = int(build_uid) build_gid = int(build_gid) @@ -137,18 +145,16 @@ def deckdebuild( symlink(build_dir, build_link) # build package in chroot - build_cmd = "cd {};".format(shlex.quote(source_dir)) + build_cmd = f"cd {shlex.quote(source_dir)};" if faketime: faketime_fmt = debsource.get_mtime(path).strftime("%Y-%m-%d %H:%M:%S") - build_cmd += "faketime -f {};".format(shlex.quote(faketime_fmt)) + build_cmd += f"faketime -f {shlex.quote(faketime_fmt)};" if build_source: - build_cmd += "dpkg-buildpackage -d -uc -us -F -r{}".format( - shlex.quote(root_cmd)) + build_cmd += f"dpkg-buildpackage -d -uc -us -F -r{shlex.quote(root_cmdv)};" else: - build_cmd += "dpkg-buildpackage -d -uc -us -b -r{}".format( - shlex.quote(root_cmd)) + build_cmd += f"dpkg-buildpackage -d -uc -us -b -r{shlex.quote(root_cmd)};" trapped = StringIO() try: @@ -164,7 +170,7 @@ def deckdebuild( os.seteuid(orig_uid) output = trapped.getvalue() - build_log = "%s/%s_%s.build" % (output_dir, source_name, source_version) + build_log = f"{output_dir}/{source_name}_{source_version}.build" with open(build_log, 'w') as fob: fob.write(output) diff --git a/libdeckdebuild/proctee.py b/libdeckdebuild/proctee.py index 66782f9..f04caf9 100644 --- a/libdeckdebuild/proctee.py +++ b/libdeckdebuild/proctee.py @@ -31,7 +31,7 @@ def _proctee( else: prefix = prefix + ' => ' - print("# {}".format(' '.join(map(shlex.quote, cmd)))) + print(f"# {' '.join(map(shlex.quote, cmd))}") proc = subprocess.Popen( cmd, From b8fbeb6ed5549b749621197e24265a4231ba0535 Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Fri, 21 Feb 2025 10:49:48 +0000 Subject: [PATCH 2/6] Remove redundant leo file --- deckdebuild.leo | 519 ------------------------------------------------ 1 file changed, 519 deletions(-) delete mode 100644 deckdebuild.leo diff --git a/deckdebuild.leo b/deckdebuild.leo deleted file mode 100644 index bd7f718..0000000 --- a/deckdebuild.leo +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - - - - - - -Project -research -explore sbuild -explore pbuilder -explore gdebi - -design -implementation -setup a build chroot -most common build dependencies - -perform build manually -cli code -build package -destroy deck unless build fails or requested -run as suid -add configurable vardir option (root-only) -add a configuration file -bug: deckdebuild won't build a package with an epoch -bug: useraufs-mount fails to mount branches with : in their path -bug: mount -t aufs won't work with paths that have ':' in them -bug: mount -t aufs fails on mount paths with : in them - - - - - - - -@nocolor - -* SUMMARY -types of build package relationships - Build-Depends - Build-Conflicts - - Build-Depends-Indep - build-Conflicts-Indep - -pbuilder-satisfydepends does what we want - works from out of the chroot - handles build-depends, build-depends-indep, build-conflicts and build-conflicts-indep - -dpkg-checkbuilddeps - check build dependencies and conflicts - we don't actually need this if satisfydepends succeeds - -three versions of pbuilder-satisfydepends in Ubuntu - experimental - gdebi - -usage of satisfydepends - cd /path/to/package - /usr/lib/pbuilder/pbuilder-satisfydepends - installs build-dependencies - doesn't check if they already exist - - works from Gentoo (with --chroot) - gdebi on the other hand, wouldn't be installed - -Virtual packages - virtual packages only exists logically - name describes common functionality (multiple implementations of awk) - list of virtual package names - new packages must use virtual package names where apropriate - examples - awk - c-shell - c-compiler - java-compiler - /usr/share/doc/debian-policy/virtual-package-names-list.txt.gz - -tweak virtual package selections by installing a package that provides the dependency to the build root - no need for stupid tables - -* QUESTIONS -Q: how does pbuilder resolve build dependencies? -A: with pbuilder-satisfydepends ---- -Q: do we debuilding from the source directory or do we only build source packages? or both? -A: we build from source directory - this way we don't have to create tarballs - sometimes creating tarballs is not an option ---- -Q: does debuild clean the environment first? -A: yes ---- -A: we debuild directly from the source directory, otherwise we have to create the source tarball - and thats not always possible ---- -Q: should we make package build configurable? -A: - we could just fix any packages that don't build with fakeroot for whatever reason - -* RANDOM IDEAS - get apt to build-dep our package? - add our package Source to its database somehow? - - write a specialized program of our own to resolve build dependencies? - - compile with dpkg-buildpackage - - show shell commands we are performing to allow user to manually reproduce them - - modify sbuild? - - if we add a source to apt cache, specify which package to query - - allow arbitrary satisfydepends program - defaults to pbuilder's - -* ABANDONED QUESTIONS -Q: does python-apt include code that makes resolving dependency versions easier? -Q: how does sbuild install them? -Q: how do we get apt-get to install them for an arbitrary source package? -Q: how do we add get APT to build-dep our package? - -* RESOURCE: file:///home/z/docs/debian/www.us.debian.org/doc/debian-policy/ch-relationships.html#s-sourcebinarydeps - -Q: how does sbuild extract build dependencies? - -it extracts Build-Depends Build-Depends-Indep Build-Conflicts and Build-Conflicts-Indep from the dsc -writes them to debian/.sbuild-build-deps - -extracts Architecture - -it applies a global table to those dependencies - - negative dependencies (I.e., conflicts) marked with "!" - -filters missing deps that are essential -if deps are virtual packages, replaces them with alternatives over all provided packages - -it uses dpkg --set-selections to install packages - -after tha it removes the installed debs - -DEBIAN_FRONTEND = "noninteractive" - - -* SUMMARY -three versions of pbuilder-satisfydepends in Ubuntu - experimental - gdebi - -usage of satisfydepends - cd /path/to/package - /usr/lib/pbuilder/pbuilder-satisfydepends - installs build-dependencies - doesn't check if they already exist - - works from Gentoo (with --chroot) - gdebi on the other hand, wouldn't be installed - -Virtual packages - virtual packages only exists logically - name describes common functionality (multiple implementations of awk) - list of virtual package names - new packages must use virtual package names where apropriate - examples - awk - c-shell - c-compiler - java-compiler - /usr/share/doc/debian-policy/virtual-package-names-list.txt.gz - -tweak virtual package selections by installing a package that provides the dependency to the build root - no need for stupid tables - -how satisfydepends works - -default - uses apt-cache to get the cached package version and check if it satisfies the dependency - uses dpkg --compare-versions "$PACKAGEVERSION" "$COMPARESTRING" "$DEPSVERSION" - - resolves build dependencies by simulating apt-get - if it doesn't work, it assumes the package is virtual and tries to find a matching Provides in the apt cache - apt-cache showpkg <virtual-package> - if multiple provides exists: selects the last - - if any build dependency can not be satisfied, errors out - - this way a list of packages to install is created - installed with apt-get -u --force-yes install <package list> - - - removes conflicting build-depends if they exist - -gdebi (written by Michael Vogt- knows what hes doing) - - INSTALL=$(/usr/bin/gdebi --quiet --apt-line --root $CHROOT $DEBIAN_CONTROL) -$CHROOTEXEC /usr/bin/apt-get install -y $INSTALL -features - written in python - has a GUI frontend - capable of resolving dependencies of packages that are not part of the archive - -* DEPENDENCIES -pbuilder -deck - -* CLI SYNTAX -deckdebuild [ -options ] /path/to/chroot [ /path/to/output/dir ] - -p --preserve-build - DECKDEBUILD_PRESERVE_BUILD=0 - - -u --user <username> - DECKDEBUILD_USER="build" - - -r --root-cmd <rootcmd> - DECKDEBUILD_ROOT_CMD="fakeroot" - - --satisfydepends-cmd /path/to/prog - DECKDEBUILD_SATISFYDEPENDS_CMD=/usr/lib/pbuilder/pbuilder-satisfydepends - -* IDEAS -show commands executed - so user can reconstruct commands manually in case of error - -don't use fakeroot? (doesn't matter anyhow?) - -clean environment before chrooting? - so we don't get weird locale errors - -make deckdebuild suid? - if chroot is unescapable then this is secure if we don't allow satisfydepends-cmd - or maybe we only allow satisfydepends-cmd when not run suid - - we can additionally restrict who is allowed to execute via group execution privileges - -* LOGIC -data flow - input: package source directory - output: - binary debs - <package-source-name>.build - -export DEBIAN_FRONTEND="noninteractive" - -parse options - option precedence - cli option - environment - built-in default - -check that we are running as root (we need root privileges) - -deck the build root -install the build dependencies - /usr/lib/pbuilder/pbuilder-satisfydepends --chroot /path/to/build/root - installs build-dependencies - doesn't check if they already exist - -if build user doesn't exist create a build user -copy the package over to the build user's home -build the package with dpkg-buildpackage under fakeroot - fakeroot dpkg-buildpackage -rfakeroot -uc -us -b - -if the build fails, raise an exception? -if the build succeeds put the packages in the parent directory of the source package + build log - -unless -p, we delete the deck environment the package was built in - -* FILE STRUCTURE -/var/lib/deckdebuild - - chroots/<package> - /home/<user>/<package> - - builds/<package> -> ../chroots/<package>/home/<user>/<package> - -roadmap - perform package build manually - cli code - save build log - destroy deck - suid stuff - no satisfydepends - path should be set - - - - -location - /turnkey/fab/buildroots - e.g., /turnkey/fab/buildroots/jaunty - -has to be a real directory, not a deck - -do we have to mount proc and devpts and such? - lets start without it - if we have to, then we'll add some default code - - the pbuilder default - USEPROC=yes - USEDEVPTS=yes - USEDEVFS=no - -configuration after debootstrap - point sources.list to the proxy (127.0.0.1:9999) - apt-get install fakeroot build-essential debhelper cdbs dpatch autotools-dev - -install most common build dependencies - -unless your sources.list contains a private repository for turnkey build components - manually build and install autoversion into the buildroot - -build depedencies virtual packages - if you have preferences for virtual packages - install them yourself - -gotcha - LOCALE warnings from perl - reason is LANG="en_GB" setting - if we clean environment prior to chroot we won't have this problem - or just clean LANG - - -mkdir -p /var/lib/deckdebuild/{chroots,builds}/hello-debhelper -deck /turnkey/fab/buildroots/jaunty/ /var/lib/deckdebuild/chroots/hello-debhelper/ - -# satisfy dependencies -/usr/lib/pbuilder/pbuilder-satisfydepends --chroot <chroot> - -# check if user exists -getenv passwd <username> # from libc6 package~ - exists: prints password entry and returns exitcode == 0 - else: doesn't print anything, exitcode == 2 - - alternative - grep -q ^<username>: /etc/passwd - -# add user -useradd -m <username> # useradd is from the passwd package - alternatives - adduser (adduser package) - is an interactive perl program - - if user already exists prints - useradd: user <username> exists # to stderr - exitcode == 9 - -# delete any remnants -chroot <chroot> su <username> -l -c "rm -rf <package-basename>" - -# copy package to chroot -tar -C ../ -cvf - $(basename $(pwd)) | chroot <chroot> su <username> -l -c "tar -xvf -" - -# setup link in /var/lib/deckdebuild/builds - -# perform build -chroot $c su <username> -l -c "cd hello-debhelper-2.1.1; dpkg-buildpackage -rfakeroot -uc -us -b" - successful build: exitcode = 1 - -# get home directory -HOMEDIR=$(chroot <chroot> su build -l -c pwd) - -cp <chroot>/$HOMEDIR/*.deb ../ # owned by invoking user - -deck -D /var/lib/deckdebuild/chroots/<package> - - -cat /var/lib/apt/lists/*Sources | - grep-dctrl -n -s Build-Depends ""| - perl -pe 's/\s*[,\|]\s*/\n/g' | - perl -pe 's/\s*\(.*//; s/^\s*//; s/\[.*//' | sort | uniq -c |sort -n -r - - 10257 debhelper - 2157 cdbs - 1338 dpatch - 1330 autotools-dev - 850 libx11-dev - 736 libgtk2.0-dev - 597 pkg-config - 591 zlib1g-dev - 488 autoconf - 477 gettext - - 458 libxt-dev - 449 libncurses5-dev - 437 perl - 397 flex - 394 bison - 390 libtool - 381 libglib2.0-dev - 375 libxext-dev - 355 quilt - 344 libxml2-dev - 324 po-debconf - 323 x-dev - 322 kdelibs4-dev - - 316 automake1.9 - 306 python-all-dev - 290 libssl-dev - 265 python-central - 260 libxpm-dev - 258 libxml-parser-perl - 246 texinfo - 241 python-support - 241 python-dev - 237 libpng12-dev - 236 libgnomeui-dev - 234 libsdl1.2-dev - 233 libgtk1.2-dev - 227 libreadline5-dev - 221 dpkg-dev - 218 xutils - 218 libjpeg62-dev - 205 libglade2-dev - 204 docbook-to-man - 202 libqt3-mt-dev - 178 intltool - 175 libxmu-dev - 172 libxaw7-dev -* CLI SYNTAX -deckdebuild [ -options ] /path/to/chroot - -p --preserve-build - DECKDEBUILD_PRESERVE_BUILD=0 - - -u --user <username> - DECKDEBUILD_USER="build" - - -r --root-cmd <rootcmd> - DECKDEBUILD_ROOT_CMD="fakeroot" - - --satisfydepends-cmd /path/to/prog - DECKDEBUILD_SATISFYDEPENDS_CMD=/usr/lib/pbuilder/pbuilder-satisfydepends - - -LOGIC - see manual build` - -Q: how do I identify packages? -A: -parse the control file and grab the names of all packages that are supposed to be built - copy any deb that starts with <package>_ - -alternatives - copy all debs - parse the changes file and copy only the debs - - - -logic - no satisfydepends should be allowed to set in suid mode - files should be copied as user - parent directory should be writeable by invoking user - e.g., don't write to directory owned by root - - - - -option to set an alternative to the default /var/lib/deckdebuild - -Q: what do we call it?? - -vardir -tmpdir - - -TODO: - add cli reference with example - function that parses configuration file - -format - <option> <value> - e.g., - user build - - -IDEAS - filter out epochs - - - -GOTCHA: cli doesn't support ':' in names? - -IDEAS - support escaping of : character? - change the character to something that can't be used in filenames - change the cli so that branches can be specified as arguments? -mount -t aufs -o dirs=a:b none c - -test: - - -Q: what uses useraufs? -A: - sumo - deck - - -WORKAROND: create a temporary symbolic link to the problem directory - -IDEA - sequence of append commands? - wouldn't work if all branches have ':' in them - -SUMMARY: - no know fix - - this is probably due to a shell script bug in /sbin/mount.aufs - - may have already been fixed? - -WORKAROUND: - ignore epochs in deckdebuild - - - From e45e94af5a7cf089b4df61655403bc7f20a42dbe Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Fri, 21 Feb 2025 11:37:28 +0000 Subject: [PATCH 3/6] Linting and style --- deckdebuild | 2 +- libdeckdebuild/__init__.py | 46 +++++++++++++++++++++++-------------- libdeckdebuild/debsource.py | 21 +++++++++++------ libdeckdebuild/proctee.py | 41 ++++++++++++++++++--------------- 4 files changed, 67 insertions(+), 43 deletions(-) diff --git a/deckdebuild b/deckdebuild index 974dd12..5df5dcf 100755 --- a/deckdebuild +++ b/deckdebuild @@ -129,5 +129,5 @@ def main(): fatal(e) -if __name__=='__main__': +if __name__ == '__main__': main() diff --git a/libdeckdebuild/__init__.py b/libdeckdebuild/__init__.py index b91f6df..d5cd3a8 100644 --- a/libdeckdebuild/__init__.py +++ b/libdeckdebuild/__init__.py @@ -9,22 +9,22 @@ from os.path import join, isdir, exists, dirname, lexists, relpath -import os import os import sys import shutil import subprocess from subprocess import PIPE -from typing import List from io import StringIO import shlex from libdeckdebuild import debsource from libdeckdebuild.proctee import proctee_joined, proctee + class DeckDebuildError(Exception): pass + def symlink(src, dst): if not exists(dirname(dst)): os.makedirs(dirname(dst)) @@ -35,37 +35,45 @@ def symlink(src, dst): os.symlink(src, dst) print(f'# ln -s {shlex.quote(src)} {shlex.quote(dst)}') -def system(cmd: List[str], prefix=None): + +def system(cmd: list[str], prefix=None): proctee_joined(cmd, None, True, prefix=prefix) -def get_returncode(cmd: List[str], prefix=None) -> int: + +def get_returncode(cmd: list[str], prefix=None) -> int: return proctee_joined(cmd, None, False, prefix=prefix)[0] -def get_output(cmd: List[str], prefix=None) -> str: + +def get_output(cmd: list[str], prefix=None) -> str: return proctee(cmd, None, None, False, prefix=prefix)[1].rstrip() + def get_source_dir(name, version): if ':' in version: version = version.split(':', 1)[1] return name + "-" + version + def apply_faketime_patch(chroot, user): - patch_command = ["find", "-name", "configure", "-exec", "sed", "-i", "s/test \"$2\" = conftest.file/true/", "{}", ";"] + patch_command = ["find", "-name", "configure", "-exec", + "sed", "-i", "s/test \"$2\" = conftest.file/true/", + "{}", ";"] system(["chroot", chroot, "su", user, "-l", "-c", *patch_command]) + def deckdebuild( path: str, buildroot: str, output_dir: str, - preserve_build: bool=False, - user: str='build', - root_cmd: str='fakeroot', - satisfydepends_cmd: str='/usr/lib/pbuilder/pbuilder-satisfydepends', - faketime: bool=False, - vardir: str='/var/lib/deckdebuilds', - build_source: bool=False): + preserve_build: bool = False, + user: str = 'build', + root_cmd: str = 'fakeroot', + satisfydepends_cmd: str = '/usr/lib/pbuilder/pbuilder-satisfydepends', + faketime: bool = False, + vardir: str = '/var/lib/deckdebuilds', + build_source: bool = False): vardir = os.fspath(vardir) @@ -151,16 +159,20 @@ def deckdebuild( faketime_fmt = debsource.get_mtime(path).strftime("%Y-%m-%d %H:%M:%S") build_cmd += f"faketime -f {shlex.quote(faketime_fmt)};" + build_cmd += "dpkg-buildpackage -d -uc -us" + if build_source: - build_cmd += f"dpkg-buildpackage -d -uc -us -F -r{shlex.quote(root_cmdv)};" + build_cmd += f" -F -r{shlex.quote(root_cmdv)};" else: - build_cmd += f"dpkg-buildpackage -d -uc -us -b -r{shlex.quote(root_cmd)};" + build_cmd += f" -b -r{shlex.quote(root_cmd)};" trapped = StringIO() try: - proctee_joined(["chroot", chroot, "mount", "-t", "tmpfs", "none", "/dev/shm"], + proctee_joined( + ["chroot", chroot, "mount", "-t", "tmpfs", "none", "/dev/shm"], output=trapped, check=True, prefix='mount') - proctee_joined(["chroot", chroot, "su", user, "-l", "-c", build_cmd], + proctee_joined( + ["chroot", chroot, "su", user, "-l", "-c", build_cmd], output=trapped, check=True, prefix='dpkg-buildpackage') except Exception as e: import traceback diff --git a/libdeckdebuild/debsource.py b/libdeckdebuild/debsource.py index 9cd9c44..727cdec 100644 --- a/libdeckdebuild/debsource.py +++ b/libdeckdebuild/debsource.py @@ -11,9 +11,11 @@ from debian import deb822 from os.path import * + class Error(Exception): pass + def get_control_fields(path): controlfile = join(path, "debian/control") control_dict = dict() @@ -21,23 +23,28 @@ def get_control_fields(path): control_dict.update(paragraph) return control_dict + def get_packages(path): controlfile = join(path, "debian/control") - return [ re.sub(r'^.*?:', '', line).strip() - for line in open(controlfile).readlines() - if re.match(r'^Package:', line, re.I) ] + return [re.sub(r'^.*?:', '', line).strip() + for line in open(controlfile).readlines() + if re.match(r'^Package:', line, re.I)] + def get_version(path): changelogfile = join(path, "debian/changelog") if not exists(changelogfile): - raise Error("no such file or directory `%s'" % changelogfile) + raise Error(f"no such file or directory `{changelogfile}'") for line in open(changelogfile).readlines(): - m = re.match('^\w[-+0-9a-z.]* \(([^\(\) \t]+)\)(?:\s+[-+0-9a-z.]+)+\;',line, re.I) + m = re.match( + r'^\w[-+0-9a-z.]* \(([^\(\) \t]+)\)(?:\s+[-+0-9a-z.]+)+\;', + line, re.I) if m: return m.group(1) - raise Error("can't parse version from `%s'" % changelogfile) + raise Error(f"can't parse version from `{changelogfile}'") + def get_mtime(path): from email.utils import parsedate @@ -50,7 +57,7 @@ def get_mtime(path): continue break - m = re.match('.*> (.*)', line) + m = re.match(r'.*> (.*)', line) assert m return datetime.datetime(*parsedate(m.group(1))[:6]) diff --git a/libdeckdebuild/proctee.py b/libdeckdebuild/proctee.py index f04caf9..92c80cd 100644 --- a/libdeckdebuild/proctee.py +++ b/libdeckdebuild/proctee.py @@ -1,7 +1,7 @@ import subprocess from subprocess import PIPE, STDOUT from threading import Thread, Lock -from typing import List, Tuple, Optional +from typing import Optional import shlex import sys import io @@ -17,13 +17,14 @@ if EXPERIMENTAL_COLORS: colorama.init(autoreset=True) + def _proctee( - cmd: List[str], - stdout_sinks: List[io.TextIOBase], - stderr_sinks: List[io.TextIOBase], + cmd: list[str], + stdout_sinks: list[io.TextIOBase], + stderr_sinks: list[io.TextIOBase], prefix: Optional[str] = None, **kwargs - ) -> int: + ) -> int: if prefix is None: prefix = '' elif prefix and EXPERIMENTAL_COLORS: @@ -35,15 +36,15 @@ def _proctee( proc = subprocess.Popen( cmd, - stdout = PIPE, - stderr = PIPE, - bufsize = 0, - text = True, + stdout=PIPE, + stderr=PIPE, + bufsize=0, + text=True, **kwargs ) lock = Lock() - def reader(io_in: io.TextIOBase, io_out: List[io.TextIOBase]): + def reader(io_in: io.TextIOBase, io_out: list[io.TextIOBase]): buff = '' while True: buff += io_in.read(1) @@ -73,19 +74,21 @@ def reader(io_in: io.TextIOBase, io_out: List[io.TextIOBase]): return proc.returncode + def proctee( - cmd: List[str], + cmd: list[str], stdout: Optional[io.TextIOBase], stderr: Optional[io.TextIOBase], - check: bool=False, + check: bool = False, **kwargs - ) -> Tuple[int, str, str]: + ) -> tuple[int, str, str]: if stdout is None: stdout = io.StringIO() if stderr is None: stderr = io.StringIO() - code = _proctee(cmd, + code = _proctee( + cmd, [stdout, sys.stdout], [stderr, sys.stderr], **kwargs) @@ -98,16 +101,18 @@ def proctee( stderr=stderr.getvalue()) return code, stdout.getvalue(), stderr.getvalue() + def proctee_joined( - cmd: List[str], + cmd: list[str], output: Optional[io.TextIOBase], - check: bool=False, + check: bool = False, **kwargs - ) -> Tuple[int, str]: + ) -> tuple[int, str]: if output is None: output = io.StringIO() - code = _proctee(cmd, + code = _proctee( + cmd, [output, sys.stdout], [output, sys.stderr], **kwargs) From ab64e8c3401000af86fdef8db9f217ae926ca62d Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Fri, 21 Feb 2025 12:49:46 +0000 Subject: [PATCH 4/6] Started adding arm support --- deckdebuild | 23 ++++++++++++++++++----- libdeckdebuild/__init__.py | 19 +++++++++++++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/deckdebuild b/deckdebuild index 5df5dcf..779b567 100755 --- a/deckdebuild +++ b/deckdebuild @@ -13,7 +13,7 @@ import os import sys from os import environ -from libdeckdebuild import deckdebuild, DeckDebuildError +from libdeckdebuild import get_host_arch, deckdebuild, DeckDebuildError from conffile import ConfFile default_values = { @@ -25,7 +25,8 @@ default_values = { "vardir": "/var/lib/deckdebuilds", "build_source": False, "path_to_buildroot": "", - "path_to_output_dir": os.getcwd() + "path_to_output_dir": os.getcwd(), + "arch": get_host_arch() } @@ -85,6 +86,11 @@ def main(): " env: DECKDEBUILD_USER" f" default: {conf.user}", default=conf.user) + parser.add_argument("-a", "--arch", + help="architechture to build package for" + " env: DECKDEBUILD_ARCH" + f" default: {conf.arch}", + default=conf.arch) parser.add_argument("-p", "--preserve-build", help="don't remove build deck after build" " env: DECKDEBUILD_PRESERVE_BUILD" @@ -110,21 +116,28 @@ def main(): " env: DECKDEBUILD_BUILD_SOURCE" f" default: {conf.build_source}", action=conf.build_source_action) + # XXX need to append arch to buildroot if it isn't already + # and need to warn user... parser.add_argument("path_to_buildroot", help="Path to an exisiting buildroot") parser.add_argument("path_to_output_dir", nargs='?', help="Path to output", default=os.getcwd()) args = parser.parse_args() + if get_host_arch != "amd64" and args.arch == "amd64": + fatal("amd64 can only be built on amd64") try: deckdebuild(os.getcwd(), - args.path_to_buildroot, args.path_to_output_dir, - root_cmd=args.root_cmd, user=args.user, + args.path_to_buildroot, + args.path_to_output_dir, + root_cmd=args.root_cmd, + user=args.user, preserve_build=args.preserve_build, faketime=args.faketime, satisfydepends_cmd=args.satisfydepends_cmd, vardir=args.vardir, - build_source=args.build_source) + build_source=args.build_source, + arch=args.arch) except DeckDebuildError as e: fatal(e) diff --git a/libdeckdebuild/__init__.py b/libdeckdebuild/__init__.py index d5cd3a8..ddf0e00 100644 --- a/libdeckdebuild/__init__.py +++ b/libdeckdebuild/__init__.py @@ -54,6 +54,18 @@ def get_source_dir(name, version): return name + "-" + version +def get_host_arch(): + host_arch = os.uname().machine.lower() + if host_arch == "x86_64": + return "amd64" + # XXX test this on ARM64 machine but should be one of these + elif host_arch == "aarch64" or host_arch == "arm64": + return "arm64" + else: + # don't know what it is!? + raise DeckDebuildError(f"Unexpected/unknown architecture {host_arch}") + + def apply_faketime_patch(chroot, user): patch_command = ["find", "-name", "configure", "-exec", @@ -73,13 +85,16 @@ def deckdebuild( satisfydepends_cmd: str = '/usr/lib/pbuilder/pbuilder-satisfydepends', faketime: bool = False, vardir: str = '/var/lib/deckdebuilds', - build_source: bool = False): + build_source: bool = False, + arch: str = get_host_arch() + ): vardir = os.fspath(vardir) path_chroots = join(vardir, 'chroots') path_builds = join(vardir, 'builds') - + # XXX the arch should be appended to the buildroot, but not yet sure of + # the best way to do that? if not isdir(buildroot): raise DeckDebuildError(f"buildroot `{buildroot}' is not a directory") From 5aec21376a7849a6dd57b1f5549f9292e62826ff Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Wed, 5 Mar 2025 06:20:00 +0000 Subject: [PATCH 5/6] get_host_arch is a function... --- deckdebuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deckdebuild b/deckdebuild index 779b567..1496c1a 100755 --- a/deckdebuild +++ b/deckdebuild @@ -73,7 +73,6 @@ class Conf(dict): def main(): conf = Conf() - parser = argparse.ArgumentParser( description="build a Debian package in a decked chroot") parser.add_argument("-r", "--root-cmd", @@ -124,7 +123,8 @@ def main(): help="Path to output", default=os.getcwd()) args = parser.parse_args() - if get_host_arch != "amd64" and args.arch == "amd64": + + if get_host_arch() != "amd64" and args.arch == "amd64": fatal("amd64 can only be built on amd64") try: deckdebuild(os.getcwd(), From 97687ccd6eb11410b8c7eb0a77fca9a2b70c5ced Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Tue, 11 Mar 2025 05:28:12 +0000 Subject: [PATCH 6/6] set arch as 'all' --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index cca107b..f4c153d 100644 --- a/debian/control +++ b/debian/control @@ -10,7 +10,7 @@ Build-Depends: Standards-Version: 4.0.0 Package: deckdebuild -Architecture: any +Architecture: all Depends: ${misc:Depends}, ${python3:Depends},