From patchwork Fri May 26 07:00:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uladzimir Bely X-Patchwork-Id: 2841 Return-Path: Received: from shymkent.ilbers.de ([unix socket]) by shymkent (Cyrus 2.5.10-Debian-2.5.10-3+deb9u2) with LMTPA; Fri, 26 May 2023 09:00:44 +0200 X-Sieve: CMU Sieve 2.4 Received: from mail-oo1-f56.google.com (mail-oo1-f56.google.com [209.85.161.56]) by shymkent.ilbers.de (8.15.2/8.15.2/Debian-8+deb9u1) with ESMTPS id 34Q70feD013370 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 26 May 2023 09:00:42 +0200 Received: by mail-oo1-f56.google.com with SMTP id 006d021491bc7-55533a40c75sf392434eaf.1; Fri, 26 May 2023 00:00:42 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1685084435; cv=pass; d=google.com; s=arc-20160816; b=P8TN1Q9E3RuLBEMnDpRUV0eqXcY7tsXWj6LbDpH71MUi+PyIOd3jfUqYx1QDFC2wZM lqerxwbvrx3W8rD7KXEYFcm/NNiXW72BJVTGPmXy034+n/I743nEQ+4ep+WHMODrngSU Xy+XlEUzgCPSBSvsYihlJAL80e9fAzwIC8UtIdhdsn6RLnGEfkEOUXjZYG7Q2yZAT4Bc N0i7JDPWLtYF3UG/iKKEGd/EzZmzK6L/jH9oLXeFPxYsBf14zJzuOZgKeLCOrxFpFO/b /nVWXq7nawFypIceMkpDAql3ai6gQIFHupp7nYxAJvx0s50CKkwOcct6f5AEU3Ymlxmu CV0w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:to:from:sender:dkim-signature; bh=/F5yFsLHdtFhcO17Qq22V9uiemUHYDb7OUrHtrxCXlk=; b=RWOIJiAL6Xm6P1pIW6qd+PR4p0xlFZWhgWhtObDULuGJuRAgBgN/6e/bnD6ErSkyub Gswgbr7XT2DN9iPyRKmZH8XAvH7A0QyQA7xU4gSwD5NlDm+wvfEi2+BDl0/BbY5i99q6 ULmSvWCi2xGvCuybMPfO7yX45dds5SCrKmRgCF2sl7Sn3jz/oOC5FAQy1X3nYsIxnSFt fSwOxZqbCwjG2SCwKEtm2dC6fbSWFNVBBx40+qv8+Cng21SGAR4FOypig90u7bOqlabm OZqo7tI6FkEmQMjLAjk8fPva5ffOA9yDWm8I2RQF57/xd64HA49QVrPlkHn4vkmaLoeG XnmQ== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) smtp.mailfrom=ubely@ilbers.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20221208; t=1685084435; x=1687676435; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:mime-version:references:in-reply-to:message-id :date:subject:to:from:sender:from:to:cc:subject:date:message-id :reply-to; bh=/F5yFsLHdtFhcO17Qq22V9uiemUHYDb7OUrHtrxCXlk=; b=Q21EmVyVLYKLKDsAE8z4z+yudl+5dQF/y2t4+KcDSgwyW6EQM8/7iHKt95u4sukLYZ 732mjF/wAtgcm6c1byKelz7ciF3Ix7OznMTGlsSvSW2hmWUNzTNCaN7XgZfyN7rkXwvb flMQvdZwyS3fG835LqrSzo9q6vX/6Kr5px9R5I6CifwaWCZJZPv0EESYmMcvlHkA8den +5rqSt9QG02Ro9LaoxvYCSUinng19KnRMWsISzRpdtGWGRsWs62rxl7TKQRe4cN1n08m zLjdOPvWFIpTGhGJ9rtGRC1QDcnBQFEQzf0RQFRb0MgsieSrhw2rEoykd7LJnJH2lpFd 2fqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685084435; x=1687676435; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence :x-original-authentication-results:x-original-sender:mime-version :references:in-reply-to:message-id:date:subject:to:from:x-beenthere :x-gm-message-state:sender:from:to:cc:subject:date:message-id :reply-to; bh=/F5yFsLHdtFhcO17Qq22V9uiemUHYDb7OUrHtrxCXlk=; b=emCP67AHbnmqQWVVrx1iV/4gPiZBcORw26gKlMgUKvqrqBtHNOrVUstt+53QG/MhtL HpEX4HGOXAes8xTcnc1SagbKtQpBKAcsBiZNiFPL3W762HTUGs9kxyB0e+RjJ/h0LG6F Totuocyv40rZ0MTrG8+6cUkbck/kBmUb/feInMx86L55afCWGSIF8YEI5Czg7UNCX6WR Cfaoou6eWUY9ilRSpWw4wHiS7e49yBUwouiADQiGbZgt1gDjllNc1SAkVHOkWjo/G3lZ JGAVnvNOXfcd11dTaRMXPxLzft8Bzxx7sX5LYisETiOizA55P3gAB1pR4tq0+taRjHW5 +lwA== Sender: isar-users@googlegroups.com X-Gm-Message-State: AC+VfDyM2esQrnPKI5G6SQoLg76iT8gL6qkru+21yDgmDBHx6UJinmMN mk7IQ6OtIWDPlpM681Q5l+4= X-Google-Smtp-Source: ACHHUZ44/69wJWfsFgOVvpnZ6Hst+I1/Dw8s2SYW28Psz4mMss9PEmpUETt0D3/YAJS5ls5Uzalqwg== X-Received: by 2002:a05:6870:76a9:b0:192:74a0:2af2 with SMTP id dx41-20020a05687076a900b0019274a02af2mr244294oab.5.1685084435707; Fri, 26 May 2023 00:00:35 -0700 (PDT) X-BeenThere: isar-users@googlegroups.com Received: by 2002:a05:6870:7728:b0:19a:2d51:c15e with SMTP id dw40-20020a056870772800b0019a2d51c15els618043oab.0.-pod-prod-07-us; Fri, 26 May 2023 00:00:35 -0700 (PDT) X-Received: by 2002:a05:6871:6ab0:b0:19e:8cd4:7148 with SMTP id zf48-20020a0568716ab000b0019e8cd47148mr366811oab.47.1685084435139; Fri, 26 May 2023 00:00:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685084435; cv=none; d=google.com; s=arc-20160816; b=nFyGtIyEaJB3pwmNveYQixpvF9rkXYlik+X/uctawTCfgb9gk/BfFlsIXm/7mLt25f 8D1AQksuWhnxRR/pjlBCzels23Iu7pxMwTtpsPN2q9E2nhMssoshpE9g75LC1frGlSVo ZrfJMgYtpSxL1LOjIbB3Ehim05zB2l/rU/tMX1z0fLYrR20Lr/6YbcXXS0tec/px0FUR /1DpN8CRtozUyjVSQxTxjus7+Jyus6lWeoy4Gxl5sdDn9NJf/MGJpqVffVZc3a57xZPx tkG93XXLFGvnlg9P5WjNbnBQTvjV7VKDm+q18uAhFRtALH5k5Xy43GlPIJVrm7LZkwum P14Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from; bh=0AyqWdfy6IbFVwmBIFgYtKYqSLOM6iybr4pLaQTR6JY=; b=X69VfrNQzQBNjj+istWIfDhvekeVre93zBeXj6OIPdsPhYEWn5GmRAdk9ESX9AErt0 mJTytOkOd4Ba75rWoqPc7y57W791ALskwPop8sS59NVgmWVdIyItWvpEmx02cLVPXVxp n+lTegXNSLty1tgDbVcvx1wgmi5GE+VvDadbMK+GH8l0kH55lrfMIYLHuaUXwOX319Nb fMyB52WAJJ6dsR/3HQOexM+ZgY0zcUZY3Aqjscf9JXUdUz947+aqCG//I17gNdRfBFui 37zFwL2EAbSC51fvZzwRmgBsVclm2Z5S4kP4z+rem80VY2L+YMTLmJY1qM2E64ZoPTX6 zWOg== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) smtp.mailfrom=ubely@ilbers.de Received: from shymkent.ilbers.de (shymkent.ilbers.de. [85.214.156.166]) by gmr-mx.google.com with ESMTPS id d15-20020a4ad34f000000b005552377a831si256497oos.1.2023.05.26.00.00.33 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Fri, 26 May 2023 00:00:35 -0700 (PDT) Received-SPF: pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) client-ip=85.214.156.166; Received: from baighyz.m.ilbers.de (host-80-81-17-52.static.customer.m-online.net [80.81.17.52]) (authenticated bits=0) by shymkent.ilbers.de (8.15.2/8.15.2/Debian-8+deb9u1) with ESMTPSA id 34Q70R3X013306 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 26 May 2023 09:00:29 +0200 From: Uladzimir Bely To: isar-users@googlegroups.com Subject: [PATCH v5 03/12] scripts: Add debrepo python script handling base-apt Date: Fri, 26 May 2023 09:00:18 +0200 Message-Id: <20230526070027.16890-4-ubely@ilbers.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20230526070027.16890-1-ubely@ilbers.de> References: <20230526070027.16890-1-ubely@ilbers.de> MIME-Version: 1.0 X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shymkent.ilbers.de X-Original-Sender: ubely@ilbers.de X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of ubely@ilbers.de designates 85.214.156.166 as permitted sender) smtp.mailfrom=ubely@ilbers.de Precedence: list Mailing-list: list isar-users@googlegroups.com; contact isar-users+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: isar-users@googlegroups.com X-Google-Group-Id: 914930254986 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= This is the main utility responsible for prefetching packages into local `base-apt` repo from external Debian mirrors. It uses python-apt module and requires some kind of minimal `rootfs` to work (let's call it "debrepo context"). Once initialized with `--init --workdir=`, it stores the initial configuration in `repo.opts` file inside the context and uses it at futher calls. In future, the logic `debrepo` script implements could be directly implemented inside bitbake classes. Signed-off-by: Uladzimir Bely --- scripts/debrepo | 443 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100755 scripts/debrepo diff --git a/scripts/debrepo b/scripts/debrepo new file mode 100755 index 00000000..2a5e5b51 --- /dev/null +++ b/scripts/debrepo @@ -0,0 +1,443 @@ +#!/usr/bin/env python3 + +# This software is a part of ISAR. +# Copyright (C) 2022 ilbers GmbH + +import os +import sys +import fcntl + +import shutil +import subprocess +import getopt +import pickle +import urllib.parse + +import apt_pkg +import apt.progress.base + + +class DebRepo(object): + def __init__(self, workdir, cmdline_opts): + self.workdir = workdir + self.optsfile = self.workdir + "/repo.opts" + + # Set default values + self.distro = "debian" + + self.repo = self.workdir + "/repo/apt" + "/" + self.distro + self.repodb = self.workdir + "/repo/db" + "/" + self.distro + self.mirror = "http://deb.debian.org/debian" + self.arch = "amd64" + self.codename = "bullseye" + self.keydir = "/etc/apt/trusted.gpg.d" + self.check_gpg = True + self.isaraptdir = "" + + # Load stored opts + opts = self.load_opts() + print("stored opts: " + str(opts)) + + # Overwrite opts by cmdline_opts + for opt, arg in cmdline_opts.items(): + opts[opt] = arg + + print("all opts: " + str(opts)) + + # Replace by values passed in commandline + for opt, arg in opts.items(): + if opt == "mirror": + self.mirror = arg + if opt == "arch": + self.arch = arg + if opt == "distro": + self.distro = arg + if opt == "codename": + self.codename = arg + if opt == "keydir": + self.keydir = arg + if opt == "isaraptdir": + self.isaraptdir = arg + if opt == "check_gpg": + self.check_gpg = arg + + self.crossarch = self.arch + for opt, arg in opts.items(): + if opt == "crossarch": + self.crossarch = arg + + self.compatarch = "" + for opt, arg in opts.items(): + if opt == "compatarch": + self.compatarch = arg + + for opt, arg in opts.items(): + if opt == "repodir": + self.repo = arg + "/" + self.distro + if opt == "repodbdir": + self.repodb = arg + "/" + self.distro + + self.save_opts(opts) + + print("workdir: " + str(self.workdir)) + print("repo: " + str(self.repo)) + print("repodb: " + str(self.repodb)) + print("mirror: " + str(self.mirror)) + print("arch: " + str(self.arch)) + print("crossarch: " + str(self.crossarch)) + if self.compatarch: + print("compatarch: " + str(self.compatarch)) + print("distro: " + str(self.distro)) + print("codename: " + str(self.codename)) + print("keydir: " + str(self.keydir)) + print("isaraptdir: " + str(self.isaraptdir)) + print("check_gpg: " + str(self.check_gpg)) + + self.cache = None + self.depcache = None + self.sr = None + + def create_rootfs(self, aptsrcsfile): + if not os.path.exists(self.workdir + "/var/lib/dpkg"): + os.makedirs(self.workdir + "/var/lib/dpkg") + with open(self.workdir + "/var/lib/dpkg" + "/status", "w"): + pass + + if not os.path.exists(self.workdir + "/etc/apt/sources.list.d"): + os.makedirs(self.workdir + "/etc/apt/sources.list.d") + if os.path.exists(aptsrcsfile): + shutil.copy(aptsrcsfile, self.workdir + "/etc/apt/sources.list.d/bootstrap.list") + + if self.isaraptdir: + with open(self.workdir + "/etc/apt/sources.list.d/isar-apt.list", "w") as f: + f.write("deb [trusted=yes] file://" + self.isaraptdir + " isar main\n") + + if not os.path.exists(self.workdir + "/../apt_cache/" + self.distro + "-" + self.codename + "/archives/partial"): + os.makedirs(self.workdir + "/../apt_cache/" + self.distro + "-" + self.codename + "/archives/partial") + + if not os.path.exists(self.workdir + "/tmp"): + os.makedirs(self.workdir + "/tmp") + + def apt_config(self, init, crossbuild): + # Configure apt to work with empty directory + if not init and self.arch != self.crossarch: + apt_pkg.config["APT::Architectures::"] = self.crossarch + apt_pkg.config["APT::Architectures::"] = self.arch + + if not init and self.compatarch: + apt_pkg.config["APT::Architectures::"] = self.compatarch + + apt_pkg.config.set("APT::Architecture", self.arch) + + apt_pkg.config.set("Dir", self.workdir) + apt_pkg.config.set("Dir::Cache", self.workdir + "/../apt_cache/" + self.distro + "-" + self.codename) + apt_pkg.config.set("Dir::State::status", self.workdir + "/var/lib/dpkg/status") + + apt_pkg.config.set("APT::Install-Recommends", "0") + apt_pkg.config.set("APT::Install-Suggests", "0") + + # Use host keys for authentification + # apt_pkg.config.set("Dir::Etc::Trusted", "/etc/apt/trusted.gpg") + # apt_pkg.config.set("Dir::Etc::TrustedParts", "/etc/apt/trusted.gpg.d") + apt_pkg.config.set("Dir::Etc::TrustedParts", self.keydir) + + # Allow using repositories without keys + if not self.check_gpg: + apt_pkg.config.set("Acquire::AllowInsecureRepositories", "1") + + def mark_essential(self): + for pkg in self.cache.packages: + if pkg.architecture == self.arch: + if pkg.essential: + self.depcache.mark_install(pkg) + + def mark_by_prio(self, priority): + for pkg in self.cache.packages: + if pkg.architecture == self.arch: + ver = self.depcache.get_candidate_ver(pkg) + if ver and ver.priority <= priority: + self.depcache.mark_install(pkg) + + def mark_pkg(self, pkgname, crossbuild): + if pkgname in self.cache: + pkg = self.cache[pkgname] + + if not crossbuild or ':' in pkgname or len(pkg.version_list) == 0: + if pkg.has_provides and not pkg.has_versions: + print("pkgname is virtual package, selecting best provide") + # Select first provide + pkg_provide = pkg.provides_list[0][2] + # Find better provide with higher version + for provide in pkg.provides_list: + if apt_pkg.version_compare(provide[2].ver_str, pkg_provide.ver_str) > 0: + pkg_provide = provide[2] + self.depcache.mark_install(pkg_provide.parent_pkg) + else: + self.depcache.mark_install(pkg) + else: + version = pkg.version_list[0] + if version.arch == "all": + self.depcache.mark_install(pkg) + else: + if version.multi_arch == version.MULTI_ARCH_FOREIGN: + if (pkgname, self.arch) in self.cache: + nativepkg = self.cache[pkgname, self.arch] + self.depcache.mark_install(nativepkg) + else: + if (pkgname, self.crossarch) in self.cache: + crosspkg = self.cache[pkgname, self.crossarch] + self.depcache.mark_install(crosspkg) + + def mark_list(self, pkglist, crossbuild): + if pkglist: + for pkgname in pkglist: + self.mark_pkg(pkgname, crossbuild) + + def handle_deb(self, item): + lockfd = open(self.repo + '/../repo.lock', 'w') + fcntl.flock(lockfd,fcntl.LOCK_EX) + subprocess.run([ + "reprepro", + "--dbdir", self.repodb, + "--outdir", self.repo, + "--confdir", self.repo + "/conf", + "-C", "main", + "includedeb", + self.codename, + item.destfile + ]) + lockfd.close() + + def handle_repo(self, fetcher): + lockfd = open(self.workdir + "/../apt_cache/" + self.distro + "-" + self.codename + ".lock", "w") + fcntl.flock(lockfd,fcntl.LOCK_EX) + fetcher.run() + lockfd.close() + for item in fetcher.items: + if item.status == item.STAT_ERROR: + print("Some error ocured: '%s'" % item.error_text) + pass + else: + self.handle_deb(item) + + def get_filename(self, uri): + path = urllib.parse.urlparse(uri).path + unquoted_path = urllib.parse.unquote(path) + basename = os.path.basename(unquoted_path) + return basename + + def download_file(self, uri): + filename = self.get_filename(uri) + subprocess.run([ + "wget", + "-H", + "--timeout=30", + "--tries=3", + "-q", + uri, + "-O", + self.workdir + "/tmp/" + filename + ]) + + def handle_dsc(self, uri): + filename = self.get_filename(uri) + lockfd = open(self.repo + '/../repo.lock', 'w') + fcntl.flock(lockfd,fcntl.LOCK_EX) + subprocess.run([ + "reprepro", + "--dbdir", self.repodb, + "--outdir", self.repo, + "--confdir", self.repo + "/conf", + "-C", "main", + "-S", "-", "-P" "source", + "--delete", + "includedsc", + self.codename, + os.path.realpath(self.workdir + "/tmp/" + filename) + ]) + lockfd.close() + + def handle_src_list(self, pkgs): + if pkgs: + for pkg in pkgs: + pkgname=pkg + pkgver="" + if '=' in pkg: + pkgname = pkg.split("=")[0] + pkgver = pkg.split("=")[1] + + self.sr.restart() + while self.sr.lookup(pkgname): + if pkgver and pkgver != self.sr.version: + continue + + for sr_file in self.sr.files: + print(self.sr.index.archive_uri(sr_file[2])) + self.download_file(self.sr.index.archive_uri(sr_file[2])) + + dsc_uri = self.sr.index.archive_uri(self.sr.files[0][2]) + self.handle_dsc(dsc_uri) + break + + def apt_run(self, init, srcmode, pkgs, controlfile, crossbuild): + apt_pkg.init() + + sources = apt_pkg.SourceList() + sources.read_main_list() + + progress = apt.progress.text.AcquireProgress() + + self.cache = apt_pkg.Cache() + self.cache.update(progress, sources) + self.cache = apt_pkg.Cache() + + self.depcache = apt_pkg.DepCache(self.cache) + self.sr = apt_pkg.SourceRecords() + + if init: + self.mark_essential() + # 1(required), 2(important), 3(standard), 4(optional), 5(extra) + self.mark_by_prio(1) + + if srcmode: + self.handle_src_list(pkgs) + else: + self.mark_list(pkgs, crossbuild) + + if controlfile: + fobj = open(controlfile, "r") + + try: + tagfile = apt_pkg.TagFile(fobj) + while tagfile.step() == 1: + deps = tagfile.section.get("Build-Depends", "") + # Remove extra commas and spaces - apt_pkg.parse_depends doesnt like + # lines like ", device-tree-compiler" + deps = ', '.join([s.strip() for s in deps.split(',') if s.strip()]) + print("parsed deps: " + str(deps)) + for item in apt_pkg.parse_depends(deps, False): + pkgname = item[0][0] + self.mark_pkg(pkgname, crossbuild) + + finally: + fobj.close() + + if init or not srcmode: + fetcher = apt_pkg.Acquire(progress) + pm = apt_pkg.PackageManager(self.depcache) + + recs = apt_pkg.PackageRecords(self.cache) + pm.get_archives(fetcher, sources, recs) + + self.handle_repo(fetcher) + + def load_opts(self): + params = {} + if os.path.isfile(self.optsfile): + with open(self.optsfile, 'rb') as file: + data = file.read() + if data: + params = pickle.loads(data) + + return params + + def save_opts(self, opts): + file = open(self.optsfile, 'wb') + pickle.dump(opts, file) + file.close() + + +class DebRepoArgs(object): + def __init__(self): + self.workdir = "" + self.init = False + self.srcmode = False + self.controlfile = "" + self.aptsrcsfile = "" + self.crossbuild = False + + self.opts = {} + self.pkgs = [] + + try: + opts, args = getopt.getopt(sys.argv[1:], "", [ + "init", + "srcmode", + "workdir=", + "repodir=", + "repodbdir=", + "mirror=", + "arch=", + "crossarch=", + "compatarch=", + "distro=", + "codename=", + "keydir=", + "isaraptdir=", + "no-check-gpg", + "controlfile=", + "aptsrcsfile=", + "crossbuild" + ]) + except getopt.GetoptError as msg: + print("Error: " + str(msg)) + sys.exit(1) + + for opt, arg in opts: + if opt in ("--workdir"): + self.workdir = arg + if opt in ("--init"): + self.init = True + if opt in ("--srcmode"): + self.srcmode = True + if opt in ("--controlfile"): + self.controlfile = arg + if opt in ("--aptsrcsfile"): + self.aptsrcsfile = arg + if opt in ("--crossbuild"): + self.crossbuild = True + + if opt in ("--repodir", + "--repodbdir", + "--mirror", + "--arch", + "--crossarch", + "--compatarch", + "--distro", + "--codename", + "--keydir", + "--isaraptdir", + "--controlfile", + ): + self.opts[opt[2:]] = arg + if opt in ("--no-check-gpg"): + self.opts['check_gpg'] = False + + if not self.workdir: + print("Error: workdir is not specified") + sys.exit(1) + + self.pkgs = args + + +def main(): + args = DebRepoArgs() + + if not (args.init or args.pkgs or args.controlfile): + print("Nothing to do") + sys.exit(0) + + if not os.path.exists(args.workdir): + os.makedirs(args.workdir) + + debrepo = DebRepo(args.workdir, args.opts) + + if (args.init): + debrepo.create_rootfs(args.aptsrcsfile) + + debrepo.apt_config(args.init, args.crossbuild) + debrepo.apt_run(args.init, args.srcmode, args.pkgs, args.controlfile, args.crossbuild) + + +if __name__ == "__main__": + main()