1 # vi: encoding=utf-8 ts=8 sts=4 sw=4 et
3 import os, config, string, urllib, re, rpm
4 from common import fileexists, noarchcachedir
5 from baseftptree import BasePkg, BaseFtpTree
13 print "%d error(s) encountered... aborting" % errnum
32 os.rename(src, dst+'/'+src.split('/')[-1])
33 #print "mv: %s %s" % (src, dst+'/'+src.split('/')[-1])
36 def __init__(self, nvr, tree):
37 BasePkg.__init__(self, nvr, tree)
38 self.name=string.join(nvr.split('-')[:-2], '-')
39 self.version=nvr.split('-')[-2]
40 self.release=nvr.split('-')[-1]
41 self.marked4removal=False
42 self.marked4moving=False
43 self.marked4movingpool=[]
47 def __cmp__(self, pkg):
48 if self.name > pkg.name:
50 elif self.name < pkg.name:
53 return rpm.labelCompare(('0', self.version, self.release),
54 ('0', pkg.version, pkg.release))
56 def mark4moving(self):
57 if not self.marked4moving:
58 # Only one pkg in this pool can be marked for moving
59 for pkg in self.marked4movingpool:
61 self.tree.marked4moving.append(self)
62 self.marked4moving=True
64 def unmark4moving(self):
65 if self.marked4moving:
66 self.tree.marked4moving.remove(self)
67 self.marked4moving=False
69 def mark4removal(self):
70 if not self.marked4removal:
71 self.tree.marked4removal.append(self)
72 self.marked4removal=True
75 self.errors.append(msg)
77 perror('%s %s' % (self.nvr, msg))
79 def warning(self, msg):
80 self.warnings.append(msg)
82 pwarning('%s %s' % (self.nvr, msg))
84 def load(self, content=None):
85 BasePkg.load(self, content)
86 if self.info.has_key('move'):
90 f=open(self.tree.basedir+'/SRPMS/.metadata/'+self.nvr+'.src.rpm.info', 'w')
91 for bid in self.build.keys():
92 f.write("info:build:%s:requester:%s\ninfo:build:%s:requester_email:%s\n" % (bid, self.build[bid].requester, bid, self.build[bid].requester_email))
93 for key in self.info.keys():
94 f.write("info:%s:%s\n" % (key, string.join(self.info[key], ':')))
95 for arch in self.files.keys():
96 for rpm in self.files[arch]:
97 f.write("file:%s:%s\n" % (arch, rpm))
100 for arch in self.files.keys():
101 for rpm in self.files[arch]:
102 rm(self.tree.basedir+'/'+arch+'/RPMS/'+rpm)
104 if fileexists(noarchcachedir+rpm+'.filelist'):
105 rm(noarchcachedir+rpm+'.filelist')
106 if fileexists(noarchcachedir+rpm+'.reqlist'):
107 rm(noarchcachedir+rpm+'.reqlist')
108 rm(self.tree.basedir+'/SRPMS/.metadata/'+self.nvr+'.src.rpm.info')
110 def move(self, dsttree):
111 if dsttree.has_key(self.nvr):
113 for arch in self.files.keys():
114 if arch in dsttree[self.nvr].files.keys():
115 pinfo("Arch %s for %s is already present in dest tree; removing from srctree" % (arch, self.nvr))
116 for rpm in self.files[arch]:
117 rm(self.tree.basedir+'/'+arch+'/RPMS/'+rpm)
120 dsttree[self.nvr].files[arch]=self.files[arch]
121 for rpm in self.files[arch]:
122 mv(self.tree.basedir+'/'+arch+'/RPMS/'+rpm, dsttree.basedir+'/'+arch+'/RPMS/')
124 for bid in self.build.keys():
125 dsttree[self.nvr].build[bid]=self.build[bid]
126 dsttree[self.nvr].writeinfo()
127 rm(self.tree.basedir+'/SRPMS/.metadata/'+self.nvr+'.src.rpm.info')
129 for arch in self.files.keys():
130 for rpm in self.files[arch]:
131 mv(self.tree.basedir+'/'+arch+'/RPMS/'+rpm, dsttree.basedir+'/'+arch+'/RPMS/')
132 mv(self.tree.basedir+'/SRPMS/.metadata/'+self.nvr+'.src.rpm.info', dsttree.basedir+'/SRPMS/.metadata/')
135 class FtpTree(BaseFtpTree):
136 def __init__(self, tree, loadall=False):
137 BaseFtpTree.__init__(self, tree)
139 self.marked4removal=[]
140 self.marked4moving=[]
142 self.__loadpkgnames()
144 for pkgname in self.pkgnames:
145 self.loadedpkgs[pkgname]=Pkg(pkgname, self)
147 self.do_checkbuild=True
149 def __getitem__(self, key):
150 if self.loadedpkgs.has_key(key):
151 return self.loadedpkgs[key]
152 elif key in self.pkgnames:
154 self.loadedpkgs[key]=pkg
159 def has_key(self, key):
160 if key in self.pkgnames:
169 return self.loadedpkgs.values()
171 def checktree(self, dsttree):
172 self.__checkbuild(self.loadedpkgs.values())
173 self.__checkarchs(dsttree, self.loadedpkgs.values())
175 def testmove(self, dsttree):
176 self.__checkbuild(self.marked4moving)
177 self.__checkarchs(dsttree, self.marked4moving)
179 def movepkgs(self, dsttree):
180 if self.do_checkbuild:
181 self.__checkbuild(self.marked4moving)
183 self.__checkarchs(dsttree, self.marked4moving)
185 self.__rmolderfromsrc()
186 self.__rmotherfromdst(dsttree)
188 for pkg in self.marked4moving:
191 def removepkgs(self):
192 if self.do_checkbuild:
193 self.__checkbuild(self.marked4removal)
195 for pkg in self.marked4removal:
198 def mark4removal(self, wannabepkgs):
199 self.__mark4something(wannabepkgs, Pkg.mark4removal)
201 def mark4moving(self, wannabepkgs):
202 self.__mark4something(wannabepkgs, Pkg.mark4moving)
205 # Internal functions below
207 def __loadpkgnames(self):
208 def checkfiletype(name):
209 if name[-13:]=='.src.rpm.info':
213 list=filter(checkfiletype, os.listdir(self.basedir+'/SRPMS/.metadata'))
214 self.pkgnames=map((lambda x: x[:-13]), list)
216 def __mark4something(self, wannabepkgs, markfunction):
217 def chopoffextension(pkg):
218 found=pkg.find('.src.rpm')
223 for wannabepkg in wannabepkgs:
224 pkgname=chopoffextension(wannabepkg)
225 if pkgname in self.pkgnames:
226 if not pkgname in self.loadedpkgs.keys():
227 self.loadedpkgs[pkgname]=Pkg(pkgname, self)
228 markfunction(self.loadedpkgs[pkgname])
230 perror('%s not found in source tree' % pkgname)
233 def __checkbuild(self, marked):
234 f=urllib.urlopen(config.builderqueue)
237 reid=re.compile(r'^.*id=(.*) pri.*$')
238 regb=re.compile(r'^group:.*$|builders:.*$', re.M)
239 for i in re.findall(regb, f.read()):
241 id=reid.sub(r'\1', i)
244 requests[id]=requests[id]+i
247 for bid in pkg.build.keys():
248 if requests.has_key(bid) and not requests[bid].find('?') == -1:
249 pkg.error("(buildid %s) building not finished" % bid)
251 def __checkarchs(self, dsttree, marked):
253 if len(pkg.files.keys()) <= 1:
254 pkg.error('has only src.rpm built')
256 otherpkgnames=self.__find_other_pkgs(pkg, dsttree)
257 if otherpkgnames: # check if we're not removing some archs
260 for somepkg in otherpkgnames:
261 curarchs.extend(Pkg(somepkg, dsttree).files.keys())
262 for arch in curarchs:
263 if arch not in pkg.files.keys():
264 missingarchs.append(arch)
266 pkg.error('moving would remove archs: %s' % missingarchs)
267 else: # warn if a package isn't built for all archs
268 if (config.separate_noarch and 'noarch' in pkg.files.keys() and
269 len(pkg.files.keys())==2):
271 elif len(pkg.files.keys()) != len(config.ftp_archs)+1:
273 for arch in config.ftp_archs:
274 if arch not in pkg.files.keys():
275 missingarchs.append(arch)
276 pkg.warning('not built for archs: %s' % missingarchs)
278 def __rmolderfromsrc(self):
279 for pkg in self.marked4moving:
280 olderpkgnames=self.__find_older_pkgs(pkg)
281 for i in olderpkgnames:
282 Pkg(i, self).remove()
284 def __rmotherfromdst(self, dsttree):
285 for pkg in self.marked4moving:
286 pkgnames=self.__find_other_pkgs(pkg, dsttree)
288 Pkg(i, dsttree).remove()
290 # Used more than once filter functions
292 def __find_other_pkgs(self, pkg, tree):
293 escapedpkgname=pkg.name.replace('.', '\.').replace('+', '\+')
294 ziewre=re.compile(escapedpkgname+'-[^-]*-[^-]*$')
295 def filter_other_pkgs(x):
296 if ziewre.match(x) and not x == pkg.nvr:
300 return filter(filter_other_pkgs, tree.pkgnames)
302 def __find_older_pkgs(self, pkg):
303 def filter_older_pkgs(x):
305 rc = rpm.labelCompare(('0', pkg.version, pkg.release),
307 if rc == 1: # pkg > x
311 return filter(filter_older_pkgs, self.__find_other_pkgs(pkg, self))