aboutsummaryrefslogtreecommitdiff
blob: 837d6280f75caeffbeff4c2c7b8c439e2b7cf5e6 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env python
#
#    make-worldconf: this file is part of the GRS suite
#    Copyright (C) 2015  Anthony G. Basile
#
#    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 3 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 or 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 <http://www.gnu.org/licenses/>.

import configparser
import copy
import os
import re
import sys

from grs import CONST

from _emerge.main import parse_opts
from _emerge.actions import load_emerge_config, create_depgraph_params
from _emerge.depgraph import backtrack_depgraph


def useflags(config, p):
    # Get all IUSE, enabled USE and EXPAND_HIDDEN flags.
    try:
        iuse = list(p.iuse.all)
        use = list(p.use.enabled)
        # expand = list(p.use.expand)
        expand_hidden = list(p.use.expand_hidden)
    except AttributeError:
        return
    except TypeError:
        return

    # We only include select USE_EXPAND flags. Note becaue of how we match 'abi_',
    # for example, will match abi_ppc, abi_mips etc.  Hopefully this will not lead
    # to any false hits.
    expand = [ 'kernel_', 'elibc_', 'userland_', 'abi_', 'linguas_', 'python_', 'ruby_' ]

    # Remove any selected USE_EXPAND and any EXPAND_HIDDEN flags from IUSE flags
    my_iuse = copy.deepcopy(iuse)
    for u in iuse:
        for e in expand + expand_hidden:
            while re.match(e, u):
                try:
                    my_iuse.remove(u)
                except ValueError:
                    break

    # Remove the same flags from the enabled USE flags
    my_use = copy.deepcopy(use)
    for u in use:
        for e in expand + expand_hidden:
            while re.match(e, u):
                try:
                    my_use.remove(u)
                except ValueError:
                    break

    # Remove the arch flag.
    # TODO: this needs to be generalized.
    my_use.remove('amd64')

    # Go through all the IUSE flags and put a - in front
    # of all the disabled USE flags.
    flags = []
    for i in my_iuse:
        if i in my_use:
            flags.append(i)
        else:
            flags.append('-%s' % i)

    # Insert nicely sorted flags.
    if len(flags) > 0:
        flags.sort()
        config[p.slot_atom]['package.use'] = p.slot_atom + ' ' + ' '.join(flags)


def keywords(config, p):
    # Stable means there is no keyword is needed.
    keyword = None
    try:
        if not p.stable:
            keyword = "??" # Something went wrong!
            if p.get_keyword_mask() == 'missing':
                keyword = '**'
            if p.get_keyword_mask() == 'unstable':
                # This needs to be generalized
                keyword = '~amd64'
    except AttributeError:
        pass
    if keyword:
        config[p.slot_atom]['package.accept_keywords'] = '=%s %s' % (p.cpv, keyword)


def from_etc_portage(config, p, subdir):
    # We could add better matching intelligence here so as to match
    # these subdirs+files for /etc/portage not maintained by GRS.
    fpath = os.path.join(CONST.PORTAGE_CONFIGDIR, '%s/%s' % \
        (subdir, re.sub('[/:]', '_', p.slot_atom)))
    if os.path.isfile(fpath):
        with open(fpath, 'r') as g:
            config[p.slot_atom][subdir] = g.read().strip()


def main():
    args = sys.argv[1:]
    if len(args) == 0:
        args =  [ '-e', '@world' ]

    myaction, myopts, myfiles = parse_opts(args, silent=True)
    emerge_config = load_emerge_config(action=myaction, args=myfiles, opts=myopts)
    mysettings, mytrees = emerge_config.target_config.settings, emerge_config.trees
    myparams = create_depgraph_params(myopts, myaction)
    success, mydepgraph, favorites = backtrack_depgraph(mysettings, mytrees, myopts, \
        myparams, myaction, myfiles, spinner=None)

    config = configparser.RawConfigParser(delimiters=':', allow_no_value=True, comment_prefixes=None)

    for p in mydepgraph.altlist():
        # Prepare an empty section for this atom
        try:
            config[p.slot_atom] = {}
        except AttributeError:
            continue

        # Populate package.use - these are read out of p
        useflags(config, p)

        # Populate package.accept_keywords - these are read out of p
        keywords(config, p)

        # Others - these are read out of /etc/portage
        from_etc_portage(config, p, 'package.mask')
        from_etc_portage(config, p, 'package.unmask')
        from_etc_portage(config, p, 'package.env')
        from_etc_portage(config, p, 'env')

        # Remove any empty sections
        if config[p.slot_atom] == {}:
            config.remove_section(p.slot_atom)

    # Recontruct a RawConfigParser from the above which has sorted sections.
    all_slot_atoms = config.sections()
    all_slot_atoms.sort()
    sorted_config = configparser.RawConfigParser(delimiters=':', allow_no_value=True, comment_prefixes=None)
    for s in all_slot_atoms:
        sorted_config[s] = config[s]

    with open('world.conf', 'w') as configfile:
        sorted_config.write(configfile)

if __name__ == "__main__":
    main()