xamarin-test-cloud 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +13 -0
 - data/lib/xamarin-test-cloud/cli.rb +416 -154
 - data/lib/xamarin-test-cloud/dsym.rb +5 -7
 - data/lib/xamarin-test-cloud/test_file.rb +2 -2
 - data/lib/xamarin-test-cloud/version.rb +1 -1
 - metadata +3 -4
 - data/lib/xamarin-test-cloud/cli.rb alias +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 7179d836cc88e3266185b3d9cd68afa6b8272681
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 50bb75d45e930271faaa5a28ae6f718895790a6d
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 2adca474985c4505d9dbe98b5ae5c0e0da1365d921578328f2a3a21a7f13d84fdc8ef07e405cb638b8042bb3543602b49b642bac55117bc37fb9c796d5ed9573
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2ed5fcd3105e9622d69c1e88318b4c64bf4fced3bc516877c7cc6804385739f46337fe7acafba81e2f80a0fb2681b8531b09f7d35d6eda65c1f9f739bde642f9
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,3 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ### 2.1.0
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * CLI#collect\_files\_with\_glob should collect . files and skip anything
         
     | 
| 
      
 4 
     | 
    
         
            +
              under \_\_MACOSX #89
         
     | 
| 
      
 5 
     | 
    
         
            +
            * Fix the collection of included files #87
         
     | 
| 
      
 6 
     | 
    
         
            +
            * Add `prepare` command to generate an upload manifest #85
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ### 2.0.3
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            * CLI: add calabash=true to upload data #82
         
     | 
| 
      
 11 
     | 
    
         
            +
            * Support --include flag #81
         
     | 
| 
      
 12 
     | 
    
         
            +
            * Gem: force HTTPClient 2.7.1 or higher #80
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
       1 
14 
     | 
    
         
             
            ### 2.0.2
         
     | 
| 
       2 
15 
     | 
    
         | 
| 
       3 
16 
     | 
    
         
             
            * Use otool-classic to check for the CalabashServer whenever it is
         
     | 
| 
         @@ -41,7 +41,7 @@ module XamarinTestCloud 
     | 
|
| 
       41 
41 
     | 
    
         
             
                              :include_files_input,
         
     | 
| 
       42 
42 
     | 
    
         
             
                              :locale, :series, :session_id
         
     | 
| 
       43 
43 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                 
     | 
| 
      
 44 
     | 
    
         
            +
                attr_reader   :included_files_map
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
                def self.exit_on_failure?
         
     | 
| 
       47 
47 
     | 
    
         
             
                  true
         
     | 
| 
         @@ -63,6 +63,7 @@ module XamarinTestCloud 
     | 
|
| 
       63 
63 
     | 
    
         
             
                FILE_UPLOAD_ENDPOINT = 'upload2'
         
     | 
| 
       64 
64 
     | 
    
         
             
                FORM_URL_ENCODED_ENDPOINT = 'upload'
         
     | 
| 
       65 
65 
     | 
    
         | 
| 
      
 66 
     | 
    
         
            +
                MANIFEST_SCHEMA_VERSION = "1.0.0"
         
     | 
| 
       66 
67 
     | 
    
         | 
| 
       67 
68 
     | 
    
         
             
                def self.source_root
         
     | 
| 
       68 
69 
     | 
    
         
             
                  File.join(File.dirname(__FILE__), '..')
         
     | 
| 
         @@ -134,8 +135,7 @@ module XamarinTestCloud 
     | 
|
| 
       134 
135 
     | 
    
         
             
                              :type => :boolean,
         
     | 
| 
       135 
136 
     | 
    
         
             
                              :default => false
         
     | 
| 
       136 
137 
     | 
    
         | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
                #A list of items which are files or folders in the workspace.
         
     | 
| 
      
 138 
     | 
    
         
            +
                # A list of items which are files or folders in the workspace.
         
     | 
| 
       139 
139 
     | 
    
         
             
                # Must be a path relative to workspace and
         
     | 
| 
       140 
140 
     | 
    
         
             
                # must not refer outside (e.g. no usage of ../ etc).  Example --include .xtc foo
         
     | 
| 
       141 
141 
     | 
    
         
             
                method_option 'include',
         
     | 
| 
         @@ -188,27 +188,8 @@ module XamarinTestCloud 
     | 
|
| 
       188 
188 
     | 
    
         
             
                    $stdout = @async_log
         
     | 
| 
       189 
189 
     | 
    
         
             
                  end
         
     | 
| 
       190 
190 
     | 
    
         | 
| 
       191 
     | 
    
         
            -
                   
     | 
| 
       192 
     | 
    
         
            -
                   
     | 
| 
       193 
     | 
    
         
            -
                    raise ValidationError, "App is not a file: #{app_path}"
         
     | 
| 
       194 
     | 
    
         
            -
                  end
         
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
                  if shared_runtime?(app_path)
         
     | 
| 
       197 
     | 
    
         
            -
                    puts "Xamarin Test Cloud doesn't yet support shared runtime apps."
         
     | 
| 
       198 
     | 
    
         
            -
                    puts "To test your app it needs to be compiled for release."
         
     | 
| 
       199 
     | 
    
         
            -
                    puts "You can learn how to compile you app for release here:"
         
     | 
| 
       200 
     | 
    
         
            -
                    puts "http://docs.xamarin.com/guides/android/deployment%2C_testing%2C_and_metrics/publishing_an_application/part_1_-_preparing_an_application_for_release"
         
     | 
| 
       201 
     | 
    
         
            -
                    # TODO Change this to: "Shared runtime apps are not supported."
         
     | 
| 
       202 
     | 
    
         
            -
                    raise ValidationError, "Aborting"
         
     | 
| 
       203 
     | 
    
         
            -
                  end
         
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
                  app_extension = File.extname(app_path)
         
     | 
| 
       206 
     | 
    
         
            -
                  unless /ipa/i.match(app_extension) || /apk/i.match(app_extension)
         
     | 
| 
       207 
     | 
    
         
            -
                    raise ValidationError, "App #{app_path} must be an .ipa or .apk file"
         
     | 
| 
       208 
     | 
    
         
            -
                  end
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
                  self.app = app_path
         
     | 
| 
      
 191 
     | 
    
         
            +
                  # Verifies the app argument and sets the @app instance variable
         
     | 
| 
      
 192 
     | 
    
         
            +
                  verify_app!(app)
         
     | 
| 
       212 
193 
     | 
    
         | 
| 
       213 
194 
     | 
    
         
             
                  self.user = options['user']
         
     | 
| 
       214 
195 
     | 
    
         | 
| 
         @@ -230,36 +211,15 @@ module XamarinTestCloud 
     | 
|
| 
       230 
211 
     | 
    
         | 
| 
       231 
212 
     | 
    
         
             
                  self.priority = options['priority']
         
     | 
| 
       232 
213 
     | 
    
         | 
| 
       233 
     | 
    
         
            -
                  self.skip_config_check = options['skip-config-check']
         
     | 
| 
       234 
214 
     | 
    
         | 
| 
       235 
215 
     | 
    
         
             
                  self.include_files_input = options['include']
         
     | 
| 
       236 
216 
     | 
    
         | 
| 
       237 
217 
     | 
    
         
             
                  # Resolves the workspace and sets the @derived_workspace variable.
         
     | 
| 
       238 
218 
     | 
    
         
             
                  expect_features_directory_in_workspace
         
     | 
| 
       239 
219 
     | 
    
         | 
| 
       240 
     | 
    
         
            -
                  #  
     | 
| 
       241 
     | 
    
         
            -
                   
     | 
| 
       242 
     | 
    
         
            -
                   
     | 
| 
       243 
     | 
    
         
            -
                    default_config = File.join(derived_workspace, 'config', 'cucumber.yml')
         
     | 
| 
       244 
     | 
    
         
            -
                    # TODO .config/cucumber.yml is valid
         
     | 
| 
       245 
     | 
    
         
            -
                    # TODO cucumber.yaml is valid
         
     | 
| 
       246 
     | 
    
         
            -
                    if File.exist?(default_config) && self.config.nil?
         
     | 
| 
       247 
     | 
    
         
            -
                      # TODO Reword the header.
         
     | 
| 
       248 
     | 
    
         
            -
                      log_header 'Warning: Detected cucumber.yml config file, but no --config specified'
         
     | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
                      # TODO Reword the message and pass to raise as message.
         
     | 
| 
       251 
     | 
    
         
            -
                      puts "Please specify --config #{default_config}"
         
     | 
| 
       252 
     | 
    
         
            -
                      puts 'and specify a profile via --profile'
         
     | 
| 
       253 
     | 
    
         
            -
                      puts 'If you know what you are doing you can skip this check with'
         
     | 
| 
       254 
     | 
    
         
            -
                      puts '--skip-config-check'
         
     | 
| 
       255 
     | 
    
         
            -
             
     | 
| 
       256 
     | 
    
         
            -
                      # TODO This error message is wrong.
         
     | 
| 
       257 
     | 
    
         
            -
                      # It should be cucumber.yml detected by no --config option set.
         
     | 
| 
       258 
     | 
    
         
            -
                      raise ValidationError, "#{default_config} detected but no profile selected."
         
     | 
| 
       259 
     | 
    
         
            -
                    end
         
     | 
| 
       260 
     | 
    
         
            -
                  end
         
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
       262 
     | 
    
         
            -
                  self.included_files_map = parse_included_folders
         
     | 
| 
      
 220 
     | 
    
         
            +
                  # Verifies the --config and --profile options and sets these variables:
         
     | 
| 
      
 221 
     | 
    
         
            +
                  # @config, @profile, @skip_config_check
         
     | 
| 
      
 222 
     | 
    
         
            +
                  verify_cucumber_config_and_profile!
         
     | 
| 
       263 
223 
     | 
    
         | 
| 
       264 
224 
     | 
    
         
             
                  if Environment.debug?
         
     | 
| 
       265 
225 
     | 
    
         
             
                    puts "Host = #{self.host}"
         
     | 
| 
         @@ -273,11 +233,10 @@ module XamarinTestCloud 
     | 
|
| 
       273 
233 
     | 
    
         
             
                    puts "Config = #{self.config}"
         
     | 
| 
       274 
234 
     | 
    
         
             
                    puts "Profile = #{self.profile}"
         
     | 
| 
       275 
235 
     | 
    
         
             
                    puts "dSym = #{self.dsym}"
         
     | 
| 
       276 
     | 
    
         
            -
                    puts "Include = #{ 
     | 
| 
      
 236 
     | 
    
         
            +
                    puts "Include = #{included_files_map}"
         
     | 
| 
       277 
237 
     | 
    
         
             
                  end
         
     | 
| 
       278 
238 
     | 
    
         | 
| 
       279 
     | 
    
         
            -
             
     | 
| 
       280 
     | 
    
         
            -
                  #Argument parsing done
         
     | 
| 
      
 239 
     | 
    
         
            +
                  # Argument parsing done
         
     | 
| 
       281 
240 
     | 
    
         | 
| 
       282 
241 
     | 
    
         
             
                  test_jon_data = submit_test_job(device_selection_data)
         
     | 
| 
       283 
242 
     | 
    
         
             
                  if self.dry_run
         
     | 
| 
         @@ -332,11 +291,197 @@ module XamarinTestCloud 
     | 
|
| 
       332 
291 
     | 
    
         
             
                  end
         
     | 
| 
       333 
292 
     | 
    
         
             
                end
         
     | 
| 
       334 
293 
     | 
    
         | 
| 
      
 294 
     | 
    
         
            +
                desc "prepare <APP>",
         
     | 
| 
      
 295 
     | 
    
         
            +
                     "Prepares workspace and creates a manifest of files to be uploaded for test"
         
     | 
| 
      
 296 
     | 
    
         
            +
                method_option :config,
         
     | 
| 
      
 297 
     | 
    
         
            +
                              :desc => "Cucumber configuration file (cucumber.yml)",
         
     | 
| 
      
 298 
     | 
    
         
            +
                              :aliases => "-c",
         
     | 
| 
      
 299 
     | 
    
         
            +
                              :type => :string
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
                method_option :profile,
         
     | 
| 
      
 302 
     | 
    
         
            +
                              :desc => "Profile to run (profile from Cucumber configuration file)",
         
     | 
| 
      
 303 
     | 
    
         
            +
                              :aliases => "-p",
         
     | 
| 
      
 304 
     | 
    
         
            +
                              :type => :string
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                method_option :workspace,
         
     | 
| 
      
 307 
     | 
    
         
            +
                              :desc => "Alternate path to your Calabash workspace",
         
     | 
| 
      
 308 
     | 
    
         
            +
                              :aliases => "-w",
         
     | 
| 
      
 309 
     | 
    
         
            +
                              :type => :string
         
     | 
| 
      
 310 
     | 
    
         
            +
             
     | 
| 
      
 311 
     | 
    
         
            +
                method_option "test-parameters",
         
     | 
| 
      
 312 
     | 
    
         
            +
                              :desc => "Example: -params username:nat@xamarin.com password:xamarin)",
         
     | 
| 
      
 313 
     | 
    
         
            +
                              :aliases => "-params",
         
     | 
| 
      
 314 
     | 
    
         
            +
                              :type => :hash,
         
     | 
| 
      
 315 
     | 
    
         
            +
                              :default => {}
         
     | 
| 
      
 316 
     | 
    
         
            +
             
     | 
| 
      
 317 
     | 
    
         
            +
                method_option "skip-config-check",
         
     | 
| 
      
 318 
     | 
    
         
            +
                              :desc => "Force running without Cucumber profile (cucumber.yml)",
         
     | 
| 
      
 319 
     | 
    
         
            +
                              :type => :boolean,
         
     | 
| 
      
 320 
     | 
    
         
            +
                              :default => false
         
     | 
| 
      
 321 
     | 
    
         
            +
             
     | 
| 
      
 322 
     | 
    
         
            +
                method_option "artifacts-dir",
         
     | 
| 
      
 323 
     | 
    
         
            +
                              :desc => "Directory where the test files should be staged.",
         
     | 
| 
      
 324 
     | 
    
         
            +
                              :type => :string,
         
     | 
| 
      
 325 
     | 
    
         
            +
                              :required => true
         
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
      
 327 
     | 
    
         
            +
                # A list of items which are files or folders in the workspace.
         
     | 
| 
      
 328 
     | 
    
         
            +
                # Must be a path relative to workspace and
         
     | 
| 
      
 329 
     | 
    
         
            +
                # must not refer outside (e.g. no usage of ../ etc).  Example --include .xtc foo
         
     | 
| 
      
 330 
     | 
    
         
            +
                method_option 'include',
         
     | 
| 
      
 331 
     | 
    
         
            +
                              :desc => 'Include folders or files in workspace in addition the features folder.',
         
     | 
| 
      
 332 
     | 
    
         
            +
                              :aliases => '-i',
         
     | 
| 
      
 333 
     | 
    
         
            +
                              :type => :array,
         
     | 
| 
      
 334 
     | 
    
         
            +
                              :default => []
         
     | 
| 
      
 335 
     | 
    
         
            +
             
     | 
| 
      
 336 
     | 
    
         
            +
                def prepare(app)
         
     | 
| 
      
 337 
     | 
    
         
            +
                  @include_files_input = options[:include]
         
     | 
| 
      
 338 
     | 
    
         
            +
                  artifact_directory = File.expand_path(options["artifacts-dir"])
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
                  # Validates and sets the @app instance variable.
         
     | 
| 
      
 341 
     | 
    
         
            +
                  verify_app!(app)
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
                  # Resolves the workspace and sets the @derived_workspace variable.
         
     | 
| 
      
 344 
     | 
    
         
            +
                  expect_features_directory_in_workspace
         
     | 
| 
      
 345 
     | 
    
         
            +
             
     | 
| 
      
 346 
     | 
    
         
            +
                  # Verifies the --config and --profile options and sets these variables:
         
     | 
| 
      
 347 
     | 
    
         
            +
                  # @config, @profile, @skip_config_check
         
     | 
| 
      
 348 
     | 
    
         
            +
                  verify_cucumber_config_and_profile!
         
     | 
| 
      
 349 
     | 
    
         
            +
             
     | 
| 
      
 350 
     | 
    
         
            +
                  require "xamarin-test-cloud/tmpdir"
         
     | 
| 
      
 351 
     | 
    
         
            +
                  bundle_package_dir = XamarinTestCloud::TmpDir.mktmpdir
         
     | 
| 
      
 352 
     | 
    
         
            +
             
     | 
| 
      
 353 
     | 
    
         
            +
                  stage_gemfile_and_bundle_package(bundle_package_dir)
         
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
                  files = collect_test_suite_files(bundle_package_dir)
         
     | 
| 
      
 356 
     | 
    
         
            +
             
     | 
| 
      
 357 
     | 
    
         
            +
                  FileUtils.mkdir_p(artifact_directory)
         
     | 
| 
      
 358 
     | 
    
         
            +
                  manifest_file = File.join(artifact_directory, "manifest.json")
         
     | 
| 
      
 359 
     | 
    
         
            +
             
     | 
| 
      
 360 
     | 
    
         
            +
                  log_header("Preparing the Artifact Directory")
         
     | 
| 
      
 361 
     | 
    
         
            +
                  test_parameters = options["test-parameters"]
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
                  manifest = generate_manifest_hash(files, test_parameters)
         
     | 
| 
      
 364 
     | 
    
         
            +
                  write_manifest_to_file(manifest, manifest_file)
         
     | 
| 
      
 365 
     | 
    
         
            +
             
     | 
| 
      
 366 
     | 
    
         
            +
                  puts ""
         
     | 
| 
      
 367 
     | 
    
         
            +
                  puts "Copied files to:"
         
     | 
| 
      
 368 
     | 
    
         
            +
                  puts "  #{File.expand_path(artifact_directory)}"
         
     | 
| 
      
 369 
     | 
    
         
            +
                  puts ""
         
     | 
| 
      
 370 
     | 
    
         
            +
                  puts "Wrote upload manifest to:"
         
     | 
| 
      
 371 
     | 
    
         
            +
                  puts "  #{File.expand_path(manifest_file)}"
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
                  files.each do |test_file|
         
     | 
| 
      
 374 
     | 
    
         
            +
                    target = File.join(artifact_directory, test_file.remote_path)
         
     | 
| 
      
 375 
     | 
    
         
            +
                    basedir = File.dirname(target)
         
     | 
| 
      
 376 
     | 
    
         
            +
                    FileUtils.mkdir_p(basedir)
         
     | 
| 
      
 377 
     | 
    
         
            +
                    FileUtils.cp(test_file.path, target)
         
     | 
| 
      
 378 
     | 
    
         
            +
                  end
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
                end
         
     | 
| 
       335 
381 
     | 
    
         | 
| 
       336 
382 
     | 
    
         
             
                default_task :submit
         
     | 
| 
       337 
383 
     | 
    
         | 
| 
       338 
384 
     | 
    
         
             
                no_tasks do
         
     | 
| 
       339 
385 
     | 
    
         | 
| 
      
 386 
     | 
    
         
            +
                  # TODO: move to separate module/class
         
     | 
| 
      
 387 
     | 
    
         
            +
                  def expect_app_exists_at_path(app_path)
         
     | 
| 
      
 388 
     | 
    
         
            +
                    unless File.exist?(File.expand_path(app_path))
         
     | 
| 
      
 389 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 390 
     | 
    
         
            +
            App does not exist at path:
         
     | 
| 
      
 391 
     | 
    
         
            +
             
     | 
| 
      
 392 
     | 
    
         
            +
            #{File.expand_path(app_path)}
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
            ]
         
     | 
| 
      
 395 
     | 
    
         
            +
                    end
         
     | 
| 
      
 396 
     | 
    
         
            +
                  end
         
     | 
| 
      
 397 
     | 
    
         
            +
             
     | 
| 
      
 398 
     | 
    
         
            +
                  # TODO: move to separate module/class
         
     | 
| 
      
 399 
     | 
    
         
            +
                  def expect_apk_or_ipa(app_path)
         
     | 
| 
      
 400 
     | 
    
         
            +
                    app_extension = File.extname(app_path)
         
     | 
| 
      
 401 
     | 
    
         
            +
                    unless /ipa/i.match(app_extension) || /apk/i.match(app_extension)
         
     | 
| 
      
 402 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 403 
     | 
    
         
            +
            App must be an .ipa or .apk file.  Found:
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
            #{app_path}
         
     | 
| 
      
 406 
     | 
    
         
            +
             
     | 
| 
      
 407 
     | 
    
         
            +
            with extension: #{app_extension}
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
      
 409 
     | 
    
         
            +
            ]
         
     | 
| 
      
 410 
     | 
    
         
            +
                    end
         
     | 
| 
      
 411 
     | 
    
         
            +
                  end
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
                  # TODO: move to separate module/class
         
     | 
| 
      
 414 
     | 
    
         
            +
                  def expect_no_shared_runtime(app_path)
         
     | 
| 
      
 415 
     | 
    
         
            +
                    if shared_runtime?(app_path)
         
     | 
| 
      
 416 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 417 
     | 
    
         
            +
            Xamarin Test Cloud does not support shared runtime apps.
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
      
 419 
     | 
    
         
            +
            To test your app it needs to be compiled for release.
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
      
 421 
     | 
    
         
            +
            You can learn how to compile your app for release here:
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
            http://docs.xamarin.com/guides/android/deployment%2C_testing%2C_and_metrics/publishing_an_application/part_1_-_preparing_an_application_for_release
         
     | 
| 
      
 424 
     | 
    
         
            +
             
     | 
| 
      
 425 
     | 
    
         
            +
            ]
         
     | 
| 
      
 426 
     | 
    
         
            +
                    end
         
     | 
| 
      
 427 
     | 
    
         
            +
                  end
         
     | 
| 
      
 428 
     | 
    
         
            +
             
     | 
| 
      
 429 
     | 
    
         
            +
                  # TODO: move to separate module/class
         
     | 
| 
      
 430 
     | 
    
         
            +
                  def expect_ipa_linked_with_calabash(app_path)
         
     | 
| 
      
 431 
     | 
    
         
            +
                    # Cannot use #is_ios because that method depends on the @app instance
         
     | 
| 
      
 432 
     | 
    
         
            +
                    # variable which is not set when this method is called.
         
     | 
| 
      
 433 
     | 
    
         
            +
                    return nil if !app_path.end_with?(".ipa")
         
     | 
| 
      
 434 
     | 
    
         
            +
             
     | 
| 
      
 435 
     | 
    
         
            +
                    # otool does not exist in non-macOS environments.  We have to rely on
         
     | 
| 
      
 436 
     | 
    
         
            +
                    # the Test Cloud to perform the validation.
         
     | 
| 
      
 437 
     | 
    
         
            +
                    return nil if !Environment.macos_env?
         
     | 
| 
      
 438 
     | 
    
         
            +
             
     | 
| 
      
 439 
     | 
    
         
            +
                    require "xamarin-test-cloud/tmpdir"
         
     | 
| 
      
 440 
     | 
    
         
            +
                    tmpdir = TmpDir.mktmpdir
         
     | 
| 
      
 441 
     | 
    
         
            +
             
     | 
| 
      
 442 
     | 
    
         
            +
                    unzip_file(app_path, tmpdir)
         
     | 
| 
      
 443 
     | 
    
         
            +
             
     | 
| 
      
 444 
     | 
    
         
            +
                    payload_dir = File.join(tmpdir, "Payload")
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                    if !File.directory?(payload_dir)
         
     | 
| 
      
 447 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 448 
     | 
    
         
            +
            Did not find a Payload directory after expanding the ipa.
         
     | 
| 
      
 449 
     | 
    
         
            +
             
     | 
| 
      
 450 
     | 
    
         
            +
            #{app_path}
         
     | 
| 
      
 451 
     | 
    
         
            +
             
     | 
| 
      
 452 
     | 
    
         
            +
            The .ipa was not packaged correctly.
         
     | 
| 
      
 453 
     | 
    
         
            +
             
     | 
| 
      
 454 
     | 
    
         
            +
            ]
         
     | 
| 
      
 455 
     | 
    
         
            +
                    end
         
     | 
| 
      
 456 
     | 
    
         
            +
             
     | 
| 
      
 457 
     | 
    
         
            +
                    app_dir = Dir.foreach("#{tmpdir}/Payload").find { |d| /\.app$/.match(d) }
         
     | 
| 
      
 458 
     | 
    
         
            +
                    res = check_for_calabash_server(tmpdir, app_dir)
         
     | 
| 
      
 459 
     | 
    
         
            +
             
     | 
| 
      
 460 
     | 
    
         
            +
                    if /CalabashServer/.match(res)
         
     | 
| 
      
 461 
     | 
    
         
            +
                      puts "ipa: #{app_path} *contains* calabash.framework"
         
     | 
| 
      
 462 
     | 
    
         
            +
                    else
         
     | 
| 
      
 463 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 464 
     | 
    
         
            +
             
     | 
| 
      
 465 
     | 
    
         
            +
            The ipa does not contain an app that is linked with Calabash.
         
     | 
| 
      
 466 
     | 
    
         
            +
             
     | 
| 
      
 467 
     | 
    
         
            +
            Your app must link the calabash.framework at compile time or it must dynamically
         
     | 
| 
      
 468 
     | 
    
         
            +
            load (in code) a Calabash dylib.
         
     | 
| 
      
 469 
     | 
    
         
            +
             
     | 
| 
      
 470 
     | 
    
         
            +
            https://github.com/calabash/calabash-ios/wiki/Tutorial%3A-How-to-add-Calabash-to-Xcode
         
     | 
| 
      
 471 
     | 
    
         
            +
            ]
         
     | 
| 
      
 472 
     | 
    
         
            +
                    end
         
     | 
| 
      
 473 
     | 
    
         
            +
                  end
         
     | 
| 
      
 474 
     | 
    
         
            +
             
     | 
| 
      
 475 
     | 
    
         
            +
                  def verify_app!(app_path)
         
     | 
| 
      
 476 
     | 
    
         
            +
                    expanded = File.expand_path(app_path)
         
     | 
| 
      
 477 
     | 
    
         
            +
                    expect_app_exists_at_path(expanded)
         
     | 
| 
      
 478 
     | 
    
         
            +
                    expect_apk_or_ipa(expanded)
         
     | 
| 
      
 479 
     | 
    
         
            +
                    expect_no_shared_runtime(expanded)
         
     | 
| 
      
 480 
     | 
    
         
            +
                    expect_ipa_linked_with_calabash(expanded)
         
     | 
| 
      
 481 
     | 
    
         
            +
             
     | 
| 
      
 482 
     | 
    
         
            +
                    @app = expanded
         
     | 
| 
      
 483 
     | 
    
         
            +
                  end
         
     | 
| 
      
 484 
     | 
    
         
            +
             
     | 
| 
       340 
485 
     | 
    
         
             
                  def dsym
         
     | 
| 
       341 
486 
     | 
    
         
             
                    if @dsym.nil?
         
     | 
| 
       342 
487 
     | 
    
         
             
                      value = options["dsym-file"]
         
     | 
| 
         @@ -437,10 +582,6 @@ module XamarinTestCloud 
     | 
|
| 
       437 
582 
     | 
    
         
             
                      log "Packaging gems in: #{tmpdir}"
         
     | 
| 
       438 
583 
     | 
    
         
             
                    end
         
     | 
| 
       439 
584 
     | 
    
         | 
| 
       440 
     | 
    
         
            -
                    # TODO Move to common expect_valid_application
         
     | 
| 
       441 
     | 
    
         
            -
                    # TODO Rename: does not need to extract a test server
         
     | 
| 
       442 
     | 
    
         
            -
                    verify_app_and_extract_test_server
         
     | 
| 
       443 
     | 
    
         
            -
             
     | 
| 
       444 
585 
     | 
    
         
             
                    stage_gemfile_and_bundle_package(tmpdir)
         
     | 
| 
       445 
586 
     | 
    
         | 
| 
       446 
587 
     | 
    
         
             
                    log_header('Verifying dependencies')
         
     | 
| 
         @@ -469,6 +610,7 @@ module XamarinTestCloud 
     | 
|
| 
       469 
610 
     | 
    
         
             
                    log_header('Uploading negotiated files')
         
     | 
| 
       470 
611 
     | 
    
         | 
| 
       471 
612 
     | 
    
         
             
                    upload_data = {
         
     | 
| 
      
 613 
     | 
    
         
            +
                      'calabash' => true,
         
     | 
| 
       472 
614 
     | 
    
         
             
                      'files' => digests_and_files,
         
     | 
| 
       473 
615 
     | 
    
         
             
                      'paths' => remote_paths,
         
     | 
| 
       474 
616 
     | 
    
         
             
                      'user' => self.user,
         
     | 
| 
         @@ -794,10 +936,16 @@ and try submitting again. 
     | 
|
| 
       794 
936 
     | 
    
         
             
                    files
         
     | 
| 
       795 
937 
     | 
    
         
             
                  end
         
     | 
| 
       796 
938 
     | 
    
         | 
| 
      
 939 
     | 
    
         
            +
                  def collect_file?(path)
         
     | 
| 
      
 940 
     | 
    
         
            +
                    File.file?(path) &&
         
     | 
| 
      
 941 
     | 
    
         
            +
                      File.basename(path) != ".DS_Store" &&
         
     | 
| 
      
 942 
     | 
    
         
            +
                      !path[/__MACOSX/]
         
     | 
| 
      
 943 
     | 
    
         
            +
                  end
         
     | 
| 
      
 944 
     | 
    
         
            +
             
     | 
| 
       797 
945 
     | 
    
         
             
                  # Returns file paths as Strings
         
     | 
| 
       798 
946 
     | 
    
         
             
                  def collect_files_with_glob(glob)
         
     | 
| 
       799 
     | 
    
         
            -
                    Dir.glob(glob).select do |path|
         
     | 
| 
       800 
     | 
    
         
            -
                       
     | 
| 
      
 947 
     | 
    
         
            +
                    Dir.glob(glob, File::FNM_DOTMATCH).select do |path|
         
     | 
| 
      
 948 
     | 
    
         
            +
                      collect_file?(path)
         
     | 
| 
       801 
949 
     | 
    
         
             
                    end
         
     | 
| 
       802 
950 
     | 
    
         
             
                  end
         
     | 
| 
       803 
951 
     | 
    
         | 
| 
         @@ -828,10 +976,26 @@ and try submitting again. 
     | 
|
| 
       828 
976 
     | 
    
         | 
| 
       829 
977 
     | 
    
         
             
                  def collect_included_files(tmpdir)
         
     | 
| 
       830 
978 
     | 
    
         
             
                    collected_files = []
         
     | 
| 
       831 
     | 
    
         
            -
                     
     | 
| 
       832 
     | 
    
         
            -
                       
     | 
| 
       833 
     | 
    
         
            -
                       
     | 
| 
       834 
     | 
    
         
            -
             
     | 
| 
      
 979 
     | 
    
         
            +
                    included_files_map.each_pair do |source, target|
         
     | 
| 
      
 980 
     | 
    
         
            +
                      # Use File.expand_path to handle the Windows case where the user passes:
         
     | 
| 
      
 981 
     | 
    
         
            +
                      # --workspace "test-cloud\ios"
         
     | 
| 
      
 982 
     | 
    
         
            +
                      # --include ".xtc\sample.txt"
         
     | 
| 
      
 983 
     | 
    
         
            +
                      #
         
     | 
| 
      
 984 
     | 
    
         
            +
                      # A File.join will result in:
         
     | 
| 
      
 985 
     | 
    
         
            +
                      #   /path/to/test-cloud/ios/.xtc\sample.txt
         
     | 
| 
      
 986 
     | 
    
         
            +
                      # because the join naively appends the ".xtc\sample.txt"
         
     | 
| 
      
 987 
     | 
    
         
            +
                      # Use File.expand_path to handle the /
         
     | 
| 
      
 988 
     | 
    
         
            +
                      tmp_target = File.expand_path(File.join(tmpdir, target))
         
     | 
| 
      
 989 
     | 
    
         
            +
             
     | 
| 
      
 990 
     | 
    
         
            +
                      FileUtils.mkdir_p(File.dirname(tmp_target))
         
     | 
| 
      
 991 
     | 
    
         
            +
                      FileUtils.cp_r(source, tmp_target)
         
     | 
| 
      
 992 
     | 
    
         
            +
             
     | 
| 
      
 993 
     | 
    
         
            +
                      if File.directory?(tmp_target)
         
     | 
| 
      
 994 
     | 
    
         
            +
                        collect_files_with_glob(File.join(tmpdir,target,"**","*")).map do |file|
         
     | 
| 
      
 995 
     | 
    
         
            +
                          collected_files << TestFile.new(file, tmpdir)
         
     | 
| 
      
 996 
     | 
    
         
            +
                        end
         
     | 
| 
      
 997 
     | 
    
         
            +
                      else
         
     | 
| 
      
 998 
     | 
    
         
            +
                        collected_files << TestFile.new(tmp_target, tmpdir)
         
     | 
| 
       835 
999 
     | 
    
         
             
                      end
         
     | 
| 
       836 
1000 
     | 
    
         
             
                    end
         
     | 
| 
       837 
1001 
     | 
    
         
             
                    collected_files
         
     | 
| 
         @@ -893,30 +1057,6 @@ and try submitting again. 
     | 
|
| 
       893 
1057 
     | 
    
         
             
                    end
         
     | 
| 
       894 
1058 
     | 
    
         
             
                  end
         
     | 
| 
       895 
1059 
     | 
    
         | 
| 
       896 
     | 
    
         
            -
                  # TODO: move to separate module/class
         
     | 
| 
       897 
     | 
    
         
            -
                  # TODO: fix the detection algorithm - it is broken
         
     | 
| 
       898 
     | 
    
         
            -
                  # TODO: remove the Frank check
         
     | 
| 
       899 
     | 
    
         
            -
                  # https://github.com/xamarinhq/test-cloud-command-line/issues/19
         
     | 
| 
       900 
     | 
    
         
            -
                  def validate_ipa(ipa)
         
     | 
| 
       901 
     | 
    
         
            -
                    result = false
         
     | 
| 
       902 
     | 
    
         
            -
                    dir = Dir.mktmpdir #do |dir|
         
     | 
| 
       903 
     | 
    
         
            -
             
     | 
| 
       904 
     | 
    
         
            -
                    unzip_file(ipa, dir)
         
     | 
| 
       905 
     | 
    
         
            -
                    unless File.directory?("#{dir}/Payload") #macos only
         
     | 
| 
       906 
     | 
    
         
            -
                      raise ValidationError, "Unzipping #{ipa} to #{dir} failed: Did not find a Payload directory (invalid .ipa)."
         
     | 
| 
       907 
     | 
    
         
            -
                    end
         
     | 
| 
       908 
     | 
    
         
            -
                    app_dir = Dir.foreach("#{dir}/Payload").find { |d| /\.app$/.match(d) }
         
     | 
| 
       909 
     | 
    
         
            -
                    res = check_for_calabash_server(dir, app_dir)
         
     | 
| 
       910 
     | 
    
         
            -
             
     | 
| 
       911 
     | 
    
         
            -
                    if /CalabashServer/.match(res)
         
     | 
| 
       912 
     | 
    
         
            -
                      puts "ipa: #{ipa} *contains* calabash.framework"
         
     | 
| 
       913 
     | 
    
         
            -
                      result = :calabash
         
     | 
| 
       914 
     | 
    
         
            -
                    end
         
     | 
| 
       915 
     | 
    
         
            -
             
     | 
| 
       916 
     | 
    
         
            -
                    result
         
     | 
| 
       917 
     | 
    
         
            -
                  end
         
     | 
| 
       918 
     | 
    
         
            -
             
     | 
| 
       919 
     | 
    
         
            -
             
     | 
| 
       920 
1060 
     | 
    
         
             
                  def log(message)
         
     | 
| 
       921 
1061 
     | 
    
         
             
                    if message.is_a? Array
         
     | 
| 
       922 
1062 
     | 
    
         
             
                      message.each { |m| log(m) }
         
     | 
| 
         @@ -934,27 +1074,6 @@ and try submitting again. 
     | 
|
| 
       934 
1074 
     | 
    
         
             
                    end
         
     | 
| 
       935 
1075 
     | 
    
         
             
                  end
         
     | 
| 
       936 
1076 
     | 
    
         | 
| 
       937 
     | 
    
         
            -
                  # TODO: rename: does not need to extract or return the server
         
     | 
| 
       938 
     | 
    
         
            -
                  def verify_app_and_extract_test_server
         
     | 
| 
       939 
     | 
    
         
            -
                    server = nil
         
     | 
| 
       940 
     | 
    
         
            -
             
     | 
| 
       941 
     | 
    
         
            -
                    unless File.exist?(app)
         
     | 
| 
       942 
     | 
    
         
            -
                      raise ValidationError, "No such file: #{app}"
         
     | 
| 
       943 
     | 
    
         
            -
                    end
         
     | 
| 
       944 
     | 
    
         
            -
                    unless (/\.(apk|ipa)$/ =~ app)
         
     | 
| 
       945 
     | 
    
         
            -
                      raise ValidationError, '<APP> should be either an ipa or apk file.'
         
     | 
| 
       946 
     | 
    
         
            -
                    end
         
     | 
| 
       947 
     | 
    
         
            -
                    if is_ios? && Environment.macos_env?
         
     | 
| 
       948 
     | 
    
         
            -
                      log_header('Checking ipa for linking with Calabash')
         
     | 
| 
       949 
     | 
    
         
            -
                      server = validate_ipa(app)
         
     | 
| 
       950 
     | 
    
         
            -
                      abort_unless(server) do
         
     | 
| 
       951 
     | 
    
         
            -
                        puts 'The .ipa file does not seem to be linked with Calabash.'
         
     | 
| 
       952 
     | 
    
         
            -
                        puts 'Verify that your app is linked correctly.'
         
     | 
| 
       953 
     | 
    
         
            -
                      end
         
     | 
| 
       954 
     | 
    
         
            -
                    end
         
     | 
| 
       955 
     | 
    
         
            -
                    server
         
     | 
| 
       956 
     | 
    
         
            -
                  end
         
     | 
| 
       957 
     | 
    
         
            -
             
     | 
| 
       958 
1077 
     | 
    
         
             
                  # TODO Rename or remove; abort is not the right verb - use exit
         
     | 
| 
       959 
1078 
     | 
    
         
             
                  # +1 for remove
         
     | 
| 
       960 
1079 
     | 
    
         
             
                  def abort(&block)
         
     | 
| 
         @@ -982,12 +1101,15 @@ and try submitting again. 
     | 
|
| 
       982 
1101 
     | 
    
         
             
                  end
         
     | 
| 
       983 
1102 
     | 
    
         | 
| 
       984 
1103 
     | 
    
         
             
                  # TODO Move to a module
         
     | 
| 
      
 1104 
     | 
    
         
            +
                  # TODO Needs tests
         
     | 
| 
       985 
1105 
     | 
    
         
             
                  def shared_runtime?(app_path)
         
     | 
| 
       986 
1106 
     | 
    
         
             
                    f = files(app_path)
         
     | 
| 
       987 
1107 
     | 
    
         
             
                    f.any? do |file|
         
     | 
| 
       988 
1108 
     | 
    
         
             
                      filename = file[:filename]
         
     | 
| 
       989 
1109 
     | 
    
         
             
                      if filename.end_with?("libmonodroid.so")
         
     | 
| 
       990 
     | 
    
         
            -
                        file[:size] < 120 * 1024 && f.none?  
     | 
| 
      
 1110 
     | 
    
         
            +
                        file[:size] < 120 * 1024 && f.none? do |x|
         
     | 
| 
      
 1111 
     | 
    
         
            +
                          x[:filename] == filename.sub("libmonodroid.so", "libmonosgen-2.0.so")
         
     | 
| 
      
 1112 
     | 
    
         
            +
                        end
         
     | 
| 
       991 
1113 
     | 
    
         
             
                      end
         
     | 
| 
       992 
1114 
     | 
    
         
             
                    end
         
     | 
| 
       993 
1115 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1001,52 +1123,186 @@ and try submitting again. 
     | 
|
| 
       1001 
1123 
     | 
    
         
             
                    end
         
     | 
| 
       1002 
1124 
     | 
    
         
             
                  end
         
     | 
| 
       1003 
1125 
     | 
    
         | 
| 
       1004 
     | 
    
         
            -
                  # TODO: extract to a module
         
     | 
| 
       1005 
     | 
    
         
            -
                  # TODO: replace unless/else branches
         
     | 
| 
       1006 
     | 
    
         
            -
                  def parse_and_set_config_and_profile
         
     | 
| 
       1007 
     | 
    
         
            -
                    config_path = options[:config]
         
     | 
| 
       1008 
1126 
     | 
    
         | 
| 
       1009 
     | 
    
         
            -
             
     | 
| 
       1010 
     | 
    
         
            -
             
     | 
| 
       1011 
     | 
    
         
            -
             
     | 
| 
      
 1127 
     | 
    
         
            +
                  # TODO: extract this method to a module
         
     | 
| 
      
 1128 
     | 
    
         
            +
                  # TODO: .config/cucumber.yml is a valid cucumber profile
         
     | 
| 
      
 1129 
     | 
    
         
            +
                  # TODO: cucumber.yaml and cucumber.yml are both valid names
         
     | 
| 
      
 1130 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1131 
     | 
    
         
            +
                  # Raises if there is config/cucumber.yml file but no --config option is
         
     | 
| 
      
 1132 
     | 
    
         
            +
                  # passed.
         
     | 
| 
      
 1133 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1134 
     | 
    
         
            +
                  # Check can be skipped by passing --skip-config-check.
         
     | 
| 
      
 1135 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1136 
     | 
    
         
            +
                  # This method, sadly, has a preconditions: @config and @skip_config_check
         
     | 
| 
      
 1137 
     | 
    
         
            +
                  # must be set correctly before calling this method.
         
     | 
| 
      
 1138 
     | 
    
         
            +
                  def expect_config_option_if_cucumber_config_file_exists
         
     | 
| 
      
 1139 
     | 
    
         
            +
                    return nil if config
         
     | 
| 
      
 1140 
     | 
    
         
            +
                    return nil if skip_config_check
         
     | 
| 
      
 1141 
     | 
    
         
            +
             
     | 
| 
      
 1142 
     | 
    
         
            +
                    default_config = File.join(derived_workspace, "config", "cucumber.yml")
         
     | 
| 
      
 1143 
     | 
    
         
            +
                    if File.exist?(default_config)
         
     | 
| 
      
 1144 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 1145 
     | 
    
         
            +
            Detected a cucumber configuration file, but no --config option was specified.
         
     | 
| 
      
 1146 
     | 
    
         
            +
             
     | 
| 
      
 1147 
     | 
    
         
            +
            #{default_config}
         
     | 
| 
      
 1148 
     | 
    
         
            +
             
     | 
| 
      
 1149 
     | 
    
         
            +
            You can pass the cucumber configuration file to the uploader using:
         
     | 
| 
      
 1150 
     | 
    
         
            +
             
     | 
| 
      
 1151 
     | 
    
         
            +
            --config #{default_config}
         
     | 
| 
      
 1152 
     | 
    
         
            +
             
     | 
| 
      
 1153 
     | 
    
         
            +
            and specify a profile using the --profile option.
         
     | 
| 
      
 1154 
     | 
    
         
            +
             
     | 
| 
      
 1155 
     | 
    
         
            +
            You can skip this check using the --skip-config-check option, but this is not
         
     | 
| 
      
 1156 
     | 
    
         
            +
            recommended.
         
     | 
| 
      
 1157 
     | 
    
         
            +
             
     | 
| 
      
 1158 
     | 
    
         
            +
            ]
         
     | 
| 
       1012 
1159 
     | 
    
         
             
                    end
         
     | 
| 
      
 1160 
     | 
    
         
            +
                  end
         
     | 
| 
       1013 
1161 
     | 
    
         | 
| 
       1014 
     | 
    
         
            -
             
     | 
| 
       1015 
     | 
    
         
            -
             
     | 
| 
       1016 
     | 
    
         
            -
             
     | 
| 
       1017 
     | 
    
         
            -
                        raise ValidationError, "Config file does not exist #{config_path}"
         
     | 
| 
       1018 
     | 
    
         
            -
                      end
         
     | 
| 
      
 1162 
     | 
    
         
            +
                  # TODO: extract this method to a module
         
     | 
| 
      
 1163 
     | 
    
         
            +
                  def resolve_cucumber_config_path(path)
         
     | 
| 
      
 1164 
     | 
    
         
            +
                    return nil if !path
         
     | 
| 
       1019 
1165 
     | 
    
         | 
| 
       1020 
     | 
    
         
            -
             
     | 
| 
       1021 
     | 
    
         
            -
             
     | 
| 
       1022 
     | 
    
         
            -
                      rescue Exception => e
         
     | 
| 
       1023 
     | 
    
         
            -
                        puts "Unable to parse #{config_path} as yml. Is this your Cucumber.yml file?"
         
     | 
| 
       1024 
     | 
    
         
            -
                        raise ValidationError, e
         
     | 
| 
       1025 
     | 
    
         
            -
                      end
         
     | 
| 
      
 1166 
     | 
    
         
            +
                    expanded = File.expand_path(path)
         
     | 
| 
      
 1167 
     | 
    
         
            +
                    return expanded if expanded == path
         
     | 
| 
       1026 
1168 
     | 
    
         | 
| 
       1027 
     | 
    
         
            -
             
     | 
| 
       1028 
     | 
    
         
            -
             
     | 
| 
       1029 
     | 
    
         
            -
             
     | 
| 
      
 1169 
     | 
    
         
            +
                    workspace = derived_workspace
         
     | 
| 
      
 1170 
     | 
    
         
            +
                    # Use File.expand_path to handle the Windows case where the user passes:
         
     | 
| 
      
 1171 
     | 
    
         
            +
                    # --workspace "test-cloud\ios"
         
     | 
| 
      
 1172 
     | 
    
         
            +
                    # --config "config\cucumber.yml"
         
     | 
| 
      
 1173 
     | 
    
         
            +
                    #
         
     | 
| 
      
 1174 
     | 
    
         
            +
                    # A File.join will result in:
         
     | 
| 
      
 1175 
     | 
    
         
            +
                    #   /path/to/test-cloud/ios/config\cucumber.yml
         
     | 
| 
      
 1176 
     | 
    
         
            +
                    # because the join naively appends the "config\cucumber.yml".
         
     | 
| 
      
 1177 
     | 
    
         
            +
                    File.expand_path(File.join(workspace, path))
         
     | 
| 
      
 1178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1179 
     | 
    
         
            +
             
     | 
| 
      
 1180 
     | 
    
         
            +
                  # TODO: extract this method to a module
         
     | 
| 
      
 1181 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1182 
     | 
    
         
            +
                  # Sets @config to a TestFile instance
         
     | 
| 
      
 1183 
     | 
    
         
            +
                  # Sets @skip_config_check to option passed on the CLI
         
     | 
| 
      
 1184 
     | 
    
         
            +
                  # Sets @profile to option passed on the CLI
         
     | 
| 
      
 1185 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1186 
     | 
    
         
            +
                  # Raises if there is problem parsing or interpreting the profile with
         
     | 
| 
      
 1187 
     | 
    
         
            +
                  # respect to the configuration file.
         
     | 
| 
      
 1188 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1189 
     | 
    
         
            +
                  # Raises if there is config/cucumber.yml file but no --config option is
         
     | 
| 
      
 1190 
     | 
    
         
            +
                  # passed.
         
     | 
| 
      
 1191 
     | 
    
         
            +
                  def verify_cucumber_config_and_profile!
         
     | 
| 
      
 1192 
     | 
    
         
            +
                    config = options[:config]
         
     | 
| 
      
 1193 
     | 
    
         
            +
                    profile = options[:profile]
         
     | 
| 
      
 1194 
     | 
    
         
            +
             
     | 
| 
      
 1195 
     | 
    
         
            +
                    if profile && !config
         
     | 
| 
      
 1196 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 1197 
     | 
    
         
            +
             
     | 
| 
      
 1198 
     | 
    
         
            +
            The --profile option was set without a --config option.
         
     | 
| 
      
 1199 
     | 
    
         
            +
             
     | 
| 
      
 1200 
     | 
    
         
            +
            If a --profile is specified, then a cucumber configuration file is required.
         
     | 
| 
      
 1201 
     | 
    
         
            +
             
     | 
| 
      
 1202 
     | 
    
         
            +
            https://github.com/cucumber/cucumber/wiki/cucumber.yml
         
     | 
| 
      
 1203 
     | 
    
         
            +
             
     | 
| 
      
 1204 
     | 
    
         
            +
            ]
         
     | 
| 
      
 1205 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1206 
     | 
    
         
            +
             
     | 
| 
      
 1207 
     | 
    
         
            +
                    # Defaults to false
         
     | 
| 
      
 1208 
     | 
    
         
            +
                    @skip_config_check = options["skip-config-check"]
         
     | 
| 
      
 1209 
     | 
    
         
            +
             
     | 
| 
      
 1210 
     | 
    
         
            +
                    if !config
         
     | 
| 
      
 1211 
     | 
    
         
            +
                      @config = nil
         
     | 
| 
      
 1212 
     | 
    
         
            +
                      @profile = nil
         
     | 
| 
      
 1213 
     | 
    
         
            +
                      expect_config_option_if_cucumber_config_file_exists
         
     | 
| 
      
 1214 
     | 
    
         
            +
                    else
         
     | 
| 
      
 1215 
     | 
    
         
            +
                      config_path = resolve_cucumber_config_path(config)
         
     | 
| 
      
 1216 
     | 
    
         
            +
             
     | 
| 
      
 1217 
     | 
    
         
            +
                      if !File.exist?(config_path)
         
     | 
| 
      
 1218 
     | 
    
         
            +
                        raise ValidationError, %Q[
         
     | 
| 
      
 1219 
     | 
    
         
            +
            File specified by --config option does not exist:
         
     | 
| 
      
 1220 
     | 
    
         
            +
             
     | 
| 
      
 1221 
     | 
    
         
            +
            #{config_path}
         
     | 
| 
      
 1222 
     | 
    
         
            +
             
     | 
| 
      
 1223 
     | 
    
         
            +
            ]
         
     | 
| 
       1030 
1224 
     | 
    
         
             
                      end
         
     | 
| 
       1031 
1225 
     | 
    
         | 
| 
       1032 
     | 
    
         
            -
                       
     | 
| 
       1033 
     | 
    
         
            -
             
     | 
| 
       1034 
     | 
    
         
            -
                         
     | 
| 
      
 1226 
     | 
    
         
            +
                      if profile
         
     | 
| 
      
 1227 
     | 
    
         
            +
                        expect_profile_exists_in_cucumber_config(config_path, profile)
         
     | 
| 
      
 1228 
     | 
    
         
            +
                        @profile = profile
         
     | 
| 
       1035 
1229 
     | 
    
         
             
                      else
         
     | 
| 
       1036 
     | 
    
         
            -
                         
     | 
| 
       1037 
     | 
    
         
            -
                          raise ValidationError, "Config file provided did not contain profile #{profile}."
         
     | 
| 
       1038 
     | 
    
         
            -
                        else
         
     | 
| 
       1039 
     | 
    
         
            -
                          puts "Using profile #{profile}..."
         
     | 
| 
       1040 
     | 
    
         
            -
                          self.profile = profile
         
     | 
| 
       1041 
     | 
    
         
            -
                        end
         
     | 
| 
       1042 
     | 
    
         
            -
                      end
         
     | 
| 
       1043 
     | 
    
         
            -
                    else
         
     | 
| 
       1044 
     | 
    
         
            -
                      if options[:profile]
         
     | 
| 
       1045 
     | 
    
         
            -
                        raise ValidationError, 'Profile selected but no config file provided.'
         
     | 
| 
      
 1230 
     | 
    
         
            +
                        @profile = nil
         
     | 
| 
       1046 
1231 
     | 
    
         
             
                      end
         
     | 
| 
      
 1232 
     | 
    
         
            +
                      @config = TestFile.cucumber_config(config_path)
         
     | 
| 
      
 1233 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1234 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1235 
     | 
    
         
            +
             
     | 
| 
      
 1236 
     | 
    
         
            +
                  # TODO: extract this method to a module
         
     | 
| 
      
 1237 
     | 
    
         
            +
                  def expect_profile_exists_in_cucumber_config(config_path, profile)
         
     | 
| 
      
 1238 
     | 
    
         
            +
                    config_yml = {}
         
     | 
| 
      
 1239 
     | 
    
         
            +
             
     | 
| 
      
 1240 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 1241 
     | 
    
         
            +
                      config_yml = YAML.load(ERB.new(File.read(config_path)).result)
         
     | 
| 
      
 1242 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 1243 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 1244 
     | 
    
         
            +
             
     | 
| 
      
 1245 
     | 
    
         
            +
            #{e.message}
         
     | 
| 
      
 1246 
     | 
    
         
            +
             
     | 
| 
      
 1247 
     | 
    
         
            +
            Unable to parse --config option as yml:
         
     | 
| 
      
 1248 
     | 
    
         
            +
             
     | 
| 
      
 1249 
     | 
    
         
            +
            #{config_path}
         
     | 
| 
      
 1250 
     | 
    
         
            +
             
     | 
| 
      
 1251 
     | 
    
         
            +
            ]
         
     | 
| 
      
 1252 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1253 
     | 
    
         
            +
             
     | 
| 
      
 1254 
     | 
    
         
            +
                    if Environment.debug?
         
     | 
| 
      
 1255 
     | 
    
         
            +
                      puts "Parsed Cucumber config as:"
         
     | 
| 
      
 1256 
     | 
    
         
            +
                      puts config_yml.inspect
         
     | 
| 
      
 1257 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1258 
     | 
    
         
            +
             
     | 
| 
      
 1259 
     | 
    
         
            +
                    if !config_yml[profile]
         
     | 
| 
      
 1260 
     | 
    
         
            +
                      raise ValidationError, %Q[
         
     | 
| 
      
 1261 
     | 
    
         
            +
            The cucumber configuration file specified by the --config option does not
         
     | 
| 
      
 1262 
     | 
    
         
            +
            contain the profile specified by --profile option:
         
     | 
| 
      
 1263 
     | 
    
         
            +
             
     | 
| 
      
 1264 
     | 
    
         
            +
               :config => #{config_path}
         
     | 
| 
      
 1265 
     | 
    
         
            +
              :profile => #{profile}
         
     | 
| 
      
 1266 
     | 
    
         
            +
             
     | 
| 
      
 1267 
     | 
    
         
            +
            ]
         
     | 
| 
       1047 
1268 
     | 
    
         
             
                    end
         
     | 
| 
      
 1269 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1270 
     | 
    
         
            +
             
     | 
| 
      
 1271 
     | 
    
         
            +
                  # TODO Make --include'd paths generic when possible (see code comment below)
         
     | 
| 
      
 1272 
     | 
    
         
            +
                  def generate_manifest_hash(test_files, test_parameters)
         
     | 
| 
      
 1273 
     | 
    
         
            +
                    files = test_files.map do |test_file|
         
     | 
| 
      
 1274 
     | 
    
         
            +
                      path = test_file.remote_path
         
     | 
| 
      
 1275 
     | 
    
         
            +
                      if path[/features/]
         
     | 
| 
      
 1276 
     | 
    
         
            +
                        "features"
         
     | 
| 
      
 1277 
     | 
    
         
            +
                      elsif path[/vendor/]
         
     | 
| 
      
 1278 
     | 
    
         
            +
                        "vendor"
         
     | 
| 
      
 1279 
     | 
    
         
            +
                      else
         
     | 
| 
      
 1280 
     | 
    
         
            +
                        # --include'd files.  It is not possible to filter these to a single
         
     | 
| 
      
 1281 
     | 
    
         
            +
                        # directory without inspecting the --include option itself.
         
     | 
| 
      
 1282 
     | 
    
         
            +
                        # Consider the example where --include is `config/xtc-users.json`.
         
     | 
| 
      
 1283 
     | 
    
         
            +
                        # We cannot filter to `config` because the config directory might
         
     | 
| 
      
 1284 
     | 
    
         
            +
                        # include a cucumber.yml or some other file that the user does _not_
         
     | 
| 
      
 1285 
     | 
    
         
            +
                        # want to upload.
         
     | 
| 
      
 1286 
     | 
    
         
            +
                        path
         
     | 
| 
      
 1287 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1288 
     | 
    
         
            +
                    end.uniq!
         
     | 
| 
      
 1289 
     | 
    
         
            +
             
     | 
| 
      
 1290 
     | 
    
         
            +
                    {
         
     | 
| 
      
 1291 
     | 
    
         
            +
                      schemaVersion: MANIFEST_SCHEMA_VERSION,
         
     | 
| 
      
 1292 
     | 
    
         
            +
                      files: files,
         
     | 
| 
      
 1293 
     | 
    
         
            +
                      testFramework: {
         
     | 
| 
      
 1294 
     | 
    
         
            +
                        name: "calabash",
         
     | 
| 
      
 1295 
     | 
    
         
            +
                        data: test_parameters
         
     | 
| 
      
 1296 
     | 
    
         
            +
                      }
         
     | 
| 
      
 1297 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1298 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1299 
     | 
    
         
            +
             
     | 
| 
      
 1300 
     | 
    
         
            +
                  def write_manifest_to_file(manifest, manifest_file)
         
     | 
| 
      
 1301 
     | 
    
         
            +
                    json = JSON.pretty_generate(manifest)
         
     | 
| 
       1048 
1302 
     | 
    
         | 
| 
       1049 
     | 
    
         
            -
                     
     | 
| 
      
 1303 
     | 
    
         
            +
                    File.open(manifest_file, "w:UTF-8") do |file|
         
     | 
| 
      
 1304 
     | 
    
         
            +
                      file.write(json)
         
     | 
| 
      
 1305 
     | 
    
         
            +
                    end
         
     | 
| 
       1050 
1306 
     | 
    
         
             
                  end
         
     | 
| 
       1051 
1307 
     | 
    
         | 
| 
       1052 
1308 
     | 
    
         
             
                  def included_files_map
         
     | 
| 
         @@ -1054,24 +1310,24 @@ and try submitting again. 
     | 
|
| 
       1054 
1310 
     | 
    
         
             
                  end
         
     | 
| 
       1055 
1311 
     | 
    
         | 
| 
       1056 
1312 
     | 
    
         
             
                  def parse_included_folders
         
     | 
| 
       1057 
     | 
    
         
            -
                    return {} unless self.include_files_input
         
     | 
| 
       1058 
1313 
     | 
    
         
             
                    basedir = derived_workspace
         
     | 
| 
       1059 
     | 
    
         
            -
                     
     | 
| 
       1060 
     | 
    
         
            -
                     
     | 
| 
       1061 
     | 
    
         
            -
                       
     | 
| 
       1062 
     | 
    
         
            -
                       
     | 
| 
       1063 
     | 
    
         
            -
                       
     | 
| 
      
 1314 
     | 
    
         
            +
                    source_target_map = {}
         
     | 
| 
      
 1315 
     | 
    
         
            +
                    include_files_input.each do |file|
         
     | 
| 
      
 1316 
     | 
    
         
            +
                      source = File.join(basedir, file)
         
     | 
| 
      
 1317 
     | 
    
         
            +
                      expect_valid_included_file(source, file)
         
     | 
| 
      
 1318 
     | 
    
         
            +
                      source_target_map[source] = file
         
     | 
| 
       1064 
1319 
     | 
    
         
             
                    end
         
     | 
| 
       1065 
     | 
    
         
            -
                     
     | 
| 
      
 1320 
     | 
    
         
            +
                    source_target_map
         
     | 
| 
       1066 
1321 
     | 
    
         
             
                  end
         
     | 
| 
       1067 
1322 
     | 
    
         | 
| 
       1068 
     | 
    
         
            -
                  def  
     | 
| 
      
 1323 
     | 
    
         
            +
                  def expect_valid_included_file(src, tgt)
         
     | 
| 
       1069 
1324 
     | 
    
         
             
                    unless File.exists?(src)
         
     | 
| 
       1070 
1325 
     | 
    
         
             
                      raise ValidationError, %Q[
         
     | 
| 
       1071 
1326 
     | 
    
         
             
            Requested include folder: #{src} does not exist.
         
     | 
| 
       1072 
1327 
     | 
    
         | 
| 
       1073 
1328 
     | 
    
         
             
            Specified include options: #{self.include_files_input}
         
     | 
| 
       1074 
     | 
    
         
            -
             
     | 
| 
      
 1329 
     | 
    
         
            +
             
     | 
| 
      
 1330 
     | 
    
         
            +
            ]
         
     | 
| 
       1075 
1331 
     | 
    
         
             
                    end
         
     | 
| 
       1076 
1332 
     | 
    
         
             
                    tgt_pathname = Pathname.new(tgt)
         
     | 
| 
       1077 
1333 
     | 
    
         
             
                    if tgt_pathname.absolute?
         
     | 
| 
         @@ -1081,7 +1337,8 @@ Only relative target path names are allowed. 
     | 
|
| 
       1081 
1337 
     | 
    
         
             
            Requested target folder: #{tgt} is an absolute file name.
         
     | 
| 
       1082 
1338 
     | 
    
         | 
| 
       1083 
1339 
     | 
    
         
             
            Specified include options: #{self.include_files_input}"
         
     | 
| 
       1084 
     | 
    
         
            -
             
     | 
| 
      
 1340 
     | 
    
         
            +
             
     | 
| 
      
 1341 
     | 
    
         
            +
            ]
         
     | 
| 
       1085 
1342 
     | 
    
         
             
                    end
         
     | 
| 
       1086 
1343 
     | 
    
         
             
                    if /\.\./.match(tgt)
         
     | 
| 
       1087 
1344 
     | 
    
         
             
                      raise ValidationError, %Q[
         
     | 
| 
         @@ -1090,10 +1347,12 @@ Only expanded relative target paths are allowed. 
     | 
|
| 
       1090 
1347 
     | 
    
         
             
            Requested target folder includes '..'.
         
     | 
| 
       1091 
1348 
     | 
    
         | 
| 
       1092 
1349 
     | 
    
         
             
            Specified include options: #{self.include_files_input}"
         
     | 
| 
       1093 
     | 
    
         
            -
             
     | 
| 
      
 1350 
     | 
    
         
            +
             
     | 
| 
      
 1351 
     | 
    
         
            +
            ]
         
     | 
| 
       1094 
1352 
     | 
    
         
             
                    end
         
     | 
| 
       1095 
1353 
     | 
    
         
             
                  end
         
     | 
| 
       1096 
1354 
     | 
    
         | 
| 
      
 1355 
     | 
    
         
            +
                  # TODO rename to verify_workspace!
         
     | 
| 
       1097 
1356 
     | 
    
         
             
                  def expect_features_directory_in_workspace
         
     | 
| 
       1098 
1357 
     | 
    
         
             
                    path = derived_workspace
         
     | 
| 
       1099 
1358 
     | 
    
         
             
                    features = File.join(path, "features")
         
     | 
| 
         @@ -1114,6 +1373,7 @@ You have two options: 
     | 
|
| 
       1114 
1373 
     | 
    
         
             
            See also
         
     | 
| 
       1115 
1374 
     | 
    
         | 
| 
       1116 
1375 
     | 
    
         
             
            $ test-cloud help submit
         
     | 
| 
      
 1376 
     | 
    
         
            +
             
     | 
| 
       1117 
1377 
     | 
    
         
             
            ])
         
     | 
| 
       1118 
1378 
     | 
    
         
             
                  end
         
     | 
| 
       1119 
1379 
     | 
    
         | 
| 
         @@ -1134,7 +1394,7 @@ $ test-cloud help submit 
     | 
|
| 
       1134 
1394 
     | 
    
         
             
                  end
         
     | 
| 
       1135 
1395 
     | 
    
         | 
| 
       1136 
1396 
     | 
    
         
             
                  def detect_workspace(options)
         
     | 
| 
       1137 
     | 
    
         
            -
                    options[ 
     | 
| 
      
 1397 
     | 
    
         
            +
                    options[:workspace] || File.expand_path(".")
         
     | 
| 
       1138 
1398 
     | 
    
         
             
                  end
         
     | 
| 
       1139 
1399 
     | 
    
         | 
| 
       1140 
1400 
     | 
    
         
             
                  def expect_workspace_directory(path)
         
     | 
| 
         @@ -1233,6 +1493,8 @@ Check your local Gemfile and and the remote Gemfile at: 
     | 
|
| 
       1233 
1493 
     | 
    
         
             
                    $?.exitstatus == 0
         
     | 
| 
       1234 
1494 
     | 
    
         
             
                  end
         
     | 
| 
       1235 
1495 
     | 
    
         | 
| 
      
 1496 
     | 
    
         
            +
                  # TODO: Server detection algorithm might be broken.
         
     | 
| 
      
 1497 
     | 
    
         
            +
                  # https://github.com/xamarinhq/test-cloud-command-line/issues/19
         
     | 
| 
       1236 
1498 
     | 
    
         
             
                  def check_for_calabash_server(dir, app_dir)
         
     | 
| 
       1237 
1499 
     | 
    
         
             
                    if system("xcrun --find otool-classic &> /dev/null")
         
     | 
| 
       1238 
1500 
     | 
    
         
             
                      otool_cmd = "xcrun otool-classic"
         
     | 
| 
         @@ -1,13 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module XamarinTestCloud
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
              # TODO validate dsym against the current application.
         
     | 
| 
       4 
     | 
    
         
            -
              #  
     | 
| 
       5 
     | 
    
         
            -
              # 
     | 
| 
       6 
     | 
    
         
            -
              #  
     | 
| 
       7 
     | 
    
         
            -
              #  
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
              # 6. confirm that they match.
         
     | 
| 
       10 
     | 
    
         
            -
              class Dsym
         
     | 
| 
      
 4 
     | 
    
         
            +
              # https://github.com/xamarinhq/test-cloud-command-line/issues/91
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # TODO dsym-file can be relative to workspace
         
     | 
| 
      
 7 
     | 
    
         
            +
              # https://github.com/xamarinhq/test-cloud-command-line/issues/92
         
     | 
| 
      
 8 
     | 
    
         
            +
            class Dsym
         
     | 
| 
       11 
9 
     | 
    
         | 
| 
       12 
10 
     | 
    
         
             
                attr_reader :path
         
     | 
| 
       13 
11 
     | 
    
         | 
| 
         @@ -76,13 +76,13 @@ expanded: #{expanded} 
     | 
|
| 
       76 
76 
     | 
    
         
             
                end
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
78 
     | 
    
         
             
                def remote_path
         
     | 
| 
       79 
     | 
    
         
            -
                  @remote_path ||=  
     | 
| 
      
 79 
     | 
    
         
            +
                  @remote_path ||= begin
         
     | 
| 
       80 
80 
     | 
    
         
             
                    require "pathname"
         
     | 
| 
       81 
81 
     | 
    
         
             
                    absolute = Pathname.new(path)
         
     | 
| 
       82 
82 
     | 
    
         
             
                    root  = Pathname.new(basedir)
         
     | 
| 
       83 
83 
     | 
    
         
             
                    relative = absolute.relative_path_from(root)
         
     | 
| 
       84 
84 
     | 
    
         
             
                    relative.to_s
         
     | 
| 
       85 
     | 
    
         
            -
                  end 
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
       86 
86 
     | 
    
         
             
                end
         
     | 
| 
       87 
87 
     | 
    
         | 
| 
       88 
88 
     | 
    
         
             
                private
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: xamarin-test-cloud
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2.0 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.1.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Karl Krukow
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2016- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2016-11-11 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: thor
         
     | 
| 
         @@ -322,7 +322,6 @@ files: 
     | 
|
| 
       322 
322 
     | 
    
         
             
            - bin/test-cloud
         
     | 
| 
       323 
323 
     | 
    
         
             
            - lib/xamarin-test-cloud/calabash_version_detector.rb
         
     | 
| 
       324 
324 
     | 
    
         
             
            - lib/xamarin-test-cloud/cli.rb
         
     | 
| 
       325 
     | 
    
         
            -
            - lib/xamarin-test-cloud/cli.rb alias
         
     | 
| 
       326 
325 
     | 
    
         
             
            - lib/xamarin-test-cloud/dsym.rb
         
     | 
| 
       327 
326 
     | 
    
         
             
            - lib/xamarin-test-cloud/environment.rb
         
     | 
| 
       328 
327 
     | 
    
         
             
            - lib/xamarin-test-cloud/http/payload.rb
         
     | 
| 
         @@ -351,7 +350,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       351 
350 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       352 
351 
     | 
    
         
             
            requirements: []
         
     | 
| 
       353 
352 
     | 
    
         
             
            rubyforge_project: 
         
     | 
| 
       354 
     | 
    
         
            -
            rubygems_version: 2. 
     | 
| 
      
 353 
     | 
    
         
            +
            rubygems_version: 2.5.1
         
     | 
| 
       355 
354 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       356 
355 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       357 
356 
     | 
    
         
             
            summary: Command-line interface to Xamarin Test Cloud
         
     | 
| 
         Binary file 
     |