aboutsummaryrefslogtreecommitdiff
blob: 7732312c89ef1216b6f42d8cc549a04d1dac7b82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""
Snapshot target
"""

import subprocess
import sys

from pathlib import Path

from catalyst import log
from catalyst.base.targetbase import TargetBase
from catalyst.lock import write_lock
from catalyst.support import CatalystError, command

class snapshot(TargetBase):
    """
    Builder class for snapshots.
    """
    required_values = frozenset([
        'target',
    ])
    valid_values = required_values | frozenset([
        'snapshot_treeish',
    ])

    def __init__(self, myspec, addlargs):
        TargetBase.__init__(self, myspec, addlargs)

        self.git = command('git')
        self.ebuild_repo = Path(self.settings['repos'],
                                self.settings['repo_name']).with_suffix('.git')
        self.gitdir = str(self.ebuild_repo)

    def update_ebuild_repo(self) -> str:
        repouri = 'https://anongit.gentoo.org/git/repo/sync/gentoo.git'

        if self.ebuild_repo.is_dir():
            git_cmds = [
                [self.git, '-C', self.gitdir, 'fetch', '--quiet', '--depth=1'],
                [self.git, '-C', self.gitdir, 'update-ref', 'HEAD', 'FETCH_HEAD'],
                [self.git, '-C', self.gitdir, 'gc', '--quiet'],
            ]
        else:
            git_cmds = [
                [self.git, 'clone', '--quiet', '--depth=1', '--bare',
                 # Set some config options to enable git gc to clean everything
                 # except what we just fetched. See git-gc(1).
                 '-c', 'gc.reflogExpire=0',
                 '-c', 'gc.reflogExpireUnreachable=0',
                 '-c', 'gc.rerereresolved=0',
                 '-c', 'gc.rerereunresolved=0',
                 '-c', 'gc.pruneExpire=now',
                 '--branch=stable',
                 repouri, self.gitdir],
            ]

        try:
            for cmd in git_cmds:
                log.notice('>>> ' + ' '.join(cmd))
                subprocess.run(cmd,
                               capture_output=True,
                               check=True,
                               encoding='utf-8',
                               close_fds=False)

            sp = subprocess.run([self.git, '-C', self.gitdir, 'rev-parse', 'stable'],
                                capture_output=True,
                                check=True,
                                encoding='utf-8',
                                close_fds=False)
            return sp.stdout.rstrip()

        except subprocess.CalledProcessError as e:
            raise CatalystError(f'{e.cmd} failed with return code'
                                f'{e.returncode}\n'
                                f'{e.output}\n')

    def run(self):
        if self.settings['snapshot_treeish'] == 'stable':
            treeish = self.update_ebuild_repo()
        else:
            treeish = self.settings['snapshot_treeish']

        self.set_snapshot(treeish)

        git_cmd = [self.git, '-C', self.gitdir, 'archive', '--format=tar',
                   treeish]
        tar2sqfs_cmd = [command('tar2sqfs'), str(self.snapshot), '-q', '-f',
                        '-j1', '-c', 'gzip']

        log.notice('Creating %s tree snapshot %s from %s',
                   self.settings['repo_name'], treeish, self.gitdir)
        log.notice('>>> ' + ' '.join([*git_cmd, '|']))
        log.notice('    ' + ' '.join(tar2sqfs_cmd))

        lockfile = self.snapshot.with_suffix('.lock')
        with write_lock(lockfile):
            git = subprocess.Popen(git_cmd,
                                   stdout=subprocess.PIPE,
                                   stderr=sys.stderr,
                                   close_fds=False)
            tar2sqfs = subprocess.Popen(tar2sqfs_cmd,
                                        stdin=git.stdout,
                                        stdout=sys.stdout,
                                        stderr=sys.stderr,
                                        close_fds=False)
            git.stdout.close()
            git.wait()
            tar2sqfs.wait()

        if tar2sqfs.returncode == 0:
            log.notice('Wrote snapshot to %s', self.snapshot)
        else:
            log.error('Failed to create snapshot')
        return tar2sqfs.returncode == 0