1 # Copyright © 2015-2016 Nick Bowler
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>
22 from portage import os
23 from portage.util import writemsg_level
24 from portage.process import spawn
25 from portage.sync.syncbase import NewBase
27 # Determine snapshot date. While timestamps from snapshots indicate
28 # early in the day (UTC), filenames indicate the previous day (snapshot
29 # at end of day). Simply subtract 4 hours before calculating the day
30 # to accomodate this difference, assuming snapshot generation is faster
33 with open(repo.sync_uri + '/metadata/timestamp.chk', 'r') as f:
34 timestamp = f.readline()
35 repotime = email.utils.mktime_tz(email.utils.parsedate_tz(timestamp))
36 return time.strftime("%Y%m%d", time.gmtime(repotime - 4*3600))
38 def repo_filename(repo):
39 opts = repo.module_specific_options
40 return '%s/%s-%s.sqfs' % (opts['squash-cache-location'],
41 repo.name, repo_date(repo))
43 class SquashMirror(NewBase):
45 NewBase.__init__(self, 'mksquashfs', 'sys-fs/squashfs-tools')
47 def msg(self, msg, level=0, noiselevel=0):
48 self.logger(self.xterm_titles, msg)
49 writemsg_level(msg + "\n", level, noiselevel)
51 def err(self, msg, level=0, noiselevel=0):
52 self.msg("!!! " + msg, level=logging.ERROR, noiselevel=-1)
54 def exists(self, **kwargs):
59 if not os.path.exists(repo_filename(self.repo)):
63 def new(self, **kwargs):
64 opts = self.repo.module_specific_options
65 filename = repo_filename(self.repo)
66 self.msg("Creating squashfs image " + filename)
68 args = [self.bin_command]
69 args.extend([self.repo.sync_uri, filename])
70 args.extend(['-no-xattrs'])
71 args.extend(['-force-uid', 'portage', '-force-gid', 'portage'])
72 args.extend(['-comp', opts['squash-compression']])
73 args.extend(opts['squash-extra-opts'].split())
75 rc = spawn(args, **self.spawn_kwargs)
77 self.err("command failed: %s" % " ".join(args))
80 symlink = "%s/%s-current.sqfs" % (opts['squash-cache-location'],
83 with contextlib.suppress(FileNotFoundError):
85 os.symlink(os.path.basename(filename), symlink)
88 def update(self, **kwargs):
89 filename = repo_filename(self.repo)
90 self.err("%s already exists; exiting." % filename);