Gentoo Archives: gentoo-commits

From: "André Erdmann" <dywi@×××××××.de>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/pkgdir/
Date: Mon, 28 Jan 2013 23:54:20
Message-Id: 1359416224.e30e6406aacc718f49eaa58723465107afa39aa8.dywi@gentoo
1 commit: e30e6406aacc718f49eaa58723465107afa39aa8
2 Author: André Erdmann <dywi <AT> mailerd <DOT> de>
3 AuthorDate: Mon Jan 28 22:43:37 2013 +0000
4 Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
5 CommitDate: Mon Jan 28 23:37:04 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=e30e6406
7
8 roverlay/overlay/pkgdir: portagemanifest
9
10 A Manifest file creation that uses the portage python libs directly.
11
12 This has the following advantages over the "ebuild" implementation:
13 * create more than one Manifest at once (thread safe)
14 * faster file creation time (direct "create Manifest" function call
15 instead of calling an external executable a few thousand times)
16
17 The downsides are:
18 * highly EXPERIMENTAL (currently)
19 * less stable to changes in portage (written for portage version 2.1.11.31)
20
21 ---
22 .../overlay/pkgdir/packagedir_portagemanifest.py | 163 ++++++++++++++++++++
23 1 files changed, 163 insertions(+), 0 deletions(-)
24
25 diff --git a/roverlay/overlay/pkgdir/packagedir_portagemanifest.py b/roverlay/overlay/pkgdir/packagedir_portagemanifest.py
26 new file mode 100644
27 index 0000000..bf9efee
28 --- /dev/null
29 +++ b/roverlay/overlay/pkgdir/packagedir_portagemanifest.py
30 @@ -0,0 +1,163 @@
31 +__all__ = [ 'PackageDir', ]
32 +
33 +import os
34 +import shlex
35 +
36 +import portage.manifest
37 +
38 +import logging
39 +logging.getLogger ( __name__ ).warning ( "experimental code" )
40 +del logging
41 +
42 +import roverlay.config
43 +import roverlay.strutil
44 +import roverlay.packageinfo
45 +import roverlay.overlay.pkgdir.packagedir_base
46 +import roverlay.overlay.pkgdir.symlink.distroot
47 +
48 +class PackageDir ( roverlay.overlay.pkgdir.packagedir_base.PackageDirBase ):
49 +
50 + MANIFEST_THREADSAFE = True
51 +
52 + def _scan_add_package ( self, efile, pvr ):
53 + """Called for each ebuild that is found during scan().
54 + Creates a PackageInfo for the ebuild and adds it to self._packages.
55 +
56 + arguments:
57 + * efile -- full path to the ebuild file
58 + * pvr -- version ($PVR) of the ebuild
59 + """
60 +
61 + # read SRC_URI from the ebuild file which is the only way to get
62 + # the correct package name
63 + src_uri = None
64 + with open ( efile, 'r' ) as FH:
65 + reader = shlex.shlex ( FH )
66 + reader.whitespace_split = False
67 + reader.wordchars += ' ,./$()[]:+-@*~<>'
68 +
69 + # assumption: only one SRC_URI= statement per ebuild
70 + # (true for roverlay ebuilds)
71 + mode = 0
72 + token = reader.get_token()
73 + while token:
74 + if mode == 0 and token == 'SRC_URI':
75 + mode = 1
76 + elif mode == 1 and token == '=':
77 + mode = 2
78 + elif mode == 2:
79 + mode = 3
80 + src_uri = tuple (
81 + roverlay.strutil.split_whitespace (
82 + roverlay.strutil.unquote ( token )
83 + )
84 + )
85 +
86 + # break loop if SRC_URI parsed
87 + token = reader.get_token() if mode < 3 else None
88 + # --- while;
89 + del token, reader, mode
90 + # --- with;
91 +
92 + if src_uri:
93 + # another assumption: src_uri [0] is the name of the R package
94 + package_filename = src_uri [0].rpartition ( '/' ) [2]
95 +
96 + p = roverlay.packageinfo.PackageInfo (
97 + physical_only=True, pvr=pvr, ebuild_file=efile,
98 + package_filename=package_filename
99 + )
100 + else:
101 + p = roverlay.packageinfo.PackageInfo (
102 + physical_only=True, pvr=pvr, ebuild_file=efile
103 + )
104 +
105 + self._packages [ p ['ebuild_verstr'] ] = p
106 + # --- end of _scan_add_package (...) ---
107 +
108 + def write_manifest ( self, ignore_empty=False ):
109 + """Generates and writes the Manifest file for this package.
110 +
111 + expects: called after writing metadata/ebuilds
112 +
113 + returns: success (True/False)
114 +
115 + raises:
116 + * Exception if no ebuild exists
117 + """
118 +
119 + # the "package_filename" key is also required
120 + pkgs_for_manifest = frozenset (
121 + p for p in self._packages.values()
122 + if p.has ( 'ebuild_filename', 'package_file' )
123 + )
124 +
125 + # TODO: this needs proper testing
126 + # * the written Manifest file must not differ from the one generated by
127 + # ebuild(1) (the order of the entries is not important, though)
128 + # * safe for incremental usage?
129 + # * correct usage of the portage libs (also see other comments below)
130 + # * what happens if an ebuild has been removed?
131 + # * ...
132 + #
133 + if pkgs_for_manifest:
134 + symlink_distdir = roverlay.overlay.pkgdir.symlink.distroot.\
135 + SymlinkDistroot.get_configured().get ( self.name )
136 +
137 + # allow_missing=True -- don't write empty Manifest files
138 + manifest = portage.manifest.Manifest (
139 + self.physical_location,
140 + str ( symlink_distdir ),
141 + allow_missing=True,
142 + )
143 +
144 + # metadata.xml
145 + # os.path.basename ( self._metadata.filepath )
146 + manifest.addFile ( 'MISC', 'metadata.xml' )
147 +
148 + for p in pkgs_for_manifest:
149 + ebuild_filename = p ['ebuild_filename']
150 + package_filename = p ['package_filename']
151 +
152 + if not manifest.hasFile ( 'EBUILD', ebuild_filename ):
153 + manifest.addFile ( 'EBUILD', ebuild_filename )
154 +
155 + if not manifest.hasFile ( 'DIST', package_filename ):
156 + symlink_distdir.add ( p ['package_file'], package_filename )
157 + manifest.addFile (
158 + 'DIST',
159 + package_filename,
160 + # TODO:
161 + # ignoreMissing for DIST files, else addFile raises
162 + # FileNotFound -- is this the correct way to add DIST files?
163 + ignoreMissing=True
164 + )
165 +
166 + # ??? FIXME: (read) portage api docs
167 + #
168 + # manifest.create -- recreate from scratch (required?)
169 + # -> assumeDistHashesSometimes:
170 + # use existing checksums for non-existent DIST files (required?)
171 + #
172 + #manifest.create ( assumeDistHashesSometimes=True )
173 + #manifest.create ( assumeDistHashesSometimes=False )
174 +
175 + manifest.write()
176 + self._need_manifest = False
177 +
178 + return True
179 +
180 + elif ignore_empty:
181 +
182 + return True
183 +
184 + else:
185 + raise Exception (
186 + 'In {mydir}: No ebuild written so far! '
187 + 'I really don\'t know what do to!'.format (
188 + mydir=self.physical_location
189 + ) )
190 +
191 + # @unreachable
192 + return False
193 + # --- end of write_manifest (...) ---