def updateInfoPlist(app, updates): path = os.path.join(app, 'Info.plist') info = plistlib27.readPlist(path) info.update(updates) plist = NSPropertyListSerialization.dataWithPropertyList_format_options_error_( info, NSPropertyListBinaryFormat_v1_0, 0, None) plist[0].writeToFile_atomically_(path, True)
def archive(app, dsym, appModifyCallback=None): appBase = os.path.basename(app) appName = os.path.splitext(appBase)[0] date = datetime.today().strftime('%m-%d-%y %H.%M %p') archive = os.path.join(tempfile.mkdtemp(), '%(appName)s %(date)s.xcarchive' % locals()) applications = os.path.join(archive, 'Products', 'Applications') archiveApp = os.path.join(applications, appBase) shutil.copytree(app, archiveApp) if appModifyCallback: appModifyCallback(archiveApp) info = plistlib27.readPlist(os.path.join(app, 'Info.plist')) dsyms = os.path.join(archive, 'dSYMs') dsymArchive = os.path.join(dsyms, os.path.basename(dsym)) shutil.copytree(dsym, dsymArchive) updateDsymIdentifier(dsymArchive, info['CFBundleIdentifier']) icons = (os.path.join('Applications', appBase, item) for item in os.listdir(app) if item.startswith('AppIcon') and item.endswith('@2x.png')) plist = { 'ApplicationProperties': { 'ApplicationPath': os.path.join('Applications', appBase), 'CFBundleIdentifier': info['CFBundleIdentifier'], 'CFBundleShortVersionString': info['CFBundleShortVersionString'], 'CFBundleVersion': info['CFBundleVersion'], 'SigningIdentity': _authority(archiveApp) or '', 'IconPaths': list(icons) }, 'ArchiveVersion': 2, 'CreationDate': datetime.utcnow(), 'Name': appName, 'SchemeName': appName } plistlib27.writePlist(plist, os.path.join(archive, 'Info.plist')) # Add SwiftSupport folder xcodePath = subprocess.check_output(["xcode-select", "--print-path"]) xcodePath = xcodePath.rstrip() libraryPath = os.path.join(xcodePath, 'Toolchains', 'XcodeDefault.xctoolchain', 'usr', 'lib', 'swift', 'iphoneos') frameworksFolder = os.path.join(app, 'Frameworks') if os.path.isdir(frameworksFolder): for framework in os.listdir(frameworksFolder): if framework.startswith("libswift"): swiftSupportFolder = os.path.join(archive, 'SwiftSupport') if not os.path.isdir(swiftSupportFolder): os.mkdir(swiftSupportFolder) print 'Added SwiftSupport folder' shutil.copy2(os.path.join(libraryPath, framework), os.path.join(swiftSupportFolder, framework)) return archive
def build(branchDirectory, target, appModifyCallback=None): os.chdir(branchDirectory) buildDirectory = tempfile.mkdtemp() xcodebuild = ("xcodebuild -target %(target)s -configuration Release "+ "OBJROOT=%(buildDirectory)s CONFIGURATION_BUILD_DIR='%(buildDirectory)s'") if subprocess.call(xcodebuild % locals(), shell=True): raise RuntimeError('Build failed') app = os.path.join(buildDirectory, target+'.app') dsym = app+'.dSYM' if appModifyCallback: appModifyCallback(app) # make sure the identifier in the dsym matches the modifed app identifier = plistlib27.readPlist(os.path.join(app, 'Info.plist'))['CFBundleIdentifier'] updateDsymIdentifier(dsym, identifier) # even through all the build items go into `buildDirectory` # an empty build directory is still created in `branchDirectory` projectBuild = os.path.join(branchDirectory, 'build') if os.path.isdir(projectBuild): shutil.rmtree(projectBuild) return (app, dsym)
def archive(app, dsym, appModifyCallback=None): appBase = os.path.basename(app) appName = os.path.splitext(appBase)[0] date = datetime.today().strftime('%m-%d-%y %H.%M %p') archive = os.path.join(tempfile.mkdtemp(), '%(appName)s %(date)s.xcarchive' % locals()) applications = os.path.join(archive, 'Products', 'Applications') archiveApp = os.path.join(applications, appBase) shutil.copytree(app, archiveApp) if appModifyCallback: appModifyCallback(archiveApp) info = plistlib27.readPlist(os.path.join(app, 'Info.plist')) dsyms = os.path.join(archive, 'dSYMs') dsymArchive = os.path.join(dsyms, os.path.basename(dsym)) shutil.copytree(dsym, dsymArchive) updateDsymIdentifier(dsymArchive, info['CFBundleIdentifier']) icons = (os.path.join('Applications', appBase, item) for item in os.listdir(app) if item.startswith('Icon') and item.endswith('png')) plist = { 'AppStoreFileSize': _directorySize(archiveApp), 'ApplicationProperties': { 'ApplicationPath': os.path.join('Applications', appBase), 'CFBundleIdentifier': info['CFBundleIdentifier'], 'CFBundleShortVersionString': info['CFBundleShortVersionString'], 'CFBundleVersion': info['CFBundleVersion'], 'SigningIdentity': _authority(archiveApp) or '', 'IconPaths': list(icons) }, 'ArchiveVersion': 2, 'CreationDate': datetime.today().strftime('%Y-%m-%dT%H:%M:%SZ'), 'Name': appName, 'SchemeName': appName } plistlib27.writePlist(plist, os.path.join(archive, 'Info.plist')) return archive
def projectShortVersion(branchDirectory, target): return plistlib27.readPlist(os.path.join(branchDirectory, target+'-Info.plist'))['CFBundleShortVersionString']
def version(app): return plistlib27.readPlist(os.path.join(app, 'Info.plist'))['CFBundleVersion']
def updateDsymIdentifier(dsym, identifier): path = os.path.join(dsym, 'Contents', 'Info.plist') info = plistlib27.readPlist(path) info['CFBundleIdentifier'] = 'com.apple.xcode.dsym.'+identifier plistlib27.writePlist(info, path)
def projectShortVersion(branchDirectory, target): return plistlib27.readPlist( os.path.join(branchDirectory, target + '-Info.plist'))['CFBundleShortVersionString']
def projectVersion(branchDirectory, target): return plistlib27.readPlist(os.path.join(branchDirectory, target + "-Info.plist"))["CFBundleVersion"]