#!/usr/bin/python import rpm import sys import os class myPkg(object): def __init__(self, hdr, path): for k in ['name', 'version', 'release', 'arch', 'summary']: setattr(self, k, hdr[k]) self.path = path # Bare minimum callback for rpm to get by: it must be able to # open a file descriptor for a package file when requested to do so, # remember it and close it when asked to. It does not have to be # an object, but as it needs to remember state, object is a fairly # obvious solution to avoid global variables. In addition, we # give the user "nice" feedback of what packages are currently # being processed. class myCallback(object): def __init__(self): self._fd = None # The actual callback function. For opening and closing files, only 'event' # and 'key' are needed: event describes the callback reason, and # key is the object - whatever it was - that we passed to # ts.addInstall() as the second argument for this particular package. # Here the key is the myPkg object we created when before ts.addInstall() def callback(self, event, amount, total, key, mydata): if event == rpm.RPMCALLBACK_INST_OPEN_FILE: print "Installing %s (%s)" % (key.name, key.summary) self._fd = os.open(key.path, os.O_RDONLY) return self._fd elif event == rpm.RPMCALLBACK_INST_CLOSE_FILE: self._fd = os.close(self._fd) if __name__ == '__main__': # A transaction set is needed for pretty much all rpm operations. ts = rpm.TransactionSet() # Add packages from the command line to our transaction for install. # Rpm grabs what it needs for its own purposes (dependency checking, # install ordering, file conflict resolution etc) from the header we # pass here, and discards it to conserve memory. The package is # reopened during the actual transaction, and this is what the # second argument is for: we need to hand the same file back to # rpm when its requested in the callback. But we want to tell # the user of whats going on, so grab a bit of information from # the header to an object of our own and pass that as the key. for path in sys.argv[1:]: fd = os.open(path, os.O_RDONLY) hdr = ts.hdrFromFdno(fd) pkg = myPkg(hdr, path) ts.addInstall(hdr, pkg, 'u') os.close(fd) # Check for missing dependencies in the transaction set ts.check() if ts.problems(): rc = 1 else: # No problems, order the transaction and let rpm free memory # which is not needed from this point onwards. ts.order() ts.clean() # With the preliminaries out of the way, run the actual transaction. # The return codes from ts.run() are obscure, but None means # 'all went well', which is sufficient for this little demo. cb = myCallback() rc = (ts.run(cb.callback, None) != None) sys.exit(rc)