mirror of
https://github.com/munki/munki.git
synced 2026-01-13 02:10:06 -06:00
- makecatalogs now has no OS X-specific dependencies - munkiimport fixes for repos hosted via SMB/CIFS. git-svn-id: http://munki.googlecode.com/svn/trunk@1097 a4e17f2e-e282-11dd-95e1-755cbddbdd66
176 lines
6.2 KiB
Python
Executable File
176 lines
6.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# encoding: utf-8
|
|
#
|
|
# Copyright 2009-2011 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.
|
|
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import optparse
|
|
|
|
try:
|
|
from munkilib import FoundationPlist as plistlib
|
|
except ImportError:
|
|
try:
|
|
import FoundationPlist as plistlib
|
|
except ImportError:
|
|
# maybe we're not on an OS X machine...
|
|
print >> sys.stderr, ("WARNING: FoundationPlist is not available, "
|
|
"using plistlib instead.")
|
|
import plistlib
|
|
|
|
try:
|
|
from munkilib.munkicommon import listdir, get_version
|
|
except ImportError:
|
|
# munkilib is not available
|
|
def listdir(path):
|
|
"""OSX HFS+ string encoding safe listdir().
|
|
|
|
Args:
|
|
path: path to list contents of
|
|
Returns:
|
|
list of contents, items as str or unicode types
|
|
"""
|
|
# if os.listdir() is supplied a unicode object for the path,
|
|
# it will return unicode filenames instead of their raw fs-dependent
|
|
# version, which is decomposed utf-8 on OSX.
|
|
#
|
|
# we use this to our advantage here and have Python do the decoding
|
|
# work for us, instead of decoding each item in the output list.
|
|
#
|
|
# references:
|
|
# http://docs.python.org/howto/unicode.html#unicode-filenames
|
|
# http://developer.apple.com/library/mac/#qa/qa2001/qa1235.html
|
|
# http://lists.zerezo.com/git/msg643117.html
|
|
# http://unicode.org/reports/tr15/ section 1.2
|
|
if type(path) is str:
|
|
path = unicode(path, 'utf-8')
|
|
elif type(path) is not unicode:
|
|
path = unicode(path)
|
|
return os.listdir(path)
|
|
|
|
def get_version():
|
|
'''Placeholder if munkilib is not available'''
|
|
return 'UNKNOWN'
|
|
|
|
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, inst:
|
|
print >> sys.stderr, ("IO error for %s: %s" %
|
|
(filepath, inst))
|
|
continue
|
|
except Exception, 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 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)
|
|
p.add_option('--version', '-V', action='store_true',
|
|
help='Print the version of the munki tools and exit.')
|
|
options, arguments = p.parse_args()
|
|
|
|
if options.version:
|
|
print get_version()
|
|
exit(0)
|
|
|
|
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()
|
|
|