bug fix: util.lower_case(str)
[lazy-man.git] / lazy_man.py
blob00aecc1a1262808ab57fc3460481dcc427db2e96
1 #!/usr/bin/env python
3 from util import *
4 import os
5 from subprocess import *
7 success_target = '<success_target>'
9 class LMException(Exception):
10 def __init__(self, msg, obj):
11 self.msg, self.obj = msg, obj
13 def __str__(self):
14 return "LMException: %s: %s"%(self.msg, self.obj)
16 def nil_action(env, target, deps, all_deps, log):
17 pass
19 class Rule:
20 def __init__(self, target=None, depends=None, action=None):
21 self.target, self.depends, self.action = target, depends, action
22 if type(self.action) == str: self.action = [self.action]
23 if type(self.depends) == str:
24 self.depends = [self.depends]
26 def get_deps(self, target):
27 return None
29 def do(self, lm, target, all_deps, log):
30 deps = self.get_deps(target)
31 if self._need_update(target, deps, all_deps):
32 if callable(self.action):
33 self.action(lm, target, deps, all_deps, log)
34 elif type(self.action) == list:
35 lm.sh(self.action, log, target=target, deps=deps,all_deps=all_deps)
36 else:
37 raise LMException("Wrong Action", self.action)
39 def __str__(self):
40 return "%s <= %s"%(self.target, self.depends)
42 @staticmethod
43 def _need_update(target, deps, all_deps):
44 if not os.path.exists(target):
45 return True
46 mtime = os.path.getmtime(target)
47 for dep in all_deps:
48 if not os.path.exists(dep):
49 continue
50 if os.path.getmtime(dep) > mtime:
51 return True
52 return False
54 class ExistFileRule(Rule):
55 def __init__(self):
56 Rule.__init__(self, action=nil_action)
58 def get_deps(self, target):
59 if os.path.exists(target):
60 return [success_target]
61 return None
63 class StaticRule(Rule):
64 def __init__(self, target, depends=[success_target], action=nil_action):
65 Rule.__init__(self, target, depends, action)
67 def get_deps(self, target):
68 if target == self.target:
69 return self.depends
70 return None
72 class RegexpRule(Rule):
73 def __init__(self, target, depends=[success_target], action=nil_action):
74 Rule.__init__(self, target, depends, action)
76 def get_deps(self, target):
77 if not re.match(self.target, target):
78 return None
79 return [re.sub(self.target, dep, target) for dep in self.depends]
81 class LazyMan(Env):
82 def __init__(self, name='default', env={}, rules=[], log=BlockStream()):
83 Env.__init__(self, env)
84 self.name, self.env, self.rules, self.log = name, env, rules, log
85 self.add(ExistFileRule())
87 def add(self, *rules):
88 self.rules.extend(list_(rules))
90 def sh(self, cmd_list, log, **args):
91 cmd_list = list_(cmd_list)
92 env = dict(self, **args)
93 expanded_cmd = [sub(cmd, env) for cmd in cmd_list]
94 for item in expanded_cmd:
95 log<< "LazyMan $ %s"% (item,)
96 if self.dry_run: continue
97 err = call(item, shell=True)
98 if err: raise LMException("Task Fail", item)
100 def do(self, target, log=None):
101 if target == success_target:
102 return
103 if log==None: log=self.log
104 if self.verbose:
105 log<< "%s =>"%target
106 rules, all_deps = self._select_rule(target)
107 if not rules: raise LMException("No Rule", target)
108 for dep in all_deps:
109 self.do(dep, log.new())
110 for rule in rules:
111 rule.do(self, target, all_deps, log)
113 def _select_rule(self, target):
114 rules_deps = [(rule,rule.get_deps(target)) for rule in self.rules]
115 rules_deps = [(rule, deps) for rule, deps in rules_deps if deps]
116 rules = [rule for rule, dep in rules_deps]
117 deps = [dep for rule, dep in rules_deps]
118 all_deps = list_(deps)
119 deps_set =set()
120 new_deps = []
121 for dep in all_deps:
122 if deps_set.issuperset(set([dep])):
123 continue
124 deps_set.add(dep)
125 new_deps.append(dep)
126 return rules, new_deps
128 def do_task(self, target=['default']):
129 target = list_(target)
130 if not target: target = ["default"]
131 for t in target:
132 try:
133 self.do(t)
134 except LMException,e:
135 print "LM: %s" % e
137 def __str__(self):
138 return "LazyMan: %s\nrules:\n%s\n"%(self.name, '\n'.join([str(rule) for rule in self.rules]))