Commit 23626caa authored by Eloy Duran's avatar Eloy Duran

Merge branch 'multiple-platforms'. Closes #63 and #79.

parents 08aa7961 dcbf5e2f
......@@ -3,6 +3,7 @@
*.rbo
*.gem
.DS_Store
.rbenv-version
xcuserdata
project.xcworkspace
DerivedData
......
......@@ -13,3 +13,6 @@
[submodule "spec/fixtures/spec-repos/master"]
path = spec/fixtures/spec-repos/master
url = https://github.com/CocoaPods/Specs.git
[submodule "spec/fixtures/integration/Reachability"]
path = spec/fixtures/integration/Reachability
url = https://github.com/tonymillion/Reachability.git
......@@ -4,12 +4,12 @@ Kicker::Recipes::Ruby.runner_bin = 'bacon'
process do |files|
specs = files.take_and_map do |file|
case file
when %r{lib/cocoapods/installer.+\.rb$}
['spec/unit/installer_spec.rb', 'spec/unit/target_installer_spec.rb']
when %r{lib/cocoapods/(.+?)\.rb$}
s = Dir.glob("spec/**/#{$1}_spec.rb")
s unless s.empty?
if file =~ %r{lib/cocoapods/(.+?)\.rb$}
s = Dir.glob("spec/**/#{File.basename(file, '.rb')}_spec.rb")
if file =~ %r{lib/cocoapods/installer.*\.rb$}
s.concat(['spec/unit/installer_spec.rb', 'spec/unit/installer/target_installer_spec.rb'])
end
s.uniq unless s.empty?
end
end
Kicker::Recipes::Ruby.run_tests(specs)
......
......@@ -13,10 +13,13 @@ with, use the `link_with` method like so:
```ruby
platform :ios
workspace 'MyWorkspace'
link_with ['MyAppTarget', 'MyOtherAppTarget']
dependency 'JSONKit'
target :test, :exclusive => true do
xcodeproj 'TestProject'
link_with 'TestRunnerTarget'
dependency 'Kiwi'
end
......@@ -24,16 +27,16 @@ end
_NOTE: As you can see it can take either one target name, or an array of names._
Alternatively, you can also specify the target to link with in the target
options like so:
* If no explicit Xcode workspace is specified and only **one** project exists in
the same directory as the Podfile, then the name of that project is used as the
workspace’s name.
```ruby
target :test, :exclusive => true, :link_with => 'TestRunnerTarget' do
dependency 'Kiwi'
end
```
* If no explicit Xcode project is specified for a target, it will use the Xcode
project of the parent target. If no target specifies an expicit Xcode project
and there is only **one** project in the same directory as the Podfile then that
project will be used.
If no explicit target is specified, then the Pods target will be linked with
* If no explicit target is specified, then the Pods target will be linked with
the first target in your project. So if you only have one target you do not
need to specify the target to link with.
......
GIT
remote: git://github.com/CocoaPods/Xcodeproj.git
revision: 338e4d37f282121754f10f6d169256a57a64860d
revision: 2817d17a0ea88dba76e898a1c71cbac615d76fc2
specs:
xcodeproj (0.1.0)
......@@ -15,15 +15,15 @@ GEM
kicker (2.5.0)
rb-fsevent
metaclass (0.0.1)
mocha (0.10.4)
mocha (0.10.5)
metaclass (~> 0.0.1)
mocha-on-bacon (0.2.0)
mocha (>= 0.9.8)
open4 (1.3.0)
rake (0.9.2.2)
rb-fsevent (0.9.0)
vcr (2.0.0)
webmock (1.8.0)
rb-fsevent (0.9.1)
vcr (2.0.1)
webmock (1.8.6)
addressable (>= 2.2.7)
crack (>= 0.1.7)
......
......@@ -143,6 +143,13 @@ namespace :spec do
end
end
end
desc "Removes the stored VCR fixture"
task :clean_vcr do
sh "rm -f spec/fixtures/vcr/tarballs.yml"
end
task :clean_env => [:clean_vcr, :unpack_fixture_tarballs, "ext:cleanbuild"]
end
namespace :examples do
......@@ -194,6 +201,16 @@ namespace :examples do
end
end
desc "Initializes your working copy to run the specs"
task :bootstrap do
puts "Updating submodules..."
`git submodule update --init --recursive`
puts "Installing gems"
`bundle install`
`cd external/XcodeProj && bundle install`
end
desc "Run all specs"
task :spec => 'spec:all'
......
* The user *has* to specify the platform of the project in the Podfile.
* No need to pass the project path and podfile separately to UserProjectIntegrator.
* Move Platform#xcodeproj to TargetDefinition#link_with.
* Add multiple-platforms section to changelog.
* Validate platforms for each target definition.
* Validate that there are dependencies in a Podfile.
* Validate that the dependencies in the targets don't conflict. E.g. two different versions of the same pod.
* Move Podfile.lock generator from Installer into its own file.
* Remove better_installer.rb file
* One or more of the specs are changing the remote URL of the master repo in ~/.cocoapods
......@@ -2,7 +2,7 @@ PODS:
- AFNetworking (0.7.0):
- JSONKit
- FormatterKit (0.7.0)
- JSONKit (1.5pre)
- JSONKit (1.4)
DEPENDENCIES:
- AFNetworking (~> 0.7.0)
......
......@@ -2,7 +2,7 @@ PODS:
- AFNetworking (0.7.0):
- JSONKit
- FormatterKit (0.7.0)
- JSONKit (1.5pre)
- JSONKit (1.4)
DEPENDENCIES:
- AFNetworking (~> 0.7.0)
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DCFB448E136F7202004B3EE0"
BuildableName = "EmbedReader.app"
BlueprintName = "EmbedReader"
ReferencedContainer = "container:EmbedReader.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
displayScaleIsEnabled = "NO"
displayScale = "1.00"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DCFB448E136F7202004B3EE0"
BuildableName = "EmbedReader.app"
BlueprintName = "EmbedReader"
ReferencedContainer = "container:EmbedReader.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
displayScaleIsEnabled = "NO"
displayScale = "1.00"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DCFB448E136F7202004B3EE0"
BuildableName = "EmbedReader.app"
BlueprintName = "EmbedReader"
ReferencedContainer = "container:EmbedReader.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Workspace version="1.0"><FileRef location="group:EmbedReader.xcodeproj"></FileRef><FileRef location="group:Pods/Pods.xcodeproj"></FileRef></Workspace>
\ No newline at end of file
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iPhone SDK 3.0 and later."
#endif
#ifdef __OBJC__
# import <UIKit/UIKit.h>
# import <Foundation/Foundation.h>
# import "ZBarSDK.h"
#endif
//
// EmbedReaderAppDelegate.h
// EmbedReader
//
// Created by spadix on 5/2/11.
//
#import <UIKit/UIKit.h>
@class EmbedReaderViewController;
@interface EmbedReaderAppDelegate
: NSObject
< UIApplicationDelegate >
{
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet EmbedReaderViewController *viewController;
@end
//
// EmbedReaderAppDelegate.m
// EmbedReader
//
// Created by spadix on 5/2/11.
//
#import "EmbedReaderAppDelegate.h"
#import "EmbedReaderViewController.h"
@implementation EmbedReaderAppDelegate
@synthesize window=_window;
@synthesize viewController=_viewController;
- (BOOL) application: (UIApplication*) application
didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
{
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
// force view class to load so it may be referenced directly from NIB
[ZBarReaderView class];
return(YES);
}
- (void) dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
@end
//
// EmbedReaderViewController.h
// EmbedReader
//
// Created by spadix on 5/2/11.
//
#import <UIKit/UIKit.h>
@interface EmbedReaderViewController
: UIViewController
< ZBarReaderViewDelegate >
{
ZBarReaderView *readerView;
UITextView *resultText;
ZBarCameraSimulator *cameraSim;
}
@property (nonatomic, retain) IBOutlet ZBarReaderView *readerView;
@property (nonatomic, retain) IBOutlet UITextView *resultText;
@end
//
// EmbedReaderViewController.m
// EmbedReader
//
// Created by spadix on 5/2/11.
//
#import "EmbedReaderViewController.h"
@implementation EmbedReaderViewController
@synthesize readerView, resultText;
- (void) cleanup
{
[cameraSim release];
cameraSim = nil;
readerView.readerDelegate = nil;
[readerView release];
readerView = nil;
[resultText release];
resultText = nil;
}
- (void) dealloc
{
[self cleanup];
[super dealloc];
}
- (void) viewDidLoad
{
[super viewDidLoad];
// the delegate receives decode results
readerView.readerDelegate = self;
// you can use this to support the simulator
if(TARGET_IPHONE_SIMULATOR) {
cameraSim = [[ZBarCameraSimulator alloc]
initWithViewController: self];
cameraSim.readerView = readerView;
}
}
- (void) viewDidUnload
{
[self cleanup];
[super viewDidUnload];
}
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) orient
{
// auto-rotation is supported
return(YES);
}
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) orient
duration: (NSTimeInterval) duration
{
// compensate for view rotation so camera preview is not rotated
[readerView willRotateToInterfaceOrientation: orient
duration: duration];
}
- (void) viewDidAppear: (BOOL) animated
{
// run the reader when the view is visible
[readerView start];
}
- (void) viewWillDisappear: (BOOL) animated
{
[readerView stop];
}
- (void) readerView: (ZBarReaderView*) view
didReadSymbols: (ZBarSymbolSet*) syms
fromImage: (UIImage*) img
{
// do something useful with results
for(ZBarSymbol *sym in syms) {
resultText.text = sym.data;
break;
}
}
@end
//
// main.m
// EmbedReader
//
// Created by spadix on 5/2/11.
//
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
platform :ios
dependency 'ZBarSDK'
PODS:
- ASIHTTPRequest (1.8.1)
- ASIHTTPRequest (1.8.1)
- CocoaLumberjack (1.3.2)
- SBJson (3.0.4)
- SBJson (3.0.4)
DEPENDENCIES:
- ASIHTTPRequest
......
platform :ios
xcodeproj "RelativePathProject/RelativePathProject.xcodeproj"
dependency "AFNetworking"
PODS:
- ZBarSDK (1.2.2)
- AFNetworking (0.9.0)
DEPENDENCIES:
- ZBarSDK
- AFNetworking
<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:RelativePathProject.xcodeproj'/><FileRef location='group:../Pods/Pods.xcodeproj'/></Workspace>
\ No newline at end of file
//
// CCPAppDelegate.h
// RelativePathProject
//
// Created by Ben Scheirman on 3/8/12.
// Copyright (c) 2012 ChaiONE. All rights reserved.
//
#import <UIKit/UIKit.h>
@class CCPViewController;
@interface CCPAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) CCPViewController *viewController;
@end
//
// CCPAppDelegate.m
// RelativePathProject
//
// Created by Ben Scheirman on 3/8/12.
// Copyright (c) 2012 ChaiONE. All rights reserved.
//
#import "CCPAppDelegate.h"
#import "CCPViewController.h"
@implementation CCPAppDelegate
@synthesize window = _window;
@synthesize viewController = _viewController;
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[[CCPViewController alloc] initWithNibName:@"CCPViewController_iPhone" bundle:nil] autorelease];
} else {
self.viewController = [[[CCPViewController alloc] initWithNibName:@"CCPViewController_iPad" bundle:nil] autorelease];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
//
// CCPViewController.h
// RelativePathProject
//
// Created by Ben Scheirman on 3/8/12.
// Copyright (c) 2012 ChaiONE. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface CCPViewController : UIViewController
@end
//
// CCPViewController.m
// RelativePathProject
//
// Created by Ben Scheirman on 3/8/12.
// Copyright (c) 2012 ChaiONE. All rights reserved.
//
#import "CCPViewController.h"
@interface CCPViewController ()
@end
@implementation CCPViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
@end
......@@ -8,10 +8,8 @@
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>net.sourceforge.zbar.${PRODUCT_NAME:rfc1034identifier}</string>
<string>com.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
......@@ -26,13 +24,22 @@
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMainNibFile</key>
<string>MainWindow</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
//
// Prefix header for all source files of the 'RelativePathProject' target in the 'RelativePathProject' project
//
#import <Availability.h>
#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1280</int>
<string key="IBDocument.SystemVersion">11C25</string>
<string key="IBDocument.InterfaceBuilderVersion">1919</string>
<string key="IBDocument.AppKitVersion">1138.11</string>
<string key="IBDocument.HIToolboxVersion">566.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">916</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUIView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="841351856">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
</object>
<object class="IBProxyObject" id="606714003">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
</object>
<object class="IBUIView" id="766721923">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<string key="NSFrame">{{0, 20}, {768, 1004}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace">
<int key="NSID">2</int>
</object>
</object>
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
<int key="IBUIStatusBarStyle">2</int>
</object>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="766721923"/>
</object>
<int key="connectionID">3</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="841351856"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="606714003"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="766721923"/>
<reference key="parent" ref="0"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">CCPViewController</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">3</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">CCPViewController</string>
<string key="superclassName">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/CCPViewController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">916</string>
</data>
</archive>
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1280</int>
<string key="IBDocument.SystemVersion">11C25</string>
<string key="IBDocument.InterfaceBuilderVersion">1919</string>
<string key="IBDocument.AppKitVersion">1138.11</string>
<string key="IBDocument.HIToolboxVersion">566.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">916</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUIView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="843779117">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="774585933">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC43NQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace">
<int key="NSID">2</int>
</object>
</object>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="774585933"/>
</object>
<int key="connectionID">7</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="372490531"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="843779117"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="774585933"/>
<reference key="parent" ref="0"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">CCPViewController</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">7</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">CCPViewController</string>
<string key="superclassName">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/CCPViewController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">916</string>
</data>
</archive>
//
// main.m
// RelativePathProject
//
// Created by Ben Scheirman on 3/8/12.
// Copyright (c) 2012 ChaiONE. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "CCPAppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([CCPAppDelegate class]));
}
}
......@@ -17,6 +17,7 @@ module Pod
autoload :Podfile, 'cocoapods/podfile'
autoload :Project, 'cocoapods/project'
autoload :Resolver, 'cocoapods/resolver'
autoload :PodPathResolver, 'cocoapods/pod_path_resolver'
autoload :Sandbox, 'cocoapods/sandbox'
autoload :Source, 'cocoapods/source'
autoload :Spec, 'cocoapods/specification'
......
......@@ -23,9 +23,18 @@ module Pod
'Options',
'-------',
'',
@command_class.options
options
].join("\n")
end
private
def options
options = @command_class.options
keys = options.map(&:first)
key_size = keys.inject(0) { |size, key| key.size > size ? key.size : size }
options.map { |key, desc| " #{key.ljust(key_size)} #{desc}" }.join("\n")
end
end
class ARGV < Array
......@@ -47,10 +56,12 @@ module Pod
end
def self.options
" --help Show help information\n" \
" --silent Print nothing\n" \
" --verbose Print more information while working\n" \
" --version Prints the version of CocoaPods"
[
['--help', 'Show help information'],
['--silent', 'Print nothing'],
['--verbose', 'Print more information while working'],
['--version', 'Prints the version of CocoaPods'],
]
end
def self.run(*argv)
......
......@@ -4,48 +4,55 @@ module Pod
def self.banner
%{Installing dependencies of a project:
$ pod install [PROJECT]
$ pod install
Downloads all dependencies defined in `Podfile' and creates an Xcode
Pods library project in `./Pods'.
In case `PROJECT' is given, it configures it to use the specified Pods
and generates a workspace with the Pods project and `PROJECT'. (It is
important that once you have run this you open the workspace instead of
`PROJECT'.) You usually specify `PROJECT' only the first time that you
run `pod install'.
The Xcode project file should be specified in your `Podfile` like this:
xcodeproj 'path/to/XcodeProject'
If no xcodeproj is specified, then a search for an Xcode project will
be made. If more than one Xcode project is found, the command will
raise an error.
This will configure the project to reference the Pods static library,
add a build configuration file, and add a post build script to copy
Pod resources.
}
end
def self.options
" --no-clean Leave SCM dirs like `.git' and `.svn' intact after downloading\n" +
" --no-doc Skip documentation generation with appledoc\n" +
" --force-doc Force the generation of documentation\n" +
" --no-update Skip running `pod repo update` before install\n" +
super
[
["--no-clean", "Leave SCM dirs like `.git' and `.svn' in tact after downloading"],
["--no-doc", "Skip documentation generation with appledoc"],
["--force-doc", "Force the generation of documentation"],
["--no-integrate", "Skip integration of the Pods libraries in the Xcode project(s)"],
["--no-update", "Skip running `pod repo update` before install"],
].concat(super)
end
def initialize(argv)
config.clean = !argv.option('--no-clean')
config.doc = !argv.option('--no-doc')
config.force_doc = argv.option('--force-doc')
@update_repo = !argv.option('--no-update')
@projpath = argv.shift_argument
config.clean = !argv.option('--no-clean')
config.doc = !argv.option('--no-doc')
config.force_doc = argv.option('--force-doc')
config.integrate_targets = !argv.option('--no-integrate')
@update_repo = !argv.option('--no-update')
super unless argv.empty?
end
def run
unless podfile = config.rootspec
unless podfile = config.podfile
raise Informative, "No `Podfile' found in the current working directory."
end
if @projpath && !File.exist?(@projpath)
raise Informative, "The specified project `#{@projpath}' does not exist."
end
if @update_repo
puts "\nUpdating Spec Repositories\n".yellow if config.verbose?
Repo.new(ARGV.new(["update"])).run
end
Installer.new(podfile, @projpath).install!
Installer.new(podfile).install!
end
end
end
......
......@@ -14,8 +14,7 @@ module Pod
end
def self.options
" --update runs `pod repo update` before list\n" +
Presenter.options + super
[["--update", "Run `pod repo update` before listing"]].concat(Presenter.options).concat(super)
end
extend Executable
......
......@@ -12,8 +12,7 @@ module Pod
end
def self.options
" --full Search by name, summary, and description\n" +
Presenter.options + super
[["--full", "Search by name, summary, and description"]].concat(Presenter.options).concat(super)
end
def initialize(argv)
......
require 'net/http'
module Pod
class Command
module SetPresent
def self.options
[
["--name-only", "Show only the names of the pods"],
["--stats", "Show additional stats (like GitHub watchers and forks)"],
]
end
def list
@list
end
def parse_set_options(argv)
@stats = argv.option('--stats')
@list = argv.option('--name-only')
end
def present_sets(array)
array.each do |set|
present_set(set)
end
end
def present_set(set)
if @list
puts set.name
else
puts "--> #{set.name} (#{set.versions.reverse.join(", ")})".green
puts_wrapped_text(set.specification.summary)
spec = set.specification.part_of_other_pod? ? set.specification.part_of_specification : set.specification
source = spec.source.reject {|k,_| k == :commit || k == :tag }.values.first
puts_detail('Homepage', spec.homepage)
puts_detail('Source', source)
if @stats
stats = stats(source)
puts_detail('Watchers', stats[:watchers])
puts_detail('Forks', stats[:forks])
end
puts
end
end
# adapted from http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
def puts_wrapped_text(txt, col = 80, indentation = 4)
indent = ' ' * indentation
puts txt.strip.gsub(/(.{1,#{col}})( +|$)\n?|(.{#{col}})/, indent + "\\1\\3\n")
end
def puts_detail(title,string)
return if !string
# 8 is the length of homepage
number_of_spaces = ((8 - title.length) > 0) ? (8 - title.length) : 0
spaces = ' ' * number_of_spaces
puts " - #{title}: #{spaces + string}"
end
def stats(url)
original_url, username, reponame = *(url.match(/[:\/]([\w\-]+)\/([\w\-]+)\.git/).to_a)
result = {}
if original_url
gh_response = Net::HTTP.get('github.com', "/api/v2/json/repos/show/#{username}/#{reponame}")
result[:watchers] = gh_response.match(/\"watchers\"\W*:\W*([0-9]+)/).to_a[1]
result[:forks] = gh_response.match(/\"forks\"\W*:\W*([0-9]+)/).to_a[1]
end
result
end
end
end
end
......@@ -15,8 +15,7 @@ module Pod
end
def self.options
" --push Use this option to enable push access once granted\n" +
super
[["--push", "Use this option to enable push access once granted"]].concat(super)
end
extend Executable
......
......@@ -10,22 +10,19 @@ module Pod
@instance = instance
end
attr_accessor :repos_dir, :project_root, :project_pods_root, :rootspec, :clean, :verbose, :silent, :doc, :doc_install, :force_doc
alias_method :clean?, :clean
alias_method :verbose?, :verbose
alias_method :silent?, :silent
alias_method :doc?, :doc
alias_method :doc_install?, :doc_install
alias_method :force_doc?, :force_doc
attr_accessor :repos_dir, :project_root, :project_pods_root, :clean, :verbose, :silent, :doc, :doc_install, :force_doc, :integrate_targets
alias_method :clean?, :clean
alias_method :verbose?, :verbose
alias_method :silent?, :silent
alias_method :doc?, :doc # TODO rename to generate_docs?
alias_method :doc_install?, :doc_install
alias_method :force_doc?, :force_doc
alias_method :integrate_targets?, :integrate_targets
def initialize
@repos_dir = Pathname.new(File.expand_path("~/.cocoapods"))
@clean = true
@verbose = false
@silent = false
@doc = true
@doc_install = true
@force_doc = false
@verbose = @silent = @force_doc = false
@clean = @doc = @doc_install = @integrate_targets = true
end
def project_root
......@@ -37,14 +34,7 @@ module Pod
end
def project_podfile
unless @project_podfile
@project_podfile = project_root + 'Podfile'
# TODO this has to go, we don't support this anymore!
unless @project_podfile.exist?
@project_podfile = project_root.glob('*.podspec').first
end
end
@project_podfile
@project_podfile ||= project_root + 'Podfile'
end
def headers_symlink_root
......@@ -52,25 +42,24 @@ module Pod
end
# Returns the spec at the pat returned from `project_podfile`.
def rootspec
unless @rootspec
if project_podfile
if project_podfile.basename.to_s == 'Podfile'
@rootspec = Podfile.from_file(project_podfile)
else
@rootspec = Specification.from_file(project_podfile)
end
end
def podfile
@podfile ||= begin
Podfile.from_file(project_podfile) if project_podfile.exist?
end
@rootspec
end
def ios?
rootspec.platform == :ios if rootspec
require 'colored'
caller.find { |line| line =~ /^(.+.podspec):\d*/ }
puts "[!] The use of `config.ios?` is deprecated and will be removed in version 0.7.#{" Called from: #{$1}" if $1}".red
podfile.target_definitions[:default].platform == :ios if podfile
end
def osx?
rootspec.platform == :osx if rootspec
require 'colored'
caller.find { |line| line =~ /^(.+.podspec):\d*/ }
puts "[!] The use of `config.ios?` is deprecated and will be removed in version 0.7.#{" Called from: #{$1}" if $1}".red
podfile.target_definitions[:default].platform == :osx if podfile
end
module Mixin
......
......@@ -76,8 +76,8 @@ module Pod
version.empty? ? @name : "#{@name} (#{version})"
end
def specification_from_sandbox(sandbox)
@external_source.specification_from_sandbox(sandbox)
def specification_from_sandbox(sandbox, platform)
@external_source.specification_from_sandbox(sandbox, platform)
end
# Taken from RubyGems 1.3.7
......@@ -128,36 +128,37 @@ module Pod
end
class AbstractExternalSource
include Config::Mixin
attr_reader :name, :params
def initialize(name, params)
@name, @params = name, params
end
def specification_from_sandbox(sandbox)
if local_pod = sandbox.installed_pod_named(name)
def specification_from_sandbox(sandbox, platform)
if local_pod = sandbox.installed_pod_named(name, platform)
local_pod.specification
else
copy_external_source_into_sandbox(sandbox)
local_pod = sandbox.installed_pod_named(name)
local_pod.clean if Config.instance.clean
local_pod = sandbox.installed_pod_named(name, platform)
local_pod.clean if config.clean?
local_pod.specification
end
end
def ==(other_source)
return if other_source.nil?
name == other_source.name &&
params == other_source.params
name == other_source.name && params == other_source.params
end
end
class GitSource < AbstractExternalSource
def copy_external_source_into_sandbox(sandbox)
puts " * Pre-downloading: '#{name}'" unless Config.instance.silent?
puts " * Pre-downloading: '#{name}'" unless config.silent?
Downloader.for_target(sandbox.root + name, @params).tap do |downloader|
downloader.download
downloader.clean if Config.instance.clean
downloader.clean if config.clean?
end
end
......@@ -174,7 +175,7 @@ module Pod
def copy_external_source_into_sandbox(sandbox)
output_path = sandbox.root + "Local Podspecs/#{name}.podspec"
output_path.dirname.mkpath
puts " * Fetching podspec for `#{name}' from: #{@params[:podspec]}" unless Config.instance.silent?
puts " * Fetching podspec for `#{name}' from: #{@params[:podspec]}" unless config.silent?
open(@params[:podspec]) do |io|
output_path.open('w') { |f| f << io.read }
end
......
......@@ -8,12 +8,12 @@ install_resource()
{
case $1 in
*\.xib)
echo "ibtool --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .xib`.nib ${SRCROOT}/Pods/$1 --sdk ${SDKROOT}"
ibtool --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .xib`.nib" "${SRCROOT}/Pods/$1" --sdk "${SDKROOT}"
echo "ibtool --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*)
echo "cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
cp -R "${SRCROOT}/Pods/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
echo "cp -R ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
cp -R "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
;;
esac
}
......
require 'colored'
module Pod
class Installer
autoload :TargetInstaller, 'cocoapods/installer/target_installer'
......@@ -5,10 +7,10 @@ module Pod
include Config::Mixin
attr_reader :sandbox
attr_reader :sandbox
def initialize(podfile, user_project_path = nil)
@podfile, @user_project_path = podfile, user_project_path
def initialize(podfile)
@podfile = podfile
# FIXME: pass this into the installer as a parameter
@sandbox = Sandbox.new(config.project_pods_root)
@resolver = Resolver.new(@podfile, @sandbox)
......@@ -20,14 +22,11 @@ module Pod
def project
return @project if @project
@project = Pod::Project.for_platform(@podfile.platform)
# First we need to resolve dependencies across *all* targets, so that the
# same correct versions of pods are being used for all targets. This
# happens when we call `activated_specifications'.
activated_specifications.each do |spec|
@project = Pod::Project.new
activated_pods.each do |pod|
# Add all source files to the project grouped by pod
group = @project.add_pod_group(spec.name)
spec.expanded_source_files.each do |path|
group = @project.add_pod_group(pod.name)
pod.source_files.each do |path|
group.files.new('path' => path.to_s)
end
end
......@@ -43,30 +42,26 @@ module Pod
end
def install_dependencies!
activated_specifications.map do |spec|
LocalPod.new(spec, sandbox).tap do |pod|
marker = config.verbose ? "\n-> ".green : ''
should_install = !pod.exists? && !spec.local?
activated_pods.each do |pod|
marker = config.verbose ? "\n-> ".green : ''
unless should_install
puts marker + "Using #{pod}" unless config.silent?
else
puts marker + "Installing #{spec}".green unless config.silent?
unless should_install = !pod.exists? && !pod.specification.local?
puts marker + "Using #{pod}" unless config.silent?
else
puts marker + "Installing #{pod.specification}".green unless config.silent?
downloader = Downloader.for_pod(pod)
downloader.download
downloader = Downloader.for_pod(pod)
downloader.download
if config.clean
downloader.clean
pod.clean
end
if config.clean
downloader.clean
pod.clean
end
end
if (should_install && config.doc?) || config.force_doc?
puts "Installing Documentation for #{spec}".green if config.verbose?
Generator::Documentation.new(pod).generate(config.doc_install?)
end
if (should_install && config.doc?) || config.force_doc?
puts "Installing Documentation for #{pod.specification}".green if config.verbose?
Generator::Documentation.new(pod).generate(config.doc_install?)
end
end
end
......@@ -74,17 +69,17 @@ module Pod
def install!
@sandbox.prepare_for_install
puts_title "Resolving dependencies of: #{@podfile.defined_in_file}"
print_title "Resolving dependencies of: #{@podfile.defined_in_file}"
specs_by_target
puts_title "Installing dependencies"
pods = install_dependencies!
print_title "Installing dependencies"
install_dependencies!
puts_title("Generating support files\n", false)
pods = activated_pods
print_title("Generating support files\n", false)
target_installers.each do |target_installer|
target_specs = activated_specifications_for_target(target_installer.target_definition)
pods_for_target = pods.select { |pod| target_specs.include?(pod.specification) }
target_installer.install!(pods_for_target, sandbox)
pods_for_target = activated_pods_by_target[target_installer.target_definition]
target_installer.install!(pods_for_target, @sandbox)
end
generate_lock_file!(pods)
......@@ -96,7 +91,7 @@ module Pod
puts "* Writing Xcode project file to `#{@sandbox.project_path}'\n\n" if config.verbose?
project.save_as(@sandbox.project_path)
UserProjectIntegrator.new(@user_project_path, @podfile).integrate! if @user_project_path
UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets?
end
def run_post_install_hooks
......@@ -114,9 +109,25 @@ module Pod
def generate_lock_file!(pods)
lock_file.open('w') do |file|
file.puts "PODS:"
pods.map do |pod|
[pod.specification.to_s, pod.specification.dependencies.map(&:to_s).sort]
end.sort_by(&:first).each do |name, deps|
# Get list of [name, dependencies] pairs.
activated_pods = pods.map do |pod|
[pod.specification.to_s, pod.dependencies.map(&:to_s).sort]
end.uniq
# Merge dependencies of ios and osx version of the same pod.
tmp = {}
activated_pods.each do |name, deps|
if tmp[name]
tmp[name].concat(deps).uniq!
else
tmp[name] = deps
end
end
activated_pods = tmp
# Sort by name and print
activated_pods.sort_by(&:first).each do |name, deps|
if deps.empty?
file.puts " - #{name}"
else
......@@ -145,20 +156,36 @@ module Pod
@specs_by_target ||= @resolver.resolve
end
# @return [Array<Specification>] All dependencies that have been resolved.
def dependency_specifications
specs_by_target.values.flatten
end
def activated_specifications
dependency_specifications.reject do |spec|
# Don't activate specs which are only wrappers of subspecs, or share
# source with another pod but aren't activated themselves.
spec.wrapper? || @resolver.cached_sets[spec.name].only_part_of_other_pod?
# @return [Array<LocalPod>] A list of LocalPod instances for each
# dependency that is not a download-only one.
def activated_pods
activated_pods_by_target.values.flatten
end
def activated_pods_by_target
result = {}
specs_by_target.each do |target_definition, specs|
result[target_definition] = specs.map do |spec|
LocalPod.new(spec, @sandbox, target_definition.platform) if activated_spec?(spec)
end.compact
end
result
end
# @return [Array<Specification>] A list of specifications for each
# dependency that is not a download-only
# one.
def activated_specifications
dependency_specifications.select { |spec| activated_spec?(spec) }
end
def activated_specifications_for_target(target_definition)
specs_by_target[target_definition]
specs_by_target[target_definition].select { |spec| activated_spec?(spec) }
end
def download_only_specifications
......@@ -167,10 +194,16 @@ module Pod
private
def puts_title(title, only_verbose = true)
if(config.verbose?)
puts "\n" + title.yellow
elsif(!config.silent? && !only_verbose)
def activated_spec?(spec)
# Don't activate specs which are only wrappers of subspecs, or share
# source with another pod but aren't activated themselves.
!spec.wrapper? && !@resolver.cached_sets[spec.name].only_part_of_other_pod?
end
def print_title(title, only_verbose = true)
if config.verbose?
puts "\n" + title.yellow
elsif !config.silent? && !only_verbose
puts title
end
end
......
......@@ -13,7 +13,7 @@ module Pod
def xcconfig
@xcconfig ||= Xcodeproj::Config.new({
# In a workspace this is where the static library headers should be found.
'PODS_ROOT' => '$(SRCROOT)/Pods',
'PODS_ROOT' => Pod::PodPathResolver.new(@target_definition).pods_root,
'ALWAYS_SEARCH_USER_PATHS' => 'YES', # needed to make EmbedReader build
'OTHER_LDFLAGS' => default_ld_flags,
})
......@@ -38,7 +38,7 @@ module Pod
def save_prefix_header_as(pathname)
pathname.open('w') do |header|
header.puts "#ifdef __OBJC__"
header.puts "#import #{@podfile.platform == :ios ? '<UIKit/UIKit.h>' : '<Cocoa/Cocoa.h>'}"
header.puts "#import #{@target_definition.platform == :ios ? '<UIKit/UIKit.h>' : '<Cocoa/Cocoa.h>'}"
header.puts "#endif"
end
end
......@@ -50,12 +50,12 @@ module Pod
# TODO move xcconfig related code into the xcconfig method, like copy_resources_script and generate_bridge_support.
def install!(pods, sandbox)
self.requires_arc = pods.any? { |pod| pod.requires_arc? }
# First add the target to the project
@target = @project.targets.new_static_library(@target_definition.label)
@target = @project.add_pod_target(@target_definition.label, @target_definition.platform)
pods.each do |pod|
xcconfig.merge!(pod.specification.xcconfig)
# TODO add methods like xcconfig to LocalPod as well? (which returns the correct platform)
xcconfig.merge!(pod.specification.xcconfig[@target_definition.platform.name])
pod.add_to_target(@target)
# TODO: this doesn't need to be done here, it has nothing to do with the target
......
......@@ -7,12 +7,8 @@ module Pod
class UserProjectIntegrator
include Pod::Config::Mixin
attr_reader :user_project_path, :user_project
def initialize(user_project_path, podfile)
@user_project_path = config.project_root + user_project_path
def initialize(podfile)
@podfile = podfile
@user_project = Xcodeproj::Project.new(user_project_path)
end
def integrate!
......@@ -20,9 +16,7 @@ module Pod
# Only need to write out the user's project if any of the target
# integrators actually did some work.
if targets.map(&:integrate!).any?
@user_project.save_as(user_project_path)
end
target_integrators.map(&:integrate!)
unless config.silent?
# TODO this really shouldn't be here
......@@ -31,39 +25,67 @@ module Pod
end
def workspace_path
config.project_root + "#{user_project_path.basename('.xcodeproj')}.xcworkspace"
@podfile.workspace || raise(Informative, "Could not automatically select an Xcode workspace. " \
"Specify one in your Podfile.")
end
def pods_project_path
config.project_root + "Pods/Pods.xcodeproj"
end
def targets
@podfile.target_definitions.values.map { |definition| Target.new(self, definition) }
def target_integrators
@target_integrators ||= @podfile.target_definitions.values.map do |definition|
TargetIntegrator.new(definition) unless definition.empty?
end.compact
end
def user_projects
@podfile.target_definitions.values.map(&:xcodeproj)
end
def create_workspace!
workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
[user_project_path, pods_project_path].each do |project_path|
[pods_project_path, *user_projects].each do |project_path|
project_path = project_path.relative_path_from(config.project_root).to_s
workspace << project_path unless workspace.include?(project_path)
end
workspace.save_as(workspace_path)
end
class Target
attr_reader :integrator, :target_definition
class TargetIntegrator
attr_reader :target_definition
def initialize(integrator, target_definition)
@integrator, @target_definition = integrator, target_definition
def initialize(target_definition)
@target_definition = target_definition
end
def inspect
"#<#{self.class} for target `#{@target_definition.label}'>"
end
def integrate!
return false if targets.empty?
return if targets.empty?
add_xcconfig_base_configuration
add_pods_library
add_copy_resources_script_phase
true
user_project.save_as(@target_definition.xcodeproj)
end
def user_project_path
if path = @target_definition.xcodeproj
unless path.exist?
raise Informative, "The Xcode project `#{path}' does not exist."
end
path
else
raise Informative, "Could not automatically select an Xcode project.\n" \
"Specify one in your Podfile like so:\n\n" \
" xcodeproj 'path/to/XcodeProject'"
end
end
def user_project
@user_project ||= Xcodeproj::Project.new(user_project_path)
end
# This returns a list of the targets from the user’s project to which
......@@ -77,23 +99,25 @@ module Pod
# the Pods lib should be linked with.
def targets
@targets ||= begin
if link_with = @target_definition.link_with
@integrator.user_project.targets.select do |target|
link_with.include? target.name
end
else
[@integrator.user_project.targets.first]
end.reject do |target|
# reject any target that already has this Pods library in one of its frameworks build phases
target.frameworks_build_phases.any? do |phase|
phase.files.any? { |build_file| build_file.file.name == @target_definition.lib_name }
end
if link_with = @target_definition.link_with
# Find explicitly named targets.
user_project.targets.select do |target|
link_with.include? target.name
end
else
# Default to the first, which in a simple project is probably an app target.
[user_project.targets.first]
end.reject do |target|
# Reject any target that already has this Pods library in one of its frameworks build phases
target.frameworks_build_phases.any? do |phase|
phase.files.any? { |file| file.name == @target_definition.lib_name }
end
end
end
end
def add_xcconfig_base_configuration
xcconfig = @integrator.user_project.files.new('path' => "Pods/#{@target_definition.xcconfig_name}") # TODO use Sandbox?
xcconfig = user_project.files.new('path' => "Pods/#{@target_definition.xcconfig_name}") # TODO use Sandbox?
targets.each do |target|
target.build_configurations.each do |config|
config.base_configuration = xcconfig
......@@ -102,11 +126,9 @@ module Pod
end
def add_pods_library
pods_library = @integrator.user_project.group("Frameworks").files.new_static_library(@target_definition.label)
pods_library = user_project.group("Frameworks").files.new_static_library(@target_definition.label)
targets.each do |target|
target.frameworks_build_phases.each do |build_phase|
build_phase.files << pods_library.build_files.new
end
target.frameworks_build_phases.each { |build_phase| build_phase << pods_library }
end
end
......
......@@ -2,13 +2,14 @@ module Pod
class LocalPod
attr_reader :specification
attr_reader :sandbox
attr_reader :platform
def initialize(specification, sandbox)
@specification, @sandbox = specification, sandbox
def initialize(specification, sandbox, platform)
@specification, @sandbox, @platform = specification, sandbox, platform
end
def self.from_podspec(podspec, sandbox)
new(Specification.from_file(podspec), sandbox)
def self.from_podspec(podspec, sandbox, platform)
new(Specification.from_file(podspec), sandbox, platform)
end
def root
......@@ -76,13 +77,17 @@ module Pod
def add_to_target(target)
implementation_files.each do |file|
target.add_source_file(file, nil, specification.compiler_flags)
target.add_source_file(file, nil, specification.compiler_flags[@platform.name].strip)
end
end
def requires_arc?
specification.requires_arc
end
def dependencies
specification.dependencies[@platform.name]
end
private
......@@ -93,7 +98,9 @@ module Pod
def relative_root
root.relative_path_from(@sandbox.root)
end
# TODO this is being overriden in the RestKit 0.9.4 spec, need to do
# something with that, and this method also still exists in Specification.
def copy_header_mappings
header_files.inject({}) do |mappings, from|
from_without_prefix = from.relative_path_from(relative_root)
......@@ -103,15 +110,16 @@ module Pod
end
end
def expanded_paths(patterns, options={})
def expanded_paths(platforms_with_patterns, options = {})
patterns = platforms_with_patterns.is_a?(Hash) ? platforms_with_patterns[@platform.name] : platforms_with_patterns
patterns.map do |pattern|
pattern = root + pattern
if pattern.directory? && options[:glob]
pattern += options[:glob]
end
pattern.glob.map do |file|
pattern.glob.map do |file|
if options[:relative_to_sandbox]
file.relative_path_from(@sandbox.root)
else
......
module Pod
class Platform
def self.ios
new :ios
end
def self.osx
new :osx
end
attr_reader :options
def initialize(symbolic_name, options = {})
......
module Pod
class PodPathResolver
include Config::Mixin
def initialize(target_definition)
@target_definition = target_definition
end
def relative_path_for_pods
pods_path = config.project_pods_root
xcode_proj_path = @target_definition.xcodeproj || ''
source_root = (config.project_root + xcode_proj_path).parent
pods_path.relative_path_from(source_root)
end
def pods_root
"$(SRCROOT)/#{relative_path_for_pods}"
end
end
end
module Pod
class Podfile
class TargetDefinition
include Config::Mixin
attr_reader :name, :target_dependencies
attr_accessor :link_with, :parent
attr_accessor :xcodeproj, :link_with, :platform, :parent, :exclusive
def initialize(name, options = {})
@name, @target_dependencies = name, []
options.each { |k, v| send("#{k}=", v) }
@parent, @exclusive = options.values_at(:parent, :exclusive)
end
# A target is automatically `exclusive` if the `platform` does not match
# the parent's `platform`.
def exclusive
if @exclusive.nil?
if @platform.nil?
false
else
@parent.platform != @platform
end
else
@exclusive
end
end
alias_method :exclusive?, :exclusive
def xcodeproj=(path)
path = path.to_s
@xcodeproj = config.project_root + (File.extname(path) == '.xcodeproj' ? path : "#{path}.xcodeproj")
end
def xcodeproj
if @xcodeproj
@xcodeproj
elsif @parent
@parent.xcodeproj
else
xcodeprojs = config.project_root.glob('*.xcodeproj')
@xcodeproj = xcodeprojs.first if xcodeprojs.size == 1
end
end
def link_with=(targets)
@link_with = targets.is_a?(Array) ? targets : [targets]
end
def platform
@platform || @parent.platform
end
def label
if name == :default
"Pods"
......@@ -47,7 +84,7 @@ module Pod
# Returns *all* dependencies of this target, not only the target specific
# ones in `target_dependencies`.
def dependencies
@target_dependencies + (@parent ? @parent.dependencies : [])
@target_dependencies + (exclusive? ? [] : @parent.dependencies)
end
def empty?
......@@ -67,7 +104,7 @@ module Pod
include Config::Mixin
def initialize(&block)
@target_definitions = { :default => (@target_definition = TargetDefinition.new(:default)) }
@target_definitions = { :default => (@target_definition = TargetDefinition.new(:default, :exclusive => true)) }
instance_eval(&block)
end
......@@ -82,25 +119,71 @@ module Pod
# platform :ios, :deployment_target => "4.0"
#
# If the deployment target requires it (< 4.3), armv6 will be added to ARCHS.
def platform(platform = nil, options={})
platform ? @platform = Platform.new(platform, options) : @platform
#
def platform(platform, options={})
@target_definition.platform = Platform.new(platform, options)
end
# Specifies the Xcode workspace that should contain all the projects.
#
# If no explicit Xcode workspace is specified and only **one** project exists
# in the same directory as the Podfile, then the name of that project is used
# as the workspace’s name.
#
# @example
#
# workspace 'MyWorkspace'
#
def workspace(path = nil)
if path
@workspace = config.project_root + (File.extname(path) == '.xcworkspace' ? path : "#{path}.xcworkspace")
elsif @workspace
@workspace
else
projects = @target_definitions.map { |_, td| td.xcodeproj }.uniq
if projects.size == 1 && (xcodeproj = @target_definitions[:default].xcodeproj)
xcodeproj.dirname + "#{xcodeproj.basename('.xcodeproj')}.xcworkspace"
end
end
end
# Specifies the Xcode project that contains the target that the Pods library
# should be linked with.
#
# If no explicit project is specified, it will use the Xcode project of the
# parent target. If none of the target definitions specify an explicit project
# and there is only **one** project in the same directory as the Podfile then
# that project will be used.
#
# @example
#
# # Look for target to link with in an Xcode project called ‘MyProject.xcodeproj’.
# xcodeproj 'MyProject'
#
# target :test do
# # This Pods library links with a target in another project.
# xcodeproj 'TestProject'
# end
#
def xcodeproj(path)
@target_definition.xcodeproj = path
end
# Specifies the target(s) in the user’s project that this Pods library
# should be linked in.
#
# If no explicit target is specified, then the Pods target will be linked
# with the first target in your project. So if you only have one target you
# do not need to specify the target to link with.
#
# @example
#
# # Link with a target in the user’s project called ‘MyApp’.
# # Link with a target called ‘MyApp’ (in the user's project).
# link_with 'MyApp'
#
# # Link with the targets in the user’s project called ‘MyApp’ and ‘MyOtherApp’.
# link_with ['MyApp', 'MyOtherApp']
#
# # You can also specify this inline when specifying a new Pods target:
# target :test, :exclusive => true, :link_with => 'TestRunner' do
# dependency 'Kiwi'
# end
def link_with(targets)
@target_definition.link_with = targets
end
......@@ -239,7 +322,7 @@ module Pod
# dependency (JSONKit).
def target(name, options = {})
parent = @target_definition
options[:parent] = parent unless options.delete(:exclusive)
options[:parent] = parent
@target_definitions[name] = @target_definition = TargetDefinition.new(name, options)
yield
ensure
......@@ -286,7 +369,7 @@ module Pod
attr_reader :target_definitions
def dependencies
@target_definitions.values.map(&:target_dependencies).flatten
@target_definitions.values.map(&:target_dependencies).flatten.uniq
end
def dependency_by_top_level_spec_name(name)
......@@ -306,10 +389,10 @@ module Pod
end
def validate!
lines = []
lines << "* the `platform` attribute should be either `:osx` or `:ios`" unless @platform && [:osx, :ios].include?(@platform.name)
lines << "* no dependencies were specified, which is, well, kinda pointless" if dependencies.empty?
raise(Informative, (["The Podfile at `#{@defined_in_file}' is invalid:"] + lines).join("\n")) unless lines.empty?
#lines = []
#lines << "* the `platform` attribute should be either `:osx` or `:ios`" unless @platform && [:osx, :ios].include?(@platform.name)
#lines << "* no dependencies were specified, which is, well, kinda pointless" if dependencies.empty?
#raise(Informative, (["The Podfile at `#{@defined_in_file}' is invalid:"] + lines).join("\n")) unless lines.empty?
end
end
end
......@@ -12,6 +12,10 @@ end
module Pod
class Project < Xcodeproj::Project
def initialize(*)
super
main_group << groups.new('name' => 'Pods')
end
# Shortcut access to the `Pods' PBXGroup.
def pods
......@@ -22,100 +26,22 @@ module Pod
def add_pod_group(name)
pods.groups.new('name' => name)
end
def build_configuration_list
objects[root_object.attributes['buildConfigurationList']]
end
# Shortcut access to build configurations
def build_configurations
build_configuration_list.build_configurations
end
def build_configuration(name)
build_configurations.find { |c| c.name == name }
end
def self.for_platform(platform)
Pod::Project.new.tap do |project|
project.main_group << project.groups.new('name' => 'Pods')
project.add_system_framework(platform == :ios ? 'Foundation' : 'Cocoa')
# TODO this should al move to Xcodeproj as the default behavior of a new project
configuration_list = project.objects.add(Xcodeproj::Project::Object::XCConfigurationList, {
'defaultConfigurationIsVisible' => '0',
'defaultConfigurationName' => 'Release',
})
configuration_list.build_configurations.new(
'name' => 'Debug',
'buildSettings' => build_settings(platform, :debug)
)
def add_pod_target(name, platform)
target = targets.new_static_library(platform.name, name)
configuration_list.build_configurations.new(
'name' => 'Release',
'buildSettings' => build_settings(platform, :release)
)
project.root_object.attributes['buildConfigurationList'] = configuration_list.uuid
settings = {}
if platform.requires_legacy_ios_archs?
settings['ARCHS'] = "armv6 armv7"
end
if platform == :ios && platform.deployment_target
settings['IPHONEOS_DEPLOYMENT_TARGET'] = platform.deployment_target.to_s
end
end
private
COMMON_BUILD_SETTINGS = {
:all => {
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
'GCC_C_LANGUAGE_STANDARD' => 'gnu99',
'INSTALL_PATH' => "$(BUILT_PRODUCTS_DIR)",
'GCC_WARN_ABOUT_MISSING_PROTOTYPES' => 'YES',
'GCC_WARN_ABOUT_RETURN_TYPE' => 'YES',
'GCC_WARN_UNUSED_VARIABLE' => 'YES',
'OTHER_LDFLAGS' => ''
}.freeze,
:debug => {
'GCC_DYNAMIC_NO_PIC' => 'NO',
'GCC_PREPROCESSOR_DEFINITIONS' => ["DEBUG=1", "$(inherited)"],
'GCC_SYMBOLS_PRIVATE_EXTERN' => 'NO',
'GCC_OPTIMIZATION_LEVEL' => '0'
}.freeze,
:ios => {
'ARCHS' => "$(ARCHS_STANDARD_32_BIT)",
'GCC_VERSION' => 'com.apple.compilers.llvmgcc42',
'IPHONEOS_DEPLOYMENT_TARGET' => '4.3',
'PUBLIC_HEADERS_FOLDER_PATH' => "$(TARGET_NAME)",
'SDKROOT' => 'iphoneos'
}.freeze,
:osx => {
'ARCHS' => "$(ARCHS_STANDARD_64_BIT)",
'GCC_ENABLE_OBJC_EXCEPTIONS' => 'YES',
'GCC_WARN_64_TO_32_BIT_CONVERSION' => 'YES',
'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
'MACOSX_DEPLOYMENT_TARGET' => '10.7',
'SDKROOT' => 'macosx'
}.freeze
}.freeze
def self.build_settings(platform, scheme)
COMMON_BUILD_SETTINGS[:all].dup.tap do |settings|
settings.merge!(COMMON_BUILD_SETTINGS[platform.name])
settings['COPY_PHASE_STRIP'] = scheme == :debug ? 'NO' : 'YES'
target.build_settings('Debug').merge!(settings)
target.build_settings('Release').merge!(settings)
if platform.requires_legacy_ios_archs?
settings['ARCHS'] = "armv6 armv7"
end
if platform == :ios && platform.deployment_target
settings['IPHONEOS_DEPLOYMENT_TARGET'] = platform.deployment_target.to_s
end
if scheme == :debug
settings.merge!(COMMON_BUILD_SETTINGS[:debug])
settings['ONLY_ACTIVE_ARCH'] = 'YES' if platform == :osx
else
settings['VALIDATE_PRODUCT'] = 'YES' if platform == :ios
settings['DEBUG_INFORMATION_FORMAT'] = "dwarf-with-dsym" if platform == :osx
end
end
target
end
end
end
require 'colored'
module Pod
class Resolver
include Config::Mixin
......@@ -15,13 +17,14 @@ module Pod
def resolve
@specs = {}
targets_and_specs = {}
result = @podfile.target_definitions.values.inject({}) do |result, target_definition|
@podfile.target_definitions.values.each do |target_definition|
puts "\nResolving dependencies for target `#{target_definition.name}'".green if config.verbose?
@loaded_specs = []
find_dependency_sets(@podfile, target_definition.dependencies)
result[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name)
result
# TODO @podfile.platform will change to target_definition.platform
find_dependency_sets(@podfile, target_definition.dependencies, target_definition.platform)
targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name)
end
# Specification doesn't need to know more about the context, so we assign
......@@ -32,17 +35,20 @@ module Pod
end
end
result
targets_and_specs
end
private
def find_cached_set(dependency)
def find_cached_set(dependency, platform)
@cached_sets[dependency.name] ||= begin
if dependency.specification
Specification::Set::External.new(dependency.specification)
elsif external_source = dependency.external_source
specification = external_source.specification_from_sandbox(@sandbox)
# The platform isn't actually being used by the LocalPod instance
# that's being used behind the scenes, but passing it anyways for
# completeness sake.
specification = external_source.specification_from_sandbox(@sandbox, platform)
Specification::Set::External.new(specification)
else
@cached_sources.search(dependency)
......@@ -50,13 +56,13 @@ module Pod
end
end
def find_dependency_sets(dependent_specification, dependencies)
def find_dependency_sets(dependent_specification, dependencies, platform)
@log_indent += 1
dependencies.each do |dependency|
puts ' ' * @log_indent + "- #{dependency}" if config.verbose?
set = find_cached_set(dependency)
set = find_cached_set(dependency, platform)
set.required_by(dependent_specification)
# Ensure we don't resolve the same spec twice
# Ensure we don't resolve the same spec twice for one target
unless @loaded_specs.include?(dependency.name)
# Get a reference to the spec that’s actually being loaded.
# If it’s a subspec dependency, e.g. 'RestKit/Network', then
......@@ -72,15 +78,16 @@ module Pod
@specs[spec.name] = spec
# And recursively load the dependencies of the spec.
find_dependency_sets(spec, spec.dependencies)
# TODO fix the need to return an empty arrayf if there are no deps for the given platform
find_dependency_sets(spec, (spec.dependencies[platform.to_sym] || []), platform)
end
end
@log_indent -= 1
end
def validate_platform!(spec)
unless spec.platform.nil? || spec.platform == @podfile.platform
raise Informative, "The platform required by the Podfile (:#{@podfile.platform}) " \
unless spec.platform.nil? || spec.platform == @podfile.target_definitions[:default].platform
raise Informative, "The platform required by the Podfile (:#{@podfile.target_definitions[:default].platform}) " \
"does not match that of #{spec} (:#{spec.platform})"
end
end
......
......@@ -54,9 +54,9 @@ module Pod
end
end
def installed_pod_named(name)
def installed_pod_named(name, platform)
if spec_path = podspec_for_name(name)
LocalPod.from_podspec(spec_path, self)
LocalPod.from_podspec(spec_path, self, platform)
end
end
end
......
......@@ -31,12 +31,17 @@ module Pod
# TODO This is just to work around a MacRuby bug
def post_initialize
@dependencies, @source_files, @resources, @clean_paths, @subspecs = [], [], [], [], []
@define_for_platforms = [:osx, :ios]
#@dependencies, @source_files, @resources, @clean_paths, @subspecs = [], [], [], [], []
@clean_paths, @subspecs = [], []
@dependencies, @source_files, @resources = { :ios => [], :osx => [] }, { :ios => [], :osx => [] }, { :ios => [], :osx => [] }
@platform = Platform.new(nil)
@xcconfig = Xcodeproj::Config.new
#@xcconfig = Xcodeproj::Config.new
@xcconfig = { :ios => Xcodeproj::Config.new, :osx => Xcodeproj::Config.new }
@compiler_flags = { :ios => '', :osx => '' }
end
# Attributes
# Attributes **without** multiple platform support
attr_accessor :name
attr_accessor :homepage
......@@ -90,25 +95,80 @@ module Pod
@part_of = dependency(*name_and_version_requirements)
end
def clean_paths=(patterns)
@clean_paths = pattern_list(patterns)
end
attr_reader :clean_paths
alias_method :clean_path=, :clean_paths=
def header_dir=(dir)
@header_dir = Pathname.new(dir)
end
def header_dir
@header_dir || pod_destroot_name
end
def platform=(platform)
@platform = Platform.new(platform)
end
attr_reader :platform
def requires_arc=(requires_arc)
self.compiler_flags = '-fobjc-arc' if requires_arc
@requires_arc = requires_arc
end
attr_reader :requires_arc
def subspec(name, &block)
subspec = Subspec.new(self, name, &block)
@subspecs << subspec
subspec
end
attr_reader :subspecs
### Attributes **with** multiple platform support
class PlatformProxy
def initialize(specification, platform)
@specification, @platform = specification, platform
end
%w{ source_files= resource= resources= xcconfig= framework= frameworks= library= libraries= compiler_flags= dependency }.each do |method|
define_method(method) do |args|
@specification._on_platform(@platform) do
@specification.send(method, args)
end
end
end
end
def ios
PlatformProxy.new(self, :ios)
end
def osx
PlatformProxy.new(self, :osx)
end
def source_files=(patterns)
@source_files = pattern_list(patterns)
@define_for_platforms.each do |platform|
@source_files[platform] = pattern_list(patterns)
end
end
attr_reader :source_files
def resources=(patterns)
@resources = pattern_list(patterns)
@define_for_platforms.each do |platform|
@resources[platform] = pattern_list(patterns)
end
end
attr_reader :resources
alias_method :resource=, :resources=
def clean_paths=(patterns)
@clean_paths = pattern_list(patterns)
end
attr_reader :clean_paths
alias_method :clean_path=, :clean_paths=
def xcconfig=(hash)
@xcconfig.merge!(hash)
def xcconfig=(build_settings)
@define_for_platforms.each do |platform|
@xcconfig[platform].merge!(build_settings)
end
end
attr_reader :xcconfig
......@@ -124,44 +184,34 @@ module Pod
end
alias_method :library=, :libraries=
def header_dir=(dir)
@header_dir = Pathname.new(dir)
end
def header_dir
@header_dir || pod_destroot_name
end
attr_writer :compiler_flags
def compiler_flags
flags = "#{@compiler_flags}"
flags << ' -fobjc-arc' if requires_arc
flags
end
def platform=(platform)
@platform = Platform.new(platform)
attr_reader :compiler_flags
def compiler_flags=(flags)
@define_for_platforms.each do |platform|
@compiler_flags[platform] << ' ' << flags
end
end
attr_reader :platform
attr_accessor :requires_arc
def dependency(*name_and_version_requirements)
name, *version_requirements = name_and_version_requirements.flatten
dep = Dependency.new(name, *version_requirements)
@dependencies << dep
@define_for_platforms.each do |platform|
@dependencies[platform] << dep
end
dep
end
attr_reader :dependencies
def subspec(name, &block)
subspec = Subspec.new(self, name, &block)
@subspecs << subspec
subspec
end
attr_reader :subspecs
### Not attributes
# Not attributes
# @visibility private
#
# This is used by PlatformProxy to assign attributes for the scoped platform.
def _on_platform(platform)
before, @define_for_platforms = @define_for_platforms, [platform]
yield
ensure
@define_for_platforms = before
end
include Config::Mixin
......@@ -185,7 +235,7 @@ module Pod
end
def wrapper?
source_files.empty? && !subspecs.empty?
source_files.values.all?(&:empty?) && !subspecs.empty?
end
def subspec_by_name(name)
......@@ -209,7 +259,11 @@ module Pod
end
def dependency_by_top_level_spec_name(name)
@dependencies.find { |d| d.top_level_spec_name == name }
@dependencies.each do |_, platform_deps|
platform_deps.each do |dep|
return dep if dep.top_level_spec_name == name
end
end
end
def pod_destroot
......@@ -244,42 +298,6 @@ module Pod
end
end
# Returns all resource files of this pod, but relative to the
# project pods root.
def expanded_resources
files = []
resources.each do |pattern|
pattern = pod_destroot + pattern
pattern.glob.each do |file|
files << file.relative_path_from(config.project_pods_root)
end
end
files
end
# Returns all source files of this pod including header files,
# but relative to the project pods root.
#
# If the pattern is the path to a directory, the pattern will
# automatically glob for c, c++, Objective-C, and Objective-C++
# files.
def expanded_source_files
files = []
source_files.each do |pattern|
pattern = pod_destroot + pattern
pattern = pattern + '*.{h,m,mm,c,cpp}' if pattern.directory?
pattern.glob.each do |file|
files << file.relative_path_from(config.project_pods_root)
end
end
files
end
# Returns only the header files of this pod.
def header_files
expanded_source_files.select { |f| f.extname == '.h' }
end
# This method takes a header path and returns the location it should have
# in the pod's header dir.
#
......@@ -290,25 +308,6 @@ module Pod
from.basename
end
# See copy_header_mapping.
def copy_header_mappings
header_files.inject({}) do |mappings, from|
from_without_prefix = from.relative_path_from(pod_destroot_name)
to = header_dir + copy_header_mapping(from_without_prefix)
(mappings[to.dirname] ||= []) << from
mappings
end
end
# Returns a list of search paths where the pod's headers can be found. This
# includes the pod's header dir root and any other directories that might
# have been added by overriding the copy_header_mapping/copy_header_mappings
# methods.
def header_search_paths
dirs = [header_dir] + copy_header_mappings.keys
dirs.map { |dir| %{"$(PODS_ROOT)/Headers/#{dir}"} }
end
def to_s
"#{name} (#{version})"
end
......
Subproject commit c8a3e521ee57ce2e6fa73c55a3e2f0042cc2033a
Subproject commit 5e19daf9a13f708108483037f9cd2c778f239475
Subproject commit e69109bd31a191be333e9b502c83e7da9e789e04
......@@ -60,7 +60,7 @@ describe "Pod::Command" do
spec.authors.should == { `git config --get user.name`.strip => `git config --get user.email`.strip, "other author" => "and email address" }
spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '1.0.0' }
spec.description.should == 'An optional longer description of Bananas.'
spec.source_files.should == ['Classes', 'Classes/**/*.{h,m}']
spec.source_files[:ios].should == ['Classes', 'Classes/**/*.{h,m}']
end
before do
......
......@@ -2,7 +2,7 @@ require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Downloader" do
before do
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox)
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Pod::Platform.ios)
end
describe "for Git" do
......
......@@ -4,22 +4,27 @@ describe Pod::Installer::UserProjectIntegrator do
extend SpecHelper::TemporaryDirectory
before do
@sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
config.project_root = @sample_project_path.dirname
sample_project_path = @sample_project_path
@podfile = Pod::Podfile.new do
platform :ios
xcodeproj sample_project_path
link_with 'SampleProject' # this is an app target!
dependency 'JSONKit'
target :test_runner, :exclusive => true, :link_with => 'TestRunner' do
target :test_runner, :exclusive => true do
link_with 'TestRunner'
dependency 'Kiwi'
end
end
@sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
config.project_root = @sample_project_path.dirname
@integrator = Pod::Installer::UserProjectIntegrator.new(@sample_project_path, @podfile)
@integrator = Pod::Installer::UserProjectIntegrator.new(@podfile)
@integrator.integrate!
@sample_project = Xcodeproj::Project.new(@sample_project_path)
end
......@@ -34,7 +39,7 @@ describe Pod::Installer::UserProjectIntegrator do
it 'adds the project being integrated to the workspace' do
workspace = Xcodeproj::Workspace.new_from_xcworkspace(@sample_project_path.dirname + "SampleProject.xcworkspace")
workspace.should.include?("SampleProject.xcodeproj")
workspace.projpaths.sort.should == %w{ Pods/Pods.xcodeproj SampleProject.xcodeproj }
end
it 'adds the Pods project to the workspace' do
......@@ -65,7 +70,7 @@ describe Pod::Installer::UserProjectIntegrator do
@podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first)
framework_build_phase = target.frameworks_build_phases.first
framework_build_phase.files.where(:file => { :name => definition.lib_name }).should.not == nil
framework_build_phase.files.where(:name => definition.lib_name).should.not == nil
end
end
......@@ -77,20 +82,28 @@ describe Pod::Installer::UserProjectIntegrator do
end
end
before do
# Reset the cached TargetIntegrator#targets lists.
@integrator.instance_variable_set(:@target_integrators, nil)
end
it "only tries to integrate Pods libraries into user targets that haven't been integrated yet" do
app, test_runner = @integrator.user_project.targets.to_a
test_runner.frameworks_build_phases.first.files.last.destroy
app_integrator = @integrator.target_integrators.find { |t| t.target_definition.name == :default }
test_runner_integrator = @integrator.target_integrators.find { |t| t.target_definition.name == :test_runner }
# Remove libPods.a from the app target. But don't do it through TargetIntegrator#targets,
# as it will return only those that still need integration.
app_target = app_integrator.user_project.targets.where(:name => 'SampleProject')
app_target.frameworks_build_phases.first.build_files.last.destroy
targets = @integrator.targets.sort_by { |target| target.target_definition.label }
@integrator.stubs(:targets).returns(targets)
app_integrator.expects(:add_pods_library)
test_runner_integrator.expects(:add_pods_library).never
targets.first.expects(:add_pods_library).never
targets.last.expects(:add_pods_library)
@integrator.integrate!
end
it "does not even try to save the project if none of the target integrators had any work to do" do
@integrator.user_project.expects(:save_as).never
@integrator.target_integrators.first.user_project.expects(:save_as).never
@integrator.integrate!
end
end
......
This diff is collapsed.
......@@ -21,6 +21,16 @@ module Bacon
extend ColorOutput
summary_at_exit
module FilterBacktraces
def handle_summary
ErrorLog.replace(ErrorLog.split("\n").reject do |line|
line =~ %r{(gems/mocha|spec_helper)}
end.join("\n").lstrip << "\n\n")
super
end
end
extend FilterBacktraces
class Context
include Pod::Config::Mixin
......@@ -29,6 +39,12 @@ module Bacon
def argv(*argv)
Pod::Command::ARGV.new(argv)
end
require 'colored'
def xit(description, *args)
puts "- #{description} [DISABLED]".yellow
ErrorLog << "[DISABLED] #{self.name} #{description}\n\n"
end
end
end
......
require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Install" do
it "should include instructions on how to reference the xcode project" do
Pod::Command::Install.banner.should.match %r{xcodeproj 'path/to/XcodeProject'}
end
end
......@@ -32,13 +32,6 @@ describe "Pod::Config" do
end
end
it "returns the path to an existing podspec file if a Podfile doesn't exist" do
(temporary_directory + 'Bananas.podspec').open('w') { |f| f << '# Yo' }
Dir.chdir(temporary_directory) do
config.project_podfile.should == Pathname.pwd + 'Bananas.podspec'
end
end
it "returns the path to the Pods directory that holds the dependencies" do
config.project_pods_root.should == Pathname.pwd + 'Pods'
end
......
......@@ -2,7 +2,7 @@ require File.expand_path('../../spec_helper', __FILE__)
def stub_pod_with_source(source_options)
specification = stub(
:part_of_other_pod? => false,
:part_of_other_pod? => false,
:source => source_options
)
stub('pod') do
......@@ -13,7 +13,7 @@ end
describe "Pod::Downloader" do
it "returns a git downloader with parsed options" do
pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox)
pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Pod::Platform.ios)
downloader = Pod::Downloader.for_pod(pod)
downloader.should.be.instance_of Pod::Downloader::Git
downloader.url.should == 'http://banana-corp.local/banana-lib.git'
......@@ -21,7 +21,7 @@ describe "Pod::Downloader" do
end
it 'returns a github downloader when the :git URL is on github' do
pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox)
pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Pod::Platform.ios)
pod.specification.stubs(:source).returns(:git => "git://github.com/CocoaPods/CocoaPods")
downloader = Pod::Downloader.for_pod(pod)
downloader.should.be.instance_of Pod::Downloader::GitHub
......
......@@ -3,7 +3,7 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Generator::Documentation do
before do
@sandbox = temporary_sandbox
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox)
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.ios)
copy_fixture_to_pod('banana-lib', @pod)
@doc_installer = Pod::Generator::Documentation.new(@pod)
end
......
require File.expand_path('../../../spec_helper', __FILE__)
TMP_POD_ROOT = ROOT + "tmp" + "podroot"
TMP_POD_ROOT = ROOT + "tmp" + "podroot" unless defined? TMP_POD_ROOT
describe Pod::Installer::TargetInstaller do
before do
before do
platform = Pod::Platform.ios
@target_definition = Pod::Podfile::TargetDefinition.new(:foo)
@target_definition.platform = platform
platform = Pod::Platform.new(:ios)
@podfile = stub('podfile', :platform => platform,
:generate_bridge_support? => false,
:set_arc_compatibility_flag? => false)
@podfile = stub('podfile',
:platform => platform,
:xcodeproj => 'dummy.xcodeproj',
:generate_bridge_support? => false,
:set_arc_compatibility_flag? => false
)
@project = Pod::Project.for_platform(platform)
@project = Pod::Project.new
@project.main_group.groups.new('name' => 'Targets Support Files')
@installer = Pod::Installer::TargetInstaller.new(@podfile, @project, @target_definition)
@sandbox = Pod::Sandbox.new(TMP_POD_ROOT)
@specification = fixture_spec('banana-lib/BananaLib.podspec')
@pods = [Pod::LocalPod.new(@specification, @sandbox)]
@pods = [Pod::LocalPod.new(@specification, @sandbox, platform)]
end
def do_install!
......
......@@ -4,39 +4,65 @@ describe Pod::Installer::UserProjectIntegrator do
extend SpecHelper::TemporaryDirectory
before do
@sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
config.project_root = @sample_project_path.dirname
sample_project_path = @sample_project_path
@podfile = Pod::Podfile.new do
platform :ios
xcodeproj sample_project_path
dependency 'JSONKit'
target :test_runner, :exclusive => true, :link_with => 'TestRunner' do
target :test_runner, :exclusive => true do
link_with 'TestRunner'
dependency 'Kiwi'
end
end
@sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
config.project_root = @sample_project_path.dirname
@integrator = Pod::Installer::UserProjectIntegrator.new(@sample_project_path, @podfile)
@integrator = Pod::Installer::UserProjectIntegrator.new(@podfile)
end
after do
config.project_root = nil
end
it "returns the path to the workspace in the project's root" do
it "returns the path to the workspace from the Podfile" do
@integrator.workspace_path.should == config.project_root + 'SampleProject.xcworkspace'
end
it "raises if no workspace could be selected" do
@podfile.stubs(:workspace)
lambda { @integrator.workspace_path }.should.raise Pod::Informative
end
it "returns the path to the Pods.xcodeproj document" do
@integrator.pods_project_path.should == config.project_root + 'Pods/Pods.xcodeproj'
end
it "returns a Pod::Installer::UserProjectIntegrator::Target for each target definition in the Podfile" do
@integrator.targets.map(&:target_definition).should == @podfile.target_definitions.values
@integrator.target_integrators.map(&:target_definition).should == @podfile.target_definitions.values
end
before do
@target_integrator = @integrator.target_integrators.first
end
it "returns the the user's project, that contains the target, from the Podfile" do
@target_integrator.user_project_path.should == @sample_project_path
@target_integrator.user_project.should == Xcodeproj::Project.new(@sample_project_path)
end
it "raises if no project could be selected" do
@target_integrator.target_definition.stubs(:xcodeproj).returns(nil)
lambda { @target_integrator.user_project_path }.should.raise Pod::Informative
end
it "raises if the project path doesn't exist" do
@target_integrator.target_definition.xcodeproj.stubs(:exist?).returns(false)
lambda { @target_integrator.user_project_path }.should.raise Pod::Informative
end
it "uses the first target in the user's project if no explicit target is specified" do
target_integrator = @integrator.targets.first
target_integrator.target_definition.stubs(:link_with).returns(nil)
target_integrator.targets.should == [Xcodeproj::Project.new(@sample_project_path).targets.first]
@target_integrator.target_definition.stubs(:link_with).returns(nil)
@target_integrator.targets.should == [Xcodeproj::Project.new(@sample_project_path).targets.first]
end
end
......@@ -28,6 +28,10 @@ describe "Pod::Installer" do
it "configures the project to load categories from the static library" do
@xcconfig['OTHER_LDFLAGS'].should == '-ObjC -all_load'
end
it "sets the PODS_ROOT build variable" do
@xcconfig['PODS_ROOT'].should.not == nil
end
end
it "generates a BridgeSupport metadata file from all the pod headers" do
......@@ -35,15 +39,12 @@ describe "Pod::Installer" do
platform :osx
dependency 'ASIHTTPRequest'
end
config.rootspec = podfile
expected = []
installer = Pod::Installer.new(podfile)
pods = installer.activated_specifications.map do |spec|
spec.header_files.each do |header|
expected << config.project_pods_root + header
end
Pod::LocalPod.new(spec, installer.sandbox)
Pod::LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform)
end
expected = pods.map { |pod| pod.header_files }.flatten.map { |header| config.project_pods_root + header }
expected.size.should > 0
installer.target_installers.first.bridge_support_generator_for(pods, installer.sandbox).headers.should == expected
end
......@@ -54,7 +55,6 @@ describe "Pod::Installer" do
dependency 'JSONKit'
end
end
config.rootspec = podfile
installer = Pod::Installer.new(podfile)
installer.target_installers.map(&:target_definition).map(&:name).should == [:not_empty]
end
......
......@@ -6,7 +6,7 @@ describe Pod::LocalPod do
before do
@sandbox = temporary_sandbox
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox)
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.new(:ios))
copy_fixture_to_pod('banana-lib', @pod)
end
......@@ -32,7 +32,7 @@ describe Pod::LocalPod do
it 'returns an expanded list of source files, relative to the sandbox root' do
@pod.source_files.sort.should == [
Pathname.new("BananaLib/Classes/Banana.m"),
Pathname.new("BananaLib/Classes/Banana.m"),
Pathname.new("BananaLib/Classes/Banana.h")
].sort
end
......@@ -78,5 +78,99 @@ describe Pod::LocalPod do
target.expects(:add_source_file).with(anything, anything, "-d some_flag")
@pod.add_to_target(target)
end
end
describe "A Pod::LocalPod, with installed source," do
#before do
#config.project_pods_root = fixture('integration')
#podspec = fixture('spec-repos/master/SSZipArchive/0.1.0/SSZipArchive.podspec')
#@spec = Pod::Specification.from_file(podspec)
#@destroot = fixture('integration/SSZipArchive')
#end
#after do
#config.project_pods_root = nil
#end
xit "returns the list of files that the source_files pattern expand to" do
files = @destroot.glob('**/*.{h,c,m}')
files = files.map { |file| file.relative_path_from(config.project_pods_root) }
@spec.expanded_source_files[:ios].sort.should == files.sort
end
xit "returns the list of headers" do
files = @destroot.glob('**/*.h')
files = files.map { |file| file.relative_path_from(config.project_pods_root) }
@spec.header_files[:ios].sort.should == files.sort
end
xit "returns a hash of mappings from the pod's destroot to its header dirs, which by default is just the pod's header dir" do
@spec.copy_header_mappings[:ios].size.should == 1
@spec.copy_header_mappings[:ios][Pathname.new('SSZipArchive')].sort.should == %w{
SSZipArchive.h
minizip/crypt.h
minizip/ioapi.h
minizip/mztools.h
minizip/unzip.h
minizip/zip.h
}.map { |f| Pathname.new("SSZipArchive/#{f}") }.sort
end
xit "allows for customization of header mappings by overriding copy_header_mapping" do
def @spec.copy_header_mapping(from)
Pathname.new('ns') + from.basename
end
@spec.copy_header_mappings[:ios].size.should == 1
@spec.copy_header_mappings[:ios][Pathname.new('SSZipArchive/ns')].sort.should == %w{
SSZipArchive.h
minizip/crypt.h
minizip/ioapi.h
minizip/mztools.h
minizip/unzip.h
minizip/zip.h
}.map { |f| Pathname.new("SSZipArchive/#{f}") }.sort
end
xit "returns a hash of mappings with a custom header dir prefix" do
@spec.header_dir = 'AnotherRoot'
@spec.copy_header_mappings[:ios][Pathname.new('AnotherRoot')].sort.should == %w{
SSZipArchive.h
minizip/crypt.h
minizip/ioapi.h
minizip/mztools.h
minizip/unzip.h
minizip/zip.h
}.map { |f| Pathname.new("SSZipArchive/#{f}") }.sort
end
xit "returns the user header search paths" do
def @spec.copy_header_mapping(from)
Pathname.new('ns') + from.basename
end
@spec.header_search_paths.should == %w{
"$(PODS_ROOT)/Headers/SSZipArchive"
"$(PODS_ROOT)/Headers/SSZipArchive/ns"
}
end
xit "returns the user header search paths with a custom header dir prefix" do
@spec.header_dir = 'AnotherRoot'
def @spec.copy_header_mapping(from)
Pathname.new('ns') + from.basename
end
@spec.header_search_paths.should == %w{
"$(PODS_ROOT)/Headers/AnotherRoot"
"$(PODS_ROOT)/Headers/AnotherRoot/ns"
}
end
xit "returns the list of files that the resources pattern expand to" do
@spec.expanded_resources.should == {}
@spec.resource = 'LICEN*'
@spec.expanded_resources[:ios].map(&:to_s).should == %w{ SSZipArchive/LICENSE }
@spec.expanded_resources[:osx].map(&:to_s).should == %w{ SSZipArchive/LICENSE }
@spec.resources = 'LICEN*', 'Readme.*'
@spec.expanded_resources[:ios].map(&:to_s).should == %w{ SSZipArchive/LICENSE SSZipArchive/Readme.markdown }
@spec.expanded_resources[:osx].map(&:to_s).should == %w{ SSZipArchive/LICENSE SSZipArchive/Readme.markdown }
end
end
require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Platform" do
describe Pod::Platform do
it "returns a new Platform instance" do
Pod::Platform.ios.should == Pod::Platform.new(:ios)
Pod::Platform.osx.should == Pod::Platform.new(:osx)
end
before do
@platform = Pod::Platform.new(:ios)
@platform = Pod::Platform.ios
end
it "exposes it's symbolic name" do
......
require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::PodPathResolver" do
it "should default to a path underneath source root" do
target_definition = Pod::Podfile::TargetDefinition.new(:default)
target_definition.xcodeproj = 'foo.xcodeproj'
resolver = Pod::PodPathResolver.new(target_definition)
resolver.pods_root.should == "$(SRCROOT)/Pods"
end
it "should work with source root one level deeper" do
target_definition = Pod::Podfile::TargetDefinition.new(:default)
target_definition.xcodeproj = 'subdir/foo.xcodeproj'
resolver = Pod::PodPathResolver.new(target_definition)
resolver.pods_root.should == "$(SRCROOT)/../Pods"
end
end
This diff is collapsed.
This diff is collapsed.
......@@ -10,7 +10,6 @@ describe "Pod::Resolver" do
platform :ios
dependency 'ASIWebPageRequest'
end
config.rootspec = @podfile
@resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
end
......@@ -66,7 +65,6 @@ describe "Pod::Resolver" do
dependency 'RestKit/Network'
dependency 'RestKit/ObjectMapping'
end
config.rootspec = @podfile
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{
LibComponentLogging-Core
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment