ios_toolchain 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 296632c1b4ca5e414c844f10e76f10923fcd9312
4
+ data.tar.gz: fac4e0181fced81f6e204f2904d2b202e669b5f9
5
+ SHA512:
6
+ metadata.gz: 32e9e80fcbe92b6686f1ebfb7727aa1c41031dcf94488f85e95c9dcdd864913bc9dca8b8112efdb0fe941d6b2c367319d80e0cbdd4e7342f8ba5aa13ff337c0f
7
+ data.tar.gz: c946c48dbd8f8f7bc906a495acd00e8f9c3c46bee6a2d0ff3647f6386c6b7b7f17eac2433dcefcd90ede05cda8c18f7f7b5ef5fd5c96df59745532b2bb88dc74
data/.gitignore ADDED
@@ -0,0 +1,81 @@
1
+ # Xcode
2
+ #
3
+ # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4
+
5
+ ## Build generated
6
+ build/
7
+ DerivedData/
8
+
9
+ ## Various settings
10
+ *.pbxuser
11
+ !default.pbxuser
12
+ *.mode1v3
13
+ !default.mode1v3
14
+ *.mode2v3
15
+ !default.mode2v3
16
+ *.perspectivev3
17
+ !default.perspectivev3
18
+ xcuserdata/
19
+
20
+ ## Other
21
+ *.moved-aside
22
+ *.xcuserstate
23
+
24
+ ## Obj-C/Swift specific
25
+ *.hmap
26
+ *.ipa
27
+ *.dSYM.zip
28
+ *.dSYM
29
+
30
+ ## Playgrounds
31
+ timeline.xctimeline
32
+ playground.xcworkspace
33
+
34
+ # Swift Package Manager
35
+ #
36
+ # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37
+ # Packages/
38
+ .build/
39
+
40
+ # CocoaPods
41
+ #
42
+ # We recommend against adding the Pods directory to your .gitignore. However
43
+ # you should judge for yourself, the pros and cons are mentioned at:
44
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45
+ #
46
+ # Pods/
47
+
48
+ # Carthage
49
+ #
50
+ # Add this line if you want to avoid checking in source code from Carthage dependencies.
51
+ # Carthage/Checkouts
52
+
53
+ Carthage/Build
54
+
55
+ # fastlane
56
+ #
57
+ # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58
+ # screenshots whenever they are needed.
59
+ # For more information about the recommended setup visit:
60
+ # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61
+
62
+ fastlane/report.xml
63
+ fastlane/Preview.html
64
+ fastlane/screenshots
65
+ fastlane/test_output
66
+
67
+
68
+
69
+ /.bundle/
70
+ /.yardoc
71
+ /Gemfile.lock
72
+ /_yardoc/
73
+ /coverage/
74
+ /doc/
75
+ /pkg/
76
+ /spec/reports/
77
+ /tmp/
78
+ *.gem
79
+
80
+ # rspec failure tracking
81
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.4.0
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.14.3
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at dschmidt@pivotal.io. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ios_toolchain.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Dennis Schmidt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # iOS Toolchain
2
+
3
+ A collection of `rake` tasks that help you keep a clean codebase and ease some of the daily pains when working in teams, like handling provisioning certificates.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ios_toolchain'
11
+ ```
12
+
13
+ Next, you need to make the included rake tasks available to your environment.
14
+
15
+ Add the following line to your `Rakefile`:
16
+
17
+ ```ruby
18
+ require 'ios_toolchain/tasks'
19
+ ```
20
+
21
+ Once this is done, verify that the tasks are now available by checking the output of `rake -T`.
22
+
23
+ Finally, most tasks require some configuration, e.g. to know where your Xcode project is located and what schemes and tasks exist. This configuration is read from a `.ios_toolchain.yml` file, which still needs to be created. Run
24
+
25
+ ```shell
26
+ $ rake toolchain:bootstrap
27
+ ```
28
+
29
+ You should now have an automatically configured `.ios_toolchain.yml`, which you can open in the editor of your choice if you need any further customization.
30
+
31
+ **Important Note:** For the above auto configuration, it is assumed that your `*.xcodeproj` file is in the root of your repository, which is also where the `.ios_toolchain.yml` *has* to be located. If your project structure differs, you can pass the path to your Xcode project file as an optional paramater to the above command.
32
+
33
+ ## Usage
34
+
35
+ ### Tasks
36
+ This is the full list of available tasks, as output by `rake -T`:
37
+
38
+ rake git:check_for_uncommitted_changes # Checks for uncommitted changes and aborts if any are found
39
+ rake git:push_origin # Pushes the current branch to origin
40
+ rake ios:build:acceptance # Builds the app with Acceptance configuration
41
+ rake ios:build:beta # Builds the app with Beta configuration
42
+ rake ios:build:default # Builds the app with Default configuration
43
+ rake ios:build:with[output_path,configuration] # Builds the app with specified Configuration to output path
44
+ rake ios:carthage:fetch # Fetches our Carthage dependencies to the locked in versions
45
+ rake ios:carthage:update # updates our Carthage dependencies to the latest version
46
+ rake ios:clean # Cleans the build & resets simulator
47
+ rake ios:clean:build # Cleans the build
48
+ rake ios:clean:simulator # Resets the simulator
49
+ rake ios:export:archive[xcarchive_path,ipa_path] # builds the app
50
+ rake ios:provisioning:copy # copies provisioning profiles from the repo to the appropriate system location
51
+ rake ios:specs # Run all the tests: unit and UI, 32bit and 64bit
52
+ rake ios:specs:slim # Run 64bit unit tests only
53
+ rake ios:specs:ui[skip_32bit] # Run the UI tests (optionally skip 32 bit devices)
54
+ rake ios:specs:unit[skip_32bit] # Run the unit tests (optionally skip 32 bit devices)
55
+ rake ios:tidy # Reports and attempts to tidy up common cleanliness problems with the codebase
56
+ rake ios:tidy:lint # Runs swiftlint
57
+ rake ios:tidy:project_file # Sorts the project file
58
+ rake ios:tidy:specs # Unfocusses any focussed Quick specs
59
+ rake ios:tidy:whitespace # Removes trailing whitespace from code files
60
+ rake shipit # Checks that we're ready to push, and then pushes the current branch to origin
61
+ rake toolchain:bootstrap[project_path] # Bootstraps iOS Toolchain configuration (project_path optional)
62
+ rake validate # Checks you if you need to do any cleanup of the code before you push
63
+
64
+ ## Contributing
65
+
66
+ Bug reports and pull requests are welcome on GitHub at https://github.com/dmrschmidt/ios_toolchain. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
67
+
68
+ ## Development
69
+
70
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
71
+
72
+ To install this gem onto your local machine, run `bundle exec rake install`.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ios_toolchain"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ echo "Make brew up-to-date"
9
+ brew update
10
+ brew doctor
11
+ brew upgrade
12
+
13
+ echo "Install Swiftlint"
14
+ brew install swiftlint
15
+
16
+ echo "Install Carthage"
17
+ brew install carthage
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ios_toolchain/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ios_toolchain"
8
+ spec.version = IosToolchain::VERSION
9
+ spec.authors = ["Dennis Schmidt"]
10
+ spec.email = ["dschmidt@pivotal.io"]
11
+
12
+ spec.summary = "Collection of rake tasks and scripts to ease iOS development."
13
+ spec.description = "Collection of rake tasks and scripts to ease iOS development."
14
+ spec.homepage = "http://github.com/dmrschmidt/ios_toolchain"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.0"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
+
26
+ spec.add_dependency "rake", "~> 12.0"
27
+ spec.add_dependency "xcodeproj", "~> 1.4"
28
+ spec.add_dependency "bundler", "~> 1.0"
29
+ spec.add_dependency "xcpretty", "~> 0.2"
30
+ end
@@ -0,0 +1,5 @@
1
+ require "ios_toolchain/version"
2
+ require "ios_toolchain/tasks"
3
+
4
+ module IosToolchain
5
+ end
@@ -0,0 +1,71 @@
1
+ require 'yaml'
2
+ require 'bundler'
3
+
4
+ module IosToolchain
5
+ class Config
6
+ def project_file_path
7
+ config_yaml['project-file-path']
8
+ end
9
+
10
+ def default_sdk
11
+ config_yaml['default-sdk']
12
+ end
13
+
14
+ def default_scheme
15
+ config_yaml['default-scheme']
16
+ end
17
+
18
+ def default_32bit_test_device
19
+ config_yaml['default-32bit-test-device']
20
+ end
21
+
22
+ def default_64bit_test_device
23
+ config_yaml['default-64bit-test-device']
24
+ end
25
+
26
+ def app_targets
27
+ config_yaml['app-targets']
28
+ end
29
+
30
+ def test_targets
31
+ config_yaml['test-targets'] || []
32
+ end
33
+
34
+ def ui_test_targets
35
+ config_yaml['ui-test-targets'] || []
36
+ end
37
+
38
+ def provisioning_path
39
+ config_yaml['provisioning-path']
40
+ end
41
+
42
+ def crashlytics_framework_path
43
+ config_yaml['crashlytics-framework-path']
44
+ end
45
+
46
+ def crashlytics_installed?
47
+ File.exists?(config_file_path) && !crashlytics_framework_path.nil?
48
+ end
49
+
50
+ def file_name
51
+ '.ios_toolchain.yml'
52
+ end
53
+
54
+ private
55
+
56
+ def config_file_path
57
+ File.join(Bundler.root, file_name)
58
+ end
59
+
60
+ def config_yaml
61
+ YAML.load_file(config_file_path) || {}
62
+ rescue
63
+ puts "\033[1;33m"
64
+ puts "WARNING: no #{file_name} config file found."
65
+ puts 'Run `rake toolchain:bootstrap`.'
66
+ puts "\033[0m"
67
+ exit
68
+ {}
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ require 'yaml'
2
+ require 'ios_toolchain/config'
3
+
4
+ module IosToolchain
5
+ class ConfigBootstrapper
6
+ def initialize(project_analyzer)
7
+ @analyzer = project_analyzer
8
+ end
9
+
10
+ def bootstrap!
11
+ File.open(config_file_path, 'w') do |file|
12
+ file.write config.to_yaml
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def config_file_name
19
+ Config.new.file_name
20
+ end
21
+
22
+ def config_file_path
23
+ File.join(analyzer.project_root, config_file_name)
24
+ end
25
+
26
+ def config
27
+ {
28
+ 'project-file-path' => analyzer.project_path,
29
+ 'default-scheme' => analyzer.default_scheme,
30
+ 'default-sdk' => 'iphoneos10.2',
31
+ 'default-32bit-test-device' => "'iOS Simulator,OS=10.2,name=iPhone 5'",
32
+ 'default-64bit-test-device' => "'iOS Simulator,OS=10.2,name=iPhone 7'",
33
+ 'app-targets' => analyzer.app_targets,
34
+ 'test-targets' => analyzer.test_targets,
35
+ 'ui-test-targets' => analyzer.ui_test_targets,
36
+ 'provisioning-path' => "#{File.join(analyzer.project_root, 'provisioning')}",
37
+ 'crashlytics-framework-path' => analyzer.crashlytics_framework_path
38
+ }
39
+ end
40
+
41
+ attr_reader :analyzer
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ require 'ios_toolchain/config'
2
+
3
+ module IosToolchain
4
+ module Helpers
5
+ LINE_LENGTH = 45
6
+
7
+ def config
8
+ @config ||= IosToolchain::Config.new
9
+ end
10
+
11
+ def bail(msg="Uh oh, looks like something isn't right")
12
+ puts "\n\n"
13
+ puts "👎 👎 👎 👎 👎 👎 👎 👎 👎 👎 👎 👎 "
14
+ print_msg(msg)
15
+ puts "👎 👎 👎 👎 👎 👎 👎 👎 👎 👎 👎 👎 "
16
+ abort
17
+ end
18
+
19
+ private
20
+
21
+ def print_msg(msg)
22
+ msg_words = msg.split(" ")
23
+ msg_lines = []
24
+
25
+ msg_line = "💩 "
26
+ msg_words.each do |word|
27
+ if msg_line.length + word.length + 2 <= LINE_LENGTH
28
+ msg_line = "#{msg_line} #{word}"
29
+ else
30
+ msg_line = pad_poo(msg_line)
31
+ msg_lines.push(msg_line)
32
+ msg_line = "💩 #{word}"
33
+ end
34
+ end
35
+
36
+ last_line = msg_lines.last
37
+ msg_lines.push(pad_poo(msg_line)) unless msg_line =~ /💩$/
38
+
39
+ msg_lines.each { |line| puts line }
40
+ end
41
+
42
+ def pad_poo(msg_line)
43
+ padding = LINE_LENGTH - msg_line.length - 3
44
+ padding = padding < 0 ? 0 : padding
45
+ "#{msg_line}#{' ' * padding} 💩"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,65 @@
1
+ require 'xcodeproj'
2
+ require 'pathname'
3
+
4
+ module IosToolchain
5
+ class ProjectAnalyzer
6
+ attr_reader :project_root, :project_path
7
+
8
+ def initialize(project_root)
9
+ @project_root = Pathname.new(project_root).realpath.to_s
10
+ @project_path = find_project_path!
11
+ @project = Xcodeproj::Project.open(@project_path)
12
+ end
13
+
14
+ def default_scheme
15
+ shared_schemes.find { |name| name == project_name }
16
+ end
17
+
18
+ def default_sdk
19
+ end
20
+
21
+ def crashlytics_framework_path
22
+ Dir.glob("#{project_root}/**/Crashlytics.framework").first
23
+ end
24
+
25
+ def app_targets
26
+ project.targets.map(&:name).find_all do |name|
27
+ !name.include?('Tests')
28
+ end
29
+ end
30
+
31
+ def test_targets
32
+ project.targets.map(&:name).find_all do |name|
33
+ name.include?('Tests') && !name.include?('UITests')
34
+ end
35
+ end
36
+
37
+ def ui_test_targets
38
+ project.targets.map(&:name).find_all do |name|
39
+ name.include?('UITests')
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def shared_schemes
46
+ Xcodeproj::Project.schemes(project_path)
47
+ end
48
+
49
+ def project_name
50
+ project_path.split(File::SEPARATOR)[-1].split('.')[-2]
51
+ end
52
+
53
+ def find_project_path!
54
+ Dir.glob(File.join(project_root, '/*.xcodeproj')).first.tap do |project|
55
+ return project unless project.nil?
56
+
57
+ error_message = "No .xcodeproj file was found in #{project_root} "
58
+ error_message += "Run `rake toolchain:bootstrap[/path/containing/project/]`"
59
+ throw error_message
60
+ end
61
+ end
62
+
63
+ attr_reader :project
64
+ end
65
+ end
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/perl -w
2
+
3
+ # Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
8
+ #
9
+ # 1. Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # 2. Redistributions in binary form must reproduce the above copyright
12
+ # notice, this list of conditions and the following disclaimer in the
13
+ # documentation and/or other materials provided with the distribution.
14
+ # 3. Neither the name of Apple Inc. ("Apple") nor the names of
15
+ # its contributors may be used to endorse or promote products derived
16
+ # from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19
+ # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ # Script to sort "children" and "files" sections in Xcode project.pbxproj files
30
+
31
+ use strict;
32
+
33
+ use File::Basename;
34
+ use File::Spec;
35
+ use File::Temp qw(tempfile);
36
+ use Getopt::Long;
37
+
38
+ sub sortChildrenByFileName($$);
39
+ sub sortFilesByFileName($$);
40
+
41
+ # Files (or products) without extensions
42
+ my %isFile = map { $_ => 1 } qw(
43
+ create_hash_table
44
+ jsc
45
+ minidom
46
+ testapi
47
+ testjsglue
48
+ );
49
+
50
+ my $printWarnings = 1;
51
+ my $showHelp;
52
+
53
+ my $getOptionsResult = GetOptions(
54
+ 'h|help' => \$showHelp,
55
+ 'w|warnings!' => \$printWarnings,
56
+ );
57
+
58
+ if (scalar(@ARGV) == 0 && !$showHelp) {
59
+ print STDERR "ERROR: No Xcode project files (project.pbxproj) listed on command-line.\n";
60
+ undef $getOptionsResult;
61
+ }
62
+
63
+ if (!$getOptionsResult || $showHelp) {
64
+ print STDERR <<__END__;
65
+ Usage: @{[ basename($0) ]} [options] path/to/project.pbxproj [path/to/project.pbxproj ...]
66
+ -h|--help show this help message
67
+ -w|--[no-]warnings show or suppress warnings (default: show warnings)
68
+ __END__
69
+ exit 1;
70
+ }
71
+
72
+ for my $projectFile (@ARGV) {
73
+ if (basename($projectFile) =~ /\.xcodeproj$/) {
74
+ $projectFile = File::Spec->catfile($projectFile, "project.pbxproj");
75
+ }
76
+
77
+ if (basename($projectFile) ne "project.pbxproj") {
78
+ print STDERR "WARNING: Not an Xcode project file: $projectFile\n" if $printWarnings;
79
+ next;
80
+ }
81
+
82
+ # Grab the mainGroup for the project file
83
+ my $mainGroup = "";
84
+ open(IN, "< $projectFile") || die "Could not open $projectFile: $!";
85
+ while (my $line = <IN>) {
86
+ $mainGroup = $2 if $line =~ m#^(\s*)mainGroup = ([0-9A-F]{24} /\* .+ \*/);$#;
87
+ }
88
+ close(IN);
89
+
90
+ my ($OUT, $tempFileName) = tempfile(
91
+ basename($projectFile) . "-XXXXXXXX",
92
+ DIR => dirname($projectFile),
93
+ UNLINK => 0,
94
+ );
95
+
96
+ # Clean up temp file in case of die()
97
+ $SIG{__DIE__} = sub {
98
+ close(IN);
99
+ close($OUT);
100
+ unlink($tempFileName);
101
+ };
102
+
103
+ my @lastTwo = ();
104
+ open(IN, "< $projectFile") || die "Could not open $projectFile: $!";
105
+ while (my $line = <IN>) {
106
+ if ($line =~ /^(\s*)files = \(\s*$/) {
107
+ print $OUT $line;
108
+ my $endMarker = $1 . ");";
109
+ my @files;
110
+ while (my $fileLine = <IN>) {
111
+ if ($fileLine =~ /^\Q$endMarker\E\s*$/) {
112
+ $endMarker = $fileLine;
113
+ last;
114
+ }
115
+ push @files, $fileLine;
116
+ }
117
+ print $OUT sort sortFilesByFileName @files;
118
+ print $OUT $endMarker;
119
+ } elsif ($line =~ /^(\s*)children = \(\s*$/) {
120
+ print $OUT $line;
121
+ my $endMarker = $1 . ");";
122
+ my @children;
123
+ while (my $childLine = <IN>) {
124
+ if ($childLine =~ /^\Q$endMarker\E\s*$/) {
125
+ $endMarker = $childLine;
126
+ last;
127
+ }
128
+ push @children, $childLine;
129
+ }
130
+ if ($lastTwo[0] =~ m#^\s+\Q$mainGroup\E = \{$#) {
131
+ # Don't sort mainGroup
132
+ print $OUT @children;
133
+ } else {
134
+ print $OUT sort sortChildrenByFileName @children;
135
+ }
136
+ print $OUT $endMarker;
137
+ } else {
138
+ print $OUT $line;
139
+ }
140
+
141
+ push @lastTwo, $line;
142
+ shift @lastTwo if scalar(@lastTwo) > 2;
143
+ }
144
+ close(IN);
145
+ close($OUT);
146
+
147
+ unlink($projectFile) || die "Could not delete $projectFile: $!";
148
+ rename($tempFileName, $projectFile) || die "Could not rename $tempFileName to $projectFile: $!";
149
+ }
150
+
151
+ exit 0;
152
+
153
+ sub sortChildrenByFileName($$)
154
+ {
155
+ my ($a, $b) = @_;
156
+ my $aFileName = $1 if $a =~ /^\s*[A-Z0-9]{24} \/\* (.+) \*\/,$/;
157
+ my $bFileName = $1 if $b =~ /^\s*[A-Z0-9]{24} \/\* (.+) \*\/,$/;
158
+ my $aSuffix = $1 if $aFileName =~ m/\.([^.]+)$/;
159
+ my $bSuffix = $1 if $bFileName =~ m/\.([^.]+)$/;
160
+ if ((!$aSuffix && !$isFile{$aFileName} && $bSuffix) || ($aSuffix && !$bSuffix && !$isFile{$bFileName})) {
161
+ return !$aSuffix ? -1 : 1;
162
+ }
163
+ return lc($aFileName) cmp lc($bFileName);
164
+ }
165
+
166
+ sub sortFilesByFileName($$)
167
+ {
168
+ my ($a, $b) = @_;
169
+ my $aFileName = $1 if $a =~ /^\s*[A-Z0-9]{24} \/\* (.+) in /;
170
+ my $bFileName = $1 if $b =~ /^\s*[A-Z0-9]{24} \/\* (.+) in /;
171
+ return lc($aFileName) cmp lc($bFileName);
172
+ }
@@ -0,0 +1,15 @@
1
+ require 'rake'
2
+ require 'ios_toolchain/config_bootstrapper'
3
+ require 'ios_toolchain/project_analyzer'
4
+
5
+ module IosToolchain
6
+ class Tasks
7
+ include Rake::DSL if defined? Rake::DSL
8
+
9
+ def install_tasks
10
+ tasks_path = File.expand_path('../tasks/**/*.rake', __FILE__)
11
+ Dir.glob(tasks_path).each { |file| load file }
12
+ end
13
+ end
14
+ end
15
+ IosToolchain::Tasks.new.install_tasks
@@ -0,0 +1,19 @@
1
+ require 'ios_toolchain/helpers'
2
+ require 'ios_toolchain/project_analyzer'
3
+ require 'ios_toolchain/config_bootstrapper'
4
+
5
+ include IosToolchain::Helpers
6
+
7
+ desc 'iOS Toolchain maintenance tasks'
8
+ namespace :toolchain do
9
+ desc "Bootstraps iOS Toolchain configuration (project_path optional)"
10
+ task :bootstrap, :project_path do |t, args|
11
+ args.with_defaults(:project_path => Bundler.root)
12
+
13
+ analyzer = IosToolchain::ProjectAnalyzer.new(args[:project_path])
14
+ bootstrapper = IosToolchain::ConfigBootstrapper.new(analyzer)
15
+ bootstrapper.bootstrap!
16
+
17
+ puts "Created #{config.file_name}."
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ include IosToolchain::Helpers
2
+
3
+ namespace :git do
4
+ desc "Checks for uncommitted changes and aborts if any are found"
5
+ task :check_for_uncommitted_changes do
6
+ puts "Checking for uncommitted changes..."
7
+ if `git status -s`.chomp.length > 0
8
+ system("git status")
9
+ bail("Uncommitted changes detected (maybe something got auto-corrected?). Please commit these and try again.")
10
+ end
11
+ puts "Done!"
12
+ end
13
+
14
+ desc "Pushes the current branch to origin"
15
+ task :push_origin do
16
+ system("git push origin head") || bail
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ require 'ios_toolchain/helpers'
2
+
3
+ include IosToolchain::Helpers
4
+
5
+ namespace :ios do
6
+ desc 'Builds the app'
7
+ namespace :build do
8
+ desc 'Builds the app with specified Configuration to output path'
9
+ task :with, :output_path, :configuration do |t, args|
10
+ args.with_defaults(:output_path => 'archive')
11
+
12
+ puts '===================================='
13
+ puts "=== Building #{args[:configuration]} archive in #{args[:output_path]}"
14
+ puts '===================================='
15
+ build_cmd = []
16
+ build_cmd << "xcodebuild -project #{config.project_file_path}"
17
+ build_cmd << "-scheme #{config.default_scheme} SYMROOT=build OBJROOT=build archive"
18
+ build_cmd << "CODE_SIGNING_REQUIRED=YES -sdk #{config.default_sdk}"
19
+ build_cmd << "-configuration #{args[:configuration]}" if args[:configuration]
20
+ build_cmd << "-archivePath #{args[:output_path]}/#{config.default_scheme}.xcarchive"
21
+ build_cmd << "-derivedDataPath derived"
22
+ sh(build_cmd.join(' '))
23
+ end
24
+
25
+ desc 'Builds the app with Default configuration'
26
+ task :default do
27
+ Rake::Task['build:with'].invoke('archive', nil)
28
+ end
29
+
30
+ desc 'Builds the app with Acceptance configuration'
31
+ task :acceptance do
32
+ Rake::Task['build:with'].invoke('archive', 'Acceptance')
33
+ end
34
+
35
+ desc 'Builds the app with Beta configuration'
36
+ task :beta do
37
+ Rake::Task['build:with'].invoke('archive', 'Beta')
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ include IosToolchain::Helpers
2
+
3
+ namespace :ios do
4
+ desc 'Cleans the build & resets simulator'
5
+ task :clean => [:'clean:build']
6
+
7
+ desc "Cleans the build"
8
+ namespace :clean do
9
+ task :build do
10
+ puts "Cleaning..."
11
+
12
+ clean_cmd = []
13
+ clean_cmd << 'xcodebuild clean'
14
+ clean_cmd << 'rm -rf build'
15
+ system(clean_cmd.join("\n"))
16
+
17
+ puts "Done!"
18
+ end
19
+
20
+ desc 'Resets the simulator'
21
+ task :simulator do
22
+ puts "Resetting simulator..."
23
+
24
+ system("osascript -e 'tell application \"iOS Simulator\" to quit'") &&
25
+ system("osascript -e 'tell application \"Simulator\" to quit'") &&
26
+ system("xcrun simctl erase all")
27
+
28
+ puts "Done!"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ namespace :ios do
2
+ namespace :carthage do
3
+ desc "updates our Carthage dependencies to the latest version"
4
+ task :update do
5
+ carthage_cmd = []
6
+ carthage_cmd << "carthage"
7
+ carthage_cmd << "update"
8
+ carthage_cmd << "--platform ios"
9
+ carthage_cmd << "--no-use-binaries"
10
+ carthage_cmd = carthage_cmd.join(" ")
11
+
12
+ system(carthage_cmd)
13
+ end
14
+
15
+ desc "Fetches our Carthage dependencies to the locked in versions"
16
+ task :fetch do
17
+ carthage_cmd = []
18
+ carthage_cmd << "carthage"
19
+ carthage_cmd << "bootstrap"
20
+ carthage_cmd << "--platform ios"
21
+ carthage_cmd << "--no-use-binaries"
22
+ carthage_cmd = carthage_cmd.join(" ")
23
+
24
+ system(carthage_cmd)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'ios_toolchain/helpers'
2
+
3
+ include IosToolchain::Helpers
4
+
5
+ if config.crashlytics_installed?
6
+ namespace :ios do
7
+ namespace :distribute do
8
+ desc 'Distribute pre-built IPA to Crashlytics'
9
+ task :crashlytics, :ipa_path, :configuration do |t, args|
10
+ args.with_defaults(ipa_path: 'archive')
11
+ puts 'Distributing to crashlytics...'
12
+
13
+ build_cmd = []
14
+ build_cmd << "#{config.crashlytics_framework_path}/submit #{ENV['FABRIC_API_KEY']} #{ENV['FABRIC_BUILD_SECRET']}"
15
+ build_cmd << "-ipaPath #{args[:ipa_path]}/#{config.default_scheme}-#{args[:configuration]}.ipa"
16
+ build_cmd << "-groupAliases #{args[:configuration]}"
17
+ sh(build_cmd.join(' '))
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require 'ios_toolchain/helpers'
2
+
3
+ include IosToolchain::Helpers
4
+
5
+ namespace :ios do
6
+ desc 'builds the app'
7
+ namespace :export do
8
+ task :archive, [:xcarchive_path, :ipa_path] do |t, args|
9
+ args.with_defaults(:xcarchive_path => 'archive', :ipa_path => 'archive')
10
+
11
+ puts '===================================='
12
+ puts "=== Input Archive Path: in #{args[:xcarchive_path]}"
13
+ puts "=== Output IPA Path: in #{args[:ipa_path]}"
14
+ puts '===================================='
15
+
16
+
17
+ build_cmd = []
18
+ build_cmd << "xcodebuild -project #{config.project_file_path}"
19
+ build_cmd << '-exportArchive'
20
+ build_cmd << "-archivePath #{args[:xcarchive_path]}/#{config.default_scheme}.xcarchive"
21
+ build_cmd << "-exportPath #{args[:ipa_path]}/#{config.default_scheme}.ipa"
22
+ system(build_cmd.join(' '))
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ include IosToolchain::Helpers
2
+ require "fileutils"
3
+
4
+ namespace :ios do
5
+ desc 'helpers for dealing with provisiong'
6
+ namespace :provisioning do
7
+ desc 'copies provisioning profiles from the repo to the appropriate system location'
8
+ task :copy do
9
+ local_profiles_path = File.join(config.provisioning_path, '*')
10
+ system_profile_path = '~/Library/MobileDevice/Provisioning\ Profiles/'
11
+ puts "copying provisioning profiles from '#{local_profiles_path}' to '#{system_profile_path}'"
12
+ system("cp -r #{local_profiles_path} #{system_profile_path}")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,49 @@
1
+ require 'ios_toolchain/helpers'
2
+
3
+ include IosToolchain::Helpers
4
+
5
+ def build_specs_cmd(scheme, options={})
6
+ puts "Running specs for #{scheme}..."
7
+ specs_cmd = []
8
+ specs_cmd << 'set -o pipefail &&'
9
+ specs_cmd << "xcodebuild -workspace #{config.project_file_path}/project.xcworkspace"
10
+ specs_cmd << "-scheme #{scheme} test CODE_SIGNING_REQUIRED=NO -sdk iphonesimulator"
11
+ specs_cmd << "-destination platform=#{config.default_32bit_test_device}" unless options[:skip_32bit]
12
+ specs_cmd << "-destination platform=#{config.default_64bit_test_device}"
13
+ specs_cmd << '| bundle exec xcpretty'
14
+ specs_cmd = specs_cmd.join(" ")
15
+ end
16
+
17
+ def run_tests_or_bail(tests, args)
18
+ args.with_defaults(:skip_32bit => false)
19
+
20
+ Rake::Task['clean:build'].reenable
21
+ Rake::Task['clean:simulator'].reenable
22
+ tests.each do |target|
23
+ if(!system(build_specs_cmd(target, skip_32bit: args[:skip_32bit])))
24
+ bail("Specs failure - please fix the failing specs and try again.")
25
+ end
26
+ end
27
+ end
28
+
29
+ namespace :ios do
30
+ desc "Run all the tests: unit and UI, 32bit and 64bit"
31
+ task :specs => ['specs:unit', 'specs:ui']
32
+
33
+ namespace :specs do
34
+ desc "Run 64bit unit tests only"
35
+ task :slim do
36
+ Rake::Task['specs:unit'].invoke(skip_32bit: true)
37
+ end
38
+
39
+ desc "Run the unit tests (optionally skip 32 bit devices)"
40
+ task :unit, [:skip_32bit] => ['clean:build', 'clean:simulator'] do |task, args|
41
+ run_tests_or_bail(config.test_targets, args)
42
+ end
43
+
44
+ desc "Run the UI tests (optionally skip 32 bit devices)"
45
+ task :ui, [:skip_32bit] => ['clean:build', 'clean:simulator'] do |task, args|
46
+ run_tests_or_bail(config.ui_test_targets, args)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,64 @@
1
+ require 'ios_toolchain/helpers'
2
+
3
+ include IosToolchain::Helpers
4
+
5
+ namespace :ios do
6
+ desc "Reports and attempts to tidy up common cleanliness problems with the codebase"
7
+ task :tidy => ['tidy:project_file', 'tidy:specs', 'tidy:whitespace', 'tidy:lint']
8
+
9
+ namespace :tidy do
10
+ desc "Unfocusses any focussed Quick specs"
11
+ task :specs do
12
+ puts "Unfocussing specs..."
13
+
14
+ find_focussed_files_cmd = []
15
+ find_focussed_files_cmd << 'grep -l -r -e'
16
+ find_focussed_files_cmd << '"fit(\\|fdescribe(\\|fcontext"'
17
+ find_focussed_files_cmd << config.test_targets
18
+ find_focussed_files_cmd << '2>/dev/null'
19
+ find_focussed_files_cmd = find_focussed_files_cmd.join(' ')
20
+
21
+ `#{find_focussed_files_cmd}`.chomp.split("\n").each do |file_with_focussed_specs|
22
+ puts "#{file_with_focussed_specs}"
23
+ unfocus_cmd = []
24
+ unfocus_cmd << "sed -i ''"
25
+ unfocus_cmd << "-e 's/fit(/it(/g'"
26
+ unfocus_cmd << "-e 's/fdescribe(/describe(/g;'"
27
+ unfocus_cmd << "-e 's/fcontext(/context(/g;'"
28
+ unfocus_cmd << "\"#{file_with_focussed_specs}\""
29
+ unfocus_cmd = unfocus_cmd.join(" ")
30
+ system(unfocus_cmd)
31
+ end
32
+
33
+ puts "Done!"
34
+ end
35
+
36
+ desc "Sorts the project file"
37
+ task :project_file do
38
+ puts "Sorting the project file..."
39
+ system("script/sort-Xcode-project-file #{config.project_file_path}")
40
+ puts "Done!"
41
+ end
42
+
43
+ desc "Removes trailing whitespace from code files"
44
+ task :whitespace do
45
+ file_extensions = %w{ h m swift }
46
+ search_pattern = file_extensions.map { |ext| "-name \"*.#{ext}\""}.join(' -o ')
47
+ puts "Removing trailing whitespace..."
48
+ system("find #{config.app_targets.join(" ")} #{config.test_targets.join(" ")} #{search_pattern} -exec sed -i '' -e's/[ ]*$//' \"{}\" \\;")
49
+ puts "Done!"
50
+ end
51
+
52
+ desc "Runs swiftlint"
53
+ task :lint do
54
+ puts "Linting..."
55
+ if !system("which swiftlint")
56
+ bail("Swiftlint is not installed - please install via `brew install swiftlint`")
57
+ end
58
+ if !system("swiftlint lint --strict")
59
+ bail("Code hygeine problems were detected via swiftlint")
60
+ end
61
+ puts "Done!"
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+
2
+ desc "Checks that we're ready to push, and then pushes the current branch to origin"
3
+ task :shipit => [:validate, "git:push_origin"] do
4
+ puts "That ship has sailed! 😎"
5
+ end
@@ -0,0 +1,15 @@
1
+
2
+ desc "Checks you if you need to do any cleanup of the code before you push"
3
+ task :validate do
4
+ Rake::Task['git:check_for_uncommitted_changes'].invoke
5
+ Rake::Task['clean:build'].invoke
6
+ Rake::Task['tidy'].invoke
7
+ Rake::Task['git:check_for_uncommitted_changes'].reenable
8
+ Rake::Task['git:check_for_uncommitted_changes'].invoke
9
+ Rake::Task['specs:slim'].invoke
10
+ puts "\n\n"
11
+ puts "👍 👍 👍 👍 👍 👍 👍 👍 👍 👍 👍 👍 "
12
+ puts "🚢 Looks like you're good to ship! 🚢 "
13
+ puts "👍 👍 👍 👍 👍 👍 👍 👍 👍 👍 👍 👍 "
14
+ puts "\n\n"
15
+ end
@@ -0,0 +1,3 @@
1
+ module IosToolchain
2
+ VERSION = "0.2.0"
3
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ios_toolchain
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Dennis Schmidt
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: xcodeproj
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: xcpretty
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.2'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.2'
97
+ description: Collection of rake tasks and scripts to ease iOS development.
98
+ email:
99
+ - dschmidt@pivotal.io
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".ruby-version"
107
+ - ".travis.yml"
108
+ - CODE_OF_CONDUCT.md
109
+ - Gemfile
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - bin/console
114
+ - bin/setup
115
+ - ios_toolchain.gemspec
116
+ - lib/ios_toolchain.rb
117
+ - lib/ios_toolchain/config.rb
118
+ - lib/ios_toolchain/config_bootstrapper.rb
119
+ - lib/ios_toolchain/helpers.rb
120
+ - lib/ios_toolchain/project_analyzer.rb
121
+ - lib/ios_toolchain/scripts/sort-Xcode-project-file
122
+ - lib/ios_toolchain/tasks.rb
123
+ - lib/ios_toolchain/tasks/bootstrap.rake
124
+ - lib/ios_toolchain/tasks/git.rake
125
+ - lib/ios_toolchain/tasks/ios/build.rake
126
+ - lib/ios_toolchain/tasks/ios/clean.rake
127
+ - lib/ios_toolchain/tasks/ios/dependencies.rake
128
+ - lib/ios_toolchain/tasks/ios/distribute.rake
129
+ - lib/ios_toolchain/tasks/ios/export.rake
130
+ - lib/ios_toolchain/tasks/ios/provisioning.rake
131
+ - lib/ios_toolchain/tasks/ios/specs.rake
132
+ - lib/ios_toolchain/tasks/ios/tidy.rake
133
+ - lib/ios_toolchain/tasks/shipit.rake
134
+ - lib/ios_toolchain/tasks/validate.rake
135
+ - lib/ios_toolchain/version.rb
136
+ homepage: http://github.com/dmrschmidt/ios_toolchain
137
+ licenses: []
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.6.8
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Collection of rake tasks and scripts to ease iOS development.
159
+ test_files: []