cocoapods 0.5.1 → 0.6.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +229 -2
- data/README.md +50 -20
- data/bin/pod +3 -2
- data/lib/cocoapods.rb +23 -9
- data/lib/cocoapods/command.rb +71 -30
- data/lib/cocoapods/command/error_report.rb +102 -0
- data/lib/cocoapods/command/install.rb +27 -19
- data/lib/cocoapods/command/list.rb +51 -8
- data/lib/cocoapods/command/presenter.rb +61 -0
- data/lib/cocoapods/command/presenter/cocoa_pod.rb +123 -0
- data/lib/cocoapods/command/push.rb +102 -0
- data/lib/cocoapods/command/repo.rb +70 -14
- data/lib/cocoapods/command/search.rb +7 -10
- data/lib/cocoapods/command/setup.rb +76 -15
- data/lib/cocoapods/command/spec.rb +581 -97
- data/lib/cocoapods/config.rb +23 -26
- data/lib/cocoapods/dependency.rb +86 -40
- data/lib/cocoapods/downloader.rb +30 -18
- data/lib/cocoapods/downloader/git.rb +125 -15
- data/lib/cocoapods/downloader/http.rb +73 -0
- data/lib/cocoapods/downloader/mercurial.rb +3 -9
- data/lib/cocoapods/downloader/subversion.rb +3 -9
- data/lib/cocoapods/executable.rb +26 -3
- data/lib/cocoapods/generator/acknowledgements.rb +37 -0
- data/lib/cocoapods/generator/acknowledgements/markdown.rb +38 -0
- data/lib/cocoapods/generator/acknowledgements/plist.rb +63 -0
- data/lib/cocoapods/generator/copy_resources_script.rb +8 -4
- data/lib/cocoapods/generator/documentation.rb +99 -0
- data/lib/cocoapods/generator/dummy_source.rb +14 -0
- data/lib/cocoapods/installer.rb +140 -109
- data/lib/cocoapods/installer/target_installer.rb +78 -83
- data/lib/cocoapods/installer/user_project_integrator.rb +162 -0
- data/lib/cocoapods/local_pod.rb +240 -0
- data/lib/cocoapods/platform.rb +41 -18
- data/lib/cocoapods/podfile.rb +234 -21
- data/lib/cocoapods/project.rb +67 -0
- data/lib/cocoapods/resolver.rb +62 -32
- data/lib/cocoapods/sandbox.rb +63 -0
- data/lib/cocoapods/source.rb +42 -20
- data/lib/cocoapods/specification.rb +294 -271
- data/lib/cocoapods/specification/set.rb +10 -28
- data/lib/cocoapods/specification/statistics.rb +112 -0
- metadata +124 -11
- data/lib/cocoapods/xcodeproj_pods.rb +0 -111
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rbconfig'
|
4
|
+
require 'cgi'
|
5
|
+
require 'rubygems'
|
6
|
+
|
7
|
+
module Pod
|
8
|
+
class Command
|
9
|
+
module ErrorReport
|
10
|
+
class << self
|
11
|
+
def report(error)
|
12
|
+
return <<-EOS
|
13
|
+
|
14
|
+
#{'――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}
|
15
|
+
|
16
|
+
### Report
|
17
|
+
|
18
|
+
* What did you do?
|
19
|
+
|
20
|
+
* What did you expect to happen?
|
21
|
+
|
22
|
+
* What happened instead?
|
23
|
+
|
24
|
+
|
25
|
+
### Stack
|
26
|
+
|
27
|
+
```
|
28
|
+
CocoaPods : #{Pod::VERSION}
|
29
|
+
Ruby : #{RUBY_DESCRIPTION}
|
30
|
+
RubyGems : #{Gem::VERSION}
|
31
|
+
Host : #{host_information}
|
32
|
+
Xcode : #{xcode_information}
|
33
|
+
Ruby lib dir : #{RbConfig::CONFIG['libdir']}
|
34
|
+
Repositories : #{repo_information.join("\n ")}
|
35
|
+
```
|
36
|
+
#{markdown_podfile}
|
37
|
+
### Error
|
38
|
+
|
39
|
+
```
|
40
|
+
#{error.message}
|
41
|
+
#{error.backtrace.join("\n")}
|
42
|
+
```
|
43
|
+
|
44
|
+
#{'――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}
|
45
|
+
|
46
|
+
#{'[!] Oh no, an error occurred.'.red}
|
47
|
+
#{error_from_podfile(error)}
|
48
|
+
#{'Search for existing github issues similar to yours:'.yellow}
|
49
|
+
#{"https://github.com/CocoaPods/CocoaPods/issues/search?q=#{CGI.escape(error.message)}"}
|
50
|
+
|
51
|
+
#{'If none exists, create a ticket, with the template displayed above, on:'.yellow}
|
52
|
+
https://github.com/CocoaPods/CocoaPods/issues/new
|
53
|
+
|
54
|
+
Don't forget to anonymize any private data!
|
55
|
+
|
56
|
+
EOS
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def markdown_podfile
|
62
|
+
return '' unless Config.instance.project_podfile && Config.instance.project_podfile.exist?
|
63
|
+
<<-EOS
|
64
|
+
|
65
|
+
### Podfile
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
#{Config.instance.project_podfile.read.strip}
|
69
|
+
```
|
70
|
+
EOS
|
71
|
+
end
|
72
|
+
|
73
|
+
def error_from_podfile(error)
|
74
|
+
if error.message =~ /Podfile:(\d*)/
|
75
|
+
"\nIt appears to have originated from your Podfile at line #{$1}.\n"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def host_information
|
80
|
+
product, version, build =`sw_vers`.strip.split("\n").map { |line| line.split(":").last.strip }
|
81
|
+
"#{product} #{version} (#{build})"
|
82
|
+
end
|
83
|
+
|
84
|
+
def xcode_information
|
85
|
+
version, build = `xcodebuild -version`.strip.split("\n").map { |line| line.split(" ").last }
|
86
|
+
"#{version} (#{build})"
|
87
|
+
end
|
88
|
+
|
89
|
+
def repo_information
|
90
|
+
Pod::Source.all.map do |source|
|
91
|
+
repo = source.repo
|
92
|
+
Dir.chdir(repo) do
|
93
|
+
url = `git config --get remote.origin.url`.strip
|
94
|
+
sha = `git rev-parse HEAD`.strip
|
95
|
+
"#{repo.basename} - #{url} @ #{sha}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -4,45 +4,53 @@ module Pod
|
|
4
4
|
def self.banner
|
5
5
|
%{Installing dependencies of a project:
|
6
6
|
|
7
|
-
$ pod install
|
7
|
+
$ pod install
|
8
8
|
|
9
9
|
Downloads all dependencies defined in `Podfile' and creates an Xcode
|
10
10
|
Pods library project in `./Pods'.
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
The Xcode project file should be specified in your `Podfile` like this:
|
13
|
+
|
14
|
+
xcodeproj 'path/to/XcodeProject'
|
15
|
+
|
16
|
+
If no xcodeproj is specified, then a search for an Xcode project will
|
17
|
+
be made. If more than one Xcode project is found, the command will
|
18
|
+
raise an error.
|
19
|
+
|
20
|
+
This will configure the project to reference the Pods static library,
|
21
|
+
add a build configuration file, and add a post build script to copy
|
22
|
+
Pod resources.
|
17
23
|
}
|
18
24
|
end
|
19
25
|
|
20
26
|
def self.options
|
21
|
-
|
22
|
-
|
23
|
-
|
27
|
+
[
|
28
|
+
["--no-clean", "Leave SCM dirs like `.git' and `.svn' intact after downloading"],
|
29
|
+
["--no-doc", "Skip documentation generation with appledoc"],
|
30
|
+
["--no-integrate", "Skip integration of the Pods libraries in the Xcode project(s)"],
|
31
|
+
["--no-update", "Skip running `pod repo update` before install"],
|
32
|
+
].concat(super)
|
24
33
|
end
|
25
34
|
|
26
35
|
def initialize(argv)
|
27
|
-
config.clean
|
28
|
-
|
29
|
-
|
36
|
+
config.clean = !argv.option('--no-clean')
|
37
|
+
config.generate_docs = !argv.option('--no-doc')
|
38
|
+
config.integrate_targets = !argv.option('--no-integrate')
|
39
|
+
@update_repo = !argv.option('--no-update')
|
30
40
|
super unless argv.empty?
|
31
41
|
end
|
32
42
|
|
33
43
|
def run
|
34
|
-
unless podfile = config.
|
44
|
+
unless podfile = config.podfile
|
35
45
|
raise Informative, "No `Podfile' found in the current working directory."
|
36
46
|
end
|
37
|
-
|
38
|
-
raise Informative, "The specified project `#{@projpath}' does not exist."
|
39
|
-
end
|
47
|
+
|
40
48
|
if @update_repo
|
49
|
+
print_title 'Updating Spec Repositories', true
|
41
50
|
Repo.new(ARGV.new(["update"])).run
|
42
51
|
end
|
43
|
-
|
44
|
-
|
45
|
-
installer.configure_project(@projpath) if @projpath
|
52
|
+
|
53
|
+
Installer.new(podfile).install!
|
46
54
|
end
|
47
55
|
end
|
48
56
|
end
|
@@ -2,24 +2,67 @@ module Pod
|
|
2
2
|
class Command
|
3
3
|
class List < Command
|
4
4
|
def self.banner
|
5
|
-
%{List all pods:
|
5
|
+
%{List all pods:
|
6
6
|
|
7
7
|
$ pod list
|
8
8
|
|
9
|
-
Lists all available pods.
|
9
|
+
Lists all available pods.
|
10
|
+
|
11
|
+
$ pod list new
|
12
|
+
|
13
|
+
Lists the pods introduced in the master repository since the last check.}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.options
|
17
|
+
[["--update", "Run `pod repo update` before listing"]].concat(Presenter.options).concat(super)
|
10
18
|
end
|
11
19
|
|
20
|
+
extend Executable
|
21
|
+
executable :git
|
22
|
+
|
12
23
|
def initialize(argv)
|
24
|
+
@update = argv.option('--update')
|
25
|
+
@new = argv.option('new')
|
26
|
+
@presenter = Presenter.new(argv)
|
27
|
+
super unless argv.empty?
|
13
28
|
end
|
14
29
|
|
15
|
-
def
|
16
|
-
Source.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
30
|
+
def list_all
|
31
|
+
sets = Source.all_sets
|
32
|
+
sets.each {|s| puts @presenter.describe(s)}
|
33
|
+
puts "\n#{sets.count} pods were found"
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_new
|
37
|
+
days = [1,2,3,5,8]
|
38
|
+
dates, groups = {}, {}
|
39
|
+
days.each {|d| dates[d] = Time.now - 60 * 60 * 24 * d}
|
40
|
+
sets = Source.all_sets
|
41
|
+
creation_dates = Pod::Specification::Statistics.instance.creation_dates(sets)
|
42
|
+
|
43
|
+
sets.each do |set|
|
44
|
+
set_date = creation_dates[set.name]
|
45
|
+
days.each do |d|
|
46
|
+
if set_date >= dates[d]
|
47
|
+
groups[d] = [] unless groups[d]
|
48
|
+
groups[d] << set
|
49
|
+
break
|
50
|
+
end
|
21
51
|
end
|
22
52
|
end
|
53
|
+
days.reverse.each do |d|
|
54
|
+
sets = groups[d]
|
55
|
+
next unless sets
|
56
|
+
puts "\nPods added in the last #{d == 1 ? 'day' : "#{d} days"}".yellow
|
57
|
+
sets.sort_by {|s| creation_dates[s.name]}.each {|s| puts @presenter.describe(s)}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def run
|
62
|
+
puts "\nUpdating Spec Repositories\n".yellow if @update && config.verbose?
|
63
|
+
Repo.new(ARGV.new(["update"])).run if @update
|
64
|
+
@new ? list_new : list_all
|
65
|
+
puts
|
23
66
|
end
|
24
67
|
end
|
25
68
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Presenter
|
4
|
+
def self.options
|
5
|
+
[["--stats", "Show additional stats (like GitHub watchers and forks)"]]
|
6
|
+
end
|
7
|
+
|
8
|
+
autoload :CocoaPod, 'cocoapods/command/presenter/cocoa_pod'
|
9
|
+
|
10
|
+
def initialize(argv)
|
11
|
+
@stats = argv.option('--stats')
|
12
|
+
end
|
13
|
+
|
14
|
+
def render(array)
|
15
|
+
result = "\n"
|
16
|
+
seats.each {|s| puts describe(s)}
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def describe(set)
|
21
|
+
pod = CocoaPod.new(set)
|
22
|
+
result = "\n--> #{pod.name} (#{pod.versions})\n".green
|
23
|
+
result << wrap_string(pod.summary)
|
24
|
+
result << detail('Homepage', pod.homepage)
|
25
|
+
result << detail('Source', pod.source_url)
|
26
|
+
if @stats
|
27
|
+
result << detail('Pushed', pod.github_last_activity)
|
28
|
+
result << detail('Authors', pod.authors) if pod.authors =~ /,/
|
29
|
+
result << detail('Author', pod.authors) if pod.authors !~ /,/
|
30
|
+
result << detail('License', pod.license)
|
31
|
+
result << detail('Platform', pod.platform)
|
32
|
+
result << detail('Watchers', pod.github_watchers)
|
33
|
+
result << detail('Forks', pod.github_forks)
|
34
|
+
end
|
35
|
+
result << detail('Sub specs', pod.subspecs)
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# adapted from http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
|
42
|
+
def wrap_string(txt, col = 80, indentation = 4)
|
43
|
+
indent = ' ' * indentation
|
44
|
+
txt.strip.gsub(/(.{1,#{col}})( +|$)\n?|(.{#{col}})/, indent + "\\1\\3\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
def detail(title, value)
|
48
|
+
return '' if !value
|
49
|
+
''.tap do |t|
|
50
|
+
t << " - #{title}:".ljust(16)
|
51
|
+
if value.class == Array
|
52
|
+
separator = "\n - "
|
53
|
+
t << separator << value.join(separator)
|
54
|
+
else
|
55
|
+
t << value.to_s << "\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Presenter
|
4
|
+
class CocoaPod
|
5
|
+
attr_accessor :set
|
6
|
+
|
7
|
+
def initialize(set)
|
8
|
+
@set = set
|
9
|
+
end
|
10
|
+
|
11
|
+
# set information
|
12
|
+
def name
|
13
|
+
@set.name
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
@set.versions.last
|
18
|
+
end
|
19
|
+
|
20
|
+
def versions
|
21
|
+
@set.versions.reverse.join(", ")
|
22
|
+
end
|
23
|
+
|
24
|
+
# specification information
|
25
|
+
def spec
|
26
|
+
@set.specification
|
27
|
+
end
|
28
|
+
|
29
|
+
def authors
|
30
|
+
oxfordify spec.authors.keys
|
31
|
+
end
|
32
|
+
|
33
|
+
def homepage
|
34
|
+
spec.homepage
|
35
|
+
end
|
36
|
+
|
37
|
+
def description
|
38
|
+
spec.description
|
39
|
+
end
|
40
|
+
|
41
|
+
def summary
|
42
|
+
spec.summary
|
43
|
+
end
|
44
|
+
|
45
|
+
def source_url
|
46
|
+
spec.source.reject {|k,_| k == :commit || k == :tag }.values.first
|
47
|
+
end
|
48
|
+
|
49
|
+
def platform
|
50
|
+
spec.available_platforms.sort { |a,b| a.to_s.downcase <=> b.to_s.downcase }.join(' - ')
|
51
|
+
end
|
52
|
+
|
53
|
+
def license
|
54
|
+
spec.license[:type] if spec.license
|
55
|
+
end
|
56
|
+
|
57
|
+
# will return array of all subspecs (recursevly) or nil
|
58
|
+
def subspecs
|
59
|
+
(spec.recursive_subspecs.any? && spec.recursive_subspecs) || nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Statistics information
|
63
|
+
def creation_date
|
64
|
+
Pod::Specification::Statistics.instance.creation_date(@set)
|
65
|
+
end
|
66
|
+
|
67
|
+
def github_watchers
|
68
|
+
Pod::Specification::Statistics.instance.github_watchers(@set)
|
69
|
+
end
|
70
|
+
|
71
|
+
def github_forks
|
72
|
+
Pod::Specification::Statistics.instance.github_forks(@set)
|
73
|
+
end
|
74
|
+
|
75
|
+
def github_last_activity
|
76
|
+
distance_from_now_in_words(Pod::Specification::Statistics.instance.github_pushed_at(@set))
|
77
|
+
end
|
78
|
+
|
79
|
+
def ==(other)
|
80
|
+
self.class === other && @set == other.set
|
81
|
+
end
|
82
|
+
|
83
|
+
def eql?(other)
|
84
|
+
self.class === other && name.eql?(other.name)
|
85
|
+
end
|
86
|
+
|
87
|
+
def hash
|
88
|
+
name.hash
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
def oxfordify words
|
93
|
+
if words.size < 3
|
94
|
+
words.join ' and '
|
95
|
+
else
|
96
|
+
"#{words[0..-2].join(', ')}, and #{words.last}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def distance_from_now_in_words(from_time)
|
101
|
+
return nil unless from_time
|
102
|
+
from_time = Time.parse(from_time)
|
103
|
+
to_time = Time.now
|
104
|
+
distance_in_days = (((to_time - from_time).abs)/60/60/24).round
|
105
|
+
|
106
|
+
case distance_in_days
|
107
|
+
when 0..7
|
108
|
+
"less than a week ago"
|
109
|
+
when 8..29
|
110
|
+
"#{distance_in_days} days ago"
|
111
|
+
when 30..45
|
112
|
+
"1 month ago"
|
113
|
+
when 46..365
|
114
|
+
"#{(distance_in_days.to_f / 30).round} months ago"
|
115
|
+
else
|
116
|
+
"more than a year ago"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Push < Command
|
6
|
+
def self.banner
|
7
|
+
%{Pushing new specifications to a spec-repo:
|
8
|
+
|
9
|
+
$ pod push [REPO]
|
10
|
+
|
11
|
+
Validates `*.podspec' in the current working dir, updates
|
12
|
+
the local copy of the repository named REPO, adds specifications
|
13
|
+
to REPO, and finally it pushes REPO to its remote.}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.options
|
17
|
+
[["--allow-warnings", "Allows to push if warnings are not evitable"]].concat(super)
|
18
|
+
end
|
19
|
+
|
20
|
+
extend Executable
|
21
|
+
executable :git
|
22
|
+
|
23
|
+
def initialize(argv)
|
24
|
+
@allow_warnings = argv.option('--allow-warnings')
|
25
|
+
@repo = argv.shift_argument
|
26
|
+
super unless argv.empty? && @repo
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
validate_podspec_files
|
31
|
+
check_repo_status
|
32
|
+
update_repo
|
33
|
+
add_specs_to_repo
|
34
|
+
push_repo
|
35
|
+
puts
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def update_repo
|
41
|
+
puts "Updating the `#{@repo}' repo\n".yellow unless config.silent
|
42
|
+
# show the output of git even if not verbose
|
43
|
+
Dir.chdir(repo_dir) { puts `git pull 2>&1` }
|
44
|
+
end
|
45
|
+
|
46
|
+
def push_repo
|
47
|
+
puts "\nPushing the `#{@repo}' repo\n".yellow unless config.silent
|
48
|
+
Dir.chdir(repo_dir) { puts `git push 2>&1` }
|
49
|
+
end
|
50
|
+
|
51
|
+
def repo_dir
|
52
|
+
dir = config.repos_dir + @repo
|
53
|
+
raise Informative, "[!] `#{@repo}' repo not found".red unless dir.exist?
|
54
|
+
dir
|
55
|
+
end
|
56
|
+
|
57
|
+
def check_repo_status
|
58
|
+
# TODO: add specs for staged and unstaged files (tested manually)
|
59
|
+
clean = Dir.chdir(repo_dir) { `git status --porcelain 2>&1` } == ''
|
60
|
+
raise Informative, "[!] `#{@repo}' repo not clean".red unless clean
|
61
|
+
end
|
62
|
+
|
63
|
+
def podspec_files
|
64
|
+
files = Pathname.glob("*.podspec")
|
65
|
+
raise Informative, "[!] Couldn't find .podspec file in current directory".red if files.empty?
|
66
|
+
files
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_podspec_files
|
70
|
+
puts "\nValidating specs".yellow unless config.silent
|
71
|
+
lint_argv = ["lint"]
|
72
|
+
lint_argv << "--only-errors" if @allow_warnings
|
73
|
+
lint_argv << "--silent" if config.silent
|
74
|
+
all_valid = Spec.new(ARGV.new(lint_argv)).run
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_specs_to_repo
|
78
|
+
puts "\nAdding the specs to the #{@repo} repo\n".yellow unless config.silent
|
79
|
+
podspec_files.each do |spec_file|
|
80
|
+
spec = Pod::Specification.from_file(spec_file)
|
81
|
+
output_path = File.join(repo_dir, spec.name, spec.version.to_s)
|
82
|
+
if Pathname.new(output_path).exist?
|
83
|
+
message = "[Fix] #{spec}"
|
84
|
+
elsif Pathname.new(File.join(repo_dir, spec.name)).exist?
|
85
|
+
message = "[Update] #{spec}"
|
86
|
+
else
|
87
|
+
message = "[Add] #{spec}"
|
88
|
+
end
|
89
|
+
puts " - #{message}" unless config.silent
|
90
|
+
|
91
|
+
FileUtils.mkdir_p(output_path)
|
92
|
+
FileUtils.cp(Pathname.new(spec.name+'.podspec'), output_path)
|
93
|
+
Dir.chdir(repo_dir) do
|
94
|
+
git("add #{spec.name}")
|
95
|
+
# Bypass the pre-commit hook because we already performed validation
|
96
|
+
git("commit --no-verify -m '#{message}'")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|