Key name changes and behavior tweaks to Heig's submission for support for bundle/plist version keys other than CFBundleShortVersionString

This commit is contained in:
Greg Neagle
2013-02-04 14:20:31 -08:00
parent 20a0b51895
commit 3c5d707ec1
2 changed files with 77 additions and 50 deletions
+35 -19
View File
@@ -1165,22 +1165,34 @@ def padVersionString(versString, tupleCount):
return '.'.join(components)
def getVersionString(plist,key='CFBundleShortVersionString'):
def getVersionString(plist, key=None):
"""Gets a version string from the plist.
By default, if there's a CFBundleShortVersionString, returns that.
If a key is explictly specified, the value of that key is
returned without modification, or an empty string if the
key does not exist.
If key is not specified:
if there's a valid CFBundleShortVersionString, returns that.
else if there's a CFBundleVersion, returns that
else returns an empty string.
If a 'key' other than CFBundleShortVersionString is passed,
and the 'key' exists in the plist, its value is returned,
otherwise, returns an empty string and does NOT attempt to
retrieve the version from CFBundleVersion.
"""
VersionString = ''
if key:
return plist.get(key, '')
# default to CFBundleShortVersionString plus magic
key = 'CFBundleShortVersionString'
if not 'CFBundleShortVersionString' in plist:
if 'Bundle versions string, short' in plist:
# workaround for broken Composer packages
# where the key is actually named
# 'Bundle versions string, short' instead of
# 'CFBundleShortVersionString'
key = 'Bundle versions string, short'
if plist.get(key):
VersionString = plist[key].split()[0]
if 'Bundle versions string, short' in plist:
VersionString = plist['Bundle versions string, short'].split()[0]
if VersionString:
if VersionString[0] in '0123456789':
# starts with a number; that's good
@@ -1188,12 +1200,11 @@ def getVersionString(plist,key='CFBundleShortVersionString'):
# replace commas with periods
VersionString = VersionString.replace(',','.')
return VersionString
if key != 'CFBundleShortVersionString':
# an arbitrary key has been provided so return its value or,
# if it doesn't exist, an empty string
return VersionString
if plist.get('CFBundleVersion'):
# no CFBundleShortVersionString, or bad one
# a future version of the Munki tools may drop this magic
# and require admins to explicitly choose the CFBundleVersion
# but for now Munki does some magic
VersionString = str(plist['CFBundleVersion']).split()[0]
if VersionString[0] in '0123456789':
# starts with a number; that's good
@@ -1205,15 +1216,20 @@ def getVersionString(plist,key='CFBundleShortVersionString'):
return ''
def getExtendedVersion(bundlepath):
def getBundleVersion(bundlepath, key=None):
"""
Returns five-part version number like Apple uses in distribution
and flat packages
Returns version number from a bundle.
Some extra code to deal with very old-style bundle packages
Specify key to use a specific key in the Info.plist for
the version string.
"""
infoPlist = os.path.join(bundlepath, 'Contents', 'Info.plist')
if not os.path.exists(infoPlist):
infoPlist = os.path.join(bundlepath, 'Resources', 'Info.plist')
if os.path.exists(infoPlist):
plist = FoundationPlist.readPlist(infoPlist)
versionstring = getVersionString(plist)
versionstring = getVersionString(plist, key)
if versionstring:
return versionstring
@@ -1409,7 +1425,7 @@ def getOnePackageInfo(pkgpath):
if 'IFPkgFlagInstalledSize' in plist:
pkginfo['installed_size'] = plist['IFPkgFlagInstalledSize']
pkginfo['version'] = getExtendedVersion(pkgpath)
pkginfo['version'] = getBundleVersion(pkgpath)
except (AttributeError,
FoundationPlist.NSPropertyListSerializationException):
pkginfo['packageid'] = 'BAD PLIST in %s' % \
@@ -1689,7 +1705,7 @@ def getPackageMetaData(pkgitem):
name = os.path.split(pkgitem)[1]
shortname = os.path.splitext(name)[0]
metaversion = getExtendedVersion(pkgitem)
metaversion = getBundleVersion(pkgitem)
if metaversion == '0.0.0.0.0':
metaversion = nameAndVersion(shortname)[1]
@@ -2032,7 +2048,7 @@ def getAppData():
iteminfo['bundleid'] = plist.get('CFBundleIdentifier','')
if 'CFBundleName' in plist:
iteminfo['name'] = plist['CFBundleName']
iteminfo['version'] = getExtendedVersion(pathname)
iteminfo['version'] = getBundleVersion(pathname)
APPDATA.append(iteminfo)
except Exception:
pass
+42 -31
View File
@@ -392,16 +392,17 @@ def compareApplicationVersion(app):
Raises munkicommon.Error if there's an error in the input
"""
if 'path' in app and 'VersionString' in app:
if 'path' in app:
filepath = os.path.join(app['path'], 'Contents', 'Info.plist')
if os.path.exists(filepath):
return compareBundleVersion(app)
# not in default location, so let's search:
# not in default location, or no path specified, so let's search:
name = app.get('CFBundleName','')
bundleid = app.get('CFBundleIdentifier','')
versionstring = app.get('VersionString')
plist_version_key = app.get('plist_version_key')
version_comparison_key = app.get(
'version_comparison_key', 'CFBundleShortVersionString')
versionstring = app.get(version_comparison_key)
minupvers = app.get('minimum_update_version')
if name == '' and bundleid == '':
@@ -441,6 +442,7 @@ def compareApplicationVersion(app):
'\tDid not find this application on the startup disk.')
return 0
# iterate through matching applications
for item in appinfo:
if 'name' in item:
munkicommon.display_debug2(
@@ -452,14 +454,14 @@ def compareApplicationVersion(app):
munkicommon.display_debug2(
'\tCFBundleIdentifier: \t %s' % item['bundleid'])
if plist_version_key and apppath:
if apppath and version_comparison_key != 'CFBundleShortVersionString':
# if a specific plist version key has been supplied,
# add the following keys to the discovered 'item'
# so that a bundle version comparison can be made
item['VersionString'] = versionstring
item['plist_version_key'] = plist_version_key
item['minimum_update_version'] = minupvers
return compareBundleVersion(item)
# if we're suppose to compare against a key other than
# 'CFBundleShortVersionString' we can't use item['version'] as-is
# so update item['version'] with info from the specific
# version key
item['version'] = munkicommon.getBundleVersion(
apppath, version_comparison_key)
if minupvers:
if compareVersions(item['version'], minupvers) < 1:
@@ -497,14 +499,17 @@ def compareBundleVersion(item):
Raises munkicommon.Error if there's an error in the input
"""
if 'path' in item and 'VersionString' in item:
vers = item['VersionString']
version_comparison_key = item.get(
'version_comparison_key', 'CFBundleShortVersionString')
versionstring = item.get(version_comparison_key, None)
if 'path' in item and versionstring:
minupvers = item.get('minimum_update_version')
else:
raise munkicommon.Error('Missing bundle path or version!')
munkicommon.display_debug1('Checking bundle %s for version %s...' %
(item['path'], vers))
munkicommon.display_debug1('Checking bundle %s for %s %s...' %
(item['path'], version_comparison_key, versionstring))
filepath = os.path.join(item['path'], 'Contents', 'Info.plist')
if not os.path.exists(filepath):
munkicommon.display_debug1('\tNo Info.plist found at %s' % filepath)
@@ -521,14 +526,16 @@ def compareBundleVersion(item):
munkicommon.display_debug1('\t%s may not be a plist!' % filepath)
return 0
if 'plist_version_key' in item:
# arbitrary key has been supplied,
if 'version_comparison_key' in item:
# specific key has been supplied,
# so use this to determine installed version
plist_version_key = item['plist_version_key']
munkicommon.display_debug1(
'\tUsing supplied plist key %s for comparison' % plist_version_key)
installedvers = munkicommon.getVersionString(plist, plist_version_key)
'\tUsing supplied plist key %s for comparison'
% version_comparison_key)
installedvers = munkicommon.getVersionString(
plist, version_comparison_key)
else:
# use default behavior
installedvers = munkicommon.getVersionString(plist)
if installedvers:
if minupvers:
@@ -537,7 +544,7 @@ def compareBundleVersion(item):
'\tVersion %s too old < %s' % (installedvers, minupvers))
return 0
return compareVersions(installedvers, vers)
return compareVersions(installedvers, versionstring)
else:
munkicommon.display_debug1('\tNo version info in %s.' % filepath)
return 0
@@ -553,15 +560,17 @@ def comparePlistVersion(item):
Raises munkicommon.Error if there's an error in the input
"""
if 'path' in item and 'VersionString' in item:
vers = item['VersionString']
version_comparison_key = item.get(
'version_comparison_key', 'CFBundleShortVersionString')
if 'path' in item and version_comparison_key in item:
versionstring = item[version_comparison_key]
filepath = item['path']
minupvers = item.get('minimum_update_version')
else:
raise munkicommon.Error('Missing plist path or version!')
munkicommon.display_debug1('Checking %s for version %s...' %
(filepath, vers))
munkicommon.display_debug1('Checking %s for version %s %s...' %
(filepath, version_comparison_key, versionstring))
if not os.path.exists(filepath):
munkicommon.display_debug1('\tNo plist found at %s' % filepath)
return 0
@@ -572,14 +581,16 @@ def comparePlistVersion(item):
munkicommon.display_debug1('\t%s may not be a plist!' % filepath)
return 0
if 'plist_version_key' in item:
# arbitrary key has been supplied,
if 'version_comparison_key' in item:
# specific key has been supplied,
# so use this to determine installed version
plist_version_key = item['plist_version_key']
munkicommon.display_debug1(
'\tUsing supplied plist key %s for comparison' % plist_version_key)
installedvers = munkicommon.getVersionString(plist, plist_version_key)
'\tUsing supplied plist key %s for comparison'
% version_comparison_key)
installedvers = munkicommon.getVersionString(
plist, version_comparison_key)
else:
# default behavior
installedvers = munkicommon.getVersionString(plist)
if installedvers:
if minupvers:
@@ -587,7 +598,7 @@ def comparePlistVersion(item):
munkicommon.display_debug1(
'\tVersion %s too old < %s' % (installedvers, minupvers))
return 0
return compareVersions(installedvers, vers)
return compareVersions(installedvers, versionstring)
else:
munkicommon.display_debug1('\tNo version info in %s.' % filepath)
return 0