File: modifyrepo.py

package info (click to toggle)
createrepo 0.4.11-1
  • links: PTS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 216 kB
  • ctags: 192
  • sloc: python: 1,581; makefile: 295; sh: 2
file content (124 lines) | stat: -rwxr-xr-x 4,515 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python
# $Id$
#
# This tools is used to insert arbitrary metadata into an RPM repository.
# Example:
#           ./modifyrepo.py updateinfo.xml myrepo/repodata
# or in Python:
#           >>> from modifyrepo import RepoMetadata
#           >>> repomd = RepoMetadata('myrepo/repodata')
#           >>> repomd.add('updateinfo.xml')
#
# 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 General Public License for more details.
#
# (C) Copyright 2006  Red Hat, Inc.
# Luke Macken <lmacken@redhat.com>

import os
import sys
import sha
import gzip

from xml.dom import minidom

class RepoMetadata:

    def __init__(self, repo):
        """ Parses the repomd.xml file existing in the given repo directory. """
        self.repodir = os.path.abspath(repo)
        self.repomdxml = os.path.join(self.repodir, 'repomd.xml')
        if not os.path.exists(self.repomdxml):
            raise Exception('%s not found' % self.repomdxml)
        self.doc = minidom.parse(self.repomdxml)

    def _insert_element(self, parent, name, attrs={}, text=None):
        child = self.doc.createElement(name)
        for item in attrs.items():
            child.setAttribute(item[0], item[1])
        if text:
            txtnode = self.doc.createTextNode(text)
            child.appendChild(txtnode)
        parent.appendChild(child)
        return child

    def add(self, metadata):
        """ Insert arbitrary metadata into this repository.
            metadata can be either an xml.dom.minidom.Document object, or
            a filename.
        """
        md = None
        if not metadata:
            raise Exception('metadata cannot be None')
        if isinstance(metadata, minidom.Document):
            md = metadata.toxml()
            mdname = 'updateinfo.xml'
        elif isinstance(metadata, str):
            if os.path.exists(metadata):
                oldmd = file(metadata, 'r')
                md = oldmd.read()
                oldmd.close()
                mdname = os.path.basename(metadata)
            else:
                raise Exception('%s not found' % metadata)
        else:
            raise Exception('invalid metadata type')

        ## Compress the metadata and move it into the repodata
        mdname += '.gz'
        mdtype = mdname.split('.')[0]
        destmd = os.path.join(self.repodir, mdname)
        newmd = gzip.GzipFile(destmd, 'wb')
        newmd.write(md)
        newmd.close()
        print "Wrote:", destmd

        ## Read the gzipped metadata
        f = file(destmd, 'r')
        newmd = f.read()
        f.close()

        ## Remove any stale metadata
        for elem in self.doc.getElementsByTagName('data'):
            if elem.attributes['type'].value == mdtype:
                self.doc.firstChild.removeChild(elem)

        ## Build the metadata
        root = self.doc.firstChild
        data = self._insert_element(root, 'data', attrs={ 'type' : mdtype })
        self._insert_element(data, 'location',
                             attrs={ 'href' : 'repodata/' + mdname })
        self._insert_element(data, 'checksum', attrs={ 'type' : 'sha' },
                             text=sha.new(newmd).hexdigest())
        self._insert_element(data, 'timestamp',
                             text=str(os.stat(destmd).st_mtime))
        self._insert_element(data, 'open-checksum', attrs={ 'type' : 'sha' },
                             text=sha.new(md).hexdigest())

        print "           type =", mdtype 
        print "       location =", 'repodata/' + mdname
        print "       checksum =", sha.new(newmd).hexdigest()
        print "      timestamp =", str(os.stat(destmd).st_mtime)
        print "  open-checksum =", sha.new(md).hexdigest()

        ## Write the updated repomd.xml
        outmd = file(self.repomdxml, 'w')
        self.doc.writexml(outmd)
        outmd.close()
        print "Wrote:", self.repomdxml


if __name__ == '__main__':
    if len(sys.argv) != 3 or '-h' in sys.argv:
        print "Usage: %s <input metadata> <output repodata>" % sys.argv[0]
        sys.exit()

    repomd = RepoMetadata(sys.argv[2])
    repomd.add(sys.argv[1])