vendor 0.0.4 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/CHANGELOG.md +22 -0
  2. data/Gemfile.lock +9 -1
  3. data/Guardfile +12 -0
  4. data/LICENSE +2 -0
  5. data/Readme.markdown +39 -23
  6. data/TODO.md +26 -0
  7. data/VERSION +1 -0
  8. data/lib/vendor.rb +6 -0
  9. data/lib/vendor/api.rb +61 -7
  10. data/lib/vendor/cli/app.rb +4 -4
  11. data/lib/vendor/cli/console.rb +7 -0
  12. data/lib/vendor/spec.rb +98 -0
  13. data/lib/vendor/templates/Vendorfile +3 -1
  14. data/lib/vendor/templates/vendorspec +15 -10
  15. data/lib/vendor/vendor_file.rb +5 -4
  16. data/lib/vendor/vendor_file/dependency_graph.rb +135 -0
  17. data/lib/vendor/vendor_file/dsl.rb +2 -0
  18. data/lib/vendor/vendor_file/library/base.rb +178 -29
  19. data/lib/vendor/vendor_file/library/git.rb +5 -1
  20. data/lib/vendor/vendor_file/library/local.rb +11 -1
  21. data/lib/vendor/vendor_file/library/remote.rb +134 -2
  22. data/lib/vendor/vendor_file/loader.rb +13 -11
  23. data/lib/vendor/vendor_spec/builder.rb +4 -7
  24. data/lib/vendor/version.rb +172 -1
  25. data/lib/vendor/xcode/project.rb +213 -4
  26. data/lib/vendor/xcode/proxy.rb +1 -0
  27. data/lib/vendor/xcode/proxy/pbx_frameworks_build_phase.rb +6 -0
  28. data/lib/vendor/xcode/proxy/pbx_reference_proxy.rb +7 -0
  29. data/lib/vendor/xcode/proxy/pbx_resources_build_phase.rb +8 -0
  30. data/lib/vendor/xcode/proxy/pbx_shell_script_build_phase.rb +8 -0
  31. data/lib/vendor/xcode/proxy/pbx_sources_build_phase.rb +6 -0
  32. data/spec/lib/vendor/api_spec.rb +54 -0
  33. data/spec/lib/vendor/spec_spec.rb +121 -0
  34. data/spec/lib/vendor/vendor_file/dependency_graph_spec.rb +129 -0
  35. data/spec/lib/vendor/vendor_file/library/base_spec.rb +174 -14
  36. data/spec/lib/vendor/vendor_file/library/remote_spec.rb +154 -4
  37. data/spec/lib/vendor/vendor_file/loader_spec.rb +4 -2
  38. data/spec/lib/vendor/vendor_spec/builder_spec.rb +2 -2
  39. data/spec/lib/vendor/version_spec.rb +168 -0
  40. data/spec/lib/vendor/xcode/project_spec.rb +175 -4
  41. data/spec/lib/vendor_spec.rb +15 -0
  42. data/spec/spec_helper.rb +3 -2
  43. data/spec/support/api_stubs.rb +57 -0
  44. data/spec/support/resources/cache/base/{DKBenchmark-Manifest → DKBenchmark-0.1-Manifest}/data/DKBenchmark.h +0 -0
  45. data/spec/support/resources/cache/base/{DKBenchmark-Manifest → DKBenchmark-0.1-Manifest}/data/DKBenchmark.m +0 -0
  46. data/spec/support/resources/cache/base/DKBenchmark-0.1-Manifest/vendor.json +1 -0
  47. data/spec/support/resources/cache/base/{DKBenchmark-Vendorspec → DKBenchmark-0.1-Nothing}/DKBenchmark.h +0 -0
  48. data/spec/support/resources/cache/base/{DKBenchmark-Vendorspec → DKBenchmark-0.1-Nothing}/DKBenchmark.m +0 -0
  49. data/spec/support/resources/cache/base/DKBenchmark-0.1-Nothing/DKBenchmark.vendorspec +16 -0
  50. data/spec/support/resources/cache/base/DKBenchmark-0.1-Vendorspec/DKBenchmark.h +18 -0
  51. data/spec/support/resources/cache/base/DKBenchmark-0.1-Vendorspec/DKBenchmark.m +73 -0
  52. data/spec/support/resources/cache/base/DKBenchmark-0.1-Vendorspec/DKBenchmark.vendorspec +24 -0
  53. data/spec/support/resources/projects/MultipleTargets/MultipleTargets.xcodeproj/project.pbxproj +624 -0
  54. data/spec/support/resources/projects/RestKitProject/RestKitProject.xcodeproj/project.pbxproj +479 -0
  55. data/spec/support/resources/projects/UtilityApplication/UtilityApplication.xcodeproj/project.pbxproj +16 -7
  56. data/spec/support/resources/vendors/DKBenchmark/DKBenchmark.vendorspec +24 -8
  57. data/spec/support/resources/vendors/DKBenchmarkUnsafe/DKBenchmark.vendorspec +17 -8
  58. data/vendor.gemspec +4 -2
  59. metadata +93 -39
  60. data/lib/vendor/vendor_spec/dsl.rb +0 -39
  61. data/lib/vendor/vendor_spec/loader.rb +0 -23
  62. data/spec/lib/vendor/vendor_spec/dsl_spec.rb +0 -67
  63. data/spec/lib/vendor/vendor_spec/loader_spec.rb +0 -41
  64. data/spec/support/resources/cache/base/DKBenchmark-Manifest/vendor.json +0 -1
  65. data/spec/support/resources/cache/base/DKBenchmark-Vendorspec/DKBenchmark.vendorspec +0 -11
@@ -0,0 +1,22 @@
1
+ ## 0.1 (November 8, 2011)
2
+
3
+ Features:
4
+
5
+ - Initial release
6
+ - Build vendor libraries with `vendor library build VENDORSPEC`
7
+ - Create template vendor libraries with `vendor library init`
8
+ - Push vendor libraries to http://vendorforge.org with `vendor library push VENDOR`
9
+ - Install vendor libraries with `vendor install` using a Vendorfile
10
+ - Basic dependency management and conflict resolution
11
+ - Vendorspecs support adding frameworks to projects
12
+ - Vendorspecs support adding build settings / compiler flags to projects
13
+ - Vendorspecs support adding build settings / compiler flags to projects
14
+ - Libraries defined in the Vendorfile can reference libraries that
15
+ exist on http://vendorforge.org
16
+ - Libraries defined in the Vendorfile can be git repositories
17
+ - Libraries defined in the Vendorfile can be a local path
18
+ - Libraries do not need to be built to be installed in a Xcode project
19
+ as long as they have a folder that contains the source files (not
20
+ the project file, tests etc). To reference this folder, you can pass a
21
+ `:require` option to the lib to declare which folder the source files
22
+ live in.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vendor (0.0.3)
4
+ vendor (0.0.4)
5
5
  highline
6
6
  json
7
7
  rake
@@ -18,6 +18,11 @@ GEM
18
18
  columnize (0.3.4)
19
19
  diff-lcs (1.1.2)
20
20
  fakeweb (1.3.0)
21
+ growl (1.0.3)
22
+ guard (0.8.4)
23
+ thor (~> 0.14.6)
24
+ guard-rspec (0.5.0)
25
+ guard (>= 0.8.4)
21
26
  highline (1.6.2)
22
27
  json (1.6.1)
23
28
  linecache (0.46)
@@ -62,6 +67,9 @@ PLATFORMS
62
67
 
63
68
  DEPENDENCIES
64
69
  fakeweb
70
+ growl
71
+ guard
72
+ guard-rspec
65
73
  rspec
66
74
  ruby-debug
67
75
  ruby-debug19
@@ -0,0 +1,12 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ watch(%r{^spec/.+_spec\.rb$})
10
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
11
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
12
+ end
data/LICENSE CHANGED
@@ -1,3 +1,5 @@
1
+ Portions Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others.
2
+
1
3
  MIT License
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
@@ -1,6 +1,11 @@
1
- # Vendor – an iOS library management system
1
+ # Vendor – an iOS library management system [![Build Status](https://secure.travis-ci.org/keithpitt/vendor.png)](http://travis-ci.org/keithpitt/vendor)
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/keithpitt/vendor.png)](http://travis-ci.org/keithpitt/vendor)
3
+ __Note: This software is currently in super alpha. I've been testing it
4
+ with my own projects, and its seemed to work so far. If you have any
5
+ problems, feel free to create an issue. If your having a problem with
6
+ installing the vendor libraries into XCode, could you also provide me
7
+ with your .xcodeproj file, you don't need to give me the source files
8
+ just the project file is all I need.__
4
9
 
5
10
  Vendor makes the process of using and managing libraries in iOS easy. Vendor is modeled after [Bundler](https://github.com/carlhuda/bundler). Vendor streamlines the installation and update process for dependent libraries. It also tracks versions and manages dependencies between libraries.
6
11
 
@@ -25,8 +30,6 @@ $ sudo gem install vendor
25
30
  Specify your dependencies in a Vendors file in your project's root.
26
31
 
27
32
  ```ruby
28
- source "https://vendorforge.com"
29
-
30
33
  # Downloads the latest version of DKBenchmark from
31
34
  # http://vendorforge.com
32
35
  lib "DKBenchmark"
@@ -75,9 +78,9 @@ Installing a vendor library gets the latest version of the code, and adds them d
75
78
 
76
79
  As part of the installation process the required frameworks are added aswell as any compiler/linker flags. The installed version of the library is captured in the Vendors.lock file.
77
80
 
78
- ### Step 3: Restart XCode
81
+ ### Step 3: There is no spoon
79
82
 
80
- XCode sometimes goes bonkers if you try and make a modification to it while its running. It's easier just to either `vendor install` while its not running, or restart right after installing libraries.
83
+ Or step 3 for that matter!
81
84
 
82
85
  ## Creating Libraries
83
86
 
@@ -98,17 +101,33 @@ $ vendor library init
98
101
  This command will create a blank `.vendorspec` file that looks something like this:
99
102
 
100
103
  ```ruby
101
- name "DKBenchmark"
102
- version "0.1"
104
+ Vendor::Spec.new do |s|
105
+
106
+ s.name "DKBenchmark"
107
+ s.version "0.1"
108
+
109
+ s.authors "keithpitt"
110
+ s.email "me@keithpitt.com"
111
+ s.description "Easy benchmarking in Objective-C using blocks"
112
+
113
+ s.homepage "http://www.keithpitt.com"
114
+ s.source "https://github.com/keithpitt/DKBenchmark"
115
+ s.docs "https://github.com/keithpitt/DKBenchmark/wiki"
103
116
 
104
- authors "keithpitt"
105
- email "me@keithpitt.com"
106
- homepage "http://www.keithpitt.com"
107
- description "Easy benchmarking in Objective-C using blocks"
117
+ s.files [ "DKBenchmark.h", "DKBenchmark.m" ]
108
118
 
109
- github "https://github.com/keithpitt/DKBenchmark"
119
+ s.build_setting :other_linker_flags, [ "-ObjC", "+lsdd" ]
120
+ s.build_setting "CLANG_WARN_OBJCPP_ARC_ABI", false
121
+ s.build_setting "GCC_PRECOMPILE_PREFIX_HEADER", "YES"
110
122
 
111
- files [ "DKBenchmark.h", "DKBenchmark.m" ]
123
+ s.framework "CoreGraphics.framework"
124
+ s.framework "UIKit.framework"
125
+
126
+ s.dependency "JSONKit", "0.5"
127
+ s.dependency "ASIHTTPRequest", "~> 4.2"
128
+ s.dependency "AFINetworking", "<= 2.5.a"
129
+
130
+ end
112
131
  ```
113
132
 
114
133
  Change what you need to match your project, then build a packaged
@@ -162,21 +181,18 @@ After reading [this blog post](http://www.germanforblack.com/articles/false-fear
162
181
 
163
182
  So I've probably made mistake or two. But thats OK, because at least I have *something* working. If you see something you think could be done better, feel free to fork and submit a pull request :)
164
183
 
165
- ## Contributers
166
-
167
- * [Keith Pitt](http://www.keithpitt.com)
168
- * [Tim Lee](http://twitter.com/#!/timothy1ee)
169
- * [Jari Bakken](https://github.com/jarib/plist/blob/master/lib/plist/ascii.rb)
170
-
171
184
  ## Special Thanks
172
185
 
173
- Thanks to the following libraries. They provided me with a great deal of
174
- inspiration and example code :D
186
+ Thanks to the following libraries and people, without their
187
+ contributions to open source, Vendor would have never been...
175
188
 
189
+ * [Rubygems](http://rubyforge.org/projects/rubygems/)
190
+ * [Bundler](https://github.com/carlhuda/bundler)
176
191
  * [CocoaPods](https://github.com/alloy/cocoapods)
177
192
  * [Kit](https://github.com/nkpart/kit)
178
193
  * [Vendor](https://github.com/bazaarlabs/vendor)
179
- * [Bundler](https://github.com/carlhuda/bundler)
194
+ * [Jari Bakken](https://github.com/jarib/plist/blob/master/lib/plist/ascii.rb)
195
+ * [Tim Lee](http://twitter.com/#!/timothy1ee)
180
196
 
181
197
  ## Note on Patches/Pull Requests
182
198
 
data/TODO.md ADDED
@@ -0,0 +1,26 @@
1
+ # TODO
2
+
3
+ * Vendor.lock creation
4
+ * Installing from Vendor.lock
5
+ * Installing sub projects
6
+ * [✔] Calculate dependencies
7
+ * [✔] Assert if there are any version conflicts
8
+ * [✔] Install libs from vendorforge.org
9
+ * [✔] Installing into targets
10
+ * [✔] Compiler flags defined in vendorspec
11
+ * [✔] Adding frameworks from the vendorspec
12
+ * Multiple download sources. Vendorfile API exists, but it needs to be
13
+ implemented into Vendor::API class
14
+ * [✔] Version deletion
15
+ * [✔] Installing a paticular version from http://vendorforge.org
16
+ * Multiple line support for descriptions
17
+ * Build https://github.com/keithpitt/gh-unit
18
+ * Build https://github.com/keithpitt/KIF
19
+ * Build https://github.com/keithpitt/Kiwi
20
+ * Build https://github.com/keithpitt/expecta
21
+ * Build https://github.com/keithpitt/cedar
22
+ * Go over https://twitter.com/github_objc and add libs from that
23
+ * [✔] Markdown support on descriptions
24
+ * [✔] Fix using local, git, and libraries with no manifest/vendorspec with
25
+ the dependency graph
26
+ * Build DDProgressView
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1
@@ -16,6 +16,8 @@ module Vendor
16
16
  autoload :VendorSpec, 'vendor/vendor_spec'
17
17
  autoload :XCode, 'vendor/xcode'
18
18
  autoload :CLI, 'vendor/cli'
19
+ autoload :Version, 'vendor/version'
20
+ autoload :Spec, 'vendor/spec'
19
21
 
20
22
  class << self
21
23
 
@@ -25,6 +27,10 @@ module Vendor
25
27
  File.join File.expand_path("../", __FILE__)
26
28
  end
27
29
 
30
+ def version
31
+ @version ||= File.read(File.join(Vendor.root, "..", "VERSION")).chomp
32
+ end
33
+
28
34
  def ui
29
35
  @ui ||= UI.new
30
36
  end
@@ -4,6 +4,7 @@ module Vendor
4
4
  module API
5
5
 
6
6
  require 'json'
7
+ require 'tmpdir'
7
8
 
8
9
  extend self
9
10
 
@@ -15,32 +16,85 @@ module Vendor
15
16
 
16
17
  def api_key(username, password)
17
18
  perform do
18
- response = resource(username, password)["users/#{username}/api_key.json"].get
19
+ url = resource(username, password)["users/#{username}/api_key.json"]
20
+ Vendor.ui.debug "GET #{url}"
21
+
22
+ response = url.get
19
23
  JSON.parse(response.body)["api_key"]
20
24
  end
21
25
  end
22
26
 
27
+ def meta(name)
28
+ @meta ||= {}
29
+
30
+ perform :on_404 => "Could not find a valid vendor '#{name}'" do
31
+ unless @meta[name]
32
+ url = resource["vendors/#{slugerize(name)}.json"]
33
+ Vendor.ui.debug "GET #{url}"
34
+
35
+ @meta[name] = JSON.parse(url.get.body)
36
+ end
37
+
38
+ @meta[name]
39
+ end
40
+ end
41
+
42
+ def download(name, version)
43
+ perform do
44
+ info = meta(name)
45
+
46
+ # Does the version exist?
47
+ unless info['versions'].find { |v| Vendor::Version.create(v[0]) == Vendor::Version.create(version) }
48
+ raise Error.new("Could not find a valid version for '#{name}' that matches '#{version}'")
49
+ end
50
+
51
+ url = resource["vendors/#{slugerize(name)}/versions/#{version}/download"]
52
+ Vendor.ui.debug "GET #{url}"
53
+ Vendor.ui.info "Downloading #{name} #{version}"
54
+
55
+ binary = url.get
56
+
57
+ filename = "#{name}-#{version}.vendor"
58
+ tmpfile = File.join(Dir.mktmpdir(filename), filename)
59
+
60
+ file = File.new(tmpfile, 'w')
61
+ file.write binary
62
+ file.close
63
+
64
+ file
65
+ end
66
+ end
67
+
23
68
  def push(options)
24
69
  perform do
25
- response = resource["vendors.json"].post :version => { :package => File.new(options[:file]) }, :api_key => options[:api_key]
26
- body = JSON.parse(response.body)
70
+ url = resource["vendors.json"]
71
+ Vendor.ui.debug "POST #{url}"
72
+
73
+ response = url.post :version => { :package => File.new(options[:file]) }, :api_key => options[:api_key]
74
+ json = JSON.parse(response.body)
27
75
 
28
- if body["status"] == "ok"
29
- body["url"]
76
+ if json["status"] == "ok"
77
+ json["url"]
30
78
  else
31
- raise Error.new(body["message"])
79
+ raise Error.new(json["message"])
32
80
  end
33
81
  end
34
82
  end
35
83
 
36
84
  private
37
85
 
38
- def perform(&block)
86
+ def slugerize(string)
87
+ string.gsub(/[^a-zA-Z0-9\-\_\s]/, ' ').gsub(/\s+/, '-')
88
+ end
89
+
90
+ def perform(options = {}, &block)
39
91
  begin
40
92
  yield
41
93
  rescue RestClient::Exception => e
42
94
  if e.http_code == 401
43
95
  raise Error.new("Login or password is incorrect")
96
+ elsif e.http_code == 404
97
+ raise Error.new(options[:on_404] || "Resource could not be found")
44
98
  else
45
99
  raise Error.new("Could not complete request. Server returned a status code of #{e.http_code}")
46
100
  end
@@ -18,7 +18,7 @@ module Vendor
18
18
  email = `git config --get user.email` ||
19
19
  "#{username}@example.com"
20
20
 
21
- Vendor::Template.copy "vendorspec", :name => "#{name.downcase}.vendorspec",
21
+ Vendor::Template.copy "vendorspec", :name => "#{name}.vendorspec",
22
22
  :locals => { :name => name,
23
23
  :username => username.chomp,
24
24
  :email => email.chomp }
@@ -62,10 +62,11 @@ module Vendor
62
62
  Vendor.ui.debug! if options["verbose"]
63
63
  end
64
64
 
65
- default_task :install
66
65
  class_option "no-color", :type => :boolean, :banner => "Disable colorization in output"
67
66
  class_option "verbose", :type => :boolean, :banner => "Enable verbose output mode", :aliases => "-V"
67
+
68
68
  map "--version" => :version
69
+ map "-v" => :version
69
70
 
70
71
  register Library, 'library', 'library <command>', 'Commands that will help you create and publish libraries', :hide => true
71
72
 
@@ -89,7 +90,6 @@ module Vendor
89
90
 
90
91
  loader = Vendor::VendorFile::Loader.new
91
92
  loader.load vendorfile
92
- loader.download
93
93
  loader.install project
94
94
 
95
95
  if project.dirty?
@@ -125,7 +125,7 @@ module Vendor
125
125
 
126
126
  desc "version", "Output the current version of vendor", :hide => true
127
127
  def version
128
- Vendor.ui.info Vendor::VERSION
128
+ Vendor.ui.info Vendor.version
129
129
  end
130
130
 
131
131
  # Exit with 1 if thor encounters an error (such as command missing)
@@ -4,6 +4,9 @@ module Vendor
4
4
 
5
5
  module Console
6
6
 
7
+ RESOURCE_PATH = File.join(Vendor.root, "..", "spec", "support", "resources")
8
+ PROJECT_RESOURCE_PATH = File.join(RESOURCE_PATH, "projects")
9
+
7
10
  # This reload method kinda works. It works if you change/add methods, but if you
8
11
  # remove methods from a class, they still seem to hang around. I believe there is
9
12
  # a fair amount of magic in rails that lets you call a reload!, but for the save
@@ -18,6 +21,10 @@ module Vendor
18
21
  "Reloaded!"
19
22
  end
20
23
 
24
+ def self.example_project!(name)
25
+ Vendor::XCode::Project.new(File.join(PROJECT_RESOURCE_PATH, "#{name}/#{name}.xcodeproj"))
26
+ end
27
+
21
28
  end
22
29
 
23
30
  end
@@ -0,0 +1,98 @@
1
+ module Vendor
2
+
3
+ class Spec
4
+
5
+ ATTRIBUTES = [ :name, :version, :email, :files, :homepage,
6
+ :description, :authors, :source, :docs ]
7
+
8
+ attr_reader :dependencies
9
+ attr_reader :frameworks
10
+ attr_reader :build_settings
11
+
12
+ BUILD_SETTING_NAMES = {
13
+ :other_linker_flags => "OTHER_LDFLAGS"
14
+ }
15
+
16
+ ATTRIBUTES.each do |attr|
17
+ class_eval %{
18
+ def #{attr}(*args)
19
+ if args.length == 1
20
+ self.#{attr} = args.first
21
+ else
22
+ @attributes[:#{attr}]
23
+ end
24
+ end
25
+
26
+ def #{attr}=(value)
27
+ @attributes[:#{attr}] = value
28
+ end
29
+ }
30
+ end
31
+
32
+ def self.load(file)
33
+ # Before evaling we need to chdir into the location of the vendorspec. This is
34
+ # so if the vendorfile does any system calls, they're expecting to be in the right
35
+ # right location.
36
+ before = Dir.pwd
37
+ Dir.chdir File.dirname(file)
38
+ spec = eval File.read(file), nil, file
39
+ Dir.chdir before
40
+ spec
41
+ end
42
+
43
+ def initialize(&block)
44
+ @attributes = {}
45
+ yield(self) if block_given?
46
+ end
47
+
48
+ def build_setting(setting, value)
49
+ @build_settings ||= []
50
+
51
+ # If you pass in a symbol, it'll try and map it.
52
+ if setting.kind_of?(Symbol)
53
+ symbol = setting
54
+ setting = BUILD_SETTING_NAMES[symbol]
55
+ raise StandardError.new("No mapping for '#{symbol}' in #{BUILD_SETTING_NAMES.inspect}") unless setting
56
+ end
57
+
58
+ # YES/NO Mappings
59
+ if value === true
60
+ value = "YES"
61
+ elsif value === false
62
+ value = "NO"
63
+ end
64
+
65
+ @build_settings << [ setting, value ]
66
+ end
67
+
68
+ def framework(name)
69
+ @frameworks ||= []
70
+ @frameworks << name
71
+ end
72
+
73
+ def dependency(name, version = nil)
74
+ @dependencies ||= []
75
+ @dependencies << [ name, version ]
76
+ end
77
+
78
+ def validate!
79
+ [ :name, :version, :email, :files ].each do |key|
80
+ value = self.send(key)
81
+
82
+ if value.respond_to?(:empty?) ? value.empty? : !value
83
+ raise StandardError.new("Specification is missing the `#{key}` option")
84
+ end
85
+ end
86
+ end
87
+
88
+ def to_json
89
+ [ ATTRIBUTES, :dependencies, :frameworks, :build_settings ].flatten.inject({}) do |hash, attr|
90
+ val = self.send(attr)
91
+ hash[attr] = val unless val.nil?
92
+ hash
93
+ end.to_json
94
+ end
95
+
96
+ end
97
+
98
+ end