]> git.ipfire.org Git - pakfire.git/blob - src/pakfire/builder.py
03ea2d64d0a76a10b45b3bab8ff3079d2336297b
[pakfire.git] / src / pakfire / builder.py
1 #!/usr/bin/python3
2 ###############################################################################
3 # #
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 import glob
23 import os
24 import uuid
25
26 from . import _pakfire
27 from . import base
28 from . import logger
29 from . import util
30
31 import logging
32 log = logging.getLogger("pakfire.builder")
33
34 from .constants import *
35 from .i18n import _
36 from .errors import *
37
38 BUILD_LOG_HEADER = """
39 ____ _ __ _ _ _ _ _
40 | _ \ __ _| | __/ _(_)_ __ ___ | |__ _ _(_) | __| | ___ _ __
41 | |_) / _` | |/ / |_| | '__/ _ \ | '_ \| | | | | |/ _` |/ _ \ '__|
42 | __/ (_| | <| _| | | | __/ | |_) | |_| | | | (_| | __/ |
43 |_| \__,_|_|\_\_| |_|_| \___| |_.__/ \__,_|_|_|\__,_|\___|_|
44
45 Version : %(version)s
46 Host : %(hostname)s (%(host_arch)s)
47 Time : %(time)s
48
49 """
50
51 class Builder(object):
52 def __init__(self, conf, arch=None, build_id=None, logfile=None, **kwargs):
53 self.conf = conf
54
55 # Settings array.
56 self.settings = {
57 "enable_ccache" : True,
58 "enable_snapshot" : True,
59 }
60
61 # Add settings from keyword arguments
62 self.settings.update(kwargs)
63
64 # Generate a build ID
65 self.build_id = build_id or "%s" % uuid.uuid4()
66
67 # Setup logging
68 self.log = self.setup_logging(logfile)
69
70 # Architecture to build for
71 self.arch = arch or _pakfire.native_arch()
72
73 def __enter__(self):
74 self.log.debug("Entering %s" % self)
75
76 # Initialise Pakfire instance
77 pakfire = base.Pakfire(
78 arch=self.arch,
79 conf=self.conf,
80
81 # Enable build mode
82 build=True,
83 **self.settings,
84 )
85
86 # Setup domain name resolution in chroot
87 for i in ("/etc/resolv.conf", "/etc/hosts"):
88 pakfire.copy_in(i, i)
89
90 return BuilderContext(pakfire, self)
91
92 def __exit__(self, type, value, traceback):
93 self.log.debug("Leaving %s" % self)
94
95 def setup_logging(self, logfile):
96 l = log.getChild(self.build_id)
97 l.setLevel(logging.DEBUG)
98
99 # Print everything to the console
100 console = logger.ConsoleHandler()
101 l.addHandler(console)
102
103 # If we have a log file, we write INFO and higher level messages to it
104 # using the build formatter which adds a timestamp
105 if logfile:
106 h = logging.FileHandler(logfile)
107 h.setLevel(logging.INFO)
108 l.addHandler(h)
109
110 # Set formatter
111 f = logger.BuildFormatter()
112 h.setFormatter(f)
113
114 return l
115
116
117 class BuilderContext(object):
118 def __init__(self, pakfire, builder):
119 self.pakfire = pakfire
120 self.builder = builder
121
122 # Get a reference to the logger
123 self.log = self.builder.log
124
125 def _install(self, packages):
126 self.log.debug(_("Installing packages in build environment:"))
127 for package in packages:
128 self.log.debug(" %s" % package)
129
130 # Initialise Pakfire
131 with self.pakfire as p:
132 # Install all required packages
133 transaction = p.install(packages)
134
135 # Return how many packages were installed/changed
136 ret = len(transaction)
137
138 # Dump transaction to log
139 t = transaction.dump()
140 self.log.info(t)
141
142 # Download transaction
143 transaction.download()
144
145 # Run the transaction
146 transaction.run()
147
148 return ret
149
150 def build(self, path, shell=True):
151 # Install the package
152 self._install([path])
153
154 for makefile in glob.glob("%s/usr/src/packages/*/*.nm" % self.pakfire.path):
155 self.pakfire.build(makefile, logging_callback=self.log.log, interactive=shell)
156
157 def shell(self, packages=[], install=None):
158 if install:
159 packages += install
160
161 self._install(packages)
162
163 # Enter the shell
164 self.pakfire.shell()
165