Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/devbot/system.py
blob: b12190a190f0d44a0ebc5ebb8eab72afa5df8b27 (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import json
import os
import subprocess
import sys

from devbot import config
from devbot import distro
from devbot import command

devnull = open("/dev/null", "w")
xvfb_display = ":100"

libdirs = ["lib",
           "lib64",
           "lib/x86_64-linux-gnu",
           "lib/i386-linux-gnu"]

def check_binary(check):
    return subprocess.call(["which", check],
                           stdout=devnull,
                           stderr=subprocess.STDOUT)

def check_pkgconfig(check):
    return subprocess.call(["pkg-config", "--exists", check]) == 1

def check_python(check):
    return subprocess.call(["python", "-c", check],
                           stdout=devnull, stderr=subprocess.STDOUT) == 1

def check_gtkmodule(check):
    # Not sure we can do better than this, the gtkmodule stuff is private
    missing = True
    
    for libdir in libdirs:
        if os.path.exists("/usr/%s/gtk-2.0/modules/lib%s.so" % (libdir, check)):
            missing = False

    return missing

def check_include(check):
    return not os.path.exists(os.path.join("/usr/include/", check))

def check_dbus(check):
    return not os.path.exists("/usr/share/dbus-1/services/%s.service" % check)

def check_metacity_theme(check):
    return not os.path.exists("/usr/share/themes/%s/metacity-1/metacity-theme-3.xml" % check)

def check_gstreamer(check):
    missing = True
    
    for libdir in libdirs:
        if os.path.exists("/usr/%s/gstreamer-0.10/libgst%s.so" % (libdir, check)):
            missing = False

    return missing

checkers = { "binary": check_binary,
             "python": check_python,
             "pkgconfig": check_pkgconfig,
             "gtkmodule": check_gtkmodule,
             "dbus": check_dbus,
             "gstreamer": check_gstreamer,
             "metacity-theme": check_metacity_theme,
             "include": check_include }

def load_deps_json(name):
    path = os.path.join(scriptdir, "deps", "%s.json" % name)
    return json.load(open(path))

def run_checks(package_manager, checks, packages):
    distro_name = distro.get_distro_name()

    failed_checks = []
    to_install = []

    for check in checks:
        checker = checkers[check["checker"]]
        if checker(check["check"]):
            check_name = check.get("check_name", check["check"])
            if distro_name in packages[check_name]:
                package_list = packages[check_name][distro_name]
                if not isinstance(package_list, list):
                    package_list = [package_list]

                for package in package_list:
                    # Might be none, if so skip on this distro_name
                    if package and package not in packages:
                        to_install.append(package)
            else:
                failed_checks.append(check)

    if to_install:
        package_manager.install_packages(to_install)

    if failed_checks:
        print "Failed checks\n"
    else:
        return True

    for check in failed_checks:
        print "[%s] %s" % (check["checker"], check["check"])

    return False

def start_xvfb():
    xvfb_proc = subprocess.Popen(args=["Xvfb", xvfb_display],
                                 stdout=devnull,
                                 stderr=subprocess.STDOUT)
    orig_display = os.environ.get("DISPLAY", None)
    os.environ["DISPLAY"] = xvfb_display

    return (xvfb_proc, orig_display)

def stop_xvfb(xvfb_proc, orig_display):
    if orig_display:
        os.environ["DISPLAY"] = xvfb_display
    else:
        del os.environ["DISPLAY"]

    xvfb_proc.terminate()

def apply_ubuntu_tweaks():
    # FIXME we don't want the package to depend on external scripts
    devbot_dir = os.path.abspath(os.path.dirname(__file__))
    scripts_dir = os.path.join(os.path.dirname(devbot_dir), "scripts")

    wrapper_config = open("/etc/X11/Xwrapper.config").read()
    if "allowed_users=anybody" not in wrapper_config:
        if "SUGAR_BUILDBOT" in os.environ:
            print "\nPlease allow anybody to run the X server with \n" \
                  "  sudo dpkg-reconfigure x11-common"        
        else:  
            print "\nWe are going to allow anybody to run the X server"            
            ubuntu_tweaks = os.path.join(scripts_dir, "ubuntu-tweaks")            
            command.run_with_sudo([ubuntu_tweaks])

def apply_distro_tweaks(distro_name):
    if distro_name == "ubuntu":
        apply_ubuntu_tweaks()

def warn_if_unsupported(distro_name):
    if distro_name == "unsupported":
        print "*********************************************************\n" \
              "You are running an unsupported distribution. You might be\n" \
              "able to make sugar work by installing or building \n" \
              "packages but it certainly won't work out of the box.\n" \
              "You are strongly encouraged to pick one of the supported \n" \
              "distributions listed in the README.\n" \
              "*********************************************************\n"

def remove_packages(package_manager, packages):
    distro_name = distro.get_distro_name()

    to_keep = []
    for package_info in packages.values():
        if distro_name in package_info:
            package_list = package_info[distro_name]
            if not isinstance(package_list, list):
                package_list = [package_list]

            for package in package_list:
                if package not in to_keep:
                    to_keep.append(package)

    try:
        to_keep = package_manager.find_with_deps(to_keep)
    except NotImplementedError:
        return

    all = package_manager.find_all()

    to_remove = []
    for package in all:
        if package not in to_keep:
            to_remove.append(package)

    if to_remove:
        package_manager.remove_packages(to_remove)

def check(remove=False, update=False, test=False):
    distro_name = distro.get_distro_name()
    package_manager = distro.get_package_manager(test=test)

    packages = config.load_packages()

    checks = config.load_prerequisites()
    if not run_checks(distro_name, checks, packages):
        sys.exit(1)

    xvfb_proc, orig_display = start_xvfb()

    run_checks(package_manager, config.load_checks(), packages)

    warn_if_unsupported(distro_name)
    apply_distro_tweaks(distro_name)

    stop_xvfb(xvfb_proc, orig_display)

    if update:
        package_manager.update()

    if remove:
	remove_packages(package_manager, packages)