Gentoo Archives: gentoo-dev

From: Terje Kvernes <terjekv@××××××××.no>
To: gentoo-dev@g.o
Subject: Re: [gentoo-dev] stabilitylevels and such issues.
Date: Sun, 21 Apr 2002 18:47:04
Message-Id: wxxbsccbond.fsf@nommo.uio.no
In Reply to: Re: [gentoo-dev] stabilitylevels and such issues. by Terje Kvernes
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.