resetting manifest requested domain to floor
[platform/upstream/createrepo.git] / modifyrepo.py
1 #!/usr/bin/python
2 # This tools is used to insert arbitrary metadata into an RPM repository.
3 # Example:
4 #           ./modifyrepo.py updateinfo.xml myrepo/repodata
5 # or in Python:
6 #           >>> from modifyrepo import RepoMetadata
7 #           >>> repomd = RepoMetadata('myrepo/repodata')
8 #           >>> repomd.add('updateinfo.xml')
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 #
20 # (C) Copyright 2006  Red Hat, Inc.
21 # Luke Macken <lmacken@redhat.com>
22 # modified by Seth Vidal 2008
23
24 import os
25 import sys
26 from createrepo import __version__
27 from createrepo.utils import checksum_and_rename, GzipFile, MDError
28 from yum.misc import checksum
29
30 from yum.repoMDObject import RepoMD, RepoMDError, RepoData
31 from xml.dom import minidom
32 from optparse import OptionParser
33
34
35 class RepoMetadata:
36
37     def __init__(self, repo):
38         """ Parses the repomd.xml file existing in the given repo directory. """
39         self.repodir = os.path.abspath(repo)
40         self.repomdxml = os.path.join(self.repodir, 'repomd.xml')
41         self.checksum_type = 'sha256'
42
43         if not os.path.exists(self.repomdxml):
44             raise MDError, '%s not found' % self.repomdxml
45
46         try:
47             self.repoobj = RepoMD(self.repodir)
48             self.repoobj.parse(self.repomdxml)
49         except RepoMDError, e:
50             raise MDError, 'Could not parse %s' % self.repomdxml
51
52
53     def add(self, metadata, mdtype=None):
54         """ Insert arbitrary metadata into this repository.
55             metadata can be either an xml.dom.minidom.Document object, or
56             a filename.
57         """
58         md = None
59         if not metadata:
60             raise MDError, 'metadata cannot be None'
61         if isinstance(metadata, minidom.Document):
62             md = metadata.toxml()
63             mdname = 'updateinfo.xml'
64         elif isinstance(metadata, str):
65             if os.path.exists(metadata):
66                 if metadata.endswith('.gz'):
67                     oldmd = GzipFile(filename=metadata, mode='rb')
68                 else:
69                     oldmd = file(metadata, 'r')
70                 md = oldmd.read()
71                 oldmd.close()
72                 mdname = os.path.basename(metadata)
73             else:
74                 raise MDError, '%s not found' % metadata
75         else:
76             raise MDError, 'invalid metadata type'
77
78         ## Compress the metadata and move it into the repodata
79         if not mdname.endswith('.gz'):
80             mdname += '.gz'
81         if not mdtype:
82             mdtype = mdname.split('.')[0]
83             
84         destmd = os.path.join(self.repodir, mdname)
85         newmd = GzipFile(filename=destmd, mode='wb')
86         newmd.write(md)
87         newmd.close()
88         print "Wrote:", destmd
89
90         open_csum = checksum(self.checksum_type, metadata)
91         csum, destmd = checksum_and_rename(destmd, self.checksum_type)
92         base_destmd = os.path.basename(destmd)
93
94
95         ## Remove any stale metadata
96         if mdtype in self.repoobj.repoData:
97             del self.repoobj.repoData[mdtype]
98             
99
100         new_rd = RepoData()
101         new_rd.type = mdtype
102         new_rd.location = (None, 'repodata/' + base_destmd)
103         new_rd.checksum = (self.checksum_type, csum)
104         new_rd.openchecksum = (self.checksum_type, open_csum)
105         new_rd.size = str(os.stat(destmd).st_size)
106         new_rd.timestamp = str(os.stat(destmd).st_mtime)
107         self.repoobj.repoData[new_rd.type] = new_rd
108         
109         print "           type =", new_rd.type
110         print "       location =", new_rd.location[1]
111         print "       checksum =", new_rd.checksum[1]
112         print "      timestamp =", new_rd.timestamp
113         print "  open-checksum =", new_rd.openchecksum[1]
114
115         ## Write the updated repomd.xml
116         outmd = file(self.repomdxml, 'w')
117         outmd.write(self.repoobj.dump_xml())
118         outmd.close()
119         print "Wrote:", self.repomdxml
120
121
122 def main(args):
123     parser = OptionParser(version='modifyrepo version %s' % __version__)
124     # query options
125     parser.add_option("--mdtype", dest='mdtype',
126                       help="specific datatype of the metadata, will be derived from the filename if not specified")
127     parser.usage = "modifyrepo [options] <input_metadata> <output repodata>"
128     
129     (opts, argsleft) = parser.parse_args(args)
130     if len(argsleft) != 2:
131         parser.print_usage()
132         return 0
133     metadata = argsleft[0]
134     repodir = argsleft[1]
135     try:
136         repomd = RepoMetadata(repodir)
137     except MDError, e:
138         print "Could not access repository: %s" % str(e)
139         return 1
140     try:
141         repomd.add(metadata, mdtype=opts.mdtype)
142     except MDError, e:
143         print "Could not add metadata from file %s: %s" % (metadata, str(e))
144         return 1
145
146 if __name__ == '__main__':
147     ret = main(sys.argv[1:])
148     sys.exit(ret)