xcode-install 2.6.6 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +13 -7
- data/.gitignore +1 -0
- data/.rubocop_todo.yml +160 -25
- data/Gemfile +1 -1
- data/README.md +13 -3
- data/XCODE_VERSION.md +49 -0
- data/lib/xcode/install/install.rb +6 -3
- data/lib/xcode/install/version.rb +1 -1
- data/lib/xcode/install.rb +82 -46
- data/spec/install_spec.rb +5 -5
- data/spec/installed_spec.rb +2 -2
- data/spec/json_spec.rb +6 -6
- data/spec/list_spec.rb +20 -4
- data/xcode-install.gemspec +1 -1
- metadata +17 -11
- data/.circleci/config.yml +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04e0e30f2230e52da44a3710cf8277f8d5e82e67d2a18d4dfa98fb9a3f40570e
|
4
|
+
data.tar.gz: 5c058cb7d8adcb3e4f800091cf7531ad8ad2010c243e8e685639df1feb658e04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21b099ccd6dd22bf8e7e652ea6ef8e1084260486784662c5781f8fa5ff169b75ec2d2dfb2cb855ba93de7a0e16519a73d9c0a07596e5b5c1d8eb70a0f2d3aae6
|
7
|
+
data.tar.gz: 5a14cef0170a25cdcc0d8dfd845f21463e0f7c38ae810a5e3328ce5f72a79eaa5fe380a70eee2c470b5395f791bce3e52ad551370491fd742e22718e8ce81626
|
data/.github/workflows/ci.yml
CHANGED
@@ -1,34 +1,40 @@
|
|
1
1
|
name: "CI"
|
2
|
-
on: [pull_request]
|
2
|
+
on: [push, pull_request]
|
3
3
|
|
4
4
|
jobs:
|
5
5
|
build:
|
6
6
|
strategy:
|
7
7
|
fail-fast: false
|
8
8
|
matrix:
|
9
|
-
ruby: ["2.5", "2.6"]
|
9
|
+
ruby: ["2.5", "2.6", "2.7", "3.0"]
|
10
10
|
|
11
11
|
runs-on: macos-latest
|
12
12
|
steps:
|
13
13
|
# Setup env
|
14
14
|
- uses: actions/checkout@v2
|
15
|
-
- uses:
|
15
|
+
- uses: ruby/setup-ruby@v1
|
16
16
|
with:
|
17
17
|
ruby-version: "${{ matrix.ruby }}"
|
18
18
|
|
19
19
|
# Show env
|
20
20
|
- name: Show macOS version
|
21
21
|
run: sw_vers
|
22
|
-
- name: Show
|
22
|
+
- name: Show env versions
|
23
23
|
run: |
|
24
24
|
ruby --version
|
25
25
|
bundler --version
|
26
|
+
echo $HOME
|
26
27
|
|
27
28
|
# Prepare
|
28
|
-
- name: Install bundler
|
29
|
-
run: gem install bundler -v "~>
|
29
|
+
- name: Install bundler 2.2.20
|
30
|
+
run: gem install bundler -v "~> 2.2.20"
|
30
31
|
- name: Install ruby dependencies
|
31
|
-
run:
|
32
|
+
run: |
|
33
|
+
bundle config --local clean 'true'
|
34
|
+
bundle config --local path '.vendor'
|
35
|
+
bundle config --local jobs 8
|
36
|
+
bundle config --local without 'system_tests'
|
37
|
+
bundle install
|
32
38
|
|
33
39
|
- name: Run test
|
34
40
|
run: bundle exec rake spec
|
data/.gitignore
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -1,78 +1,213 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2021-07-06 16:06:45 UTC using RuboCop version 1.12.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: Include.
|
11
|
+
# Include: **/*.gemspec
|
12
|
+
Gemspec/RequiredRubyVersion:
|
13
|
+
Exclude:
|
14
|
+
- 'xcode-install.gemspec'
|
15
|
+
|
9
16
|
# Offense count: 3
|
10
17
|
# Cop supports --auto-correct.
|
11
|
-
|
12
|
-
# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
|
13
|
-
Layout/IndentHeredoc:
|
18
|
+
Layout/ClosingHeredocIndentation:
|
14
19
|
Exclude:
|
15
20
|
- 'lib/xcode/install.rb'
|
16
21
|
|
17
22
|
# Offense count: 12
|
23
|
+
# Cop supports --auto-correct.
|
24
|
+
Layout/EmptyLineAfterGuardClause:
|
25
|
+
Exclude:
|
26
|
+
- 'lib/xcode/install.rb'
|
27
|
+
- 'lib/xcode/install/cleanup.rb'
|
28
|
+
- 'lib/xcode/install/simulators.rb'
|
29
|
+
- 'lib/xcode/install/uninstall.rb'
|
30
|
+
|
31
|
+
# Offense count: 3
|
32
|
+
# Cop supports --auto-correct.
|
33
|
+
Layout/HeredocIndentation:
|
34
|
+
Exclude:
|
35
|
+
- 'lib/xcode/install.rb'
|
36
|
+
|
37
|
+
# Offense count: 3
|
38
|
+
# Cop supports --auto-correct.
|
39
|
+
Lint/BooleanSymbol:
|
40
|
+
Exclude:
|
41
|
+
- 'lib/xcode/install/install.rb'
|
42
|
+
- 'lib/xcode/install/select.rb'
|
43
|
+
- 'lib/xcode/install/uninstall.rb'
|
44
|
+
|
45
|
+
# Offense count: 6
|
46
|
+
Lint/DuplicateMethods:
|
47
|
+
Exclude:
|
48
|
+
- 'lib/xcode/install.rb'
|
49
|
+
|
50
|
+
# Offense count: 2
|
51
|
+
# Configuration parameters: MaximumRangeSize.
|
52
|
+
Lint/MissingCopEnableDirective:
|
53
|
+
Exclude:
|
54
|
+
- 'lib/xcode/install.rb'
|
55
|
+
|
56
|
+
# Offense count: 1
|
57
|
+
# Cop supports --auto-correct.
|
58
|
+
Lint/UriRegexp:
|
59
|
+
Exclude:
|
60
|
+
- 'lib/xcode/install/install.rb'
|
61
|
+
|
62
|
+
# Offense count: 12
|
63
|
+
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
|
18
64
|
Metrics/AbcSize:
|
19
|
-
Max:
|
65
|
+
Max: 45
|
20
66
|
|
21
|
-
# Offense count:
|
22
|
-
# Configuration parameters: CountComments, ExcludedMethods.
|
67
|
+
# Offense count: 5
|
68
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
69
|
+
# IgnoredMethods: refine
|
23
70
|
Metrics/BlockLength:
|
24
71
|
Max: 76
|
25
72
|
|
26
|
-
# Offense count:
|
27
|
-
# Configuration parameters:
|
28
|
-
Metrics/ClassLength:
|
29
|
-
Max: 246
|
30
|
-
|
31
|
-
# Offense count: 3
|
73
|
+
# Offense count: 6
|
74
|
+
# Configuration parameters: IgnoredMethods.
|
32
75
|
Metrics/CyclomaticComplexity:
|
33
76
|
Max: 10
|
34
77
|
|
35
|
-
# Offense count:
|
36
|
-
# Configuration parameters: CountComments.
|
78
|
+
# Offense count: 17
|
79
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
37
80
|
Metrics/MethodLength:
|
38
|
-
Max:
|
81
|
+
Max: 50
|
39
82
|
|
40
83
|
# Offense count: 1
|
41
|
-
# Configuration parameters: CountKeywordArgs.
|
84
|
+
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
42
85
|
Metrics/ParameterLists:
|
43
86
|
Max: 7
|
44
87
|
|
45
|
-
# Offense count:
|
88
|
+
# Offense count: 2
|
89
|
+
# Configuration parameters: IgnoredMethods.
|
46
90
|
Metrics/PerceivedComplexity:
|
47
91
|
Max: 12
|
48
92
|
|
49
93
|
# Offense count: 1
|
94
|
+
Security/MarshalLoad:
|
95
|
+
Exclude:
|
96
|
+
- 'lib/xcode/install.rb'
|
97
|
+
|
98
|
+
# Offense count: 16
|
99
|
+
# Cop supports --auto-correct.
|
100
|
+
# Configuration parameters: EnforcedStyle.
|
101
|
+
# SupportedStyles: separated, grouped
|
102
|
+
Style/AccessorGrouping:
|
103
|
+
Exclude:
|
104
|
+
- 'lib/xcode/install.rb'
|
105
|
+
|
106
|
+
# Offense count: 1
|
107
|
+
Style/CombinableLoops:
|
108
|
+
Exclude:
|
109
|
+
- 'lib/xcode/install.rb'
|
110
|
+
|
111
|
+
# Offense count: 1
|
112
|
+
# Cop supports --auto-correct.
|
113
|
+
Style/Encoding:
|
114
|
+
Exclude:
|
115
|
+
- 'xcode-install.gemspec'
|
116
|
+
|
117
|
+
# Offense count: 14
|
50
118
|
# Cop supports --auto-correct.
|
51
|
-
|
119
|
+
Style/ExpandPathArguments:
|
120
|
+
Exclude:
|
121
|
+
- 'bin/xcversion'
|
122
|
+
- 'bin/🎉'
|
123
|
+
- 'spec/cli_spec.rb'
|
124
|
+
- 'spec/curl_spec.rb'
|
125
|
+
- 'spec/install_spec.rb'
|
126
|
+
- 'spec/installed_spec.rb'
|
127
|
+
- 'spec/installer_spec.rb'
|
128
|
+
- 'spec/json_spec.rb'
|
129
|
+
- 'spec/list_spec.rb'
|
130
|
+
- 'spec/prerelease_spec.rb'
|
131
|
+
- 'spec/spec_helper.rb'
|
132
|
+
- 'spec/uninstall_spec.rb'
|
133
|
+
- 'xcode-install.gemspec'
|
134
|
+
|
135
|
+
# Offense count: 28
|
136
|
+
# Cop supports --auto-correct.
|
137
|
+
# Configuration parameters: EnforcedStyle.
|
138
|
+
# SupportedStyles: always, always_true, never
|
139
|
+
Style/FrozenStringLiteralComment:
|
140
|
+
Enabled: false
|
141
|
+
|
142
|
+
# Offense count: 2
|
143
|
+
# Cop supports --auto-correct.
|
144
|
+
Style/IfUnlessModifier:
|
145
|
+
Exclude:
|
146
|
+
- 'lib/xcode/install.rb'
|
147
|
+
|
148
|
+
# Offense count: 8
|
149
|
+
# Configuration parameters: AllowedMethods.
|
150
|
+
# AllowedMethods: respond_to_missing?
|
151
|
+
Style/OptionalBooleanParameter:
|
52
152
|
Exclude:
|
53
153
|
- 'lib/xcode/install.rb'
|
54
154
|
|
55
155
|
# Offense count: 1
|
56
156
|
# Cop supports --auto-correct.
|
57
|
-
|
58
|
-
|
157
|
+
Style/RedundantBegin:
|
158
|
+
Exclude:
|
159
|
+
- 'lib/xcode/install.rb'
|
160
|
+
|
161
|
+
# Offense count: 2
|
162
|
+
# Cop supports --auto-correct.
|
163
|
+
Style/RedundantRegexpEscape:
|
59
164
|
Exclude:
|
60
165
|
- 'lib/xcode/install.rb'
|
61
166
|
|
62
167
|
# Offense count: 1
|
63
|
-
|
168
|
+
# Cop supports --auto-correct.
|
169
|
+
# Configuration parameters: AllowMultipleReturnValues.
|
170
|
+
Style/RedundantReturn:
|
64
171
|
Exclude:
|
65
172
|
- 'lib/xcode/install.rb'
|
66
173
|
|
67
|
-
# Offense count:
|
174
|
+
# Offense count: 2
|
68
175
|
# Cop supports --auto-correct.
|
69
|
-
# Configuration parameters: EnforcedStyle
|
176
|
+
# Configuration parameters: EnforcedStyle.
|
177
|
+
# SupportedStyles: implicit, explicit
|
178
|
+
Style/RescueStandardError:
|
179
|
+
Exclude:
|
180
|
+
- 'lib/xcode/install.rb'
|
181
|
+
|
182
|
+
# Offense count: 1
|
183
|
+
# Cop supports --auto-correct.
|
184
|
+
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods.
|
185
|
+
# AllowedMethods: present?, blank?, presence, try, try!
|
186
|
+
Style/SafeNavigation:
|
187
|
+
Exclude:
|
188
|
+
- 'lib/xcode/install.rb'
|
189
|
+
|
190
|
+
# Offense count: 14
|
191
|
+
# Cop supports --auto-correct.
|
192
|
+
# Configuration parameters: EnforcedStyle.
|
70
193
|
# SupportedStyles: only_raise, only_fail, semantic
|
71
194
|
Style/SignalException:
|
72
195
|
Exclude:
|
73
196
|
- 'lib/xcode/install.rb'
|
74
|
-
- 'lib/xcode/install/cli.rb'
|
75
197
|
- 'lib/xcode/install/install.rb'
|
76
198
|
- 'lib/xcode/install/select.rb'
|
77
199
|
- 'lib/xcode/install/simulators.rb'
|
78
200
|
- 'lib/xcode/install/uninstall.rb'
|
201
|
+
|
202
|
+
# Offense count: 2
|
203
|
+
# Cop supports --auto-correct.
|
204
|
+
Style/StderrPuts:
|
205
|
+
Exclude:
|
206
|
+
- 'lib/xcode/install.rb'
|
207
|
+
|
208
|
+
# Offense count: 4
|
209
|
+
# Cop supports --auto-correct.
|
210
|
+
Style/StringConcatenation:
|
211
|
+
Exclude:
|
212
|
+
- 'lib/xcode/install.rb'
|
213
|
+
- 'spec/spec_helper.rb'
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Xcode::Install
|
2
2
|
|
3
|
-
[![Gem Version](http://img.shields.io/gem/v/xcode-install.svg?style=flat)](http://badge.fury.io/rb/xcode-install) [![
|
3
|
+
[![Gem Version](http://img.shields.io/gem/v/xcode-install.svg?style=flat)](http://badge.fury.io/rb/xcode-install) [![Build Status](https://github.com/xcpretty/xcode-install/actions/workflows/ci.yml/badge.svg)](https://github.com/xcpretty/xcode-install/actions)
|
4
4
|
|
5
5
|
Install and update your Xcodes automatically.
|
6
6
|
|
@@ -87,6 +87,16 @@ $ xcversion list
|
|
87
87
|
|
88
88
|
They have to be installed using the full name, e.g. `xcversion install '7 GM seed'`.
|
89
89
|
|
90
|
+
#### `.xcode-version`
|
91
|
+
|
92
|
+
We recommend the creation of a `.xcode-version` file to explicitly declare and store the Xcode version to be used by your CI environment as well as your team.
|
93
|
+
|
94
|
+
```
|
95
|
+
12.5
|
96
|
+
```
|
97
|
+
|
98
|
+
Read [the proposal](/XCODE_VERSION.md) of `.xcode-version`.
|
99
|
+
|
90
100
|
### Select
|
91
101
|
|
92
102
|
To see the currently selected version, run
|
@@ -151,7 +161,7 @@ to a dialog popping up. Feel free to dupe [the radar][5]. 📡
|
|
151
161
|
|
152
162
|
XcodeInstall normally relies on the Spotlight index to locate installed versions of Xcode. If you use it while
|
153
163
|
indexing is happening, it might show inaccurate results and it will not be able to see installed
|
154
|
-
versions on unindexed volumes.
|
164
|
+
versions on unindexed volumes.
|
155
165
|
|
156
166
|
To workaround the Spotlight limitation, XcodeInstall searches `/Applications` folder to locate Xcodes when Spotlight is disabled on the machine, or when Spotlight query for Xcode does not return any results. But it still won't work if your Xcodes are not located under `/Applications` folder.
|
157
167
|
|
@@ -165,7 +175,7 @@ project, especially [@henrikhodne][6] and [@lacostej][7] for making XcodeInstall
|
|
165
175
|
|
166
176
|
## Contributing
|
167
177
|
|
168
|
-
1. Fork it ( https://github.com/
|
178
|
+
1. Fork it ( https://github.com/xcpretty/xcode-install/fork )
|
169
179
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
170
180
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
171
181
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/XCODE_VERSION.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# `.xcode-version`
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
This is a proposal for a new standard for the iOS community: a text-based file that defines the Xcode version to use to compile and package a given iOS project.
|
6
|
+
|
7
|
+
This will be used by this gem, however it's designed in a way that any tool in the future can pick it up, no matter if it's Ruby based, Swift, JavaScript, etc.
|
8
|
+
|
9
|
+
Similar to the [.ruby-version file](https://en.wikipedia.org/wiki/Ruby_Version_Manager), the `.xcode-version` file allows any CI system or IDE to automatically install and switch to the Xcode version needed for a given project to successfully compile your project.
|
10
|
+
|
11
|
+
## Filename
|
12
|
+
|
13
|
+
The filename must always be `.xcode-version`.
|
14
|
+
|
15
|
+
## File location
|
16
|
+
|
17
|
+
The file must be located in the same directory as your Xcode project/workspace, and you should add it to your versioning system (e.g. git).
|
18
|
+
|
19
|
+
## File content
|
20
|
+
|
21
|
+
The file content must be a simple string in a text file. The file may or may not end with an empty new line, this gem is responsible for stripping out the trailing `\n` (if used).
|
22
|
+
|
23
|
+
### Sample files
|
24
|
+
|
25
|
+
To define an official Xcode release
|
26
|
+
|
27
|
+
```
|
28
|
+
9.3
|
29
|
+
```
|
30
|
+
|
31
|
+
```
|
32
|
+
7.2.1
|
33
|
+
```
|
34
|
+
|
35
|
+
You can also use pre-releases
|
36
|
+
|
37
|
+
```
|
38
|
+
11.5 GM Seed
|
39
|
+
```
|
40
|
+
|
41
|
+
```
|
42
|
+
12 beta 6
|
43
|
+
```
|
44
|
+
|
45
|
+
Always following the same version naming listed by `xcversion list`.
|
46
|
+
|
47
|
+
**Note**: Be aware that pre-releases might be eventually taken down from Apple's servers, meaning that it won't allow you to have fully reproducible builds as you won't be able to download the Xcode release once it's gone.
|
48
|
+
|
49
|
+
It is recommended to only use non-beta releases in an `.xcode-version` file to have fully reproducible builds that you'll be able to run in a few years also.
|
@@ -17,13 +17,14 @@ module XcodeInstall
|
|
17
17
|
['--no-install', 'Only download DMG, but do not install it.'],
|
18
18
|
['--no-progress', 'Don’t show download progress.'],
|
19
19
|
['--no-clean', 'Don’t delete DMG after installation.'],
|
20
|
-
['--no-show-release-notes', 'Don’t open release notes in browser after installation.']
|
20
|
+
['--no-show-release-notes', 'Don’t open release notes in browser after installation.'],
|
21
|
+
['--retry-download-count', 'Count of retrying download when curl is failed.']].concat(super)
|
21
22
|
end
|
22
23
|
|
23
24
|
def initialize(argv)
|
24
25
|
@installer = Installer.new
|
25
26
|
@version = argv.shift_argument
|
26
|
-
@version ||= File.read('.xcode-version') if File.exist?('.xcode-version')
|
27
|
+
@version ||= File.read('.xcode-version').strip if File.exist?('.xcode-version')
|
27
28
|
@url = argv.option('url')
|
28
29
|
@force = argv.flag?('force', false)
|
29
30
|
@should_clean = argv.flag?('clean', true)
|
@@ -31,6 +32,7 @@ module XcodeInstall
|
|
31
32
|
@should_switch = argv.flag?('switch', true)
|
32
33
|
@progress = argv.flag?('progress', true)
|
33
34
|
@show_release_notes = argv.flag?('show-release-notes', true)
|
35
|
+
@retry_download_count = argv.option('retry-download-count', '3')
|
34
36
|
super
|
35
37
|
end
|
36
38
|
|
@@ -44,11 +46,12 @@ module XcodeInstall
|
|
44
46
|
end
|
45
47
|
fail Informative, "Version #{@version} doesn't exist." unless @url || @installer.exist?(@version)
|
46
48
|
fail Informative, "Invalid URL: `#{@url}`" unless !@url || @url =~ /\A#{URI.regexp}\z/
|
49
|
+
fail Informative, "Invalid Retry: `#{@retry_download_count} is not positive number.`" if (@retry_download_count =~ /\A[0-9]*\z/).nil?
|
47
50
|
end
|
48
51
|
|
49
52
|
def run
|
50
53
|
@installer.install_version(@version, @should_switch, @should_clean, @should_install,
|
51
|
-
@progress, @url, @show_release_notes)
|
54
|
+
@progress, @url, @show_release_notes, nil, @retry_download_count.to_i)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
data/lib/xcode/install.rb
CHANGED
@@ -25,13 +25,14 @@ module XcodeInstall
|
|
25
25
|
# @param progress: parse and show the progress?
|
26
26
|
# @param progress_block: A block that's called whenever we have an updated progress %
|
27
27
|
# the parameter is a single number that's literally percent (e.g. 1, 50, 80 or 100)
|
28
|
-
#
|
28
|
+
# @param retry_download_count: A count to retry the downloading Xcode dmg/xip
|
29
29
|
def fetch(url: nil,
|
30
30
|
directory: nil,
|
31
31
|
cookies: nil,
|
32
32
|
output: nil,
|
33
33
|
progress: nil,
|
34
|
-
progress_block: nil
|
34
|
+
progress_block: nil,
|
35
|
+
retry_download_count: 3)
|
35
36
|
options = cookies.nil? ? [] : ['--cookie', cookies, '--cookie-jar', COOKIES_PATH]
|
36
37
|
|
37
38
|
uri = URI.parse(url)
|
@@ -78,38 +79,8 @@ module XcodeInstall
|
|
78
79
|
# "Partial file. Only a part of the file was transferred."
|
79
80
|
# https://curl.haxx.se/mail/archive-2008-07/0098.html
|
80
81
|
# https://github.com/KrauseFx/xcode-install/issues/210
|
81
|
-
|
82
|
-
|
83
|
-
# We're not using the block based syntax, as the bacon testing
|
84
|
-
# library doesn't seem to support writing tests for it
|
85
|
-
stdin, stdout, stderr, wait_thr = Open3.popen3(command_string)
|
86
|
-
|
87
|
-
# Poll the file and see if we're done yet
|
88
|
-
while wait_thr.alive?
|
89
|
-
sleep(0.5) # it's not critical for this to be real-time
|
90
|
-
next unless File.exist?(progress_log_file) # it might take longer for it to be created
|
91
|
-
|
92
|
-
progress_content = File.read(progress_log_file).split("\r").last
|
93
|
-
|
94
|
-
# Print out the progress for the CLI
|
95
|
-
if progress
|
96
|
-
print "\r#{progress_content}%"
|
97
|
-
$stdout.flush
|
98
|
-
end
|
99
|
-
|
100
|
-
# Call back the block for other processes that might be interested
|
101
|
-
matched = progress_content.match(/^\s*(\d+)/)
|
102
|
-
next unless matched && matched.length == 2
|
103
|
-
percent = matched[1].to_i
|
104
|
-
progress_block.call(percent) if progress_block
|
105
|
-
end
|
106
|
-
|
107
|
-
# as we're not making use of the block-based syntax
|
108
|
-
# we need to manually close those
|
109
|
-
stdin.close
|
110
|
-
stdout.close
|
111
|
-
stderr.close
|
112
|
-
|
82
|
+
retry_download_count.times do
|
83
|
+
wait_thr = poll_file(command_string: command_string, progress_log_file: progress_log_file, progress: progress, progress_block: progress_block)
|
113
84
|
return wait_thr.value.success? if wait_thr.value.success?
|
114
85
|
end
|
115
86
|
false
|
@@ -117,6 +88,41 @@ module XcodeInstall
|
|
117
88
|
FileUtils.rm_f(COOKIES_PATH)
|
118
89
|
FileUtils.rm_f(progress_log_file)
|
119
90
|
end
|
91
|
+
|
92
|
+
def poll_file(command_string:, progress_log_file:, progress: nil, progress_block: nil)
|
93
|
+
# Non-blocking call of Open3
|
94
|
+
# We're not using the block based syntax, as the bacon testing
|
95
|
+
# library doesn't seem to support writing tests for it
|
96
|
+
stdin, stdout, stderr, wait_thr = Open3.popen3(command_string)
|
97
|
+
|
98
|
+
# Poll the file and see if we're done yet
|
99
|
+
while wait_thr.alive?
|
100
|
+
sleep(0.5) # it's not critical for this to be real-time
|
101
|
+
next unless File.exist?(progress_log_file) # it might take longer for it to be created
|
102
|
+
|
103
|
+
progress_content = File.read(progress_log_file).split("\r").last || ''
|
104
|
+
|
105
|
+
# Print out the progress for the CLI
|
106
|
+
if progress
|
107
|
+
print "\r#{progress_content}%"
|
108
|
+
$stdout.flush
|
109
|
+
end
|
110
|
+
|
111
|
+
# Call back the block for other processes that might be interested
|
112
|
+
matched = progress_content.match(/^\s*(\d+)/)
|
113
|
+
next unless matched && matched.length == 2
|
114
|
+
percent = matched[1].to_i
|
115
|
+
progress_block.call(percent) if progress_block
|
116
|
+
end
|
117
|
+
|
118
|
+
# as we're not making use of the block-based syntax
|
119
|
+
# we need to manually close those
|
120
|
+
stdin.close
|
121
|
+
stdout.close
|
122
|
+
stderr.close
|
123
|
+
|
124
|
+
wait_thr
|
125
|
+
end
|
120
126
|
end
|
121
127
|
|
122
128
|
# rubocop:disable Metrics/ClassLength
|
@@ -135,7 +141,7 @@ module XcodeInstall
|
|
135
141
|
File.symlink?(SYMLINK_PATH) ? SYMLINK_PATH : nil
|
136
142
|
end
|
137
143
|
|
138
|
-
def download(version, progress, url = nil, progress_block = nil)
|
144
|
+
def download(version, progress, url = nil, progress_block = nil, retry_download_count = 3)
|
139
145
|
xcode = find_xcode_version(version) if url.nil?
|
140
146
|
return if url.nil? && xcode.nil?
|
141
147
|
|
@@ -147,7 +153,8 @@ module XcodeInstall
|
|
147
153
|
cookies: url ? nil : spaceship.cookie,
|
148
154
|
output: dmg_file,
|
149
155
|
progress: progress,
|
150
|
-
progress_block: progress_block
|
156
|
+
progress_block: progress_block,
|
157
|
+
retry_download_count: retry_download_count
|
151
158
|
)
|
152
159
|
result ? CACHE_DIR + dmg_file : nil
|
153
160
|
end
|
@@ -280,8 +287,8 @@ HELP
|
|
280
287
|
end
|
281
288
|
|
282
289
|
# rubocop:disable Metrics/ParameterLists
|
283
|
-
def install_version(version, switch = true, clean = true, install = true, progress = true, url = nil, show_release_notes = true, progress_block = nil)
|
284
|
-
dmg_path = get_dmg(version, progress, url, progress_block)
|
290
|
+
def install_version(version, switch = true, clean = true, install = true, progress = true, url = nil, show_release_notes = true, progress_block = nil, retry_download_count = 3)
|
291
|
+
dmg_path = get_dmg(version, progress, url, progress_block, retry_download_count)
|
285
292
|
fail Informative, "Failed to download Xcode #{version}." if dmg_path.nil?
|
286
293
|
|
287
294
|
if install
|
@@ -314,7 +321,7 @@ HELP
|
|
314
321
|
end
|
315
322
|
|
316
323
|
def list
|
317
|
-
list_annotated(list_versions.
|
324
|
+
list_annotated(list_versions.sort { |first, second| compare_versions(first, second) })
|
318
325
|
end
|
319
326
|
|
320
327
|
def rm_list_cache
|
@@ -370,7 +377,7 @@ HELP
|
|
370
377
|
`sudo /usr/sbin/dseditgroup -o edit -t group -a staff _developer`
|
371
378
|
end
|
372
379
|
|
373
|
-
def get_dmg(version, progress = true, url = nil, progress_block = nil)
|
380
|
+
def get_dmg(version, progress = true, url = nil, progress_block = nil, retry_download_count = 3)
|
374
381
|
if url
|
375
382
|
path = Pathname.new(url)
|
376
383
|
return path if path.exist?
|
@@ -381,7 +388,7 @@ HELP
|
|
381
388
|
end
|
382
389
|
end
|
383
390
|
|
384
|
-
download(version, progress, url, progress_block)
|
391
|
+
download(version, progress, url, progress_block, retry_download_count)
|
385
392
|
end
|
386
393
|
|
387
394
|
def fetch_seedlist
|
@@ -461,6 +468,35 @@ HELP
|
|
461
468
|
links
|
462
469
|
end
|
463
470
|
|
471
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
472
|
+
def compare_versions(first, second)
|
473
|
+
# Sort by version number
|
474
|
+
numeric_comparation = first.to_f <=> second.to_f
|
475
|
+
return numeric_comparation if numeric_comparation != 0
|
476
|
+
|
477
|
+
# Return beta versions before others
|
478
|
+
is_first_beta = first.include?('beta')
|
479
|
+
is_second_beta = second.include?('beta')
|
480
|
+
return -1 if is_first_beta && !is_second_beta
|
481
|
+
return 1 if !is_first_beta && is_second_beta
|
482
|
+
|
483
|
+
# Return GM versions before others
|
484
|
+
is_first_gm = first.include?('GM')
|
485
|
+
is_second_gm = second.include?('GM')
|
486
|
+
return -1 if is_first_gm && !is_second_gm
|
487
|
+
return 1 if !is_first_gm && is_second_gm
|
488
|
+
|
489
|
+
# Return Release Candidate versions before others
|
490
|
+
is_first_rc = first.include?('RC') || first.include?('Release Candidate')
|
491
|
+
is_second_rc = second.include?('RC') || second.include?('Release Candidate')
|
492
|
+
return -1 if is_first_rc && !is_second_rc
|
493
|
+
return 1 if !is_first_rc && is_second_rc
|
494
|
+
|
495
|
+
# Sort alphabetically
|
496
|
+
first <=> second
|
497
|
+
end
|
498
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
499
|
+
|
464
500
|
def hdiutil(*args)
|
465
501
|
io = IO.popen(['hdiutil', *args])
|
466
502
|
result = io.read
|
@@ -512,12 +548,13 @@ HELP
|
|
512
548
|
end
|
513
549
|
end
|
514
550
|
|
515
|
-
def download(progress, progress_block = nil)
|
551
|
+
def download(progress, progress_block = nil, retry_download_count = 3)
|
516
552
|
result = Curl.new.fetch(
|
517
553
|
url: source,
|
518
554
|
directory: CACHE_DIR,
|
519
555
|
progress: progress,
|
520
|
-
progress_block: progress_block
|
556
|
+
progress_block: progress_block,
|
557
|
+
retry_download_count: retry_download_count
|
521
558
|
)
|
522
559
|
result ? dmg_path : nil
|
523
560
|
end
|
@@ -673,11 +710,10 @@ HELP
|
|
673
710
|
`touch #{cache_dir}com.apple.dt.Xcode.InstallCheckCache_#{osx_build_version}_#{tools_version}`
|
674
711
|
end
|
675
712
|
|
676
|
-
# This method might take a few ms, this could be improved by implementing https://github.com/KrauseFx/xcode-install/issues/273
|
677
713
|
def fetch_version
|
678
|
-
output =
|
714
|
+
output = `/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "#{@path}/Contents/version.plist"`
|
679
715
|
return '0.0' if output.nil? || output.empty? # ¯\_(ツ)_/¯
|
680
|
-
output.
|
716
|
+
output.sub("\n", '')
|
681
717
|
end
|
682
718
|
|
683
719
|
def verify_integrity
|
data/spec/install_spec.rb
CHANGED
@@ -12,32 +12,32 @@ module XcodeInstall
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'downloads and installs' do
|
15
|
-
Installer.any_instance.expects(:download).with('6.3', true, nil, nil).returns('/some/path')
|
15
|
+
Installer.any_instance.expects(:download).with('6.3', true, nil, nil, 3).returns('/some/path')
|
16
16
|
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
|
17
17
|
Command::Install.run(['6.3'])
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'downloads and installs with custom HTTP URL' do
|
21
21
|
url = 'http://yolo.com/xcode.dmg'
|
22
|
-
Installer.any_instance.expects(:download).with('6.3', true, url, nil).returns('/some/path')
|
22
|
+
Installer.any_instance.expects(:download).with('6.3', true, url, nil, 3).returns('/some/path')
|
23
23
|
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
|
24
24
|
Command::Install.run(['6.3', "--url=#{url}"])
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'downloads and installs and does not switch if --no-switch given' do
|
28
|
-
Installer.any_instance.expects(:download).with('6.3', true, nil, nil).returns('/some/path')
|
28
|
+
Installer.any_instance.expects(:download).with('6.3', true, nil, nil, 3).returns('/some/path')
|
29
29
|
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', false, true)
|
30
30
|
Command::Install.run(['6.3', '--no-switch'])
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'downloads without progress if switch --no-progress is given' do
|
34
|
-
Installer.any_instance.expects(:download).with('6.3', false, nil, nil).returns('/some/path')
|
34
|
+
Installer.any_instance.expects(:download).with('6.3', false, nil, nil, 3).returns('/some/path')
|
35
35
|
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
|
36
36
|
Command::Install.run(['6.3', '--no-progress'])
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'reads .xcode-version' do
|
40
|
-
Installer.any_instance.expects(:download).with('6.3', true, nil, nil).returns('/some/path')
|
40
|
+
Installer.any_instance.expects(:download).with('6.3', true, nil, nil, 3).returns('/some/path')
|
41
41
|
Installer.any_instance.expects(:install_dmg).with('/some/path', '-6.3', true, true)
|
42
42
|
File.expects(:exist?).with('.xcode-version').returns(true)
|
43
43
|
File.expects(:read).returns('6.3')
|
data/spec/installed_spec.rb
CHANGED
@@ -5,13 +5,13 @@ module XcodeInstall
|
|
5
5
|
|
6
6
|
describe InstalledXcode do
|
7
7
|
it 'finds the current Xcode version with whitespace chars' do
|
8
|
-
InstalledXcode.any_instance.expects(:`).with("
|
8
|
+
InstalledXcode.any_instance.expects(:`).with("/usr/libexec/PlistBuddy -c \"Print :CFBundleShortVersionString\" \"#{xcode_path}/Contents/version.plist\"").returns('6.3.1')
|
9
9
|
installed = InstalledXcode.new(xcode_path)
|
10
10
|
installed.version.should == '6.3.1'
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'is robust against broken Xcode installations' do
|
14
|
-
InstalledXcode.any_instance.expects(:`).with("
|
14
|
+
InstalledXcode.any_instance.expects(:`).with("/usr/libexec/PlistBuddy -c \"Print :CFBundleShortVersionString\" \"#{xcode_path}/Contents/version.plist\"").returns(nil)
|
15
15
|
installed = InstalledXcode.new(xcode_path)
|
16
16
|
installed.version.should == '0.0'
|
17
17
|
end
|
data/spec/json_spec.rb
CHANGED
@@ -20,14 +20,14 @@ module XcodeInstall
|
|
20
20
|
installer.stubs(:xcodes).returns(seedlist)
|
21
21
|
|
22
22
|
versions = [
|
23
|
-
'4.3 for Lion', '4.3.1 for Lion', '4.3.2 for Lion', '4.3.3 for Lion', '4.4.1', '4.5', '4.6
|
24
|
-
'5
|
23
|
+
'4.3 for Lion', '4.3.1 for Lion', '4.3.2 for Lion', '4.3.3 for Lion', '4.4.1', '4.5', '4.6', '4.6.1', '4.6.2', '4.6.3',
|
24
|
+
'5', '5.0.1', '5.0.2', '5.1', '5.1.1',
|
25
25
|
'6.0.1', '6.1', '6.1.1', '6.2', '6.3', '6.3.1', '6.3.2', '6.4',
|
26
|
-
'7', '7.0.1', '7.1', '7.1.1', '7.2
|
27
|
-
'8', '8.1', '8.2', '8.2.1', '8.3
|
26
|
+
'7', '7.0.1', '7.1', '7.1.1', '7.2', '7.2.1', '7.3', '7.3.1',
|
27
|
+
'8', '8.1', '8.2', '8.2.1', '8.3', '8.3.2', '8.3.3',
|
28
28
|
'9', '9.0.1', '9.1', '9.2', '9.3', '9.3.1', '9.4', '9.4.1',
|
29
|
-
'10', '10.1', '10.2
|
30
|
-
'11', '11.1', '11.2', '11.2.1', '11.3 beta', '11.3', '11.3.1', '11.4 beta', '11.4', '11.4 beta 3', '11.4
|
29
|
+
'10', '10.1', '10.2', '10.2.1', '10.3',
|
30
|
+
'11', '11.1', '11.2', '11.2.1', '11.3 beta', '11.3', '11.3.1', '11.4 beta', '11.4 beta 2', '11.4 beta 3', '11.4', '11.4.1', '11.5 beta', '11.5 beta 2', '11.5 GM Seed', '11.5'
|
31
31
|
]
|
32
32
|
installer.list.split("\n").should == versions
|
33
33
|
end
|
data/spec/list_spec.rb
CHANGED
@@ -43,7 +43,23 @@ module XcodeInstall
|
|
43
43
|
it 'lists all versions' do
|
44
44
|
fake_xcodes '1', '2.3', '2.3.1', '2.3.2', '3 some', '4 beta', '10 beta'
|
45
45
|
fake_installed_xcodes
|
46
|
-
installer.list.should == "1\n2.3
|
46
|
+
installer.list.should == "1\n2.3\n2.3.1\n2.3.2\n3 some\n4 beta\n10 beta"
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'lists all versions in the correct order' do
|
50
|
+
fake_xcodes(
|
51
|
+
'12 beta 4', '12 beta 3', '12 beta 2', '12 for macOS Universal Apps beta 2',
|
52
|
+
'12 beta', '12 for macOS Universal Apps beta', '12.0.1', '12', '12 beta 6',
|
53
|
+
'12 beta 5', '12.1 GM seed', '12.2 beta 3', '12.2 beta', '12.2 beta 2'
|
54
|
+
)
|
55
|
+
fake_installed_xcodes
|
56
|
+
|
57
|
+
versions = [
|
58
|
+
'12 beta', '12 beta 2', '12 beta 3', '12 beta 4', '12 beta 5', '12 beta 6',
|
59
|
+
'12 for macOS Universal Apps beta', '12 for macOS Universal Apps beta 2',
|
60
|
+
'12', '12.0.1', '12.1 GM seed', '12.2 beta', '12.2 beta 2', '12.2 beta 3'
|
61
|
+
]
|
62
|
+
installer.list.split("\n").should == versions
|
47
63
|
end
|
48
64
|
end
|
49
65
|
|
@@ -51,7 +67,7 @@ module XcodeInstall
|
|
51
67
|
it 'lists all versions with annotations' do
|
52
68
|
fake_xcodes '1', '2.3', '2.3.1', '2.3.2', '3 some', '4.3.1 for Lion', '9.4.1', '10 beta'
|
53
69
|
fake_installed_xcodes '2.3', '4.3.1 for Lion', '10 beta'
|
54
|
-
installer.list.should == "1\n2.3
|
70
|
+
installer.list.should == "1\n2.3 (installed)\n2.3.1\n2.3.2\n3 some\n4.3.1 for Lion (installed)\n9.4.1\n10 beta (installed)"
|
55
71
|
end
|
56
72
|
|
57
73
|
it 'distinguish between beta and official_version' do
|
@@ -61,9 +77,9 @@ module XcodeInstall
|
|
61
77
|
end
|
62
78
|
|
63
79
|
it 'distinguish each beta versions' do
|
64
|
-
fake_xcodes '11.4 beta', '11.4 beta
|
80
|
+
fake_xcodes '11.4 beta 3', '11.4 beta'
|
65
81
|
fake_installed_xcodes '11.4 beta'
|
66
|
-
installer.list.should == "11.4 beta
|
82
|
+
installer.list.should == "11.4 beta (installed)\n11.4 beta 3"
|
67
83
|
end
|
68
84
|
end
|
69
85
|
end
|
data/xcode-install.gemspec
CHANGED
@@ -27,6 +27,6 @@ Gem::Specification.new do |spec|
|
|
27
27
|
# contains spaceship, which is used for auth and dev portal interactions
|
28
28
|
spec.add_dependency 'fastlane', '>= 2.1.0', '< 3.0.0'
|
29
29
|
|
30
|
-
spec.add_development_dependency 'bundler', '
|
30
|
+
spec.add_development_dependency 'bundler', '>= 2.0.0', '< 3.0.0'
|
31
31
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
32
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcode-install
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boris Bügling
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: claide
|
@@ -54,16 +54,22 @@ dependencies:
|
|
54
54
|
name: bundler
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- - "
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 2.0.0
|
60
|
+
- - "<"
|
58
61
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
62
|
+
version: 3.0.0
|
60
63
|
type: :development
|
61
64
|
prerelease: false
|
62
65
|
version_requirements: !ruby/object:Gem::Requirement
|
63
66
|
requirements:
|
64
|
-
- - "
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.0.0
|
70
|
+
- - "<"
|
65
71
|
- !ruby/object:Gem::Version
|
66
|
-
version:
|
72
|
+
version: 3.0.0
|
67
73
|
- !ruby/object:Gem::Dependency
|
68
74
|
name: rake
|
69
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,7 +93,6 @@ executables:
|
|
87
93
|
extensions: []
|
88
94
|
extra_rdoc_files: []
|
89
95
|
files:
|
90
|
-
- ".circleci/config.yml"
|
91
96
|
- ".gitattributes"
|
92
97
|
- ".github/workflows/ci.yml"
|
93
98
|
- ".gitignore"
|
@@ -97,6 +102,7 @@ files:
|
|
97
102
|
- LICENSE
|
98
103
|
- README.md
|
99
104
|
- Rakefile
|
105
|
+
- XCODE_VERSION.md
|
100
106
|
- bin/xcversion
|
101
107
|
- "bin/\U0001F389"
|
102
108
|
- lib/xcode/install.rb
|
@@ -145,7 +151,7 @@ homepage: https://github.com/neonichu/xcode-install
|
|
145
151
|
licenses:
|
146
152
|
- MIT
|
147
153
|
metadata: {}
|
148
|
-
post_install_message:
|
154
|
+
post_install_message:
|
149
155
|
rdoc_options: []
|
150
156
|
require_paths:
|
151
157
|
- lib
|
@@ -160,8 +166,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
166
|
- !ruby/object:Gem::Version
|
161
167
|
version: '0'
|
162
168
|
requirements: []
|
163
|
-
rubygems_version: 3.
|
164
|
-
signing_key:
|
169
|
+
rubygems_version: 3.2.19
|
170
|
+
signing_key:
|
165
171
|
specification_version: 4
|
166
172
|
summary: Xcode installation manager.
|
167
173
|
test_files:
|
data/.circleci/config.yml
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
version: 2
|
2
|
-
|
3
|
-
jobs:
|
4
|
-
build:
|
5
|
-
macos:
|
6
|
-
xcode: "9.0"
|
7
|
-
working_directory: ~/xcode-install
|
8
|
-
shell: /bin/bash --login -eo pipefail
|
9
|
-
steps:
|
10
|
-
- checkout
|
11
|
-
|
12
|
-
# See Also: https://discuss.circleci.com/t/circleci-2-0-ios-error-installing-gems/23291/4
|
13
|
-
- run:
|
14
|
-
name: Set Ruby Version
|
15
|
-
command: echo "ruby-2.4" > ~/.ruby-version
|
16
|
-
|
17
|
-
- run:
|
18
|
-
name: Install ruby dependencies
|
19
|
-
command: bundle install
|
20
|
-
|
21
|
-
- run:
|
22
|
-
name: Run test
|
23
|
-
command: bundle exec rake spec
|
24
|
-
|
25
|
-
- run:
|
26
|
-
name: Run lint
|
27
|
-
command: bundle exec rake rubocop
|
28
|
-
|
29
|
-
workflows:
|
30
|
-
version: 2
|
31
|
-
build_and_test:
|
32
|
-
jobs:
|
33
|
-
- build
|