11bc4dc9ea40806bfe6bbeef163a30bd198a0a11
[cdist.git] / cdist / tree.py
1 #
2 #    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
3 #
4 #    This program is free software; you can redistribute it and/or modify
5 #    it under the terms of the GNU General Public License as published by
6 #    the Free Software Foundation; either version 2 of the License, or
7 #    (at your option) any later version.
8 #
9 #    This program is distributed in the hope that it will be useful,
10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #    GNU General Public License for more details.
13
14 #    You should have received a copy of the GNU General Public License
15 #    along with this program; if not, write to the Free Software
16 #    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 import os
19 import copy
20 import inspect
21
22 import globals
23 from util import *
24 from version import Version
25 from tree_directory import TreeDirectory
26
27 class Tree(object):
28     """Description of a tree, which is a checkout of a project,
29        possibly built.  This class is never exposed to cscripts.
30        Attributes:
31            name -- name of git repository (without the .git)
32            specifier -- git tag or revision to use
33            target --- target object that we are using
34            version --- version from the wscript (if one is present)
35            git_commit -- git revision that is actually being used
36            built --- true if the tree has been built yet in this run
37     """
38
39     def __init__(self, name, specifier, target):
40         self.name = name
41         self.specifier = specifier
42         self.target = target
43         self.version = None
44         self.git_commit = None
45         self.built = False
46
47         cwd = os.getcwd()
48
49         flags = ''
50         redirect = ''
51         if globals.quiet:
52             flags = '-q'
53             redirect = '>/dev/null'
54         command('git clone %s %s/%s.git %s/src/%s' % (flags, globals.config.get('git_prefix'), self.name, target.directory, self.name))
55         chdir('%s/src/%s' % (target.directory, self.name))
56
57         spec = self.specifier
58         if spec is None:
59             spec = 'master'
60
61         command('git checkout %s %s %s' % (flags, spec, redirect))
62         self.git_commit = command_and_read('git rev-parse --short=7 HEAD').readline().strip()
63         command('git submodule init --quiet')
64         command('git submodule update --quiet')
65
66         proj = '%s/src/%s' % (target.directory, self.name)
67
68         self.cscript = {}
69         execfile('%s/cscript' % proj, self.cscript)
70
71         if os.path.exists('%s/wscript' % proj):
72             v = read_wscript_variable(proj, "VERSION");
73             if v is not None:
74                 self.version = Version(v)
75
76         chdir(cwd)
77
78     def call(self, function, *args):
79         with TreeDirectory(self):
80             return self.cscript[function](self.target, *args)
81
82     def build_dependencies(self):
83         if 'dependencies' in self.cscript:
84             for d in self.cscript['dependencies'](self.target):
85                 log('Building dependency %s %s of %s' % (d[0], d[1], self.name))
86                 dep = globals.trees.get(d[0], d[1], self.target)
87                 dep.build_dependencies()
88
89                 # Make the options to pass in from the option_defaults of the thing
90                 # we are building and any options specified by the parent.
91                 options = {}
92                 if 'option_defaults' in dep.cscript:
93                     options = dep.cscript['option_defaults']()
94                     if len(d) > 2:
95                         for k, v in d[2].iteritems():
96                             options[k] = v
97
98                 dep.build(options)
99
100     def build(self, options=None):
101         if self.built:
102             return
103
104         variables = copy.copy(self.target.variables)
105
106         if len(inspect.getargspec(self.cscript['build']).args) == 2:
107             self.call('build', options)
108         else:
109             self.call('build')
110
111         self.target.variables = variables
112         self.built = True