comparison treepkg/packager.py @ 4:fee641fec94e

Separate the kolab specific parts.
author Bernhard Herzog <bh@intevation.de>
date Fri, 09 Mar 2007 12:26:01 +0100
parents e6a9f4037f68
children 96f4f58c62b5
comparison
equal deleted inserted replaced
3:7e9db903ba16 4:fee641fec94e
25 return property(get) 25 return property(get)
26 26
27 27
28 class SourcePackager(object): 28 class SourcePackager(object):
29 29
30 # Derived classes must supply the package basename
31 pkg_basename = None
32
30 def __init__(self, plant, status, work_dir, src_dir, revision): 33 def __init__(self, plant, status, work_dir, src_dir, revision):
31 self.plant = plant 34 self.plant = plant
32 self.status = status 35 self.status = status
33 self.work_dir = work_dir 36 self.work_dir = work_dir
34 self.src_dir = src_dir 37 self.src_dir = src_dir
35 self.revision = revision 38 self.revision = revision
36 self.enterprise_version = (time.strftime("%Y%m%d", time.localtime()) \ 39 assert(self.pkg_basename)
37 + "." + str(self.revision))
38
39 def kdepim_version(self, directory):
40 """Determine the kdepim version.
41
42 The version is taken from the kdepim.lsm file in the plants
43 checkout dir.
44 """
45 return util.extract_lsm_version(os.path.join(directory, "kdepim.lsm"))
46 40
47 def determine_package_version(self, directory): 41 def determine_package_version(self, directory):
48 enterprise_version = self.enterprise_version 42 """Returns the version number of the new package as a string
49 kdepimversion = self.kdepim_version(directory) 43
50 version_template = "%(kdepimversion)s.enterprise.0.%(enterprise_version)s" 44 The directory parameter is the name of the directory containing
51 return version_template % locals() 45 the newly exported sources. The sources were exported with the
46 export_sources method.
47
48 The default implementation simply returns the revision converted
49 to a string.
50 """
51 return str(self.revision)
52 52
53 def export_sources(self): 53 def export_sources(self):
54 """Export the sources from the subversion working directory
55
56 This method first exports the sources to a temporary directory
57 and then renames the directory. The new name is of the form
58
59 <pkg_basename>-<version>
60
61 Where pkg_basename is the value of self.pkg_basename and version
62 is the return value of the determine_package_version() method.
63 """
54 temp_dir = os.path.join(self.work_dir, "temp") 64 temp_dir = os.path.join(self.work_dir, "temp")
55 self.plant.export_sources(temp_dir) 65 self.plant.export_sources(temp_dir)
56 66
57 pkgbaseversion = self.determine_package_version(temp_dir) 67 pkgbaseversion = self.determine_package_version(temp_dir)
58 pkgbasedir = os.path.join(self.work_dir, "kdepim-" + pkgbaseversion) 68 pkgbasedir = os.path.join(self.work_dir,
69 self.pkg_basename + "-" + pkgbaseversion)
59 70
60 os.rename(temp_dir, pkgbasedir) 71 os.rename(temp_dir, pkgbasedir)
61 return pkgbaseversion, pkgbasedir 72 return pkgbaseversion, pkgbasedir
62 73
63 74
64 def update_version_numbers(self, pkgbasedir): 75 def update_version_numbers(self, pkgbasedir):
65 versionstring = "(enterprise %s)" % self.enterprise_version 76 """Updates the version numbers in the code in pkgbasedir.
66 for versionfile in ["kmail/kmversion.h", "kontact/src/main.cpp", 77
67 "korganizer/version.h"]: 78 The default implementation does nothing. Derived classes should
68 filename = os.path.join(pkgbasedir, versionfile) 79 override this method if necessary.
69 patched = re.sub("\(enterprise ([^)]*)\)", versionstring, 80 """
70 open(filename).read())
71 f = open(filename, "w")
72 f.write(patched)
73 f.close()
74 81
75 def create_tarball(self, tarballname, workdir, basedir): 82 def create_tarball(self, tarballname, workdir, basedir):
83 """Creates a new tarball.
84
85 Parameters:
86
87 tarballname -- the filename of the new tarball
88 workdir -- The directory into which to change before running tar.
89 (actually this is done with GNUI tar's -C option)
90 basedir -- The basedirectory of the files that are packaged
91 into the tarfile. This should be a relative
92 filename directly in workdir.
93 """
76 logging.info("Creating tarball %r", tarballname) 94 logging.info("Creating tarball %r", tarballname)
77 run.call(["tar", "czf", tarballname, "-C", workdir, basedir]) 95 run.call(["tar", "czf", tarballname, "-C", workdir, basedir])
78 96
79 def copy_debian_directory(self, pkgbasedir, pkgbaseversion, changemsg): 97 def copy_debian_directory(self, pkgbasedir, pkgbaseversion, changemsg):
98 """Copies the debian directory and updates the copy's changelog
99
100 Parameter:
101 pkgbasedir -- The directory holding the unpacked source package
102 pkgbaseversion -- The version to update the changelog to
103 changemsg -- The message for the changelog
104
105 When determining the actual version for the new package, this
106 function looks at the previous version in the changelog. If it
107 has a prefix separated from the version number by a colon this
108 prefix is prepended to the pkgbaseversion parameter. Debian
109 uses such prefixes for the kde packages.
110 """
80 debian_dir = os.path.join(pkgbasedir, "debian") 111 debian_dir = os.path.join(pkgbasedir, "debian")
81 changelog = os.path.join(debian_dir, "changelog") 112 changelog = os.path.join(debian_dir, "changelog")
82 113
83 self.plant.copy_debian_directory(debian_dir) 114 self.plant.copy_debian_directory(debian_dir)
84 115
93 changemsg], 124 changemsg],
94 env=self.plant.debian_environment()) 125 env=self.plant.debian_environment())
95 126
96 127
97 def create_source_package(self, pkgbasedir, origtargz): 128 def create_source_package(self, pkgbasedir, origtargz):
129 """Creates a new source package from pkgbasedir and origtargz"""
98 logging.info("Creating new source package") 130 logging.info("Creating new source package")
99 run.call(["dpkg-source", "-b", os.path.basename(pkgbasedir), 131 run.call(["dpkg-source", "-b", os.path.basename(pkgbasedir),
100 os.path.basename(origtargz)], 132 os.path.basename(origtargz)],
101 cwd=os.path.dirname(pkgbasedir), 133 cwd=os.path.dirname(pkgbasedir),
102 suppress_output=True, 134 suppress_output=True,
103 env=self.plant.debian_environment()) 135 env=self.plant.debian_environment())
104 136
137 def move_source_package(self, pkgbasename):
138 """Moves the new source package from the work_dir to the src_dir"""
139 logging.info("Moving source package to %r", self.src_dir)
140 util.ensure_directory(self.src_dir)
141 for filename in [filename for filename in os.listdir(self.work_dir)
142 if filename.startswith(pkgbasename)]:
143 os.rename(os.path.join(self.work_dir, filename),
144 os.path.join(self.src_dir, filename))
145
105 def package(self): 146 def package(self):
147 """Creates a source package from a subversion checkout.
148
149 After setting up the working directory, this method calls the
150 do_package method to do the actual packaging. Afterwards the
151 work directory is removed.
152 """
106 util.ensure_directory(self.work_dir) 153 util.ensure_directory(self.work_dir)
107 try: 154 try:
108 self.status.set("creating_source_package") 155 self.status.set("creating_source_package")
109 pkgbaseversion, pkgbasedir = self.export_sources() 156 self.do_package()
110 self.update_version_numbers(pkgbasedir)
111
112 pkgbasename = "kdepim_" + pkgbaseversion
113 origtargz = os.path.join(self.work_dir,
114 pkgbasename + ".orig.tar.gz")
115 self.create_tarball(origtargz, self.work_dir,
116 os.path.basename(pkgbasedir))
117
118 changemsg = ("Update to SVN enterprise branch rev. %d"
119 % (self.revision,))
120 self.copy_debian_directory(pkgbasedir, pkgbaseversion,
121 changemsg)
122
123 self.create_source_package(pkgbasedir, origtargz)
124
125 logging.info("Moving source package to %r", self.src_dir)
126 util.ensure_directory(self.src_dir)
127 for filename in [filename for filename in os.listdir(self.work_dir)
128 if filename.startswith(pkgbasename)]:
129 os.rename(os.path.join(self.work_dir, filename),
130 os.path.join(self.src_dir, filename))
131 self.status.set("source_package_created") 157 self.status.set("source_package_created")
132 finally: 158 finally:
133 logging.info("Removing workdir %r", self.work_dir) 159 logging.info("Removing workdir %r", self.work_dir)
134 shutil.rmtree(self.work_dir) 160 shutil.rmtree(self.work_dir)
161
162 def do_package(self):
163 """Does the work of creating a source package
164 This method must be overriden by derived classes.
165
166 The method should do the work in self.work_dir. When the
167 package is done, the source package files should be in
168 self.src_dir.
169 """
170 raise NotImplementedError
135 171
136 172
137 class BinaryPackager(object): 173 class BinaryPackager(object):
138 174
139 def __init__(self, plant, status, binary_dir, dsc_file, logfile): 175 def __init__(self, plant, status, binary_dir, dsc_file, logfile):
153 self.status.set("binary_package_created") 189 self.status.set("binary_package_created")
154 190
155 191
156 class RevisionPackager(object): 192 class RevisionPackager(object):
157 193
194 source_packager_cls = SourcePackager
195 binary_packager_cls = BinaryPackager
196
158 def __init__(self, plant, revision): 197 def __init__(self, plant, revision):
159 self.plant = plant 198 self.plant = plant
160 self.revision = revision 199 self.revision = revision
161 self.base_dir = self.plant.pkg_dir_for_revision(self.revision, 1) 200 self.base_dir = self.plant.pkg_dir_for_revision(self.revision, 1)
162 self.status = util.StatusFile(os.path.join(self.base_dir, "status")) 201 self.status = util.StatusFile(os.path.join(self.base_dir, "status"))
171 return os.path.join(self.src_dir, filename) 210 return os.path.join(self.src_dir, filename)
172 return None 211 return None
173 212
174 def package(self): 213 def package(self):
175 try: 214 try:
176 src_packager = SourcePackager(self.plant, self.status, 215 src_packager = self.source_packager_cls(self.plant, self.status,
177 self.work_dir, self.src_dir, 216 self.work_dir, self.src_dir,
178 self.revision) 217 self.revision)
179 src_packager.package() 218 src_packager.package()
180 219
181 dsc_file = self.find_dsc_file() 220 dsc_file = self.find_dsc_file()
182 if dsc_file is None: 221 if dsc_file is None:
183 raise RuntimeError("Cannot find dsc File in %r" % self.src_dir) 222 raise RuntimeError("Cannot find dsc File in %r" % self.src_dir)
184 223
185 bin_packager = BinaryPackager(self.plant, self.status, 224 bin_packager = self.binary_packager_cls(self.plant, self.status,
186 self.binary_dir, dsc_file, 225 self.binary_dir, dsc_file,
187 os.path.join(self.base_dir, 226 os.path.join(self.base_dir,
188 "build.log")) 227 "build.log"))
189 bin_packager.package() 228 bin_packager.package()
190 except: 229 except:
191 self.status.set("failed", traceback.format_exc()) 230 self.status.set("failed", traceback.format_exc())
192 raise 231 raise
193 232
196 shutil.rmtree(self.base_dir) 235 shutil.rmtree(self.base_dir)
197 236
198 237
199 class AssemblyLine(object): 238 class AssemblyLine(object):
200 239
240 revision_packager_cls = RevisionPackager
241
242 svn_external_subdirs = []
243
244 extra_config_desc = []
245
201 def __init__(self, name, base_dir, svn_url, root_cmd, deb_email, 246 def __init__(self, name, base_dir, svn_url, root_cmd, deb_email,
202 deb_fullname): 247 deb_fullname, packager_class="treepkg.packager"):
203 self.name = name 248 self.name = name
204 self.base_dir = base_dir 249 self.base_dir = base_dir
205 self.svn_url = svn_url 250 self.svn_url = svn_url
206 self.root_cmd = root_cmd 251 self.root_cmd = root_cmd
207 self.deb_email = deb_email 252 self.deb_email = deb_email
217 def pkg_dir_for_revision(self, revision, increment): 262 def pkg_dir_for_revision(self, revision, increment):
218 return os.path.join(self.pkg_dir, 263 return os.path.join(self.pkg_dir,
219 self.pkg_dir_template % locals()) 264 self.pkg_dir_template % locals())
220 265
221 def last_changed_revision(self): 266 def last_changed_revision(self):
222 rev1 = subversion.last_changed_revision(self.checkout_dir) 267 revisions = []
223 rev2 = subversion.last_changed_revision(os.path.join(self.checkout_dir, 268 for directory in [self.checkout_dir] + self.svn_external_subdirs:
224 "admin")) 269 directory = os.path.join(self.checkout_dir, directory)
225 return max(rev1, rev2) 270 revisions.append(subversion.last_changed_revision(directory))
271 return max(revisions)
226 272
227 def last_packaged_revision(self): 273 def last_packaged_revision(self):
228 """Returns the revision number of the highest packaged revision. 274 """Returns the revision number of the highest packaged revision.
229 275
230 If the revision cannot be determined because no already packaged 276 If the revision cannot be determined because no already packaged
263 logging.info("Exporting sources for tarball to %r", to_dir) 309 logging.info("Exporting sources for tarball to %r", to_dir)
264 subversion.export(self.checkout_dir, to_dir) 310 subversion.export(self.checkout_dir, to_dir)
265 # some versions of svn (notably version 1.4.2 shipped with etch) 311 # some versions of svn (notably version 1.4.2 shipped with etch)
266 # do export externals such as the admin subdirectory. We may 312 # do export externals such as the admin subdirectory. We may
267 # have to do that in an extra step. 313 # have to do that in an extra step.
268 admindir = os.path.join(to_dir, "admin") 314 for subdir in self.svn_external_subdirs:
269 if not os.path.isdir(admindir): 315 absdir = os.path.join(to_dir, subdir)
270 subversion.export(os.path.join(self.checkout_dir, "admin"), 316 if not os.path.isdir(absdir):
271 admindir) 317 subversion.export(os.path.join(self.checkout_dir, subdir),
318 absdir)
272 319
273 def copy_debian_directory(self, to_dir): 320 def copy_debian_directory(self, to_dir):
274 logging.info("Copying debian directory to %r", to_dir) 321 logging.info("Copying debian directory to %r", to_dir)
275 shutil.copytree(self.debian_dir, to_dir) 322 shutil.copytree(self.debian_dir, to_dir)
276 323
288 logging.info("New revision is %d", current_revision) 335 logging.info("New revision is %d", current_revision)
289 previous_revision = self.last_packaged_revision() 336 previous_revision = self.last_packaged_revision()
290 logging.info("Previously packaged revision was %d", previous_revision) 337 logging.info("Previously packaged revision was %d", previous_revision)
291 if current_revision > previous_revision: 338 if current_revision > previous_revision:
292 logging.info("New revision is not packaged yet") 339 logging.info("New revision is not packaged yet")
293 return RevisionPackager(self, current_revision) 340 return self.revision_packager_cls(self, current_revision)
294 else: 341 else:
295 logging.info("New revision already packaged.") 342 logging.info("New revision already packaged.")
296 343
344
345 def create_packager(packager_class, **kw):
346 module = util.import_dotted_name(packager_class)
347 return module.AssemblyLine(**kw)
297 348
298 349
299 class Packager(object): 350 class Packager(object):
300 351
301 def __init__(self, assembly_lines, check_interval): 352 def __init__(self, assembly_lines, check_interval):
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)