carthage_remote_cache 0.0.5 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/lib/api.rb CHANGED
@@ -1,15 +1,45 @@
1
1
  class API
2
- def initialize(shell, networking, options)
2
+ def initialize(shell, config, networking, options)
3
3
  @shell = shell
4
+ @config = config
4
5
  @networking = networking
5
6
  @options = options
7
+ @unpack_mutex = Mutex.new
6
8
  end
7
9
 
8
- def version_file_matches_server?(carthage_dependency, version_file)
10
+ def verify_server_version
11
+ server_version = @networking.get_server_version
12
+ unless server_version == VERSION
13
+ raise ServerVersionMismatchError.new, version_mismatch_message(server_version)
14
+ end
15
+ end
16
+
17
+ def verify_build_dir_matches_cartfile_resolved
18
+ errors = []
19
+ for carthage_dependency in @config.carthage_resolved_dependencies
20
+ begin
21
+ version_file = carthage_dependency.new_version_file
22
+ carthage_dependency.verify_version_in_version_file(version_file)
23
+ rescue VersionFileDoesNotExistError => e
24
+ errors << OutdatedFrameworkBuildError.new(
25
+ carthage_dependency.guessed_framework_basename,
26
+ "-",
27
+ carthage_dependency.version
28
+ )
29
+ rescue OutdatedFrameworkBuildError => e
30
+ errors << e
31
+ end
32
+ end
33
+ if errors.count > 0
34
+ raise FrameworkValidationError.new(errors)
35
+ end
36
+ end
37
+
38
+ def version_file_matches_server?(carthage_dependency, version_file, platforms)
9
39
  if @options[:force]
10
40
  false
11
41
  else
12
- server_version_file = @networking.download_version_file(carthage_dependency)
42
+ server_version_file = @networking.download_version_file(carthage_dependency, platforms)
13
43
  result = version_file.same_content?(server_version_file)
14
44
  server_version_file.remove unless server_version_file.nil?
15
45
  result
@@ -19,7 +49,7 @@ class API
19
49
  # @return zip archive size in Bytes
20
50
  def create_and_upload_archive(carthage_dependency, framework_name, platform)
21
51
  archive = CarthageArchive.new(framework_name, platform)
22
- archive.create_archive(@shell, carthage_dependency.should_include_dsym)
52
+ archive.create_archive(@shell)
23
53
  archive_size = archive.archive_size
24
54
  begin
25
55
  checksum = crc32(archive.archive_path)
@@ -49,7 +79,10 @@ class API
49
79
  archive_size = archive.archive_size
50
80
  begin
51
81
  $LOG.debug("Downloaded #{archive.archive_path}")
52
- archive.unpack_archive(@shell)
82
+ # Can't unpack multiple archives concurrently.
83
+ @unpack_mutex.synchronize do
84
+ archive.unpack_archive(@shell)
85
+ end
53
86
  ensure
54
87
  archive.delete_archive
55
88
  end
@@ -58,6 +91,17 @@ class API
58
91
 
59
92
  private
60
93
 
94
+ def version_mismatch_message(server_version)
95
+ <<~EOS
96
+ Version mismatch:
97
+ Cache server version: #{server_version}
98
+ Client version: #{VERSION}
99
+
100
+ Please use the same version as cache server by running:
101
+ $ gem install carthage_remote_cache -v #{server_version}
102
+ EOS
103
+ end
104
+
61
105
  def checksum_error_message(path, remote, local)
62
106
  <<~EOS
63
107
  Checksums for '#{path}' do not match:
@@ -1,3 +1,5 @@
1
+ require "fileutils"
2
+
1
3
  class CarthageArchive
2
4
  attr_reader :archive_filename, :archive_path
3
5
 
@@ -15,7 +17,7 @@ class CarthageArchive
15
17
  # - Carthage/Build/iOS/Alamofire.framework/Alamofire
16
18
  # - Carthage/Build/iOS/618BEB79-4C7F-3692-B140-131FB983AC5E.bcsymbolmap
17
19
  # into Alamofire-iOS.zip
18
- def create_archive(shell, should_include_dsym, carthage_build_dir = CARTHAGE_BUILD_DIR)
20
+ def create_archive(shell, carthage_build_dir = CARTHAGE_BUILD_DIR)
19
21
  $LOG.debug("Archiving #{@framework_name} for #{@platform}")
20
22
 
21
23
  platform_path = File.join(carthage_build_dir, platform_to_carthage_dir_string(@platform))
@@ -25,12 +27,8 @@ class CarthageArchive
25
27
  # It's very likely, that binary releases don't contain DSYMs.
26
28
  dsym_path = File.join(platform_path, "#{@framework_name}.framework.dSYM")
27
29
  unless File.exist?(dsym_path)
28
- if should_include_dsym
29
- raise AppError.new, "DSYM File #{dsym_path} not found"
30
- else
31
- $LOG.error("DSYM File #{dsym_path} not found, continuing")
32
- dsym_path = nil
33
- end
30
+ $LOG.error("DSYM File #{dsym_path} not found, continuing")
31
+ dsym_path = nil
34
32
  end
35
33
 
36
34
  binary_path = File.join(framework_path, @framework_name)
@@ -50,8 +48,11 @@ class CarthageArchive
50
48
  $LOG.debug("Created #{@archive_path} archive, file size: #{formatted_archive_size}")
51
49
  end
52
50
 
53
- def unpack_archive(shell)
51
+ def unpack_archive(shell, carthage_build_dir = CARTHAGE_BUILD_DIR)
54
52
  raise AppError.new, "Archive #{@archive_path} is missing" unless File.exist?(@archive_path)
53
+
54
+ delete_existing_build_framework_if_exists(carthage_build_dir)
55
+
55
56
  $LOG.debug("Unpacking #{@archive_path}, file size: #{formatted_archive_size}")
56
57
  shell.unpack(@archive_path)
57
58
  end
@@ -85,4 +86,13 @@ class CarthageArchive
85
86
  def formatted_archive_size
86
87
  format_file_size(archive_size)
87
88
  end
89
+
90
+ def delete_existing_build_framework_if_exists(carthage_build_dir)
91
+ platform_path = File.join(carthage_build_dir, platform_to_carthage_dir_string(@platform))
92
+ framework_path = File.join(platform_path, "#{@framework_name}.framework")
93
+ if File.exist?(framework_path)
94
+ $LOG.debug("Deleting #{framework_path}")
95
+ FileUtils.rm_rf(framework_path)
96
+ end
97
+ end
88
98
  end
@@ -27,6 +27,10 @@ class CarthageDependency
27
27
  @version = args[:version]
28
28
  end
29
29
 
30
+ def new_version_file
31
+ VersionFile.new(version_filepath)
32
+ end
33
+
30
34
  # Since one Cartfile.resolved entry may produce multiple differently named frameworks,
31
35
  # this is an entry point to identifying a framework name.
32
36
  def guessed_framework_basename
@@ -52,38 +56,13 @@ class CarthageDependency
52
56
  File.join(CARTHAGE_BUILD_DIR, version_filename)
53
57
  end
54
58
 
55
- def should_include_dsym
56
- case @origin
57
- when :github
58
- true
59
- when :git
60
- true
61
- when :binary
62
- false
63
- else
64
- raise AppError.new, "Unrecognized origin '#{@origin}'"
65
- end
66
- end
67
-
68
- def validate_version_file(version_file)
59
+ def verify_version_in_version_file(version_file)
69
60
  if @version != version_file.version
70
- raise OutdatedFrameworkBuildError.new, version_validation_message(version_file)
61
+ raise OutdatedFrameworkBuildError.new(guessed_framework_basename, version_file.version, @version)
71
62
  end
72
63
  end
73
64
 
74
65
  def to_s
75
66
  "#{@origin.to_s} \"#{@source}\" \"#{@version}\""
76
67
  end
77
-
78
- private
79
-
80
- def version_validation_message(version_file)
81
- <<~EOS
82
- Outdated version of '#{guessed_framework_basename}' framework detected:
83
- Expected version '#{@version}'
84
- Found version '#{version_file.version}'
85
-
86
- Please run `carthage bootstrap` to build frameworks.
87
- EOS
88
- end
89
68
  end
@@ -1,16 +1,17 @@
1
1
  lib = File.expand_path("..", __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
- require 'api'
5
- require 'carthage_archive'
6
- require 'carthage_dependency'
7
- require 'constants'
8
- require 'configuration'
9
- require 'crc32'
10
- require 'errors'
11
- require 'log'
12
- require 'networking'
13
- require 'shell_wrapper'
14
- require 'utils'
15
- require 'version'
16
- require 'version_file'
4
+ require "api"
5
+ require "carthage_archive"
6
+ require "carthage_dependency"
7
+ require "constants"
8
+ require "configuration"
9
+ require "crc32"
10
+ require "errors"
11
+ require "log"
12
+ require "networking"
13
+ require "shell_wrapper"
14
+ require "table"
15
+ require "utils"
16
+ require "version"
17
+ require "version_file"
data/lib/commands.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  lib = File.expand_path("..", __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
- require 'commands/download_command'
5
- require 'commands/init_command'
6
- require 'commands/server_command'
7
- require 'commands/upload_command'
4
+ require "commands/download_command"
5
+ require "commands/init_command"
6
+ require "commands/server_command"
7
+ require "commands/upload_command"
8
+ require "commands/verify_command"
@@ -1,16 +1,17 @@
1
- require 'concurrent'
1
+ require "concurrent"
2
2
 
3
3
  class DownloadCommand
4
4
  def self.new_with_defaults(options)
5
5
  shell = ShellWrapper.new
6
6
  config = Configuration.new(shell)
7
- networking = Networking.new(config)
8
- api = API.new(shell, networking, options)
7
+ networking = Networking.new(config, options[:is_retry_enabled])
8
+ api = API.new(shell, config, networking, options)
9
9
 
10
10
  DownloadCommand.new(
11
11
  config: config,
12
12
  networking: networking,
13
13
  api: api,
14
+ platforms: options[:platforms],
14
15
  )
15
16
  end
16
17
 
@@ -18,17 +19,22 @@ class DownloadCommand
18
19
  @config = args[:config]
19
20
  @networking = args[:networking]
20
21
  @api = args[:api]
22
+ @platforms = args[:platforms]
21
23
  end
22
24
 
23
25
  def run
26
+ @config.ensure_shell_commands
27
+ @api.verify_server_version
28
+
24
29
  pool = Concurrent::FixedThreadPool.new(THREAD_POOL_SIZE)
25
30
 
31
+ @mutex = Mutex.new
26
32
  @number_of_downloaded_archives = 0
27
33
  @number_of_skipped_archives = 0
28
34
  @total_archive_size = 0
29
35
  errors = Concurrent::Array.new
30
36
 
31
- for carthage_dependency in @config.carthage_dependencies
37
+ for carthage_dependency in @config.carthage_resolved_dependencies
32
38
  pool.post(carthage_dependency) do |carthage_dependency|
33
39
  begin
34
40
  download(carthage_dependency)
@@ -53,27 +59,30 @@ class DownloadCommand
53
59
  private
54
60
 
55
61
  def download(carthage_dependency)
56
- local_version_file =
57
- if File.exist?(carthage_dependency.version_filepath)
58
- VersionFile.new(carthage_dependency.version_filepath)
62
+ local_version_file = if File.exist?(carthage_dependency.version_filepath)
63
+ carthage_dependency.new_version_file
59
64
  else
60
65
  nil
61
66
  end
62
67
 
63
- if !local_version_file.nil? && @api.version_file_matches_server?(carthage_dependency, local_version_file)
68
+ if !local_version_file.nil? && @api.version_file_matches_server?(carthage_dependency, local_version_file, @platforms)
64
69
  $LOG.debug("Version file #{local_version_file.path} matches server version, skipping download")
65
- @number_of_skipped_archives += local_version_file.number_of_frameworks
70
+ @mutex.synchronize do
71
+ @number_of_skipped_archives += local_version_file.number_of_frameworks
72
+ end
66
73
  return
67
74
  end
68
75
 
69
- version_file = @networking.download_version_file(carthage_dependency)
76
+ version_file = @networking.download_version_file(carthage_dependency, @platforms)
70
77
  raise AppError.new, "Version file #{carthage_dependency.version_filename} is not present on the server, please run `carthagerc upload` first" if version_file.nil?
71
78
 
72
79
  version_file.frameworks_by_platform.each do |platform, framework_names|
73
80
  for framework_name in framework_names
74
81
  archive_size = @api.download_and_unpack_archive(carthage_dependency, framework_name, platform)
75
- @number_of_downloaded_archives += 1
76
- @total_archive_size += archive_size
82
+ @mutex.synchronize do
83
+ @number_of_downloaded_archives += 1
84
+ @total_archive_size += archive_size
85
+ end
77
86
  end
78
87
  end
79
88
  version_file.move_to_build_dir
@@ -4,8 +4,8 @@ class ServerCommand
4
4
  end
5
5
 
6
6
  def run
7
- ENV['RACK_ENV'] = 'production'
8
- require 'server/server_app'
7
+ ENV["RACK_ENV"] = "production"
8
+ require "server/server_app"
9
9
  Rack::Handler::WEBrick.run(
10
10
  Sinatra::Application,
11
11
  :Port => @options[:server_port],
@@ -1,11 +1,11 @@
1
- require 'concurrent'
1
+ require "concurrent"
2
2
 
3
3
  class UploadCommand
4
4
  def self.new_with_defaults(options)
5
5
  shell = ShellWrapper.new
6
6
  config = Configuration.new(shell)
7
- networking = Networking.new(config)
8
- api = API.new(shell, networking, options)
7
+ networking = Networking.new(config, options[:is_retry_enabled])
8
+ api = API.new(shell, config, networking, options)
9
9
 
10
10
  UploadCommand.new(
11
11
  config: config,
@@ -21,16 +21,21 @@ class UploadCommand
21
21
  end
22
22
 
23
23
  def run
24
+ @config.ensure_shell_commands
25
+ @api.verify_server_version
26
+ @api.verify_build_dir_matches_cartfile_resolved
27
+
24
28
  pool = Concurrent::FixedThreadPool.new(THREAD_POOL_SIZE)
25
29
 
26
30
  $LOG.debug("Will upload frameworks: #{@config.all_framework_names}")
27
31
 
32
+ @mutex = Mutex.new
28
33
  @number_of_uploaded_archives = 0
29
34
  @number_of_skipped_archives = 0
30
35
  @total_archive_size = 0
31
36
  errors = Concurrent::Array.new
32
37
 
33
- for carthage_dependency in @config.carthage_dependencies
38
+ for carthage_dependency in @config.carthage_resolved_dependencies
34
39
  pool.post(carthage_dependency) do |carthage_dependency|
35
40
  begin
36
41
  upload(carthage_dependency)
@@ -55,13 +60,13 @@ class UploadCommand
55
60
  private
56
61
 
57
62
  def upload(carthage_dependency)
58
- version_file = VersionFile.new(carthage_dependency.version_filepath)
59
-
60
- carthage_dependency.validate_version_file(version_file)
63
+ version_file = carthage_dependency.new_version_file
61
64
 
62
- if @api.version_file_matches_server?(carthage_dependency, version_file)
65
+ if @api.version_file_matches_server?(carthage_dependency, version_file, nil)
63
66
  $LOG.debug("Version file #{version_file.path} matches server version, skipping upload")
64
- @number_of_skipped_archives += version_file.number_of_frameworks
67
+ @mutex.synchronize do
68
+ @number_of_skipped_archives += version_file.number_of_frameworks
69
+ end
65
70
  return
66
71
  end
67
72
 
@@ -70,8 +75,10 @@ class UploadCommand
70
75
  version_file.frameworks_by_platform.each do |platform, framework_names|
71
76
  for framework_name in framework_names
72
77
  archive_size = @api.create_and_upload_archive(carthage_dependency, framework_name, platform)
73
- @number_of_uploaded_archives += 1
74
- @total_archive_size += archive_size
78
+ @mutex.synchronize do
79
+ @number_of_uploaded_archives += 1
80
+ @total_archive_size += archive_size
81
+ end
75
82
  end
76
83
  end
77
84
  end
@@ -0,0 +1,18 @@
1
+ class VerifyCommand
2
+ def self.new_with_defaults(options)
3
+ shell = ShellWrapper.new
4
+ config = Configuration.new(shell)
5
+ networking = Networking.new(config, options[:is_retry_enabled])
6
+ api = API.new(shell, config, networking, options)
7
+
8
+ VerifyCommand.new(api: api)
9
+ end
10
+
11
+ def initialize(args)
12
+ @api = args[:api]
13
+ end
14
+
15
+ def run
16
+ @api.verify_build_dir_matches_cartfile_resolved
17
+ end
18
+ end
data/lib/configuration.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'uri'
1
+ require "uri"
2
2
 
3
3
  class Configuration
4
4
  class UserConfig
@@ -11,14 +11,15 @@ class Configuration
11
11
  yield(@@user_config)
12
12
  end
13
13
 
14
- attr_reader :xcodebuild_version, :swift_version, :carthage_dependencies, :server_uri
14
+ attr_reader :carthage_resolved_dependencies, :server_uri
15
15
 
16
16
  def self.new_with_defaults
17
17
  Configuration.new(ShellWrapper.new)
18
18
  end
19
19
 
20
20
  def initialize(shell)
21
- initialize_env(shell)
21
+ @shell = shell
22
+ initialize_cartfile_resolved
22
23
  initialize_cartrcfile
23
24
  end
24
25
 
@@ -26,16 +27,40 @@ class Configuration
26
27
  version_files.flat_map { |vf| vf.framework_names }.uniq.sort
27
28
  end
28
29
 
30
+ # Ensure, that these lazy properties are loaded before kicking off async code.
31
+ def ensure_shell_commands
32
+ xcodebuild_version
33
+ swift_version
34
+ end
35
+
36
+ def xcodebuild_version
37
+ if @xcodebuild_version.nil?
38
+ xcodebuild_raw_version = @shell.xcodebuild_version
39
+ @xcodebuild_version = xcodebuild_raw_version[/Build version (.*)$/, 1]
40
+ raise AppError.new, "Could not parse build version from '#{xcodebuild_raw_version}'" if @xcodebuild_version.nil?
41
+ end
42
+ @xcodebuild_version
43
+ end
44
+
45
+ def swift_version
46
+ if @swift_version.nil?
47
+ swift_raw_version = @shell.swift_version
48
+ @swift_version = swift_raw_version[/Apple Swift version (.*) \(/, 1]
49
+ raise AppError.new, "Could not parse swift version from '#{raw_swift_version}'" if @swift_version.nil?
50
+ end
51
+ @swift_version
52
+ end
53
+
29
54
  def to_s
30
55
  <<~EOS
31
- Xcodebuild: #{@xcodebuild_version}
56
+ Xcodebuild: #{xcodebuild_version}
32
57
  ---
33
- Swift: #{@swift_version}
58
+ Swift: #{swift_version}
34
59
  ---
35
60
  Server: #{@server_uri.to_s}
36
61
  ---
37
62
  Cartfile.resolved:
38
- #{@carthage_dependencies.join("\n")}
63
+ #{@carthage_resolved_dependencies.join("\n")}
39
64
  ---
40
65
  Local Build Frameworks:
41
66
  #{framework_names_with_platforms.join("\n")}
@@ -44,17 +69,9 @@ class Configuration
44
69
 
45
70
  private
46
71
 
47
- def initialize_env(shell)
48
- xcodebuild_raw_version = shell.xcodebuild_version
49
- @xcodebuild_version = xcodebuild_raw_version[/Build version (.*)$/, 1]
50
- raise AppError.new, "Could not parse build version from '#{xcodebuild_raw_version}'" if @xcodebuild_version.nil?
51
-
52
- swift_raw_version = shell.swift_version
53
- @swift_version = swift_raw_version[/Apple Swift version (.*) \(/, 1]
54
- raise AppError.new, "Could not parse swift version from '#{raw_swift_version}'" if @swift_version.nil?
55
-
72
+ def initialize_cartfile_resolved
56
73
  raise AppError.new, "Misssing #{CARTFILE_RESOLVED}" unless File.exist?(CARTFILE_RESOLVED)
57
- @carthage_dependencies = File.readlines(CARTFILE_RESOLVED)
74
+ @carthage_resolved_dependencies = File.readlines(CARTFILE_RESOLVED)
58
75
  .map { |line| CarthageDependency.parse_cartfile_resolved_line(line) }
59
76
  .compact
60
77
  end
@@ -79,6 +96,6 @@ class Configuration
79
96
  end
80
97
 
81
98
  def version_files
82
- @carthage_dependencies.map { |d| VersionFile.new(d.version_filepath) }
99
+ @carthage_resolved_dependencies.map { |d| d.new_version_file }
83
100
  end
84
101
  end