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 (...) --- |