【发布时间】:2011-06-30 22:06:11
【问题描述】:
在 Xcode 3 中,应用程序被归档在 .apparchive 文件夹中。
在 Xcode 4 中,应用程序现在存档在 .xcarchive 包中。
有没有办法转换 .xcarchive 包中的 .apparchive 文件夹或使用 Xcode 4 打开 .apparchive 文件夹?
【问题讨论】:
在 Xcode 3 中,应用程序被归档在 .apparchive 文件夹中。
在 Xcode 4 中,应用程序现在存档在 .xcarchive 包中。
有没有办法转换 .xcarchive 包中的 .apparchive 文件夹或使用 Xcode 4 打开 .apparchive 文件夹?
【问题讨论】:
Dave Dunkin 的脚本效果很好,但在某些情况下我错过了图标和版本。下面是稍微调整过的脚本版本。 您需要安装 MacRuby,可在此处获得:http://www.macruby.org/downloads.html。
#!/System/Library/PrivateFrameworks/MacRuby.framework/Versions/A/usr/bin/macruby
framework 'Cocoa'
require 'date'
require 'fileutils'
Dir.glob(Dir.home() + '/Library/Application Support/Developer/Shared/Archived Applications/*.apparchive').each { |apparchivePath|
print "Found archive at #{apparchivePath}... "
archiveInfo = NSDictionary.dictionaryWithContentsOfURL(NSURL.fileURLWithPath(apparchivePath + '/ArchiveInfo.plist'))
name = archiveInfo['XCUserProvidedName'] || archiveInfo['XCApplicationName']
appFilename = archiveInfo['XCApplicationFilename']
appPath = 'Applications/' + appFilename
archiveDate = archiveInfo['XCArchivedDate']
xcarchivePath = Dir.home() + '/Library/Developer/Xcode/Archives/' + archiveDate.strftime('%Y-%m-%d') + '/' + name + ' ' + archiveDate.strftime('%m-%d-%y %I.%M %p') + '.xcarchive'
appVersion = archiveInfo['CFBundleVersion']
iconPaths = archiveInfo['XCInfoPlist']['CFBundleIconFiles']
if not iconPaths
iconPaths = appPath + '/' + archiveInfo['XCInfoPlist']['CFBundleIconFile']
else
iconPaths = archiveInfo['XCInfoPlist']['CFBundleIconFiles'].collect { |f| appPath + '/' + f }
end
if File.directory?(xcarchivePath)
puts 'skipping'
else
puts 'importing'
FileUtils.mkdir_p(xcarchivePath)
xcarchiveInfo = {
'ApplicationProperties' => {
'ApplicationPath' => appPath,
'CFBundleIdentifier' => archiveInfo['CFBundleIdentifier'],
'CFBundleShortVersionString' => appVersion,
'IconPaths' => iconPaths
},
'ArchiveVersion' => 1,
'CreationDate' => archiveDate,
'Name' => name,
'SchemeName' => archiveInfo['XCApplicationName']
}
if archiveInfo.has_key?('XCUserProvidedComment')
xcarchiveInfo['Comment'] = archiveInfo['XCUserProvidedComment']
end
xcarchiveInfo.writeToURL(NSURL.fileURLWithPath(xcarchivePath + '/Info.plist'), atomically:false)
FileUtils.mkdir_p(xcarchivePath + '/Products/Applications')
FileUtils.cp_r(apparchivePath + '/' + appFilename, xcarchivePath + '/Products/Applications')
FileUtils.mkdir_p(xcarchivePath + '/dSYMs')
FileUtils.cp_r(apparchivePath + '/' + appFilename + '.dSYM', xcarchivePath + '/dSYMs')
end
}
【讨论】:
这是我为自己编写的 MacRuby 脚本。
#!/usr/local/bin/macruby
framework 'Cocoa'
require 'date'
require 'fileutils'
Dir.glob(Dir.home() + '/Library/Application Support/Developer/Shared/Archived Applications/*.apparchive').each { |apparchivePath|
print "Found archive at #{apparchivePath}... "
archiveInfo = NSDictionary.dictionaryWithContentsOfURL(NSURL.fileURLWithPath(apparchivePath + '/ArchiveInfo.plist'))
name = archiveInfo['XCUserProvidedName'] || archiveInfo['XCApplicationName']
appFilename = archiveInfo['XCApplicationFilename']
appPath = 'Applications/' + appFilename
archiveDate = archiveInfo['XCArchivedDate']
xcarchivePath = Dir.home() + '/Library/Developer/Xcode/Archives/' + archiveDate.strftime('%Y-%m-%d') + '/' + name + ' ' + archiveDate.strftime('%m-%d-%y %I.%M %p') + '.xcarchive'
if File.directory?(xcarchivePath)
puts 'skipping'
else
puts 'importing'
FileUtils.mkdir_p(xcarchivePath)
xcarchiveInfo = {
'ApplicationProperties' => {
'ApplicationPath' => appPath,
'CFBundleIdentifier' => archiveInfo['CFBundleIdentifier'],
'IconPaths' => archiveInfo['XCInfoPlist']['CFBundleIconFiles'].collect { |f| appPath + '/' + f }
},
'ArchiveVersion' => 1,
'CreationDate' => archiveDate,
'Name' => name,
'SchemeName' => archiveInfo['XCApplicationName']
}
if archiveInfo.has_key?('XCUserProvidedComment')
xcarchiveInfo['Comment'] = archiveInfo['XCUserProvidedComment']
end
xcarchiveInfo.writeToURL(NSURL.fileURLWithPath(xcarchivePath + '/Info.plist'), atomically:false)
FileUtils.mkdir_p(xcarchivePath + '/Products/Applications')
FileUtils.cp_r(apparchivePath + '/' + appFilename, xcarchivePath + '/Products/Applications')
FileUtils.mkdir_p(xcarchivePath + '/dSYMs')
FileUtils.cp_r(apparchivePath + '/' + appFilename + '.dSYM', xcarchivePath + '/dSYMs')
end
}
【讨论】:
我只是手工完成了一个,所以这绝对是可能的,但是对于不止一两个来说很乏味。有一点时间,有人可以写一个脚本来做到这一点。
.xcarchive 包只是目录,就像它们之前的.apparchive 包一样。较新的格式移动了一些东西并简化了顶级Info.plist。
Xcode 3 将档案存储在~/Library/Application Support/Developer/Shared/Archived Applications 中。单个存档包被命名为 GUID。每个内部都是ArchiveInfo.plist、实际的.app 包和.dSYM 包。
Xcode 4 将档案存储在~/Library/Developer/Xcode/Archives 中,分成以档案创建日期命名的文件夹。每个日期文件夹中都有 .xcarchive 包,使用可读名称而不是 GUID。其中是Info.plist,.app 所在的Products 文件夹,以及用于保存.dSYM 包的dSYMs 文件夹。
将.apparchive 复制到.xcarchive 的快捷方式:
.apparchive 的内容复制到新文件夹中以.xcarchive 结尾的新文件夹中。cd 进入新的 .xcarchive 文件夹。从现在开始,一切都与此相关。Products 和dSYMs 文件夹。.app 捆绑包移动到 Products。.dSYM 捆绑包移动到 dSYMs。ArchiveInfo.plist 文件。Info.plist,并酌情替换。(结束列表以便 StackOverflow 正确格式化 XML...)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ApplicationProperties</key>
<dict>
<key>ApplicationPath</key>
<string>AppBundleName.app</string>
<key>CFBundleIdentifier</key>
<string>com.example.app-id</string>
<key>IconPaths</key>
<array>
<string>AppBundleName.app/Icon.png</string>
<string>AppBundleName.app/Icon-Small.png</string>
</array>
</dict>
<key>ArchiveVersion</key>
<real>1</real>
<key>CreationDate</key>
<date>2010-12-15T15:10:34Z</date> <!-- this is a GMT time stamp -->
<key>Name</key>
<string>AppName</string>
<key>SchemeName</key>
<string>AppName</string>
</dict>
</plist>
【讨论】: