Files
munki/code/client/makecatalogs
Greg Neagle a326c38ec9 Better handling of plist exceptions when given valid plists in non-XML format (ascii, binary).
makecatalogs now should be able to run on non-OS X platforms as long as there is a plistlib module available. (Untested)

git-svn-id: http://munki.googlecode.com/svn/trunk@785 a4e17f2e-e282-11dd-95e1-755cbddbdd66
2010-10-08 18:00:00 +00:00

136 lines
4.8 KiB
Python
Executable File

#!/usr/bin/python
# encoding: utf-8
#
# Copyright 2009-2010 Greg Neagle.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
makecatalogs
Created by Greg Neagle on 2009-03-30.
Recursively scans a directory, looking for installer item info files.
Builds a repo catalog from these files.
Assumes a pkgsinfo directory under repopath.
User calling this needs to be able to write to repo/catalogs.
TO-DOs:
Maybe generate a checksum so we can verify the installer item is the right one
"""
import sys
import os
import optparse
try:
from munkilib import FoundationPlist as plistlib
except ImportError:
try:
import FoundationPlist as plistlib
except ImportError:
print >> sys.stderr, ("WARNING: FoundationPlist is not available, "
"using plistlib instead.")
import plistlib
def makecatalogs(repopath):
'''Assembles all pkginfo files into catalogs.
Assumes a pkgsinfo directory under repopath.
User calling this needs to be able to write to repo/catalogs.'''
pkgsinfopath = os.path.join(repopath, 'pkgsinfo')
if not os.path.exists(pkgsinfopath):
print >> sys.stderr, "pkgsinfo path %s doesn't exist!" % pkgsinfopath
exit(-1)
catalogs = {}
catalogs['all'] = []
for dirpath, dirnames, filenames in os.walk(pkgsinfopath):
subdir = dirpath[len(pkgsinfopath):]
for name in filenames:
if name.startswith("._") or name == ".DS_Store":
# don't process these
continue
filepath = os.path.join(dirpath, name)
try:
pkginfo = plistlib.readPlist(filepath)
except IOError as inst:
print >> sys.stderr, ("IO error for %s: %s" %
(filepath, inst))
continue
except Exception as inst:
print >> sys.stderr, ("Unexpected error for %s: %s" %
(filepath, inst))
continue
#simple sanity checking
if not 'installer_item_location' in pkginfo:
print >> sys.stderr, \
("WARNING: file %s is missing installer_item_location" %
filepath)
continue
installeritempath = os.path.join(repopath, "pkgs",
pkginfo['installer_item_location'])
if not os.path.exists(installeritempath):
print >> sys.stderr, ("WARNING: Info file %s refers to "
"missing installer item: %s" %
(filepath[len(pkgsinfopath)+1:],
pkginfo['installer_item_location']))
continue
catalogs['all'].append(pkginfo)
for catalogname in pkginfo.get("catalogs", []):
if not catalogname in catalogs:
catalogs[catalogname] = []
catalogs[catalogname].append(pkginfo)
print "Adding %s to %s..." % \
(filepath[len(pkgsinfopath)+1:], catalogname)
# clear out old catalogs
catalogpath = os.path.join(repopath, "catalogs")
if not os.path.exists(catalogpath):
os.mkdir(catalogpath)
else:
for item in os.listdir(catalogpath):
itempath = os.path.join(catalogpath, item)
if os.path.isfile(itempath):
os.remove(itempath)
# write the new catalogs
for key in catalogs.keys():
catalogpath = os.path.join(repopath, "catalogs", key)
plistlib.writePlist(catalogs[key], catalogpath)
def main():
'''Main'''
usage = "usage: %prog [options] /path/to/repo_root"
p = optparse.OptionParser(usage=usage)
options, arguments = p.parse_args()
if len(arguments) == 0:
print >> sys.stderr, "Need to specify a path to the repo root!"
exit(-1)
repopath = arguments[0].rstrip("/")
if not os.path.exists(repopath):
print >> sys.stderr, "Repo root path %s doesn't exist!" % repopath
exit(-1)
makecatalogs(repopath)
if __name__ == '__main__':
main()