aboutsummaryrefslogtreecommitdiff
blob: c24a82c279ebbf1cd09393f2f5ec2c39a543b9bf (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
"""Use Flag Mechanics """

import random
import re
import math
from portage.dep import check_required_use, dep_getcpv
from subprocess import *

from .tool import unique
from gentoolkit.flag import get_flags, reduce_flags

def all_valid_flags(flag):
    return True

def check_uses(ruse, uselist, sw, package):
    act = [] # check_required_use doesn't like -flag entries
    for pos in range(len(uselist)):
        if ((2**pos) & sw):
            act.append(uselist[pos])
    if bool(check_required_use(ruse, " ".join(act), all_valid_flags)):
        return True
    else:
        print("  " + package.packageString() + ": ignoring invalid USE flag combination", act)
        return False

## Useflag Combis ##
def findUseFlagCombis (package, config, port):
    """
    Generate combinations of use flags to test
    The output will be a list each containing a ready to use USE=... string
    """
    uselist = sorted(reduce_flags(get_flags(dep_getcpv(package.packageString()))))
    # The uselist could have duplicates due to slot-conditional
    # output of equery
    uselist=unique(uselist)
    for i in config['ignoreprefix']:
        uselist=[u for u in uselist if not re.match(i,u)]

    ruse = " ".join(port.aux_get(dep_getcpv(package.packageString()), ["REQUIRED_USE"]))
    swlist = []
    if config['usecombis'] == 0:
        # Do only all and nothing:
        if check_uses(ruse, uselist, 0, package):
            swlist.append(0)
        if check_uses(ruse, uselist, 2**len(uselist) - 1):
            swlist.append(2**len(uselist) - 1)
    # Test if we can exhaust all USE-combis by computing the binary logarithm.
    elif len(uselist) > math.log(config['usecombis'],2):
        
        # Generate a sample of USE combis
        s = 2**(len (uselist))
        rnds = set()
        random.seed()
        
        attempts = 0
        ignore_use_expand = False

        while len(swlist) < config['usecombis'] and len(rnds) < s:
            if attempts >= 10000 and not ignore_use_expand:
                # After 10000 attempts, let's give up on USE_EXPAND.
                ignore_use_expand = True
                attempts = 0

                print("Giving up on USE_EXPAND after {0} tries to find valid USE combinations".format(attempts))
                print("We've found {0} USE combinations so far".format(len(swlist)))
                uselist = [use for use in uselist if not "_" in use]
                
            if attempts >= 10000 and ignore_use_expand:
                # Let's give up entirely and use what we have.
                print("Giving up on finding more USE combinations after {0} further attempts".format(attempts))
                print("We've found {0} USE combinations".format(len(swlist)))
                break

            r = random.randint(0, s-1)
            if r in rnds:
                # already checked
                continue
            rnds.add(r)

            if not check_uses(ruse, uselist, r, package):
                attempts += 1
                # invalid combination
                continue

            swlist.append(r)

        swlist.sort()
    else:
        # Yes we can: generate all combinations
        for pos in range(2**len(uselist)):
            if check_uses(ruse, uselist, pos, package):
                swlist.append(pos)

    usecombis=[]
    for sw in swlist:
        mod = []
        for pos in range(len(uselist)):
            if ((2**pos) & sw):
                mod.append("")
            else:
                mod.append("-")
        usecombis.append(" ".join(["".join(uf) for uf in list(zip(mod, uselist))]))

    # Merge everything to a USE="" string
    return ["USE=\'" + uc + "\'" for uc in usecombis]