File: debomatic.py

package info (click to toggle)
debomatic 0.8-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 344 kB
  • ctags: 69
  • sloc: python: 642; sh: 67; makefile: 12
file content (145 lines) | stat: -rw-r--r-- 4,830 bytes parent folder | download
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
# Deb-o-Matic
#
# Copyright (C) 2007-2009 Luca Falavigna
#
# Author: Luca Falavigna <dktrkranz@debian.org>
#
# 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; version 3 of the License.
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

import os
import sys
import threading
from fcntl import lockf, LOCK_EX, LOCK_NB
from getopt import getopt, GetoptError
from signal import pause
from time import sleep
from Debomatic import build
from Debomatic import commands
from Debomatic import Options
from Debomatic import modules
from Debomatic import running

def main():
    conffile = None
    daemon = True
    if os.getuid():
        print _('You must run deb-o-matic as root')
        sys.exit(-1)
    try:
        opts, args = getopt(sys.argv[1:], 'c:n', ['config=', 'nodaemon'])
    except GetoptError, error:
        print error.msg
        sys.exit(-1)
    for o, a in opts:
        if o in ("-c", "--config"):
            conffile = a
        if o in ('-n', '--nodaemon'):
            daemon = False
    parse_default_options(conffile)

    # If daemon mode is set, detach from the terminal and run in background.
    if daemon:
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError:
            print _('Unable to enter daemon mode')
            sys.exit(-1)
        os.setsid()
        os.chdir('/')
        os.umask(0)
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError:
            print _('Unable to enter daemon mode')
            sys.exit(-1)
        fin = open('/dev/null', 'r')
        fout = open(Options.get('default', 'logfile'), 'a+')
        ferr = open(Options.get('default', 'logfile'), 'a+', 0)
        os.dup2(fin.fileno(), sys.stdin.fileno())
        os.dup2(fout.fileno(), sys.stdout.fileno())
        os.dup2(ferr.fileno(), sys.stderr.fileno())

    fd = os.open('/var/run/debomatic.lock', os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
    try:
        lockf(fd, LOCK_EX | LOCK_NB)
    except IOError:
        print _('Another instance is running. Aborting')
        sys.exit(-1)
    mod_sys = modules.Module()
    mod_sys.execute_hook("on_start", {})
    launcher()

def parse_default_options(conffile):
    defaultoptions = ('builder', 'packagedir', 'configdir', 'maxbuilds', 'inotify', 'sleep', 'logfile')
    if not conffile:
        print _('Please specify a configuration file')
        sys.exit(-1)
    if not os.path.exists(conffile):
        print _('Configuration file %s does not exist') % conffile
        sys.exit(-1)
    Options.read(conffile)
    for opt in defaultoptions:
        if not Options.has_option('default', opt) or not Options.get('default', opt):
            print _('Please set "%(opt)s" in %(conffile)s') % {'opt':opt, 'conffile':conffile}
            sys.exit(-1)

try:
    import os
    import pyinotify
    from re import findall

    class PE(pyinotify.ProcessEvent):
        def process_IN_CLOSE_WRITE(self, event):
            if findall('source.changes$', event.name):
                threading.Thread(None, build.build_process).start()
            elif findall('commands$', event.name):
                threading.Thread(None, commands.process_commands).start()

    def launcher_inotify():
        if Options.getint('default', 'inotify'):
            wm = pyinotify.WatchManager()
            notifier = pyinotify.Notifier(wm, PE())
            wm.add_watch(Options.get('default', 'packagedir'), pyinotify.IN_CLOSE_WRITE, rec=True)
            notifier.loop(callback=exit_routine)
except:
    def launcher_inotify():
        pass

def launcher_timer():
    while exit_routine():
        threading.Thread(None, commands.process_commands).start()
        threading.Thread(None, build.build_process).start()
        sleep(Options.getint('default', 'sleep'))

def launcher():
    threading.Thread(None, launcher_inotify).start()
    threading.Thread(None, launcher_timer).start()
    try:
        pause()
    except KeyboardInterrupt:
        print _('\nWaiting for threads to finish, it could take a while...')
        exit_routine(exiting=True)

def exit_routine(self=None, exiting=False):
    global running
    if exiting:
        running = False
        return
    if not running:
        sys.exit(0)
    return running