1 |
Terje Kvernes <terjekv@××××××××.no> writes: |
2 |
|
3 |
[ ... ] |
4 |
|
5 |
> now, the thing is that now, suddenly, with PORTAGE_LEVEL="stable" |
6 |
> set in /etc/make.conf, then you can only ask to merge packages of |
7 |
> that level into the system. this is somewhat broken when it comes |
8 |
> to dependencies yet (this is because I've only patched the calls to |
9 |
> get package "foo", not ">foo" or anything like that. I'll try to |
10 |
> get this working during the weekend or so. but, until then, if you |
11 |
> emerge a package with the "stable" level, then you're (so far) not |
12 |
> guaranteed that the dependencies will be stable. |
13 |
|
14 |
some simple testing has been done and well, now things seem to work. |
15 |
the patch has become a bit longer, and it should now handle |
16 |
dependencies. |
17 |
|
18 |
a quick example: we want to emerge package cat/foo that depends on |
19 |
>=cat/bar-1.0, and we have set a level[1] of "mystate" in |
20 |
/etc/make.conf[2]. portage will now look for |
21 |
'/usr/portage/cat/bar-mystate'. if this isn't found, emerge aborts |
22 |
at once. if it is found, the symlink is resolved, and if the |
23 |
package that the symlinks points to is new enough, emerge continues. |
24 |
|
25 |
now, if you're daring to test this, you need to label a lot of |
26 |
packages something so you can set that level. a very quick and |
27 |
dirty hack (yes, it is _that_ quick and ugly) called |
28 |
"make_portage_level" can be found here: |
29 |
|
30 |
<url: http://terje.kvernes.no/gentoo/utils/ > |
31 |
|
32 |
it wants a _file_ containing one package per line on the following |
33 |
form: |
34 |
|
35 |
dev-java/java-config-0.2.2 |
36 |
|
37 |
and nothing else. an easy way to build such a list from your |
38 |
current setup, and then to call that "mystable" would be something |
39 |
like this: |
40 |
|
41 |
/usr/lib/portage/bin/pkglist > /tmp/packages |
42 |
make_portage_level /tmp/packages mystable |
43 |
|
44 |
a word about levels... there are some limits to names. until |
45 |
further testing is done, names should match [a-z]+ and nothing |
46 |
else. |
47 |
|
48 |
again, this stuff isn't tested very well, it probably will break |
49 |
something. you _should_ take a backup of your portage-tree if |
50 |
you're even thinking of fiddeling with this stuff. |
51 |
|
52 |
but, if anyone is willing to test this, I would be _very_ happy to |
53 |
get bugreports. the patch follows, but patches can also be found |
54 |
on my website: <url: http://terje.kvernes.no/gentoo/patches/ > |
55 |
|
56 |
--- /usr/lib/python2.2/site-packages/portage-clean.py Sat Apr 20 01:19:57 2002 |
57 |
+++ /usr/lib/python2.2/site-packages/portage.py Mon Apr 22 01:33:50 2002 |
58 |
@@ -2003,35 +2003,37 @@ |
59 |
""" |
60 |
mypkgdep=self.dep_pkgcat(mypkgdep) |
61 |
|
62 |
- if (mypkgdep[0]=="="): |
63 |
- if mypkgdep[-1]=="*": |
64 |
- if not isspecific(mypkgdep[1:-1]): |
65 |
- return "" |
66 |
- mycatpkg=catpkgsplit(mypkgdep[1:-1]) |
67 |
- try: |
68 |
- mynewver=mycatpkg[2] |
69 |
- mynewsplit=string.split(mycatpkg[2],'.') |
70 |
- mynewsplit[-1]=`int(mynewsplit[-1])+1` |
71 |
- except: |
72 |
- return "" |
73 |
- mynodes=[] |
74 |
- cmp1=mycatpkg[1:] |
75 |
- cmp2=[mycatpkg[1],string.join(mynewsplit,"."),"r0"] |
76 |
- for x in self.getnode(mycatpkg[0]+"/"+mycatpkg[1]): |
77 |
- if (pkgcmp(x[1][1:],cmp1)>=0) and (pkgcmp(x[1][1:],cmp2)<0): |
78 |
- mynodes.append(x) |
79 |
- if len(mynodes)==0: |
80 |
- return "" |
81 |
- bestmatch=mynodes[0] |
82 |
- for x in mynodes[1:]: |
83 |
- if pkgcmp(x[1][1:],bestmatch[1][1:])>0: |
84 |
- bestmatch=x |
85 |
- return bestmatch[0] |
86 |
- else: |
87 |
- if self.exists_specific(mypkgdep[1:]): |
88 |
- return mypkgdep[1:] |
89 |
+ if settings['PORTAGE_LEVEL']: |
90 |
+ level = settings['PORTAGE_LEVEL'] |
91 |
+ req_package = self.get_base_name(mypkgdep) |
92 |
+ # in case we get a package without any version information |
93 |
+ if not isspecific(mypkgdep): |
94 |
+ level_ebuild = self.get_level_package(mypkgdep, level) |
95 |
+ [ cat, name ] = mypkgdep.split("/") |
96 |
+ if not level_ebuild: |
97 |
+ print "\n>>> " + mypkgdep + " has no ebuild with label '" + level + "'." |
98 |
+ sys.exit(1) |
99 |
else: |
100 |
- return "" |
101 |
+ return cat + "/" + level_ebuild |
102 |
+ |
103 |
+ [req_dir, req_name, req_ver, req_rel] = catpkgsplit(req_package) |
104 |
+ package = req_dir + "/" + req_name |
105 |
+ # then get the ebuild that this name relates to. |
106 |
+ level_ebuild = self.get_level_package(package, level) |
107 |
+ if not level_ebuild: |
108 |
+ print "\n>>> " + package + " has no ebuild with label '" + level + "'." |
109 |
+ sys.exit(1) |
110 |
+ |
111 |
+ # check if the package version is high enough. |
112 |
+ if self.package_version_ok(req_dir + "/" + level_ebuild, req_package) >= 0: |
113 |
+ return req_dir + "/" + level_ebuild |
114 |
+ else: |
115 |
+ print "\n>>> '" + level + "' " + package + " is currently " + level_ebuild + "." |
116 |
+ print " Required version is " + mypkgdep + ". Aborting merge." |
117 |
+ sys.exit(1) |
118 |
+ |
119 |
+ if (mypkgdep[0]=="="): |
120 |
+ self.get_spesific_version(mypkgdep) |
121 |
elif (mypkgdep[0]==">") or (mypkgdep[0]=="<"): |
122 |
if mypkgdep[1]=="=": |
123 |
cmpstr=mypkgdep[0:2] |
124 |
@@ -2081,17 +2083,93 @@ |
125 |
else: |
126 |
return mymatch |
127 |
elif not isspecific(mypkgdep): |
128 |
- if not self.hasnode(mypkgdep): |
129 |
+ return self.get_latest_version(mypkgdep) |
130 |
+ |
131 |
+ def get_spesific_version(self, mypkgdep): |
132 |
+ if mypkgdep[-1]=="*": |
133 |
+ if not isspecific(mypkgdep[1:-1]): |
134 |
return "" |
135 |
- mynodes=self.getnode(mypkgdep)[:] |
136 |
- if len(mynodes)==0: |
137 |
+ mycatpkg=catpkgsplit(mypkgdep[1:-1]) |
138 |
+ try: |
139 |
+ mynewver=mycatpkg[2] |
140 |
+ mynewsplit=string.split(mycatpkg[2],'.') |
141 |
+ mynewsplit[-1]=`int(mynewsplit[-1])+1` |
142 |
+ except: |
143 |
+ return "" |
144 |
+ mynodes=[] |
145 |
+ cmp1=mycatpkg[1:] |
146 |
+ cmp2=[mycatpkg[1],string.join(mynewsplit,"."),"r0"] |
147 |
+ for x in self.getnode(mycatpkg[0]+"/"+mycatpkg[1]): |
148 |
+ if (pkgcmp(x[1][1:],cmp1)>=0) and (pkgcmp(x[1][1:],cmp2)<0): |
149 |
+ mynodes.append(x) |
150 |
+ if len(mynodes)==0: |
151 |
+ return "" |
152 |
+ bestmatch=mynodes[0] |
153 |
+ for x in mynodes[1:]: |
154 |
+ if pkgcmp(x[1][1:],bestmatch[1][1:])>0: |
155 |
+ bestmatch=x |
156 |
+ return bestmatch[0] |
157 |
+ else: |
158 |
+ if self.exists_specific(mypkgdep[1:]): |
159 |
+ return mypkgdep[1:] |
160 |
+ else: |
161 |
+ return "" |
162 |
+ |
163 |
+ def get_latest_version(self, mypkgdep): |
164 |
+ """ |
165 |
+ returns the latest version of a package. |
166 |
+ |
167 |
+ """ |
168 |
+ if not self.hasnode(mypkgdep): |
169 |
+ return "" |
170 |
+ mynodes=self.getnode(mypkgdep)[:] |
171 |
+ if len(mynodes)==0: |
172 |
+ return "" |
173 |
+ bestmatch=mynodes[0] |
174 |
+ for x in mynodes[1:]: |
175 |
+ if pkgcmp(x[1][1:],bestmatch[1][1:])>0: |
176 |
+ bestmatch=x |
177 |
+ return bestmatch[0] |
178 |
+ |
179 |
+ |
180 |
+ def get_base_name(self, mypkgdep): |
181 |
+ """ |
182 |
+ returns the base name of package, removing *<>=~ at |
183 |
+ the start, if they exist. |
184 |
+ |
185 |
+ """ |
186 |
+ package = mypkgdep |
187 |
+# print "\nget_package_name: " + mypkgdep + " -> " + package |
188 |
+ while package[0] == "=" or package[0] == ">" or package[0] == "<" or package[0] == "~" or package[0] == "*": |
189 |
+ package = package[1:] |
190 |
+ return package |
191 |
+ |
192 |
+ def get_level_package(self, package, level): |
193 |
+ """ |
194 |
+ resolves the symlink package-level and returns package-version. exits if the file |
195 |
+ |
196 |
+ """ |
197 |
+# print "\nget_level_package: " + package + " " + level |
198 |
+ if package.find("/") > -1: |
199 |
+ [ dir, name ] = package.split("/") |
200 |
+ try: |
201 |
+ ebuild = os.readlink("/usr/portage/" + package + "/" + name + "-" + level.lower()) |
202 |
+ ebuild = ebuild.replace(".ebuild", "") |
203 |
+ return ebuild |
204 |
+ except OSError: |
205 |
return "" |
206 |
- bestmatch=mynodes[0] |
207 |
- for x in mynodes[1:]: |
208 |
- if pkgcmp(x[1][1:],bestmatch[1][1:])>0: |
209 |
- bestmatch=x |
210 |
- return bestmatch[0] |
211 |
|
212 |
+ def package_version_ok(self, candidate, requirement): |
213 |
+ """ |
214 |
+ package_version_ok() returns 0 if the candidate is an |
215 |
+ exact match, 1 if the candidate is more recent than |
216 |
+ the requirement, and -1 if the candidate is older than |
217 |
+ the requirement. |
218 |
+ """ |
219 |
+ |
220 |
+# print "package_version_ok: C:" + candidate + " R:" + requirement |
221 |
+ return pkgcmp(pkgsplit(candidate),pkgsplit(requirement)) |
222 |
+ |
223 |
def dep_nomatch(self,mypkgdep): |
224 |
"""dep_nomatch() has a very specific purpose. You pass it a dep, like =sys-apps/foo-1.0. |
225 |
Then, it scans the sys-apps/foo category and returns a list of sys-apps/foo packages that |
226 |
|
227 |
|
228 |
|
229 |
[1] or snapshot, mask, whatever you want to call it. you can have |
230 |
as many as you want. |
231 |
|
232 |
[2] PORTAGE_LEVEL="mystate" |
233 |
|
234 |
-- |
235 |
Terje - who's calling it a night. |