# Copyright © 2015-2016 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see import time import email.utils import logging import contextlib import portage from portage import os from portage.util import writemsg_level from portage.process import spawn from portage.sync.syncbase import NewBase # Determine snapshot date. While timestamps from snapshots indicate # early in the day (UTC), filenames indicate the previous day (snapshot # at end of day). Simply subtract 4 hours before calculating the day # to accomodate this difference, assuming snapshot generation is faster # than that. def repo_date(repo): with open(repo.sync_uri + '/metadata/timestamp.chk', 'r') as f: timestamp = f.readline() repotime = email.utils.mktime_tz(email.utils.parsedate_tz(timestamp)) return time.strftime("%Y%m%d", time.gmtime(repotime - 4*3600)) def repo_filename(repo): opts = repo.module_specific_options return '%s/%s-%s.sqfs' % (opts['squash-cache-location'], repo.name, repo_date(repo)) class SquashMirror(NewBase): def __init__(self): NewBase.__init__(self, 'mksquashfs', 'sys-fs/squashfs-tools') def msg(self, msg, level=0, noiselevel=0): self.logger(self.xterm_titles, msg) writemsg_level(msg + "\n", level, noiselevel) def err(self, msg, level=0, noiselevel=0): self.msg("!!! " + msg, level=logging.ERROR, noiselevel=-1) def exists(self, **kwargs): if kwargs: self._kwargs(kwargs) elif not self.repo: return False if not os.path.exists(repo_filename(self.repo)): return False return True; def new(self, **kwargs): opts = self.repo.module_specific_options filename = repo_filename(self.repo) self.msg("Creating squashfs image " + filename) args = [self.bin_command] args.extend([self.repo.sync_uri, filename]) args.extend(['-no-xattrs']) args.extend(['-force-uid', 'portage', '-force-gid', 'portage']) args.extend(['-comp', opts['squash-compression']]) args.extend(opts['squash-extra-opts'].split()) rc = spawn(args, **self.spawn_kwargs) if rc != os.EX_OK: self.err("command failed: %s" % " ".join(args)) return (rc, False) symlink = "%s/%s-current.sqfs" % (opts['squash-cache-location'], self.repo.name) with contextlib.suppress(FileNotFoundError): os.remove(symlink) os.symlink(os.path.basename(filename), symlink) return (0, True) def update(self, **kwargs): filename = repo_filename(self.repo) self.err("%s already exists; exiting." % filename); return (1, False)