开发者

Can we import .apparchive bundles in Xcode 4

In Xcode 3, applications were archived in .apparchive folders.

In Xcode 4, applications are now archived in an .xcarchive bundle.

Is there a way开发者_高级运维 to convert .apparchive folders in .xcarchive bundles or to open .apparchive folders with Xcode 4?


Dave Dunkin's script worked great, but I missed the icon and version in some cases. Below a slightly adjusted version of the script. You need to install MacRuby, available here: http://www.macruby.org/downloads.html.

#!/System/Library/PrivateFrameworks/MacRuby.framework/Versions/A/usr/bin/macrub‌​y

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
}


Here's a MacRuby script I wrote to do this for me.

#!/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
}


I just did one by hand, so it's definitely possible, but tedious for more than one or two. With a bit of time, someone could write a script to do this.

.xcarchive bundles are just directories, like .apparchive bundles before them. The newer format moved some things around and simplified the top level Info.plist.

Xcode 3 stores the archives in ~/Library/Application Support/Developer/Shared/Archived Applications. Individual archive bundles are named as a GUID. Inside each is the ArchiveInfo.plist, the actual .app bundle and the .dSYM bundle.

Xcode 4 stores the archives in ~/Library/Developer/Xcode/Archives, separated into folders named after the date the archive is created. Within each date folder is the .xcarchive bundle, using a readable name instead of a GUID. Within that is the Info.plist, a Products folder where the .app lives, and a dSYMs folder to hold the .dSYM bundles.

A quick-and-dirty way to copy a .apparchive to a .xcarchive:

  1. Create a new folder with the date when the archive was created.
  2. Copy the contents of the .apparchive into a new folder ending with .xcarchive inside that new folder.
  3. cd into that new .xcarchive folder. Everything is relative to that from this point forward.
  4. Create Products and dSYMs folders.
  5. Move your .app bundle into Products.
  6. Move your .dSYM bundle into dSYMs.
  7. Remove the old ArchiveInfo.plist file.
  8. Create a new Info.plist that looks like this, substituting as appropriate.

(ending the list so StackOverflow formats the XML properly...)

<?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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜