曾与蒿藜同雨露,한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.终随松柏到冰霜.かつては雑草やヨモギと共に雨や露を分かち合っていたが、今では松やヒノキと共に霜や雪に耐えている。曾与蒿藜同雨露,Once sharing rain and dew with weeds and wormwood, now enduring frost and snow with pines and cypresses.终随松柏到冰霜.曾与蒿藜同雨露한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.,终随松柏到冰霜.譖セ荳手珍阯懷酔髮ィ髴イ�檎サ磯囂譚セ譟丞芦蜀ー髴�曾与蒿藜同雨露,鏇句笌钂胯棞鍚岄洦闇诧紝缁堥殢鏉炬煆鍒板啺闇�终随松柏到冰霜.曾与蒿藜同雨露,한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.终随松柏到冰霜.曾与蒿藜同雨露,终随松柏到冰霜.
#!/usr/bin/python -tt
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2006 Duke University
from yum.misc import cElementTree_iterparse as iterparse
from yum.misc import _available_compression, stat_f
from Errors import RepoMDError
import sys
import types
from misc import AutoFileChecksums, to_xml
def ns_cleanup(qn):
if qn.find('}') == -1: return qn
return qn.split('}')[1]
class RepoData:
"""represents anything beneath a <data> tag"""
def __init__(self, elem=None):
self.type = None
if elem:
self.type = elem.attrib.get('type')
self.location = (None, None)
self.checksum = (None,None) # type,value
self.openchecksum = (None,None) # type,value
self.timestamp = None
self.dbversion = None
self.size = None
self.opensize = None
self.deltas = []
if elem:
self.parse(elem)
def parse(self, elem):
for child in elem:
child_name = ns_cleanup(child.tag)
if child_name == 'location':
relative = child.attrib.get('href')
base = child.attrib.get('base')
self.location = (base, relative)
elif child_name == 'checksum':
csum_value = child.text
csum_type = child.attrib.get('type')
self.checksum = (csum_type,csum_value)
elif child_name == 'open-checksum':
csum_value = child.text
csum_type = child.attrib.get('type')
self.openchecksum = (csum_type, csum_value)
elif child_name == 'timestamp':
self.timestamp = child.text
elif child_name == 'database_version':
self.dbversion = child.text
elif child_name == 'size':
self.size = child.text
elif child_name == 'open-size':
self.opensize = child.text
elif child_name == 'delta':
delta = RepoData(child)
delta.type = self.type
self.deltas.append(delta)
def dump_xml(self):
msg = ""
top = """<data type="%s">\n""" % to_xml(self.type, attrib=True)
msg += top
for (data, xmlname) in [('checksum', 'checksum'),('openchecksum', 'open-checksum')]:
if hasattr(self, data):
val = getattr(self, data)
if val[0]:
d_xml = """ <%s type="%s">%s</%s>\n""" % (xmlname,
to_xml(val[0], attrib=True),
to_xml(val[1]), xmlname)
msg += d_xml
if hasattr(self, 'location'):
val = getattr(self, 'location')
if val[1]:
loc = """ <location href="%s"/>\n""" % to_xml(val[1], attrib=True)
if val[0]:
loc = """ <location xml:base="%s" href="%s"/>\n""" % (
to_xml(val[0], attrib=True), to_xml(val[1], attrib=True))
msg += loc
for (data,xmlname) in [('timestamp', 'timestamp'),
('dbversion', 'database_version'),
('size','size'), ('opensize', 'open-size')]:
val = getattr(self, data)
if val:
d_xml = """ <%s>%s</%s>\n""" % (xmlname, to_xml(val),
xmlname)
msg += d_xml
for delta in self.deltas:
# change tag to "delta" and increase indent
body = '\n '.join(delta.dump_xml().split('\n')[1:-2])
msg += ' <delta>\n %s\n </delta>\n' % body
bottom = """</data>\n"""
msg += bottom
return msg
def getDelta(self, old_timestamp):
old_timestamp = int(old_timestamp)
for deltamd in self.deltas:
if int(deltamd.timestamp) <= old_timestamp:
return deltamd
class RepoMD:
"""represents the repomd xml file"""
def __init__(self, repoid, srcfile=None):
"""takes a repoid and a filename for the repomd.xml"""
self.timestamp = 0
self.repoid = repoid
self.repoData = {}
self.checksums = {}
self.length = 0
self.revision = None
self.tags = {'content' : set(), 'distro' : {}, 'repo': set()}
if srcfile:
self.parse(srcfile)
def parse(self, srcfile):
if type(srcfile) in types.StringTypes:
# srcfile is a filename string
try:
infile = open(srcfile, 'rt')
except IOError:
raise RepoMDError, "Unable to open %s" %(srcfile,)
else:
# srcfile is a file object
infile = srcfile
srcfile = None
# We trust any of these to mean the repomd.xml is valid.
infile = AutoFileChecksums(infile, ['sha256', 'sha512'],
ignore_missing=True, ignore_none=True)
parser = iterparse(infile)
try:
for event, elem in parser:
elem_name = ns_cleanup(elem.tag)
if elem_name == "data":
thisdata = RepoData(elem=elem)
old = self.repoData.get(thisdata.type)
if (old and old.size and old.size < thisdata.size
and old.location[1].rsplit('.', 1)[1] in _available_compression
and srcfile and stat_f(srcfile.rsplit('/', 1)[0] +'/'+
thisdata.location[1].rsplit('/', 1)[1]) is None):
# previous is smaller, can unzip it, and next is not cached
thisdata = old
self.repoData[thisdata.type] = thisdata
try:
# NOTE: This will fail on float timestamps, this is
# required for compatability. Fix is to not generate
# float timestamps in repomd.xml.
nts = int(thisdata.timestamp)
if nts > self.timestamp: # max() not in old python
self.timestamp = nts
except:
pass
elif elem_name == "revision":
self.revision = elem.text
elif elem_name == "tags":
for child in elem:
child_name = ns_cleanup(child.tag)
if child_name == 'content':
self.tags['content'].add(child.text)
if child_name == 'distro':
cpeid = child.attrib.get('cpeid', '')
distro = self.tags['distro'].setdefault(cpeid,set())
distro.add(child.text)
self.checksums = infile.checksums.hexdigests()
self.length = len(infile.checksums)
except SyntaxError, e:
raise RepoMDError, "Damaged repomd.xml file"
def fileTypes(self):
"""return list of metadata file types available"""
return self.repoData.keys()
def getData(self, type):
if type in self.repoData:
return self.repoData[type]
else:
raise RepoMDError, "requested datatype %s not available" % type
def dump(self):
"""dump fun output"""
print "file timestamp: %s" % self.timestamp
print "file length : %s" % self.length
for csum in sorted(self.checksums):
print "file checksum : %s/%s" % (csum, self.checksums[csum])
if self.revision is not None:
print 'revision: %s' % self.revision
if self.tags['content']:
print 'tags content: %s' % ", ".join(sorted(self.tags['content']))
if self.tags['distro']:
for distro in sorted(self.tags['distro']):
print 'tags distro: %s' % distro
tags = self.tags['distro'][distro]
print ' tags: %s' % ", ".join(sorted(tags))
print '\n---- Data ----'
for ft in sorted(self.fileTypes()):
thisdata = self.repoData[ft]
print ' datatype: %s' % thisdata.type
print ' location : %s %s' % thisdata.location
print ' timestamp : %s' % thisdata.timestamp
print ' size : %s' % thisdata.size
print ' open size : %s' % thisdata.opensize
print ' checksum : %s - %s' % thisdata.checksum
print ' open checksum: %s - %s' % thisdata.openchecksum
print ' dbversion : %s' % thisdata.dbversion
print ''
def dump_xml(self):
msg = ""
top = """<?xml version="1.0" encoding="UTF-8"?>
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">\n"""
msg += top
if self.revision:
rev = """ <revision>%s</revision>\n""" % to_xml(self.revision)
msg += rev
if self.tags['content'] or self.tags['distro'] or self.tags['repo']:
tags = """ <tags>\n"""
for item in self.tags['content']:
tag = """ <content>%s</content>\n""" % (to_xml(item))
tags += tag
for item in self.tags['repo']:
tag = """ <repo>%s</repo>\n""" % (to_xml(item))
tags += tag
distro = self.tags['distro']
if isinstance(distro, dict):
lst = []
for cpeid in sorted(distro):
for item in sorted(distro[cpeid]):
lst.append((cpeid, item))
distro = lst
for (cpeid, item) in distro:
if cpeid:
tag = """ <distro cpeid="%s">%s</distro>\n""" % (
to_xml(cpeid, attrib=True), to_xml(item))
else:
tag = """ <distro>%s</distro>\n""" % (to_xml(item))
tags += tag
tags += """ </tags>\n"""
msg += tags
for md in self.repoData.values():
msg += md.dump_xml()
msg += """</repomd>\n"""
return msg
def main():
try:
print "file : %s" % sys.argv[1]
p = RepoMD('repoid', sys.argv[1])
p.dump()
except IOError:
print >> sys.stderr, "newcomps.py: No such file:\'%s\'" % sys.argv[1]
sys.exit(1)
if __name__ == '__main__':
main()