Print this page
9726 solaris.py needs to use new service for /etc/security/*attr files in build 118
| Split |
Close |
| Expand all |
| Collapse all |
--- old/src/util/distro-import/solaris.py
+++ new/src/util/distro-import/solaris.py
1 1 #!/usr/bin/python2.4
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 # Use is subject to license terms.
24 24
25 25
26 26 import fnmatch
27 27 import getopt
28 28 import gettext
29 29 import os
30 30 import pkg.depotcontroller as depotcontroller
31 31 import pkg.publish.transaction as trans
32 32 import re
33 33 import shlex
34 34 import sys
35 35 import urllib
36 36 import urlparse
37 37
38 38 from datetime import datetime
39 39 from itertools import groupby
40 40 from pkg import actions, elf
41 41 from pkg.bundle.SolarisPackageDirBundle import SolarisPackageDirBundle
42 42 from pkg.sysvpkg import SolarisPackage
43 43 from tempfile import mkstemp
44 44
45 45 gettext.install("import", "/usr/lib/locale")
46 46
47 47 class package(object):
48 48 def __init__(self, name):
49 49 self.name = name
50 50 self.files = []
51 51 self.depend = []
52 52 self.file_depend = []
53 53 self.idepend = [] #svr4 pkg deps, if any
54 54 self.undepend = []
55 55 self.extra = []
56 56 self.dropped_licenses = []
57 57 self.nonhollow_dirs = {}
58 58 self.srcpkgs = []
59 59 self.classification = []
60 60 self.desc = ""
61 61 self.summary = ""
62 62 self.version = ""
63 63 self.imppkg = None
64 64 pkgdict[name] = self
65 65
66 66 def import_pkg(self, imppkg, line):
67 67 try:
68 68 p = SolarisPackage(pkg_path(imppkg))
69 69 except:
70 70 raise RuntimeError("No such package: '%s'" % imppkg)
71 71
72 72 self.imppkg = p
73 73
74 74 svr4pkgpaths[p.pkginfo["PKG.PLAT"]] = pkg_path(imppkg)
75 75
76 76 # filename NOT always same as pkgname
77 77 imppkg = p.pkginfo["PKG.PLAT"]
78 78 svr4pkgsseen[imppkg] = p
79 79
80 80 if "SUNW_PKG_HOLLOW" in p.pkginfo and \
81 81 p.pkginfo["SUNW_PKG_HOLLOW"].lower() == "true":
82 82 hollow_pkgs[imppkg] = True
83 83
84 84 excludes = dict((f, True) for f in line.split())
85 85
86 86 # XXX This isn't thread-safe. We want a dict method that adds
87 87 # the key/value pair, but throws an exception if the key is
88 88 # already present.
89 89 for o in p.manifest:
90 90 if o.pathname in excludes:
91 91 print "excluding %s from %s" % \
92 92 (o.pathname, imppkg)
93 93 continue
94 94
95 95 if o.pathname in elided_files:
96 96 print "ignoring %s in %s" % (o.pathname, imppkg)
97 97 continue
98 98
99 99 if o.type == "e":
100 100 if o.pathname not in editable_files:
101 101 editable_files[o.pathname] = \
102 102 [(imppkg, self)]
103 103 else:
104 104 editable_files[o.pathname].append(
105 105 (imppkg, self))
106 106
107 107 # XXX This decidedly ignores "e"-type files.
108 108
109 109 if o.type in "fv" and o.pathname in usedlist:
110 110 s = reuse_err % (
111 111 o.pathname,
112 112 self.name,
113 113 imppkg,
114 114 svr4pkgpaths[imppkg],
115 115 usedlist[o.pathname][1].name,
116 116 usedlist[o.pathname][0],
117 117 svr4pkgpaths[usedlist[o.pathname][0]])
118 118 print s
119 119 raise RuntimeError(s)
120 120 elif o.type == "i" and o.pathname == "copyright":
121 121 # Fake up a unique path for each license.
122 122 o.pathname = "//license/%s" % imppkg
123 123 usedlist[o.pathname] = (imppkg, self)
124 124 self.files.append(o)
125 125 elif o.type != "i":
126 126 if o.type in "dx" and imppkg not in hollow_pkgs:
127 127 self.nonhollow_dirs[o.pathname] = True
128 128
129 129 usedlist[o.pathname] = (imppkg, self)
130 130 self.check_perms(o)
131 131 self.files.append(o)
132 132
133 133 if not self.version:
134 134 self.version = "%s-%s" % (def_vers,
135 135 get_branch(self.name))
136 136 if not self.desc:
137 137 try:
138 138 self.desc = p.pkginfo["DESC"]
139 139 except KeyError:
140 140 self.desc = None
141 141 if not self.summary:
142 142 self.summary = zap_strings(p.pkginfo["NAME"],
143 143 summary_detritus)
144 144
145 145 # This is how we'd import dependencies, but we'll use
146 146 # file-specific dependencies only, since these tend to be
147 147 # broken.
148 148 # self.depend.extend(
149 149 # d.req_pkg_fmri
150 150 # for d in p.deps
151 151 # )
152 152
153 153 self.add_svr4_src(imppkg)
154 154
155 155 def add_svr4_src(self, imppkg):
156 156 if imppkg in destpkgs:
157 157 destpkgs[imppkg].append(self.name)
158 158 else:
159 159 destpkgs[imppkg] = [self.name]
160 160 self.srcpkgs.append(imppkg)
161 161
162 162 def import_file(self, fname, line):
163 163 imppkgname = self.imppkg.pkginfo["PKG.PLAT"]
164 164
165 165 if "SUNW_PKG_HOLLOW" in self.imppkg.pkginfo and \
166 166 self.imppkg.pkginfo["SUNW_PKG_HOLLOW"].lower() == "true":
167 167 hollow_pkgs[imppkgname] = True
168 168
169 169 if fname in usedlist:
170 170 t = [
171 171 f for f in usedlist[fname][1].files
172 172 if f.pathname == fname
173 173 ][0].type
174 174 if t in "fv":
175 175 assert imppkgname == usedlist[fname][0]
176 176 raise RuntimeError(reuse_err % (
177 177 fname,
178 178 self.name,
179 179 self.imppkg,
180 180 svr4pkgpaths[self.imppkg],
181 181 usedlist[fname][1].name,
182 182 usedlist[fname][0],
183 183 svr4pkgpaths[usedlist[fname][0]]))
184 184
185 185 usedlist[fname] = (imppkgname, self)
186 186 o = [
187 187 o
188 188 for o in self.imppkg.manifest
189 189 if o.pathname == fname
190 190 ]
191 191 # There should be only one file with a given pathname in a
192 192 # single package.
193 193 if len(o) != 1:
194 194 print "ERROR: %s %s" % (imppkgname, fname)
195 195 assert len(o) == 1
196 196
197 197 if line:
198 198 a = actions.fromstr(
199 199 "%s path=%s %s" % \
200 200 (
201 201 self.convert_type(o[0].type),
202 202 o[0].pathname,
203 203 line
204 204 )
205 205 )
206 206 for attr in a.attrs:
207 207 if attr == "owner":
208 208 o[0].owner = a.attrs[attr]
209 209 elif attr == "group":
210 210 o[0].group = a.attrs[attr]
211 211 elif attr == "mode":
212 212 o[0].mode = a.attrs[attr]
213 213 self.check_perms(o[0])
214 214 self.files.extend(o)
215 215
216 216 def convert_type(self, svrtype):
217 217 """ given sv4r type, return IPS type"""
218 218 return {
219 219 "f": "file", "e": "file", "v": "file",
220 220 "d": "dir", "x": "dir",
221 221 "s": "link",
222 222 "l": "hardlink"
223 223 }[svrtype]
224 224
225 225 def type_convert(self, ipstype):
226 226 """ given IPS type, return svr4 type(s)"""
227 227 return {
228 228 "file": "fev", "dir": "dx", "link": "s",
229 229 "hardlink": "l"
230 230 }[ipstype]
231 231
232 232 def file_to_action(self, f):
233 233
234 234 if f.type in "dx":
235 235 action = actions.directory.DirectoryAction(
236 236 None, mode = f.mode, owner = f.owner,
237 237 group = f.group, path = f.pathname)
238 238 elif f.type in "efv":
239 239 action = actions.file.FileAction(
240 240 None, mode = f.mode, owner = f.owner,
241 241 group = f.group, path = f.pathname)
242 242 elif f.type == "s":
243 243 action = actions.link.LinkAction(None,
244 244 target = f.target, path = f.pathname)
245 245 elif f.type == "l":
246 246 action = actions.hardlink.HardLinkAction(None,
247 247 target = f.target, path = f.pathname)
248 248 else:
249 249 print "unknown type %s - path %s" % \
250 250 ( f.type, f.pathname)
251 251
252 252 return action
253 253
254 254 def check_perms(self, manifest):
255 255 if manifest.type not in "fevdxbc":
256 256 return
257 257
258 258 if manifest.owner == "?":
259 259 manifest.owner = "root"
260 260 print "File %s in pkg %s owned by '?': mapping to %s" \
261 261 % (manifest.pathname, self.name, manifest.owner)
262 262
263 263 if manifest.group == "?":
264 264 manifest.group = "bin"
265 265 print "File %s in pkg %s of group '?': mapping to %s" \
266 266 % (manifest.pathname, self.name, manifest.group)
267 267 if manifest.mode == "?":
268 268 if manifest.type in "dx":
269 269 manifest.mode = "0755"
270 270 else:
271 271 manifest.mode = "0444"
272 272 print "File %s in pkg %s mode '?': mapping to %s" % \
273 273 (manifest.pathname, self.name, manifest.mode)
274 274
275 275
276 276 def chattr(self, fname, line):
277 277 o = [f for f in self.files if f.pathname == fname]
278 278 if not o:
279 279 raise RuntimeError("No file '%s' in package '%s'" % \
280 280 (fname, curpkg.name))
281 281
282 282 line = line.rstrip()
283 283
284 284 # is this a deletion?
285 285 if line.startswith("drop"):
286 286 for f in o:
287 287 # deletion of existing attribute
288 288 if not hasattr(f, "deleted_attrs"):
289 289 f.deleted_attrs = []
290 290 print "Adding drop on %s of %s" % \
291 291 (fname, line.split()[1:])
292 292 f.deleted_attrs.extend(line.split()[1:])
293 293 return
294 294
295 295 # handle insertion/modification case
296 296 for f in o:
297 297 # create attribute dictionary from line
298 298 new_type = self.convert_type(f.type)
299 299 new_attrs = actions._fromstr("%s %s" %
300 300 (new_type, line.rstrip()))[2]
301 301 # get path if we're not changing it
302 302 if "path" not in new_attrs:
303 303 new_attrs["path"] = fname
304 304 a = actions.types[new_type](**new_attrs)
305 305 if show_debug:
306 306 print "Updating attributes on " + \
307 307 "'%s' in '%s' with '%s'" % \
308 308 (f.pathname, curpkg.name, a)
309 309 orig_action = self.file_to_action(f)
310 310
311 311 if not hasattr(f, "changed_attrs"):
312 312 f.changed_attrs = {}
313 313
314 314 # each chattr produces a dictionary of actions
315 315 # including a path=xxxx and whatever modifications
316 316 # are made. Note that the path value may be a list in
317 317 # the case of modifications to the path... since
318 318 # each chattr produces another path= entry and results
319 319 # from applying the changes to the original file spec,
320 320 # we need to ignore path if it hasn't changed... for
321 321 # generality, we ignore all unchanged attributes in
322 322 # the code below, adding into changed_attrs only those
323 323 # that are different from the original... this also
324 324 # insulates us from the possibility of actions.fromstr
325 325 # adding additional attributes in the constructor...
326 326
327 327 for key in a.attrs.keys():
328 328 if key not in orig_action.attrs or \
329 329 orig_action.attrs[key] != a.attrs[key]:
330 330 if key in f.changed_attrs:
331 331 print "Warning: overwriting " \
332 332 "changed attr %s on %s " \
333 333 "from %s to %s" % \
334 334 (key, f.pathname,
335 335 f.changed_attrs[key],
336 336 a.attrs[key])
337 337 f.changed_attrs[key] = a.attrs[key]
338 338
339 339
340 340 # apply a chattr to wildcarded files/dirs
341 341 # also allows package specification, wildcarding, regexp edit
342 342
343 343 def chattr_glob(self, glob, line):
344 344 args = line.split()
345 345 if args[0] == "from":
346 346 args.pop(0)
347 347 pkgglob = args.pop(0)
348 348 line = " ".join(args)
349 349 else:
350 350 pkgglob = "*"
351 351
352 352 if args[0] == "type": # we care about type
353 353 args.pop(0)
354 354 types = self.type_convert(args.pop(0))
355 355 line = " ".join(args)
356 356 else:
357 357 types = "dfevslx"
358 358
359 359 if args[0] == "edit": # we're doing regexp edit of attr
360 360 edit = True
361 361 args.pop(0)
362 362 target = args.pop(0)
363 363 regexp = re.compile(args.pop(0))
364 364 replace = args.pop(0)
365 365 line = " ".join(args)
366 366 else:
367 367 edit = False
368 368
369 369 o = [
370 370 f
371 371 for f in self.files
372 372 if fnmatch.fnmatchcase(f.pathname, glob) and
373 373 fnmatch.fnmatchcase(
374 374 usedlist[f.pathname][0], pkgglob) and
375 375 f.type in types
376 376 ]
377 377
378 378 chattr_line = line
379 379
380 380 for f in o:
381 381 fname = f.pathname
382 382 orig_action = self.file_to_action(f)
383 383 if edit:
384 384 if target in orig_action.attrs:
385 385 old_value = orig_action.attrs[target]
386 386 new_value = regexp.sub(replace, \
387 387 old_value)
388 388 if old_value == new_value:
389 389 continue
390 390 chattr_line = "%s=%s %s" % \
391 391 (target, new_value, line)
392 392 else:
393 393 continue
394 394 chattr_line = chattr_line.rstrip()
395 395 if show_debug:
396 396 print "Updating attributes on " + \
397 397 "'%s' in '%s' with '%s'" % \
398 398 (fname, curpkg.name, chattr_line)
399 399
400 400 # create attribute dictionary from line
401 401 new_type = self.convert_type(f.type)
402 402 new_attrs = actions._fromstr("%s %s" %
403 403 (new_type, chattr_line.rstrip()))[2]
404 404 # get path if we're not changing it
405 405 if "path" not in new_attrs:
406 406 new_attrs["path"] = fname
407 407 a = actions.types[new_type](**new_attrs)
408 408 # each chattr produces a dictionary of actions
409 409 # including a path=xxxx and whatever modifications
410 410 # are made. Note that the path value may be a list in
411 411 # the case of modifications to the path... since
412 412 # each chattr produces another path= entry and results
413 413 # from applying the changes to the original file spec,
414 414 # we need to ignore path if it hasn't changed... for
415 415 # generality, we ignore all unchanged attributes in
416 416 # the code below, adding into changed_attrs only those
417 417 # that are different from the original... this also
418 418 # insulates us from the possibility of actions.fromstr
419 419 # adding additional attributes in the constructor...
420 420
421 421 if not hasattr(f, "changed_attrs"):
422 422 f.changed_attrs = {}
423 423 for key in a.attrs.keys():
424 424 if key not in orig_action.attrs or \
425 425 orig_action.attrs[key] != a.attrs[key]:
426 426 if key in f.changed_attrs:
427 427 print "Warning: overwriting " \
428 428 "changed attr %s on %s " \
429 429 "from %s to %s" % \
430 430 (key, f.pathname,
431 431 f.changed_attrs[key],
432 432 a.attrs[key])
433 433 f.changed_attrs[key] = a.attrs[key]
434 434
435 435 pkgpaths = {}
436 436
437 437 def pkg_path(pkgname):
438 438 name = os.path.basename(pkgname)
439 439 if pkgname in pkgpaths:
440 440 return pkgpaths[name]
441 441 if "/" in pkgname:
442 442 pkgpaths[name] = os.path.realpath(pkgname)
443 443 return pkgname
|
↓ open down ↓ |
443 lines elided |
↑ open up ↑ |
444 444 else:
445 445 for each_path in wos_path:
446 446 if os.path.exists(each_path + "/" + pkgname):
447 447 pkgpaths[name] = each_path + "/" + pkgname
448 448 return pkgpaths[name]
449 449
450 450 raise RuntimeError("package %s not found" % pkgname)
451 451
452 452
453 453 def start_package(pkgname):
454 + set_macro("PKGNAME", urllib.quote(pkgname, ""))
454 455 return package(pkgname)
455 456
456 457 def end_package(pkg):
457 458 pkg_branch = get_branch(pkg.name)
458 459 if not pkg.version:
459 460 pkg.version = "%s-%s" % (def_vers, pkg_branch)
460 461 elif "-" not in pkg.version:
461 462 pkg.version += "-%s" % pkg_branch
462 463
464 + clear_macro("PKGNAME")
463 465 print "Package '%s'" % pkg.name
464 466 print " Version:", pkg.version
465 467 print " Description:", pkg.desc
466 468 print " Summary:", pkg.summary
467 469 print " Classification: ", ",".join(pkg.classification)
468 470
469 471 def publish_pkg(pkg):
470 472
471 473 new_pkg_name = "%s@%s" % (pkg.name, pkg.version)
472 474 t = trans.Transaction(def_repo, create_repo=create_repo,
473 475 pkg_name=new_pkg_name, noexecute=nopublish)
474 476
475 477 print " open %s" % new_pkg_name
476 478 transaction_id = t.open()
477 479
478 480 # Publish non-file objects first: they're easy.
479 481 for f in pkg.files:
480 482 if f.type in "dx":
481 483 action = actions.directory.DirectoryAction(
482 484 None, mode = f.mode, owner = f.owner,
483 485 group = f.group, path = f.pathname)
484 486 if hasattr(f, "changed_attrs"):
485 487 action.attrs.update(f.changed_attrs)
486 488 # chattr may have produced two path values
487 489 action.attrs["path"] = \
488 490 action.attrlist("path")[-1]
489 491 print " %s add dir %s %s %s %s" % (
490 492 pkg.name,
491 493 action.attrs["mode"],
492 494 action.attrs["owner"],
493 495 action.attrs["group"],
494 496 action.attrs["path"]
495 497 )
496 498 elif f.type == "s":
497 499 action = actions.link.LinkAction(None,
498 500 target = f.target, path = f.pathname)
499 501 if hasattr(f, "changed_attrs"):
500 502 action.attrs.update(f.changed_attrs)
501 503 # chattr may have produced two path values
502 504 action.attrs["path"] = \
503 505 action.attrlist("path")[-1]
504 506 print " %s add link %s %s" % (
505 507 pkg.name,
506 508 action.attrs["path"],
507 509 action.attrs["target"]
508 510 )
509 511 elif f.type == "l":
510 512 action = actions.hardlink.HardLinkAction(None,
511 513 target = f.target, path = f.pathname)
512 514 if hasattr(f, "changed_attrs"):
513 515 action.attrs.update(f.changed_attrs)
514 516 # chattr may have produced two path values
515 517 action.attrs["path"] = \
516 518 action.attrlist("path")[-1]
517 519 pkg.depend += process_link_dependencies(
518 520 action.attrs["path"], action.attrs["target"])
519 521 print " %s add hardlink %s %s" % (
520 522 pkg.name,
521 523 action.attrs["path"],
522 524 action.attrs["target"]
523 525 )
524 526 else:
525 527 continue
526 528
527 529 #
528 530 # If the originating package was hollow, tag this file
529 531 # as being global zone only.
530 532 #
531 533
532 534 if f.type not in "dx" and f.pathname in usedlist and \
533 535 usedlist[f.pathname][0] in hollow_pkgs:
534 536 action.attrs["opensolaris.zone"] = "global"
535 537 action.attrs["variant.opensolaris.zone"] = "global"
536 538
537 539 if f.type in "dx" and f.pathname in usedlist and \
538 540 usedlist[f.pathname][0] in hollow_pkgs and \
539 541 f.pathname not in pkg.nonhollow_dirs:
540 542 action.attrs["opensolaris.zone"] = "global"
541 543 action.attrs["variant.opensolaris.zone"] = "global"
542 544
543 545 # handle attribute deletion
544 546 if hasattr(f, "deleted_attrs"):
545 547 for d in f.deleted_attrs:
546 548 if d in action.attrs:
547 549 del action.attrs[d]
548 550
549 551 t.add(action)
550 552
551 553 # Group the files in a (new) package based on what (old) package they
552 554 # came from, so that we can iterate through all files in a single (old)
553 555 # package (and, therefore, in a single bzip2 archive) before moving on
554 556 # to the next. Because groupby() needs its input pre-sorted by group
555 557 # and we want to maintain the order that the files come out of the cpio
556 558 # archives, we coalesce the groups with the groups dictionary.
557 559 def fn(key):
558 560 return usedlist[key.pathname][0]
559 561 groups = {}
560 562 for k, g in groupby((f for f in pkg.files if f.type in "fevi"), fn):
561 563 if k in groups:
562 564 groups[k].extend(g)
563 565 else:
564 566 groups[k] = list(g)
565 567
566 568 def otherattrs(action):
567 569 s = " ".join(
568 570 "%s=%s" % (a, action.attrs[a])
569 571 for a in action.attrs
570 572 if a not in ("owner", "group", "mode", "path")
571 573 )
572 574 if s:
573 575 return " " + s
574 576 else:
575 577 return ""
576 578
577 579 # Maps class names to preserve attribute values.
578 580 preserve_dict = {
579 581 "renameold": "renameold",
580 582 "renamenew": "renamenew",
581 583 "preserve": "true",
582 584 "svmpreserve": "true"
583 585 }
584 586
585 587 undeps = set()
586 588 for g in groups.values():
587 589 pkgname = usedlist[g[0].pathname][0]
588 590 print "pulling files from archive in package", pkgname
589 591 bundle = SolarisPackageDirBundle(svr4pkgpaths[pkgname])
590 592 pathdict = dict((f.pathname, f) for f in g)
591 593 for f in bundle:
592 594 if f.name == "license":
593 595 if f.attrs["license"] in pkg.dropped_licenses:
594 596 continue
595 597 # add transaction id so that every version
596 598 # of a pkg will have a unique license to prevent
597 599 # license from disappearing on upgrade
598 600 f.attrs["transaction_id"] = transaction_id
599 601 # The "path" attribute is confusing and
600 602 # unnecessary for licenses.
601 603 del f.attrs["path"]
602 604 print " %s add license %s" % \
603 605 (pkg.name, f.attrs["license"])
604 606 t.add(f)
605 607 elif f.attrs["path"] in pathdict:
606 608 if pkgname in hollow_pkgs:
607 609 f.attrs["opensolaris.zone"] = "global"
608 610 f.attrs["variant.opensolaris.zone"] = \
609 611 "global"
610 612 path = f.attrs["path"]
611 613 if pathdict[path].type in "ev":
612 614 f.attrs["preserve"] = "true"
613 615 f.attrs["owner"] = pathdict[path].owner
614 616 f.attrs["group"] = pathdict[path].group
615 617 f.attrs["mode"] = pathdict[path].mode
616 618
617 619 # is this a file for which we need a timestamp?
618 620 basename = os.path.basename(path)
619 621 for file_pattern in timestamp_files:
620 622 if fnmatch.fnmatch(basename,
621 623 file_pattern):
622 624 break
623 625 else:
624 626 del f.attrs["timestamp"]
625 627 if pathdict[path].klass in preserve_dict.keys():
626 628 f.attrs["preserve"] = \
627 629 preserve_dict[pathdict[path].klass]
628 630 if hasattr(pathdict[path], "changed_attrs"):
629 631 f.attrs.update(
630 632 pathdict[path].changed_attrs)
631 633 # chattr may have produced two values
632 634 f.attrs["path"] = f.attrlist("path")[-1]
633 635
634 636 print " %s add file %s %s %s %s%s" % \
635 637 (pkg.name, f.attrs["mode"],
636 638 f.attrs["owner"], f.attrs["group"],
637 639 f.attrs["path"], otherattrs(f))
638 640
639 641 # handle attribute deletion
640 642 if hasattr(pathdict[path], "deleted_attrs"):
641 643 for d in pathdict[path].deleted_attrs:
642 644 if d in f.attrs:
643 645 print "removed %s from %s in pkg %s" % (d, path, new_pkg_name)
644 646 del f.attrs[d]
645 647
646 648 # Read the file in chunks to avoid a memory
647 649 # footprint blowout.
648 650 fo = f.data()
649 651 bufsz = 256 * 1024
650 652 sz = int(f.attrs["pkg.size"])
651 653 fd, tmp = mkstemp(prefix="pkg.")
652 654 while sz > 0:
653 655 d = fo.read(min(bufsz, sz))
654 656 os.write(fd, d)
655 657 sz -= len(d)
656 658 d = None
657 659 os.close(fd)
658 660
659 661 # Fool the action into pulling from a
660 662 # temporary file so that both add() and
661 663 # process_dependencies() can read() the
662 664 # data.
663 665 f.data = lambda: open(tmp, "rb")
664 666 t.add(f)
665 667
666 668 # Look for dependencies
667 669 deps, u = process_dependencies(tmp, path)
668 670 pkg.depend += deps
669 671 if u:
670 672 print \
671 673 "%s has missing dependencies: %s" \
672 674 % (path, u)
673 675 undeps |= set(u)
674 676 os.unlink(tmp)
675 677
676 678 # process any dependencies on files
677 679 for f in pkg.file_depend:
678 680 f = f.lstrip("/") # remove any leading /
679 681 if f in usedlist:
680 682 pkg.depend += [ "%s@%s" %
681 683 (usedlist[f][1].name,
682 684 usedlist[f][1].version)
683 685 ]
684 686 else:
685 687 print "Warning: pkg %s: depend_path %s not satisfied" \
686 688 % (pkg.name, f)
687 689 undeps.add(f)
688 690 # Publish dependencies
689 691
690 692 missing_cnt = 0
691 693
692 694 for p in set(pkg.idepend): # over set of svr4 deps, append ipkgs
693 695 if p in destpkgs:
694 696 pkg.depend.extend(destpkgs[p])
695 697 else:
696 698 print "pkg %s: SVR4 package %s not seen" % \
697 699 (pkg.name, p)
698 700 missing_cnt += 1
699 701 if missing_cnt > 0:
700 702 raise RuntimeError("missing packages!")
701 703
702 704 for p in set(pkg.depend) - set(pkg.undepend):
703 705 # Don't make a package depend on itself.
704 706 if p.split("@")[0] == pkg.name:
705 707 continue
706 708 # enhance unqualified dependencies to include current
707 709 # pkg version
708 710 if "@" not in p and p in pkgdict:
709 711 p = "%s@%s" % (p, pkgdict[p].version)
710 712
711 713 print " %s add depend require %s" % (pkg.name, p)
712 714 action = actions.depend.DependencyAction(None,
713 715 type = "require", fmri = p)
714 716 t.add(action)
715 717
716 718 for a in pkg.extra:
717 719 print " %s add %s" % (pkg.name, a)
718 720 action = actions.fromstr(a)
719 721 if hasattr(action, "hash"):
720 722 fname, fd = sourcehook(action.hash)
721 723 fd.close()
722 724 action.data = lambda: file(fname, "rb")
723 725 action.attrs["pkg.size"] = str(os.stat(fname).st_size)
724 726 if action.name == "license":
725 727 action.attrs["transaction_id"] = transaction_id
726 728 elif "path" in action.attrs:
727 729 path = action.attrs["path"]
728 730 deps, u = process_dependencies(fname, path)
729 731 pkg.depend += deps
730 732 if u:
731 733 print "%s has missing dependencies: " \
732 734 "%s" % (path, u)
733 735 undeps |= set(u)
734 736 #
735 737 # fmris may not be completely specified; enhance them to current
736 738 # version if this is the case
737 739 #
738 740 for attr in action.attrs:
739 741 if attr == "fmri" and \
740 742 "@" not in action.attrs[attr] and \
741 743 action.attrs[attr][5:] in pkgdict:
742 744 action.attrs[attr] += "@%s" % \
743 745 pkgdict[action.attrs[attr][5:]].version
744 746 t.add(action)
745 747
746 748 if pkg.desc:
747 749 print " %s add set pkg.description=%s" % (pkg.name, pkg.desc)
748 750 attrs = dict(name="pkg.description", value=pkg.desc)
749 751 action = actions.attribute.AttributeAction(None, **attrs)
750 752 t.add(action)
751 753
752 754 if pkg.summary:
753 755 print " %s add set pkg.summary=%s" % (pkg.name, pkg.summary)
754 756 attrs = dict(name="pkg.summary", value=pkg.summary)
755 757 action = actions.attribute.AttributeAction(None, **attrs)
756 758 t.add(action)
757 759
758 760 # Retain the description entry in the package manifest for
759 761 # now for backward compatibility.
760 762 print " %s add set description=%s" % (pkg.name, pkg.summary)
761 763 action = actions.attribute.AttributeAction(None,
762 764 description = pkg.summary)
763 765 t.add(action)
764 766
765 767 if pkg.classification:
766 768 print " %s add set info.classification=%s" % \
767 769 (pkg.name, pkg.classification)
768 770 attrs = dict(name="info.classification",
769 771 value=pkg.classification)
770 772 action = actions.attribute.AttributeAction(None, **attrs)
771 773 t.add(action)
772 774
773 775 if pkg.name != "SUNWipkg":
774 776 for p in pkg.srcpkgs:
775 777 try:
776 778 sp = svr4pkgsseen[p]
777 779 except KeyError:
778 780 continue
779 781
780 782 wanted_attrs = (
781 783 "PKG", "NAME", "ARCH", "VERSION", "CATEGORY",
782 784 "VENDOR", "DESC", "HOTLINE"
783 785 )
784 786 attrs = dict(
785 787 (k.lower(), v)
786 788 for k, v in sp.pkginfo.iteritems()
787 789 if k in wanted_attrs
788 790 )
789 791 attrs["pkg"] = sp.pkginfo["PKG.PLAT"]
790 792
791 793 action = actions.legacy.LegacyAction(None, **attrs)
792 794
793 795 print " %s add %s" % (pkg.name, action)
794 796 t.add(action)
795 797
796 798 if undeps:
797 799 print "Missing dependencies:", list(undeps)
798 800
799 801 print " close"
800 802 pkg_fmri, pkg_state = t.close(refresh_index=not defer_refresh)
801 803 print "%s: %s\n" % (pkg_fmri, pkg_state)
802 804
803 805 def process_link_dependencies(path, target):
804 806 orig_target = target
805 807 if target[0] != "/":
806 808 target = os.path.normpath(
807 809 os.path.join(os.path.split(path)[0], target))
808 810
809 811 if target in usedlist:
810 812 if show_debug:
811 813 print "hardlink %s -> %s makes %s depend on %s" % \
812 814 (
813 815 path, orig_target,
814 816 usedlist[path][1].name,
815 817 usedlist[target][1].name
816 818 )
817 819 return ["%s@%s" % (usedlist[target][1].name,
818 820 usedlist[target][1].version)]
819 821 else:
820 822 return []
821 823
822 824 def process_dependencies(fname, path):
823 825 if not elf.is_elf_object(fname):
824 826 return process_non_elf_dependencies(fname, path)
825 827
826 828 ei = elf.get_info(fname)
827 829 try:
828 830 ed = elf.get_dynamic(fname)
829 831 except elf.ElfError:
830 832 deps = []
831 833 rp = []
832 834 else:
833 835 deps = [
834 836 d[0]
835 837 for d in ed.get("deps", [])
836 838 ]
837 839 rp = ed.get("runpath", "").split(":")
838 840 if len(rp) == 1 and rp[0] == "":
839 841 rp = []
840 842
841 843 rp = [
842 844 os.path.normpath(p.replace("$ORIGIN", "/" + os.path.dirname(path)))
843 845 for p in rp
844 846 ]
845 847
846 848 kernel64 = None
847 849
848 850 # For kernel modules, default path resolution is /platform/<platform>,
849 851 # /kernel, /usr/kernel. But how do we know what <platform> would be for
850 852 # a given module? Does it do fallbacks to, say, sun4u?
851 853 if path.startswith("kernel") or path.startswith("usr/kernel") or \
852 854 (path.startswith("platform") and path.split("/")[2] == "kernel"):
853 855 if rp:
854 856 print "RUNPATH set for kernel module (%s): %s" % \
855 857 (path, rp)
856 858 # Default kernel search path
857 859 rp.extend(("/kernel", "/usr/kernel"))
858 860 # What subdirectory should we look in for 64-bit kernel modules?
859 861 if ei["bits"] == 64:
860 862 if ei["arch"] == "i386":
861 863 kernel64 = "amd64"
862 864 elif ei["arch"] == "sparc":
863 865 kernel64 = "sparcv9"
864 866 else:
865 867 print ei["arch"]
866 868 else:
867 869 if "/lib" not in rp:
868 870 rp.append("/lib")
869 871 if "/usr/lib" not in rp:
870 872 rp.append("/usr/lib")
871 873
872 874 # XXX Do we need to handle anything other than $ORIGIN? x86 images have
873 875 # a couple of $PLATFORM and $ISALIST instances.
874 876 for p in rp:
875 877 if "$" in p:
876 878 tok = p[p.find("$"):]
877 879 if "/" in tok:
878 880 tok = tok[:tok.find("/")]
879 881 print "%s has dynamic token %s in rpath" % (path, tok)
880 882
881 883 dep_pkgs = []
882 884 undeps = []
883 885 depend_list = []
884 886 for d in deps:
885 887 for p in rp:
886 888 # The instances of "[1:]" below are because usedlist
887 889 # stores paths without leading slash
888 890 if kernel64:
889 891 # Find 64-bit modules the way krtld does.
890 892 # XXX We don't resolve dependencies found in
891 893 # /platform, since we don't know where under
892 894 # /platform to look.
893 895 head, tail = os.path.split(d)
894 896 deppath = os.path.join(p,
895 897 head,
896 898 kernel64,
897 899 tail)[1:]
898 900 else:
899 901 # This is a hack for when a runpath uses the 64
900 902 # symlink to the actual 64-bit directory.
901 903 # Better would be to see if the runpath was a
902 904 # link, and if so, use its resolution, but
903 905 # extracting that information from used list is
904 906 # a pain, especially because you potentially
905 907 # have to resolve symlinks at all levels of the
906 908 # path.
907 909 if p.endswith("/64"):
908 910 if ei["arch"] == "i386":
909 911 p = p[:-2] + "amd64"
910 912 elif ei["arch"] == "sparc":
911 913 p = p[:-2] + "sparcv9"
912 914 deppath = os.path.join(p, d)[1:]
913 915 if deppath in usedlist:
914 916 dep_pkgs += [ "%s@%s" %
915 917 (usedlist[deppath][1].name,
916 918 usedlist[deppath][1].version) ]
917 919 depend_list.append(
918 920 (
919 921 deppath,
920 922 usedlist[deppath][1].name
921 923 )
922 924 )
923 925 break
924 926 else:
925 927 undeps += [ d ]
926 928
927 929 if show_debug:
928 930 print "%s makes %s depend on %s" % \
929 931 (path, usedlist[path][1].name, depend_list)
930 932
931 933 return dep_pkgs, undeps
932 934
933 935 def process_non_elf_dependencies(localpath, path):
934 936 # localpath is path to actual file
935 937 # path is path in installed image
936 938 # take 1
937 939 dep_pkgs = []
938 940 undeps = []
939 941
940 942 f = file(localpath)
941 943 l = f.readline()
942 944 f.close()
943 945
944 946 # add #!/ dependency
945 947 if l.startswith("#!/"):
946 948 # usedlist omits leading /
947 949 p = (l[2:].split()[0]) # first part of string is path (removes options)
948 950 # we don't handle dependencies through links, so fix up the common one
949 951 if p.startswith("/bin"):
950 952 p = "/usr" + p
951 953 if p[1:] in usedlist:
952 954 dep_pkgs += [ "%s@%s" % (
953 955 usedlist[p[1:]][1].name,
954 956 usedlist[p[1:]][1].version)
955 957 ]
956 958 print "Added dependency on %s because of %s" % (usedlist[p[1:]][1].name, p)
957 959 else:
958 960 undeps = [ p ]
959 961
960 962 return dep_pkgs, undeps
961 963
962 964 def zap_strings(instr, strings):
963 965 """takes an input string and a list of strings to be removed, ignoring
964 966 case"""
965 967 for s in strings:
966 968 ls = s.lower()
967 969 while True:
968 970 li = instr.lower()
969 971 i = li.find(ls)
970 972 if i < 0:
971 973 break
972 974 instr = instr[0:i] + instr[i + len(ls):]
973 975 return instr
974 976
975 977 def get_branch(name):
976 978 return branch_dict.get(name, def_branch)
977 979
978 980 def_vers = "0.5.11"
979 981 def_branch = ""
980 982 def_wos_path = ["/net/netinstall.eng/export/nv/x/latest/Solaris_11/Product"]
981 983 create_repo = False
982 984 nopublish = False
983 985 show_debug = False
984 986 print_pkg_names = False
985 987 def_repo = "http://localhost:10000"
986 988 wos_path = []
987 989 include_path = []
988 990 branch_dict = {}
989 991 timestamp_files = []
990 992
991 993 #
992 994 # files (by path) we always delete for bulk imports
993 995 # note that we ignore these if specifically included.
994 996 #
995 997 elided_files = {}
996 998 #
997 999 # if user uses -j, just_these_pkgs becomes list of pkgs to process
998 1000 # allowing other arguments to be read in as files...
999 1001 #
1000 1002 just_these_pkgs = []
1001 1003 #
1002 1004 # strings to rip out of summaries (case insensitve)
|
↓ open down ↓ |
530 lines elided |
↑ open up ↑ |
1003 1005 #
1004 1006 summary_detritus = [", (usr)", ", (root)", " (usr)", " (root)",
1005 1007 " (/usr)", " - / filesystem", ",root(/)"]
1006 1008 #
1007 1009 # list of global includes to add to every package
1008 1010 #
1009 1011 global_includes = []
1010 1012 # list of macro substitutions
1011 1013 macro_definitions = {}
1012 1014
1015 +def set_macro(key, value):
1016 + macro_definitions.update([("$(%s)" % key, value)])
1017 +
1018 +def clear_macro(key):
1019 + del macro_definitions["$(%s)" % key]
1020 +
1013 1021 try:
1014 1022 _opts, _args = getopt.getopt(sys.argv[1:], "B:D:I:G:NT:b:dj:m:ns:v:w:p:")
1015 1023 except getopt.GetoptError, _e:
1016 1024 print "unknown option", _e.opt
1017 1025 sys.exit(1)
1018 1026
1019 1027 g_proto_area = os.environ.get("ROOT", "")
1020 1028
1021 1029 for opt, arg in _opts:
1022 1030 if opt == "-b":
1023 1031 def_branch = arg.rstrip("abcdefghijklmnopqrstuvwxyz")
1024 1032 elif opt == "-d":
1025 1033 show_debug = True
1026 1034 elif opt == "-j": # means we're using the new argument form...
1027 1035 just_these_pkgs.append(arg)
1028 1036 elif opt == "-m":
1029 1037 _a = arg.split("=", 1)
1030 - macro_definitions.update([("$(%s)" % _a[0], _a[1])])
1038 + set_macro(_a[0], _a[1])
1031 1039 elif opt == "-n":
1032 1040 nopublish = True
1033 1041 elif opt == "-p":
1034 1042 if not os.path.exists(arg):
1035 1043 raise RuntimeError("Invalid prototype area specified.")
1036 1044 # Clean up relative ../../, etc. out of path to proto
1037 1045 g_proto_area = os.path.realpath(arg)
1038 1046 elif opt == "-s":
1039 1047 def_repo = arg
1040 1048 if def_repo.startswith("file://"):
1041 1049 # When publishing to file:// repositories, automatically
1042 1050 # create the target repository if needed.
1043 1051 create_repo = True
1044 1052 elif opt == "-v":
1045 1053 def_vers = arg
1046 1054 elif opt == "-w":
1047 1055 wos_path.append(arg)
1048 1056 elif opt == "-D":
1049 1057 elided_files[arg] = True
1050 1058 elif opt == "-I":
1051 1059 include_path.extend(arg.split(":"))
1052 1060 elif opt == "-B":
1053 1061 branch_file = file(arg)
1054 1062 for _line in branch_file:
1055 1063 if not _line.startswith("#"):
1056 1064 bfargs = _line.split()
1057 1065 if len(bfargs) == 2:
1058 1066 branch_dict[bfargs[0]] = bfargs[1]
1059 1067 branch_file.close()
1060 1068 elif opt == "-G": #another file of global includes
1061 1069 global_includes.append(arg)
1062 1070 elif opt == "-N":
1063 1071 print_pkg_names = True
1064 1072 elif opt == "-T":
1065 1073 timestamp_files.append(arg)
1066 1074
1067 1075 if not def_branch:
1068 1076 print "need a branch id (build number)"
1069 1077 sys.exit(1)
1070 1078 elif "." not in def_branch:
1071 1079 print "branch id needs to be of the form 'x.y'"
1072 1080 sys.exit(1)
1073 1081
1074 1082 if not _args:
1075 1083 print "need argument!"
1076 1084 sys.exit(1)
1077 1085
1078 1086 if not wos_path:
1079 1087 wos_path = def_wos_path
1080 1088
1081 1089 if just_these_pkgs:
1082 1090 filelist = _args
1083 1091 else:
1084 1092 filelist = _args[0:1]
1085 1093 just_these_pkgs = _args[1:]
1086 1094
1087 1095
1088 1096 in_multiline_import = False
1089 1097
1090 1098 # This maps what files we've seen to a tuple of what packages they came from and
1091 1099 # what packages they went into, so we can prevent more than one package from
1092 1100 # grabbing the same file.
1093 1101 usedlist = {}
1094 1102
1095 1103 #
1096 1104 # pkgdict contains ipkgs by name
1097 1105 #
1098 1106 pkgdict = {}
1099 1107
1100 1108 #
1101 1109 # destpkgs contains the list of ipkgs generated from each svr4 pkg
1102 1110 # this is needed to generate metaclusters
1103 1111 #
1104 1112 destpkgs = {}
1105 1113
1106 1114 #
1107 1115 #svr4 pkgs seen - pkgs indexed by name
1108 1116 #
1109 1117 svr4pkgsseen = {}
1110 1118
1111 1119 #
1112 1120 #paths where we found the packages we need
1113 1121 #
1114 1122 svr4pkgpaths = {}
1115 1123
1116 1124 #
1117 1125 # editable files and where they're found
1118 1126 #
1119 1127 editable_files = {}
1120 1128
1121 1129 #
1122 1130 # hollow svr4 packages processed
1123 1131 #
1124 1132 hollow_pkgs = {}
1125 1133
1126 1134
1127 1135 reuse_err = \
1128 1136 "Conflict in path %s: IPS %s SVR4 %s from %s with IPS %s SVR4 %s from %s"
1129 1137
1130 1138
1131 1139 # First pass: don't actually publish anything, because we're not collecting
1132 1140 # dependencies here.
1133 1141 def read_full_line(lexer, continuation='\\'):
1134 1142 """Read a complete line, allowing for the possibility of it being
1135 1143 continued over multiple lines. Returns a single joined line, with
1136 1144 continuation characters and leading and trailing spaces removed.
1137 1145 """
1138 1146
1139 1147 lines = []
1140 1148 while True:
1141 1149 line = lexer.instream.readline().strip()
1142 1150 lexer.lineno = lexer.lineno + 1
1143 1151 if line[-1] in continuation:
1144 1152 lines.append(line[:-1])
1145 1153 else:
1146 1154 lines.append(line)
1147 1155 break
1148 1156
1149 1157 return apply_macros(' '.join(lines))
1150 1158
1151 1159 def apply_macros(s):
1152 1160 """Apply macro subs defined on command line... keep applying
1153 1161 macros until no translations are found. If macro translates
1154 1162 to a comment, replace entire token text."""
1155 1163 while s and "$(" in s:
1156 1164 for key in macro_definitions.keys():
1157 1165 if key in s:
1158 1166 value = macro_definitions[key]
1159 1167 if value == "#": # comment character
1160 1168 s = "#" # affects whole token
1161 1169 break
1162 1170 s = s.replace(key, value)
1163 1171 break # look for more substitutions
1164 1172 else:
1165 1173 break # no more substitutable tokens
1166 1174 return s
1167 1175
1168 1176 def sourcehook(filename):
1169 1177 """ implement include hierarchy """
1170 1178 for i in include_path:
1171 1179 f = os.path.join(i, filename)
1172 1180 if os.path.exists(f):
1173 1181 return (f, open(f))
1174 1182
1175 1183 return filename, open(filename)
1176 1184
1177 1185 class tokenlexer(shlex.shlex):
1178 1186 def read_token(self):
1179 1187 """ simple replacement of $(ARCH) with a non-special
1180 1188 value defined on the command line is trivial. Since
1181 1189 shlex's read_token routine also strips comments and
1182 1190 white space, this read_token cannot return either
1183 1191 one so any macros that translate to either spaces or
1184 1192 # (comment) need to be removed from the token stream."""
1185 1193
1186 1194 while True:
1187 1195 s = apply_macros(shlex.shlex.read_token(self))
1188 1196 if s == "#": # discard line if comment; try again
1189 1197 self.instream.readline()
1190 1198 self.lineno = self.lineno + 1
1191 1199 # bail on EOF or not space; loop on space
1192 1200 elif s == None or (s != "" and not s.isspace()):
1193 1201 break
1194 1202 return s
1195 1203
1196 1204 curpkg = None
1197 1205 def SolarisParse(mf):
1198 1206 global curpkg
1199 1207 global in_multiline_import
1200 1208
1201 1209 lexer = tokenlexer(file(mf), mf, True)
1202 1210 lexer.whitespace_split = True
1203 1211 lexer.source = "include"
1204 1212 lexer.sourcehook = sourcehook
1205 1213
1206 1214 while True:
1207 1215 token = lexer.get_token()
1208 1216
1209 1217 if not token:
1210 1218 break
1211 1219
1212 1220 if token == "package":
1213 1221 curpkg = start_package(lexer.get_token())
1214 1222
1215 1223 if print_pkg_names:
1216 1224 print "-j %s" % curpkg.name
1217 1225
1218 1226 elif token == "end":
1219 1227 endarg = lexer.get_token()
1220 1228 if endarg == "package":
1221 1229 if print_pkg_names:
1222 1230 curpkg = None
1223 1231 continue
1224 1232
1225 1233 for filename in global_includes:
1226 1234 for i in include_path:
1227 1235 f = os.path.join(i, filename)
1228 1236 if os.path.exists(f):
1229 1237 SolarisParse(f)
1230 1238 break
1231 1239 else:
1232 1240 raise RuntimeError("File not "
1233 1241 "found: %s" % filename)
1234 1242 try:
1235 1243 end_package(curpkg)
1236 1244 except Exception, e:
1237 1245 print "ERROR(end_pkg):", e
1238 1246
1239 1247 curpkg = None
1240 1248 if endarg == "import":
1241 1249 in_multiline_import = False
1242 1250 curpkg.imppkg = None
1243 1251
1244 1252 elif token == "version":
1245 1253 curpkg.version = lexer.get_token()
1246 1254
1247 1255 elif token == "import":
1248 1256 package_name = lexer.get_token()
1249 1257 next = lexer.get_token()
1250 1258 if next != "exclude":
1251 1259 line = ""
1252 1260 lexer.push_token(next)
1253 1261 else:
1254 1262 line = read_full_line(lexer)
1255 1263
1256 1264 if not print_pkg_names:
1257 1265 curpkg.import_pkg(package_name, line)
1258 1266
1259 1267 elif token == "from":
1260 1268 pkgspec = lexer.get_token()
1261 1269 if not print_pkg_names:
1262 1270 p = SolarisPackage(pkg_path(pkgspec))
1263 1271 curpkg.imppkg = p
1264 1272 spkgname = p.pkginfo["PKG.PLAT"]
1265 1273 svr4pkgpaths[spkgname] = pkg_path(pkgspec)
1266 1274 svr4pkgsseen[spkgname] = p
1267 1275 curpkg.add_svr4_src(spkgname)
1268 1276
1269 1277 junk = lexer.get_token()
1270 1278 assert junk == "import"
1271 1279 in_multiline_import = True
1272 1280
1273 1281 elif token == "classification":
1274 1282 cat_subcat = lexer.get_token()
1275 1283 curpkg.classification.append(
1276 1284 "org.opensolaris.category.2008:%s" % cat_subcat)
1277 1285
1278 1286 elif token == "description":
1279 1287 curpkg.desc = lexer.get_token()
1280 1288
1281 1289 elif token == "summary":
1282 1290 curpkg.summary = lexer.get_token()
1283 1291
1284 1292 elif token == "depend":
1285 1293 curpkg.depend.append(lexer.get_token())
1286 1294
1287 1295 elif token == "depend_path":
1288 1296 curpkg.file_depend.append(lexer.get_token())
1289 1297
1290 1298 elif token == "cluster":
1291 1299 curpkg.add_svr4_src(lexer.get_token())
1292 1300
1293 1301 elif token == "idepend":
1294 1302 curpkg.idepend.append(lexer.get_token())
1295 1303
1296 1304 elif token == "undepend":
1297 1305 curpkg.undepend.append(lexer.get_token())
1298 1306
1299 1307 elif token == "add":
1300 1308 curpkg.extra.append(read_full_line(lexer))
1301 1309
1302 1310 elif token == "drop":
1303 1311 f = lexer.get_token()
1304 1312 if print_pkg_names:
1305 1313 continue
1306 1314 l = [o for o in curpkg.files if o.pathname == f]
1307 1315 if not l:
1308 1316 print "Cannot drop '%s' from '%s': not " \
1309 1317 "found" % (f, curpkg.name)
1310 1318 else:
1311 1319 del curpkg.files[curpkg.files.index(l[0])]
1312 1320 # XXX The problem here is that if we do this on
1313 1321 # a shared file (directory, etc), then it's
1314 1322 # missing from usedlist entirely, since we don't
1315 1323 # keep around *all* packages delivering a shared
1316 1324 # file, just the last seen. This probably
1317 1325 # doesn't matter much.
1318 1326 del usedlist[f]
1319 1327
1320 1328 elif token == "drop_license":
1321 1329 curpkg.dropped_licenses.append(lexer.get_token())
1322 1330
1323 1331 elif token == "chattr":
1324 1332 fname = lexer.get_token()
1325 1333 line = read_full_line(lexer)
1326 1334 if print_pkg_names:
1327 1335 continue
1328 1336 try:
1329 1337 curpkg.chattr(fname, line)
1330 1338 except Exception, e:
1331 1339 print "Can't change attributes on " + \
1332 1340 "'%s': not in the package" % fname, e
1333 1341 raise
1334 1342
1335 1343 elif token == "chattr_glob":
1336 1344 glob = lexer.get_token()
1337 1345 line = read_full_line(lexer)
1338 1346 if print_pkg_names:
1339 1347 continue
1340 1348 try:
1341 1349 curpkg.chattr_glob(glob, line)
1342 1350 except Exception, e:
1343 1351 print "Can't change attributes on " + \
1344 1352 "'%s': no matches in the package" % \
1345 1353 glob, e
1346 1354 raise
1347 1355
1348 1356 elif in_multiline_import:
1349 1357 next = lexer.get_token()
1350 1358 if next == "with":
1351 1359 # I can't imagine this is supported, but there's
1352 1360 # no other way to read the rest of the line
1353 1361 # without a whole lot more pain.
1354 1362 line = read_full_line(lexer)
1355 1363 else:
1356 1364 lexer.push_token(next)
1357 1365 line = ""
1358 1366
1359 1367 try:
1360 1368 curpkg.import_file(token, line)
1361 1369 except Exception, e:
1362 1370 print "ERROR(import_file):", e
1363 1371 raise
1364 1372 else:
1365 1373 raise RuntimeError("Error: unknown token '%s' "
1366 1374 "(%s:%s)" % (token, lexer.infile, lexer.lineno))
1367 1375
1368 1376 if print_pkg_names:
1369 1377 for _mf in filelist:
1370 1378 SolarisParse(_mf)
1371 1379 sys.exit(0)
1372 1380
1373 1381
1374 1382 print "First pass:", datetime.now()
1375 1383
1376 1384 for _mf in filelist:
1377 1385 SolarisParse(_mf)
1378 1386
1379 1387 seenpkgs = set(i[0] for i in usedlist.values())
1380 1388
1381 1389 print "Files you seem to have forgotten:\n " + "\n ".join(
1382 1390 "%s %s" % (f.type, f.pathname)
1383 1391 for pkg in seenpkgs
1384 1392 for f in svr4pkgsseen[pkg].manifest
1385 1393 if f.type != "i" and f.pathname not in usedlist)
1386 1394
1387 1395 print "\n\nDuplicate Editables files list:\n"
1388 1396
1389 1397 if editable_files:
1390 1398 length = 2 + max(len(p) for p in editable_files)
1391 1399 for paths in editable_files:
1392 1400 if len(editable_files[paths]) > 1:
1393 1401 print ("%s:" % paths).ljust(length - 1) + \
1394 1402 ("\n".ljust(length)).join("%s (from %s)" % \
1395 1403 (l[1].name, l[0]) for l in editable_files[paths])
1396 1404
1397 1405
1398 1406 # Second pass: iterate over the existing package objects, gathering dependencies
1399 1407 # and publish!
1400 1408
1401 1409 print "Second pass:", datetime.now()
1402 1410
1403 1411 print "New packages:\n"
1404 1412 # XXX Sort these. Preferably topologically, if possible, alphabetically
1405 1413 # otherwise (for a rough progress gauge).
1406 1414 if just_these_pkgs:
1407 1415 newpkgs = set(pkgdict[name]
1408 1416 for name in pkgdict.keys()
1409 1417 if name in just_these_pkgs
1410 1418 )
1411 1419 else:
1412 1420 newpkgs = set(pkgdict.values())
1413 1421
1414 1422 # Indicates whether search indices refresh will be deferred until the end.
1415 1423 defer_refresh = False
1416 1424 # Indicates whether local publishing is active.
1417 1425 local_publish = False
1418 1426 if def_repo.startswith("file:"):
1419 1427 # If publishing to disk, the search indices should be refreshed at
1420 1428 # the end of the publishing process and the feed cache will have to be
1421 1429 # generated by starting the depot server using the provided path and
1422 1430 # then accessing it.
1423 1431 defer_refresh = True
1424 1432 local_publish = True
1425 1433
1426 1434 processed = 0
1427 1435 total = len(newpkgs)
1428 1436 for _p in sorted(newpkgs):
1429 1437 print "Package '%s'" % _p.name
1430 1438 print " Version:", _p.version
1431 1439 print " Description:", _p.desc
1432 1440 print " Summary:", _p.summary
1433 1441 print " Classification:", ",".join(_p.classification)
1434 1442 try:
1435 1443 publish_pkg(_p)
1436 1444 except trans.TransactionError, _e:
1437 1445 print "%s: FAILED: %s\n" % (_p.name, _e)
1438 1446 processed += 1
1439 1447 print "%d/%d packages processed; %.2f%% complete" % (processed, total,
1440 1448 processed * 100.0 / total)
1441 1449
1442 1450 if not nopublish and defer_refresh:
1443 1451 # This has to be done at the end for some publishing modes.
1444 1452 print "Updating search indices..."
1445 1453 _t = trans.Transaction(def_repo)
1446 1454 _t.refresh_index()
1447 1455
1448 1456 # Ensure that the feed is updated and cached to reflect changes.
1449 1457 if not nopublish:
1450 1458 print "Caching RSS/Atom feed..."
1451 1459 dc = None
1452 1460 durl = def_repo
1453 1461 if local_publish:
1454 1462 # The depot server isn't already running, so will have to be
1455 1463 # temporarily started to allow proper feed cache generation.
1456 1464 dc = depotcontroller.DepotController()
1457 1465 dc.set_depotd_path(g_proto_area + "/usr/lib/pkg.depotd")
1458 1466 dc.set_depotd_content_root(g_proto_area + "/usr/share/lib/pkg")
1459 1467
1460 1468 _scheme, _netloc, _path, _params, _query, _fragment = \
1461 1469 urlparse.urlparse(def_repo, "file", allow_fragments=0)
1462 1470
1463 1471 dc.set_repodir(_path)
1464 1472
1465 1473 # XXX There must be a better way...
1466 1474 dc.set_port(29083)
1467 1475
1468 1476 # Start the depot
1469 1477 dc.start()
1470 1478
1471 1479 durl = "http://localhost:29083"
1472 1480
1473 1481 _f = urllib.urlopen("%s/feed" % durl)
1474 1482 _f.close()
1475 1483
1476 1484 if dc:
1477 1485 dc.stop()
1478 1486 dc = None
1479 1487
1480 1488 print "Done:", datetime.now()
|
↓ open down ↓ |
440 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX