diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 5d2cfd72..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,33 +0,0 @@ -version: 2 - -jobs: - build: - macos: - xcode: "9.0" - working_directory: ~/xcode-install - shell: /bin/bash --login -eo pipefail - steps: - - checkout - - # See Also: https://discuss.circleci.com/t/circleci-2-0-ios-error-installing-gems/23291/4 - - run: - name: Set Ruby Version - command: echo "ruby-2.4" > ~/.ruby-version - - - run: - name: Install ruby dependencies - command: bundle install - - - run: - name: Run test - command: bundle exec rake spec - - - run: - name: Run lint - command: bundle exec rake rubocop - -workflows: - version: 2 - build_and_test: - jobs: - - build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e8ed6c5..9f15ebc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,34 +1,40 @@ name: "CI" -on: [pull_request] +on: [push, pull_request] jobs: build: strategy: fail-fast: false matrix: - ruby: ["2.5", "2.6"] + ruby: ["2.5", "2.6", "2.7", "3.0"] runs-on: macos-latest steps: # Setup env - uses: actions/checkout@v2 - - uses: actions/setup-ruby@v1 + - uses: ruby/setup-ruby@v1 with: ruby-version: "${{ matrix.ruby }}" # Show env - name: Show macOS version run: sw_vers - - name: Show ruby version + - name: Show env versions run: | ruby --version bundler --version + echo $HOME # Prepare - - name: Install bundler 1.7 - run: gem install bundler -v "~> 1.7" + - name: Install bundler 2.2.20 + run: gem install bundler -v "~> 2.2.20" - name: Install ruby dependencies - run: bundle install -j4 --clean --path=vendor + run: | + bundle config --local clean 'true' + bundle config --local path '.vendor' + bundle config --local jobs 8 + bundle config --local without 'system_tests' + bundle install - name: Run test run: bundle exec rake spec diff --git a/.gitignore b/.gitignore index 4e57d3fd..d3896b53 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ mkmf.log .DS_Store test +.vendor diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index dd4d01c3..cc8fac98 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,78 +1,213 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2017-08-24 11:09:20 +0200 using RuboCop version 0.49.1. +# on 2021-07-06 16:06:45 UTC using RuboCop version 1.12.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. +# Offense count: 1 +# Configuration parameters: Include. +# Include: **/*.gemspec +Gemspec/RequiredRubyVersion: + Exclude: + - 'xcode-install.gemspec' + # Offense count: 3 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent -Layout/IndentHeredoc: +Layout/ClosingHeredocIndentation: Exclude: - 'lib/xcode/install.rb' # Offense count: 12 +# Cop supports --auto-correct. +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'lib/xcode/install.rb' + - 'lib/xcode/install/cleanup.rb' + - 'lib/xcode/install/simulators.rb' + - 'lib/xcode/install/uninstall.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Layout/HeredocIndentation: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Lint/BooleanSymbol: + Exclude: + - 'lib/xcode/install/install.rb' + - 'lib/xcode/install/select.rb' + - 'lib/xcode/install/uninstall.rb' + +# Offense count: 6 +Lint/DuplicateMethods: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 2 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Lint/UriRegexp: + Exclude: + - 'lib/xcode/install/install.rb' + +# Offense count: 12 +# Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: - Max: 44 + Max: 45 -# Offense count: 4 -# Configuration parameters: CountComments, ExcludedMethods. +# Offense count: 5 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +# IgnoredMethods: refine Metrics/BlockLength: Max: 76 -# Offense count: 1 -# Configuration parameters: CountComments. -Metrics/ClassLength: - Max: 246 - -# Offense count: 3 +# Offense count: 6 +# Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: Max: 10 -# Offense count: 11 -# Configuration parameters: CountComments. +# Offense count: 17 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: - Max: 51 + Max: 50 # Offense count: 1 -# Configuration parameters: CountKeywordArgs. +# Configuration parameters: CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: Max: 7 -# Offense count: 3 +# Offense count: 2 +# Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: Max: 12 # Offense count: 1 +Security/MarshalLoad: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 16 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: separated, grouped +Style/AccessorGrouping: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 1 +Style/CombinableLoops: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/Encoding: + Exclude: + - 'xcode-install.gemspec' + +# Offense count: 14 # Cop supports --auto-correct. -Performance/CompareWithBlock: +Style/ExpandPathArguments: + Exclude: + - 'bin/xcversion' + - 'bin/🎉' + - 'spec/cli_spec.rb' + - 'spec/curl_spec.rb' + - 'spec/install_spec.rb' + - 'spec/installed_spec.rb' + - 'spec/installer_spec.rb' + - 'spec/json_spec.rb' + - 'spec/list_spec.rb' + - 'spec/prerelease_spec.rb' + - 'spec/spec_helper.rb' + - 'spec/uninstall_spec.rb' + - 'xcode-install.gemspec' + +# Offense count: 28 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +Style/IfUnlessModifier: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 8 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: Exclude: - 'lib/xcode/install.rb' # Offense count: 1 # Cop supports --auto-correct. -# Configuration parameters: IncludeActiveSupportAliases. -Performance/DoubleStartEndWith: +Style/RedundantBegin: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/RedundantRegexpEscape: Exclude: - 'lib/xcode/install.rb' # Offense count: 1 -Security/MarshalLoad: +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: Exclude: - 'lib/xcode/install.rb' -# Offense count: 15 +# Offense count: 2 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 14 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. # SupportedStyles: only_raise, only_fail, semantic Style/SignalException: Exclude: - 'lib/xcode/install.rb' - - 'lib/xcode/install/cli.rb' - 'lib/xcode/install/install.rb' - 'lib/xcode/install/select.rb' - 'lib/xcode/install/simulators.rb' - 'lib/xcode/install/uninstall.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/StderrPuts: + Exclude: + - 'lib/xcode/install.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +Style/StringConcatenation: + Exclude: + - 'lib/xcode/install.rb' + - 'spec/spec_helper.rb' diff --git a/Gemfile b/Gemfile index ccc9cc90..82fba13a 100644 --- a/Gemfile +++ b/Gemfile @@ -8,5 +8,5 @@ group :development do gem 'mocha', '~> 0.11.4' gem 'mocha-on-bacon' gem 'prettybacon' - gem 'rubocop', '~> 0.49.1', require: false + gem 'rubocop', '~> 1.18', require: false end diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 00000000..c6a782fb --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,129 @@ +# This project is being sunset + +A brief history of `xcode-install` aka `xcversion`, as well as a guide on how to migrate from it, to a more modern tool. + +For brevity sake I'm going to refer to this project always as `xcode-install` in this document. + +## Overview + +The more time goes by, the more we realized this project had already provided the community the value it needed, served its purpose, and become obsolete. We believe it was the time to officially sunset this project, and this document will guide you to use a more modern and well maintained tool. + +## Some Context + +`xcode-install` (originally a @neonichu's project, which got transferred to @KrauseFx, which got transferred to the @xcpretty GitHub organization), had been around since April 2015, back when there were no other good options to manage multiple versions of Xcode. + +Fast forward to Feb 2019, [`xcodes`](https://github.com/RobotsAndPencils/xcodes) was born to provide a more user friendly experience. It based itself off of this project to figure out the complex Xcode downloading logic, but has since then been actively maintained and new features are incorporated into it on a regular basis. To name a few, that are not present in `xcode-install`: + +- GUI (via [`Xcodes.app`](https://github.com/RobotsAndPencils/XcodesApp)) +- Support to `aria2` (which has been requested in https://github.com/xcpretty/xcode-install/issues/425 but we never got to implement it), which uses up to 16 connections to download Xcode 3-5x faster +- Support to [`unxip`](https://github.com/saagarjha/unxip), providing unxipping up to 70% faster +- New in Xcode 14: Sessionless downloads, just announced by [@xcodesapp](https://twitter.com/xcodesapp): https://twitter.com/xcodesapp/status/1570991082359627779?s=46&t=qVETxqxGI7ZZsFLLrledIg, available in https://github.com/RobotsAndPencils/XcodesApp/releases/tag/v1.8.0b16 + +These features, plus the fact that this project wasn't getting the attention it needed to keep supporting newer versions of Xcode and bug fixes, made us believe it was time to sunset this project. + +# Migrating _fastlane_ actions that depend on the `xcode-install` gem, to use `xcodes` + +As of https://github.com/fastlane/fastlane/pull/20672, a new action was introduced to _fastlane_ called `xcodes`. You can find its full documentation here: https://docs.fastlane.tools/actions/xcodes + +Keep in mind that the `xcodes` action depends on [`xcodes`](https://github.com/RobotsAndPencils/xcodes) CLI, so make sure you have it installed in your environment. For the installation guide, see: https://github.com/RobotsAndPencils/xcodes#installation + +There are 3 actions that depend on `xcode-install` gem. Below you can find how to migrate each one of them: + +## 1. `xcode_install` + +`xcode_install` used to receive an Xcode version and "install if needed", which is the new `xcodes` action's main purpose. + +Before: + +```ruby +xcode_install( + version: '14', + username: 'example@example.com', + team_id: 'ABCD1234', + download_retry_attempts: 5, +) +``` + +Now: + +The `team_id` and `download_retry_attempts` options are no longer needed (nor supported). + +```ruby +xcodes( + version: '14', + username: 'example@example.com', +) +``` + +## 2. `xcversion` + +`xcversion` used to receive an Xcode version and select it for the current build steps, which in `xcodes` action that's the `select_for_current_build_only` option. + +Before: + +```ruby +xcversion(version: '14') +``` + +Now: + +```ruby +xcodes( + version: '14', + select_for_current_build_only: true, +) +``` + +## 3. `ensure_xcode_version` + +This action wasn't migrated to use `xcodes` within _fastlane_ yet, mainly because of the somewhat complex logic around the non-strict version checking. This document as well as fastlane's `ensure_xcode_version` action documentation will be updated when the new `xcodes` action officially deprecates the `ensure_xcode_version` action. For now, if you don't use the `strict: false` option of `ensure_xcode_version`, you can migrate to `xcodes` action by passing `select_for_current_build_only: true`, which will raise an error if the given version can't be selected: + +Before: + +```ruby +ensure_xcode_version( + version: '14', + strict: false, +) +``` + +```ruby +ensure_xcode_version(version: '14') +``` + +Now: + +```ruby +xcodes( + version: '14', + select_for_current_build_only: true, +) +``` + +## Managing Simulator Runtimes + +You can install them via, e.g.: + +```sh +xcodes runtimes install 'iOS 16.0' +``` + +More documentation about this will be created soon, directly in the `xcodes` repository. + +## Advanced Usage + +If there are other use cases that you don't see covered so far, check out the full documentation here: https://docs.fastlane.tools/actions/xcodes + +All the lanes that supported `.xcode-version` still support it :tada: + +# Migrating `xcode-install` CLI to `xcodes` + +If you're using `xcode-install` as a CLI, the process to migrate to `xcodes` is more straightforward: simply visit https://github.com/RobotsAndPencils/xcodes and check their installation and usage guide. + +`xcode-install` CLI supported `.xcode-version` and so does `xcodes` :tada: + +## Shout Outs & Mentions + +Huge shout out to @neonichu, @KrauseFx, @mrcljx, @jpsim, @timsutton, and many other contributors (which you can check here: https://github.com/xcpretty/xcode-install/graphs/contributors) for the work they put into this project! It advanced the state of the art in its field, and the community benefitted a lot from it! `xcodes` wouldn't be where it is today without your effort into this project 💟 + +Thank you all, and see you on the other side! diff --git a/README.md b/README.md index bb51d4cb..2d99bbe6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Xcode::Install -[![Gem Version](http://img.shields.io/gem/v/xcode-install.svg?style=flat)](http://badge.fury.io/rb/xcode-install) [![CircleCI](https://circleci.com/gh/xcpretty/xcode-install.svg?style=svg)](https://circleci.com/gh/xcpretty/xcode-install) +[![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) + +# This project is being sunset. See the migration guide here: [MIGRATION.md](/MIGRATION.md) Install and update your Xcodes automatically. @@ -87,6 +89,16 @@ $ xcversion list They have to be installed using the full name, e.g. `xcversion install '7 GM seed'`. +#### `.xcode-version` + +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. + +``` +12.5 +``` + +Read [the proposal](/XCODE_VERSION.md) of `.xcode-version`. + ### Select To see the currently selected version, run @@ -151,7 +163,7 @@ to a dialog popping up. Feel free to dupe [the radar][5]. 📡 XcodeInstall normally relies on the Spotlight index to locate installed versions of Xcode. If you use it while indexing is happening, it might show inaccurate results and it will not be able to see installed -versions on unindexed volumes. +versions on unindexed volumes. 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. @@ -165,7 +177,7 @@ project, especially [@henrikhodne][6] and [@lacostej][7] for making XcodeInstall ## Contributing -1. Fork it ( https://github.com/KrauseFx/xcode-install/fork ) +1. Fork it ( https://github.com/xcpretty/xcode-install/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) diff --git a/XCODE_VERSION.md b/XCODE_VERSION.md new file mode 100644 index 00000000..7c98af99 --- /dev/null +++ b/XCODE_VERSION.md @@ -0,0 +1,49 @@ +# `.xcode-version` + +## Introduction + +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. + +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. + +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. + +## Filename + +The filename must always be `.xcode-version`. + +## File location + +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). + +## File content + +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). + +### Sample files + +To define an official Xcode release + +``` +9.3 +``` + +``` +7.2.1 +``` + +You can also use pre-releases + +``` +11.5 GM Seed +``` + +``` +12 beta 6 +``` + +Always following the same version naming listed by `xcversion list`. + +**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. + +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. diff --git a/lib/xcode/install.rb b/lib/xcode/install.rb index 78f25bbf..0eefb978 100644 --- a/lib/xcode/install.rb +++ b/lib/xcode/install.rb @@ -26,7 +26,6 @@ class Curl # @param progress_block: A block that's called whenever we have an updated progress % # the parameter is a single number that's literally percent (e.g. 1, 50, 80 or 100) # @param retry_download_count: A count to retry the downloading Xcode dmg/xip - # rubocop:disable Metrics/AbcSize def fetch(url: nil, directory: nil, cookies: nil, @@ -81,37 +80,7 @@ def fetch(url: nil, # https://curl.haxx.se/mail/archive-2008-07/0098.html # https://github.com/KrauseFx/xcode-install/issues/210 retry_download_count.times do - # Non-blocking call of Open3 - # We're not using the block based syntax, as the bacon testing - # library doesn't seem to support writing tests for it - stdin, stdout, stderr, wait_thr = Open3.popen3(command_string) - - # Poll the file and see if we're done yet - while wait_thr.alive? - sleep(0.5) # it's not critical for this to be real-time - next unless File.exist?(progress_log_file) # it might take longer for it to be created - - progress_content = File.read(progress_log_file).split("\r").last - - # Print out the progress for the CLI - if progress - print "\r#{progress_content}%" - $stdout.flush - end - - # Call back the block for other processes that might be interested - matched = progress_content.match(/^\s*(\d+)/) - next unless matched && matched.length == 2 - percent = matched[1].to_i - progress_block.call(percent) if progress_block - end - - # as we're not making use of the block-based syntax - # we need to manually close those - stdin.close - stdout.close - stderr.close - + wait_thr = poll_file(command_string: command_string, progress_log_file: progress_log_file, progress: progress, progress_block: progress_block) return wait_thr.value.success? if wait_thr.value.success? end false @@ -119,6 +88,41 @@ def fetch(url: nil, FileUtils.rm_f(COOKIES_PATH) FileUtils.rm_f(progress_log_file) end + + def poll_file(command_string:, progress_log_file:, progress: nil, progress_block: nil) + # Non-blocking call of Open3 + # We're not using the block based syntax, as the bacon testing + # library doesn't seem to support writing tests for it + stdin, stdout, stderr, wait_thr = Open3.popen3(command_string) + + # Poll the file and see if we're done yet + while wait_thr.alive? + sleep(0.5) # it's not critical for this to be real-time + next unless File.exist?(progress_log_file) # it might take longer for it to be created + + progress_content = File.read(progress_log_file).split("\r").last || '' + + # Print out the progress for the CLI + if progress + print "\r#{progress_content}%" + $stdout.flush + end + + # Call back the block for other processes that might be interested + matched = progress_content.match(/^\s*(\d+)/) + next unless matched && matched.length == 2 + percent = matched[1].to_i + progress_block.call(percent) if progress_block + end + + # as we're not making use of the block-based syntax + # we need to manually close those + stdin.close + stdout.close + stderr.close + + wait_thr + end end # rubocop:disable Metrics/ClassLength @@ -317,7 +321,7 @@ def list_annotated(xcodes_list) end def list - list_annotated(list_versions.sort_by(&:to_f)) + list_annotated(list_versions.sort { |first, second| compare_versions(first, second) }) end def rm_list_cache @@ -464,6 +468,35 @@ def prereleases links end + # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def compare_versions(first, second) + # Sort by version number + numeric_comparation = first.to_f <=> second.to_f + return numeric_comparation if numeric_comparation != 0 + + # Return beta versions before others + is_first_beta = first.include?('beta') + is_second_beta = second.include?('beta') + return -1 if is_first_beta && !is_second_beta + return 1 if !is_first_beta && is_second_beta + + # Return GM versions before others + is_first_gm = first.include?('GM') + is_second_gm = second.include?('GM') + return -1 if is_first_gm && !is_second_gm + return 1 if !is_first_gm && is_second_gm + + # Return Release Candidate versions before others + is_first_rc = first.include?('RC') || first.include?('Release Candidate') + is_second_rc = second.include?('RC') || second.include?('Release Candidate') + return -1 if is_first_rc && !is_second_rc + return 1 if !is_first_rc && is_second_rc + + # Sort alphabetically + first <=> second + end + # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + def hdiutil(*args) io = IO.popen(['hdiutil', *args]) result = io.read @@ -677,11 +710,10 @@ def install_components `touch #{cache_dir}com.apple.dt.Xcode.InstallCheckCache_#{osx_build_version}_#{tools_version}` end - # This method might take a few ms, this could be improved by implementing https://github.com/KrauseFx/xcode-install/issues/273 def fetch_version - output = `DEVELOPER_DIR='' "#{@path}/Contents/Developer/usr/bin/xcodebuild" -version` + output = `/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "#{@path}/Contents/version.plist"` return '0.0' if output.nil? || output.empty? # ¯\_(ツ)_/¯ - output.split("\n").first.split(' ')[1] + output.sub("\n", '') end def verify_integrity diff --git a/lib/xcode/install/install.rb b/lib/xcode/install/install.rb index c2926e4f..1e07fcdb 100644 --- a/lib/xcode/install/install.rb +++ b/lib/xcode/install/install.rb @@ -24,7 +24,7 @@ def self.options def initialize(argv) @installer = Installer.new @version = argv.shift_argument - @version ||= File.read('.xcode-version') if File.exist?('.xcode-version') + @version ||= File.read('.xcode-version').strip if File.exist?('.xcode-version') @url = argv.option('url') @force = argv.flag?('force', false) @should_clean = argv.flag?('clean', true) diff --git a/lib/xcode/install/version.rb b/lib/xcode/install/version.rb index 1da17d29..4ec5dfaa 100644 --- a/lib/xcode/install/version.rb +++ b/lib/xcode/install/version.rb @@ -1,3 +1,3 @@ module XcodeInstall - VERSION = '2.6.6'.freeze + VERSION = '2.8.1'.freeze end diff --git a/spec/installed_spec.rb b/spec/installed_spec.rb index 1c02afd3..3b6d4427 100644 --- a/spec/installed_spec.rb +++ b/spec/installed_spec.rb @@ -5,13 +5,13 @@ module XcodeInstall describe InstalledXcode do it 'finds the current Xcode version with whitespace chars' do - InstalledXcode.any_instance.expects(:`).with("DEVELOPER_DIR='' \"#{xcode_path}/Contents/Developer/usr/bin/xcodebuild\" -version").returns("Xcode 6.3.1\nBuild version 6D1002") + InstalledXcode.any_instance.expects(:`).with("/usr/libexec/PlistBuddy -c \"Print :CFBundleShortVersionString\" \"#{xcode_path}/Contents/version.plist\"").returns('6.3.1') installed = InstalledXcode.new(xcode_path) installed.version.should == '6.3.1' end it 'is robust against broken Xcode installations' do - InstalledXcode.any_instance.expects(:`).with("DEVELOPER_DIR='' \"#{xcode_path}/Contents/Developer/usr/bin/xcodebuild\" -version").returns(nil) + InstalledXcode.any_instance.expects(:`).with("/usr/libexec/PlistBuddy -c \"Print :CFBundleShortVersionString\" \"#{xcode_path}/Contents/version.plist\"").returns(nil) installed = InstalledXcode.new(xcode_path) installed.version.should == '0.0' end diff --git a/spec/json_spec.rb b/spec/json_spec.rb index 439fd563..c6fe13fb 100644 --- a/spec/json_spec.rb +++ b/spec/json_spec.rb @@ -20,14 +20,14 @@ module XcodeInstall installer.stubs(:xcodes).returns(seedlist) versions = [ - '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.2', '4.6', '4.6.1', '4.6.3', - '5.0.1', '5', '5.0.2', '5.1', '5.1.1', + '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', + '5', '5.0.1', '5.0.2', '5.1', '5.1.1', '6.0.1', '6.1', '6.1.1', '6.2', '6.3', '6.3.1', '6.3.2', '6.4', - '7', '7.0.1', '7.1', '7.1.1', '7.2.1', '7.2', '7.3', '7.3.1', - '8', '8.1', '8.2', '8.2.1', '8.3.2', '8.3.3', '8.3', + '7', '7.0.1', '7.1', '7.1.1', '7.2', '7.2.1', '7.3', '7.3.1', + '8', '8.1', '8.2', '8.2.1', '8.3', '8.3.2', '8.3.3', '9', '9.0.1', '9.1', '9.2', '9.3', '9.3.1', '9.4', '9.4.1', - '10', '10.1', '10.2.1', '10.2', '10.3', - '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 beta 2', '11.4.1', '11.5 beta 2', '11.5', '11.5 GM Seed', '11.5 beta' + '10', '10.1', '10.2', '10.2.1', '10.3', + '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' ] installer.list.split("\n").should == versions end diff --git a/spec/list_spec.rb b/spec/list_spec.rb index 799ada85..1b7b7da3 100644 --- a/spec/list_spec.rb +++ b/spec/list_spec.rb @@ -43,7 +43,23 @@ def fake_installed_xcodes(*names) it 'lists all versions' do fake_xcodes '1', '2.3', '2.3.1', '2.3.2', '3 some', '4 beta', '10 beta' fake_installed_xcodes - installer.list.should == "1\n2.3.2\n2.3.1\n2.3\n3 some\n4 beta\n10 beta" + installer.list.should == "1\n2.3\n2.3.1\n2.3.2\n3 some\n4 beta\n10 beta" + end + + it 'lists all versions in the correct order' do + fake_xcodes( + '12 beta 4', '12 beta 3', '12 beta 2', '12 for macOS Universal Apps beta 2', + '12 beta', '12 for macOS Universal Apps beta', '12.0.1', '12', '12 beta 6', + '12 beta 5', '12.1 GM seed', '12.2 beta 3', '12.2 beta', '12.2 beta 2' + ) + fake_installed_xcodes + + versions = [ + '12 beta', '12 beta 2', '12 beta 3', '12 beta 4', '12 beta 5', '12 beta 6', + '12 for macOS Universal Apps beta', '12 for macOS Universal Apps beta 2', + '12', '12.0.1', '12.1 GM seed', '12.2 beta', '12.2 beta 2', '12.2 beta 3' + ] + installer.list.split("\n").should == versions end end @@ -51,7 +67,7 @@ def fake_installed_xcodes(*names) it 'lists all versions with annotations' do fake_xcodes '1', '2.3', '2.3.1', '2.3.2', '3 some', '4.3.1 for Lion', '9.4.1', '10 beta' fake_installed_xcodes '2.3', '4.3.1 for Lion', '10 beta' - installer.list.should == "1\n2.3.2\n2.3.1\n2.3 (installed)\n3 some\n4.3.1 for Lion (installed)\n9.4.1\n10 beta (installed)" + 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)" end it 'distinguish between beta and official_version' do @@ -61,9 +77,9 @@ def fake_installed_xcodes(*names) end it 'distinguish each beta versions' do - fake_xcodes '11.4 beta', '11.4 beta 3' + fake_xcodes '11.4 beta 3', '11.4 beta' fake_installed_xcodes '11.4 beta' - installer.list.should == "11.4 beta 3\n11.4 beta (installed)" + installer.list.should == "11.4 beta (installed)\n11.4 beta 3" end end end diff --git a/xcode-install.gemspec b/xcode-install.gemspec index 84d955a2..2746b0c4 100644 --- a/xcode-install.gemspec +++ b/xcode-install.gemspec @@ -22,11 +22,11 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] # CLI parsing - spec.add_dependency 'claide', '>= 0.9.1', '< 1.1.0' + spec.add_dependency 'claide', '>= 0.9.1' # contains spaceship, which is used for auth and dev portal interactions spec.add_dependency 'fastlane', '>= 2.1.0', '< 3.0.0' - spec.add_development_dependency 'bundler', '~> 1.7' + spec.add_development_dependency 'bundler', '>= 2.0.0', '< 3.0.0' spec.add_development_dependency 'rake', '>= 12.3.3' end