class VirtApt(object): def __init__(self, xml): # pylint: disable=too-many-statements self.xml = xml arch = xml.text("project/buildimage/arch", key="arch") suite = xml.text("project/suite") self.basefs = TmpdirFilesystem() self.initialize_dirs() create_apt_prefs(self.xml, self.basefs) mirror = self.xml.create_apt_sources_list(build_sources=True, initvm=False) self.basefs.write_file("etc/apt/sources.list", 0o644, mirror) self.setup_gpg() self.import_keys() apt_pkg.config.set("APT::Architecture", arch) apt_pkg.config.set("APT::Architectures", arch) apt_pkg.config.set("Acquire::http::Proxy::127.0.0.1", "DIRECT") apt_pkg.config.set("APT::Install-Recommends", "0") apt_pkg.config.set("Dir::Etc", self.basefs.fname('/')) apt_pkg.config.set("Dir::Etc::Trusted", self.basefs.fname('/etc/apt/trusted.gpg')) apt_pkg.config.set("Dir::Etc::TrustedParts", self.basefs.fname('/etc/apt/trusted.gpg.d')) apt_pkg.config.set("APT::Cache-Limit", "0") apt_pkg.config.set("APT::Cache-Start", "32505856") apt_pkg.config.set("APT::Cache-Grow", "2097152") apt_pkg.config.set("Dir::State", self.basefs.fname("state")) apt_pkg.config.set("Dir::State::status", self.basefs.fname("state/status")) apt_pkg.config.set("Dir::Cache", self.basefs.fname("cache")) apt_pkg.config.set("Dir::Cache::archives", self.basefs.fname("cache/archives")) apt_pkg.config.set("Dir::Etc", self.basefs.fname("etc/apt")) apt_pkg.config.set("Dir::Log", self.basefs.fname("log")) if self.xml.has('project/noauth'): apt_pkg.config.set("APT::Get::AllowUnauthenticated", "1") apt_pkg.config.set("Acquire::AllowInsecureRepositories", "1") else: apt_pkg.config.set("APT::Get::AllowUnauthenticated", "0") apt_pkg.config.set("Acquire::AllowInsecureRepositories", "0") apt_pkg.init_system() self.source = apt_pkg.SourceList() self.source.read_main_list() self.cache = apt_pkg.Cache() try: self.cache.update(self, self.source) except BaseException as e: print(e) apt_pkg.config.set("APT::Default-Release", suite) self.cache = apt_pkg.Cache() try: self.cache.update(self, self.source) except BaseException as e: print(e) try: self.depcache = apt_pkg.DepCache(self.cache) prefs_name = self.basefs.fname("/etc/apt/preferences") self.depcache.read_pinfile(prefs_name) except BaseException as e: print(e) self.downloads = {} self.acquire = apt_pkg.Acquire(self) def add_key(self, key): cmd = 'echo "%s" > %s' % (key, self.basefs.fname("tmp/key.pub")) clean = 'rm -f %s' % self.basefs.fname("tmp/key.pub") system(cmd) system('fakeroot apt-key --keyring "%s" add "%s"' % (self.basefs.fname('/etc/apt/trusted.gpg'), self.basefs.fname("tmp/key.pub"))) system(clean) def import_keys(self): if self.xml.has('project/mirror/url-list'): # Should we use self.xml.prj.has("noauth")??? # # If so, this is related to issue #220 - # https://github.com/Linutronix/elbe/issues/220 # # I could make a none global 'noauth' flag for mirrors for url in self.xml.node('project/mirror/url-list'): if url.has('raw-key'): key = "\n".join( line.strip(" \t") for line in url.text('raw-key').splitlines()[1:-1]) self.add_key(key) def start(self): pass def stop(self): pass @staticmethod def pulse(_obj): return True def initialize_dirs(self): self.basefs.mkdir_p("cache/archives/partial") self.basefs.mkdir_p("etc/apt/preferences.d") self.basefs.mkdir_p("etc/apt/trusted.gpg.d") self.basefs.mkdir_p("db") self.basefs.mkdir_p("log") self.basefs.mkdir_p("state/lists/partial") self.basefs.mkdir_p("tmp") self.basefs.touch_file("state/status") def setup_gpg(self): ring_path = self.basefs.fname("etc/apt/trusted.gpg") if not os.path.isdir("/etc/apt/trusted.gpg.d"): print("/etc/apt/trusted.gpg.d doesn't exist") print("apt-get install debian-archive-keyring may " "fix this problem") sys.exit(20) if os.path.exists("/etc/apt/trusted.gpg"): system('cp /etc/apt/trusted.gpg "%s"' % ring_path) trustkeys = os.listdir("/etc/apt/trusted.gpg.d") for key in trustkeys: system('cp "/etc/apt/trusted.gpg.d/%s" "%s"' % (key, ring_path + '.d')) def mark_install(self, pkgname): self.depcache.mark_install(self.cache[pkgname]) def marked_install(self, pkgname): return self.depcache.marked_install(self.cache[pkgname]) def get_candidate_ver(self, pkgname): return self.depcache.get_candidate_ver(self.cache[pkgname]).ver_str def has_pkg(self, pkgname): return pkgname in self.cache def mark_pkg_download(self, pkgname): pkg = self.cache[pkgname] c = self.depcache.get_candidate_ver(pkg) r = apt_pkg.PackageRecords(self.cache) r.lookup(c.file_list[0]) x = self.source.find_index(c.file_list[0][0]) uri = x.archive_uri(r.filename) hashval = str(r.hashes.find('SHA256')) acq = apt_pkg.AcquireFile(self.acquire, uri, hash=hashval, size=c.size, descr=r.long_desc, short_descr=r.short_desc, destdir=self.basefs.fname('/cache/archives')) self.downloads[pkgname] = acq def do_downloads(self): res = self.acquire.run() print(res) def get_downloaded_files(self): ret = [] for _, d in self.downloads.items(): if d.complete: ret.append(d.destfile) else: print('incomplete download "%s"' % d.desc_uri) return ret def get_downloaded_pkg(self, pkgname): d = self.downloads[pkgname] if not d.complete: print('incomplete download "%s"' % d.desc_uri) raise KeyError return d.destfile def get_uri(self, target_pkg, incl_deps=False): d = apt_pkg.DepCache(self.cache) if not incl_deps: return [lookup_uri(self, d, target_pkg)] deps = [lookup_uri(self, d, target_pkg)] togo = [target_pkg] while togo: pp = togo.pop() try: pkg = self.cache[pp] c = d.get_candidate_ver(pkg) except KeyError: pkg = None c = None if not c: # pylint: disable=E1133 for p in self.cache.packages: for x in p.provides_list: if pp == x[0]: pkg = self.cache[x[2].parent_pkg.name] c = d.get_candidate_ver(pkg) if not c: print("couldnt get candidate: %s" % pkg) else: for p in getdeps(c): if [y for y in deps if y[0] == p]: continue if p != target_pkg and p == pp: continue deps.append(lookup_uri(self, d, p)) togo.append(p) return list(set(deps))
class TestCopyFilelist(unittest.TestCase): def setUp(self): self.src = TmpdirFilesystem() self.dst = TmpdirFilesystem() def tearDown(self): del self.src del self.dst def test_usrmerge_abs(self): self.src.mkdir_p('/usr/bin') # this will link to /usr/bin in the host RFS, # when no special logic is applied. self.src.symlink('/usr/bin', '/bin') self.src.write_file('/bin/bla', 0o644, 'bla') copy_filelist(self.src, ['/bin/bla'], self.dst) # We should now have the same content from /SRC/usr/bin/bla in # /DST/usr/bin/bla self.assertEqual(self.src.read_file('/usr/bin/bla'), self.dst.read_file('/usr/bin/bla')) def test_usrmerge_rel(self): self.src.mkdir_p('/usr/bin') # create a proper relative path, that should # work fine from inside. self.src.symlink('usr/bin', '/bin') self.src.write_file('/bin/bla', 0o644, 'bla') copy_filelist(self.src, ['/bin/bla'], self.dst) # We should now have the same content from /SRC/usr/bin/bla in # /DST/usr/bin/bla self.assertEqual(self.src.read_file('/usr/bin/bla'), self.dst.read_file('/usr/bin/bla')) def test_deeplinks(self): self.src.mkdir_p('/a/b/c') # c <- /a/b/d self.src.symlink('c', '/a/b/d') # This write into /a/b/c/bla (c instead of d) self.src.write_file('/a/b/d/bla', 0o644, 'bla') copy_filelist(self.src, ['/a/b/d/bla'], self.dst) # We should now have the same content from /SRC/a/b/c/bla in # /DST/a/b/c/bla self.assertEqual(self.src.read_file('/a/b/c//bla'), self.dst.read_file('/a/b/c/bla')) def test_multilinks(self): self.src.mkdir_p('/a') # a <- b # ../b <- /a/c self.src.symlink('a', '/b') self.src.symlink('../b', '/a/c') # This write into /a/bla self.src.write_file('a/c/bla', 0o644, 'bla') copy_filelist(self.src, ['/a/c/bla'], self.dst) # We should now have the content from /SRC/a/bla in /DST/a/bla self.assertEqual(self.src.read_file('/a/bla'), self.dst.read_file('/a/bla')) @unittest.expectedFailure def test_badfile(self): # This should throw a CommandError copy_filelist(self.src, ['/doesnt/exist'], self.dst)