carthage_remote_cache 0.0.8 → 0.0.11

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.
@@ -1,10 +1,10 @@
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)
7
+ networking = Networking.new(config, options[:is_retry_enabled])
8
8
  api = API.new(shell, config, networking, options)
9
9
 
10
10
  UploadCommand.new(
@@ -62,7 +62,7 @@ class UploadCommand
62
62
  def upload(carthage_dependency)
63
63
  version_file = carthage_dependency.new_version_file
64
64
 
65
- if @api.version_file_matches_server?(carthage_dependency, version_file)
65
+ if @api.version_file_matches_server?(carthage_dependency, version_file, nil)
66
66
  $LOG.debug("Version file #{version_file.path} matches server version, skipping upload")
67
67
  @mutex.synchronize do
68
68
  @number_of_skipped_archives += version_file.number_of_frameworks
@@ -72,9 +72,9 @@ class UploadCommand
72
72
 
73
73
  @networking.upload_version_file(carthage_dependency)
74
74
 
75
- version_file.frameworks_by_platform.each do |platform, framework_names|
76
- for framework_name in framework_names
77
- archive_size = @api.create_and_upload_archive(carthage_dependency, framework_name, platform)
75
+ version_file.frameworks_by_platform.each do |platform, frameworks|
76
+ for framework in frameworks
77
+ archive_size = @api.create_and_upload_archive(carthage_dependency, framework, platform)
78
78
  @mutex.synchronize do
79
79
  @number_of_uploaded_archives += 1
80
80
  @total_archive_size += archive_size
@@ -2,7 +2,7 @@ class VerifyCommand
2
2
  def self.new_with_defaults(options)
3
3
  shell = ShellWrapper.new
4
4
  config = Configuration.new(shell)
5
- networking = Networking.new(config)
5
+ networking = Networking.new(config, options[:is_retry_enabled])
6
6
  api = API.new(shell, config, networking, options)
7
7
 
8
8
  VerifyCommand.new(api: api)
data/lib/commands.rb CHANGED
@@ -1,8 +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'
8
- require 'commands/verify_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"
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
data/lib/constants.rb CHANGED
@@ -1,12 +1,14 @@
1
- CARTHAGE_DIR = 'Carthage'
2
- CARTHAGE_BUILD_DIR = File.join(CARTHAGE_DIR, 'Build')
3
- CARTFILE_RESOLVED = 'Cartfile.resolved'
4
- CARTRCFILE = 'Cartrcfile'
1
+ CARTHAGE_DIR = "Carthage"
2
+ CARTHAGE_BUILD_DIR = File.join(CARTHAGE_DIR, "Build")
3
+ CARTFILE_RESOLVED = "Cartfile.resolved"
4
+ CARTRCFILE = "Cartrcfile"
5
5
  THREAD_POOL_SIZE = 8
6
6
 
7
7
  SERVER_DEFAULT_PORT = 9292
8
- SERVER_CACHE_DIR = File.join(Dir.home, '.carthagerc_server')
8
+ SERVER_CACHE_DIR = File.join(Dir.home, ".carthagerc_server")
9
9
 
10
10
  ARCHIVE_CHECKSUM_HEADER_REST_CLIENT = :archive_checksum
11
- ARCHIVE_CHECKSUM_HEADER_SINATRA_IN = 'HTTP_ARCHIVE_CHECKSUM'
12
- ARCHIVE_CHECKSUM_HEADER_SINATRA_OUT = 'Archive-Checksum'
11
+ ARCHIVE_CHECKSUM_HEADER_SINATRA_IN = "HTTP_ARCHIVE_CHECKSUM"
12
+ ARCHIVE_CHECKSUM_HEADER_SINATRA_OUT = "Archive-Checksum"
13
+
14
+ PLATFORMS = [:iOS, :macOS, :tvOS, :watchOS]
data/lib/crc32.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'digest'
2
- require 'zlib'
1
+ require "digest"
2
+ require "zlib"
3
3
 
4
4
  class Digest::CRC32 < Digest::Class
5
5
  include Digest::Instance
@@ -17,6 +17,6 @@ class Digest::CRC32 < Digest::Class
17
17
  end
18
18
 
19
19
  def finish
20
- [@crc32].pack('N')
20
+ [@crc32].pack("N")
21
21
  end
22
22
  end
data/lib/errors.rb CHANGED
@@ -51,7 +51,7 @@ class FrameworkValidationError < AppError
51
51
  end
52
52
 
53
53
  def to_s
54
- header = ['Framework', CARTHAGE_BUILD_DIR, CARTFILE_RESOLVED]
54
+ header = ["Framework", CARTHAGE_BUILD_DIR, CARTFILE_RESOLVED]
55
55
  rows = @errors.map { |e| [e.framework_name, e.build_version, e.cartfile_resolved_version] }
56
56
  table = Table.new(header, rows)
57
57
  <<~EOS
@@ -69,3 +69,14 @@ end
69
69
  class MissingFrameworkDirectoryError < AppError; end
70
70
 
71
71
  class ServerVersionMismatchError < AppError; end
72
+
73
+ class PlatformMismatchError < AppError
74
+ def initialize(platform)
75
+ @platform = platform
76
+ end
77
+
78
+ def to_s
79
+ platforms = PLATFORMS.map(&:to_s).join(", ")
80
+ "Platform '#{@platform}' doesn't match any of: #{platforms}"
81
+ end
82
+ end
data/lib/framework.rb ADDED
@@ -0,0 +1,19 @@
1
+ # Example data:
2
+ # - "name" : "Sentry",
3
+ # - "linking" : "dynamic"
4
+ class Framework
5
+ attr_reader :name
6
+
7
+ def self.parse(json)
8
+ Framework.new(json["name"], json["linking"])
9
+ end
10
+
11
+ def initialize(name, linking)
12
+ @name = name
13
+ @linking = linking
14
+ end
15
+
16
+ def make_archive(platform)
17
+ FrameworkCarthageArchive.new(name, platform)
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ require "fileutils"
2
+
3
+ class FrameworkCarthageArchive < CarthageArchive
4
+
5
+ # Aggregate following files:
6
+ # - Carthage/Build/iOS/Alamofire.framework
7
+ # - Carthage/Build/iOS/Alamofire.framework/Alamofire
8
+ # - Carthage/Build/iOS/618BEB79-4C7F-3692-B140-131FB983AC5E.bcsymbolmap
9
+ # into Alamofire-iOS.zip
10
+ def compress_archive(shell, carthage_build_dir = CARTHAGE_BUILD_DIR)
11
+ $LOG.debug("Archiving #{@framework_name} for #{@platform}")
12
+
13
+ platform_path = File.join(carthage_build_dir, platform_to_carthage_dir_string(@platform))
14
+ framework_path = File.join(platform_path, "#{@framework_name}.framework")
15
+ raise MissingFrameworkDirectoryError.new, "Archive can't be created, no framework directory at #{framework_path}" unless Dir.exist?(framework_path)
16
+
17
+ # It's very likely, that binary releases don't contain DSYMs.
18
+ dsym_path = File.join(platform_path, "#{@framework_name}.framework.dSYM")
19
+ unless File.exist?(dsym_path)
20
+ $LOG.error("DSYM File #{dsym_path} not found, continuing")
21
+ dsym_path = nil
22
+ end
23
+
24
+ binary_path = File.join(framework_path, @framework_name)
25
+ raise AppError.new, "Binary #{binary_path} is missing, failed to read .bcsymbolmap files" unless File.exist?(binary_path)
26
+
27
+ bcsymbolmap_paths = find_bcsymbolmap_paths(shell, platform_path, binary_path)
28
+
29
+ input_paths = []
30
+ input_paths << framework_path
31
+ input_paths << dsym_path unless dsym_path.nil?
32
+ input_paths += bcsymbolmap_paths
33
+
34
+ $LOG.debug("Adding > #{input_paths.inspect}")
35
+
36
+ delete_archive
37
+ shell.archive(input_paths, @archive_path)
38
+ $LOG.debug("Created #{@archive_path} archive, file size: #{formatted_archive_size}")
39
+ end
40
+
41
+ private
42
+
43
+ def find_bcsymbolmap_paths(shell, platform_path, binary_path)
44
+ raw_dwarfdump = shell.dwarfdump(binary_path)
45
+ uuids = parse_uuids(raw_dwarfdump)
46
+ bcsymbolmap_paths = uuids.map { |uuid| File.join(platform_path, "#{uuid}.bcsymbolmap") }.select { |path| File.exist?(path) }
47
+ bcsymbolmap_paths
48
+ end
49
+
50
+ # Example dwarfdump link:
51
+ # UUID: 618BEB79-4C7F-3692-B140-131FB983AC5E (i386) Carthage/Build/iOS/CocoaLumberjackSwift.framework/CocoaLumberjackSwift
52
+ def parse_uuids(raw_dwarfdump)
53
+ lines = raw_dwarfdump.split("\n")
54
+ uuids = lines.map { |line| line[/^UUID: ([A-Z0-9\-]+)\s+\(.*$/, 1] }
55
+ uuids.compact
56
+ end
57
+ end
data/lib/log.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'logger'
1
+ require "logger"
2
2
 
3
3
  $LOG = Logger.new(STDOUT)
4
4
  $LOG.level = Logger::INFO
data/lib/networking.rb CHANGED
@@ -1,9 +1,10 @@
1
- require 'rest-client'
2
- require 'uri'
1
+ require "rest-client"
2
+ require "uri"
3
3
 
4
4
  class Networking
5
- def initialize(config)
5
+ def initialize(config, is_retry_enabled)
6
6
  @config = config
7
+ @is_retry_enabled = is_retry_enabled
7
8
  end
8
9
 
9
10
  # Version
@@ -11,11 +12,13 @@ class Networking
11
12
  def get_server_version
12
13
  url = new_version_url
13
14
  $LOG.debug("Fetching server version from #{url}")
14
- server_version = RestClient.get(url) do |response, request, result|
15
- if response.code == 200
16
- response.strip
17
- else
18
- raise AppError.new, "Failed to read server version from #{url}, response:\n #{response[0...300]}"
15
+ server_version = perform_network_request do
16
+ RestClient.get(url) do |response, request, result|
17
+ if response.code == 200
18
+ response.strip
19
+ else
20
+ raise AppError.new, "Failed to read server version from #{url}, response:\n #{response[0...300]}"
21
+ end
19
22
  end
20
23
  end
21
24
  server_version
@@ -24,15 +27,22 @@ class Networking
24
27
  # Version Files
25
28
 
26
29
  # @return VersionFile or nil
27
- def download_version_file(carthage_dependency)
30
+ def download_version_file(carthage_dependency, platforms)
28
31
  url = new_version_file_url(carthage_dependency)
29
- $LOG.debug("Downloading version file from #{url}")
30
- version_file = RestClient.get(url) do |response, request, result|
31
- if response.code == 200
32
- File.write(carthage_dependency.version_filename, response.to_s)
33
- VersionFile.new(carthage_dependency.version_filename)
34
- else
35
- nil
32
+ params = {}
33
+ unless platforms.nil?
34
+ params[:platform] = platforms.map(&:to_s).join(",")
35
+ end
36
+
37
+ version_file = perform_network_request do
38
+ $LOG.debug("Downloading version file from #{url}, params: #{params}")
39
+ RestClient.get(url, { params: params }) do |response, request, result|
40
+ if response.code == 200
41
+ File.write(carthage_dependency.version_filename, response.to_s)
42
+ VersionFile.new(carthage_dependency.version_filename)
43
+ else
44
+ nil
45
+ end
36
46
  end
37
47
  end
38
48
  version_file
@@ -41,10 +51,12 @@ class Networking
41
51
  # @raise AppError on upload failure
42
52
  def upload_version_file(carthage_dependency)
43
53
  url = new_version_file_url(carthage_dependency)
44
- $LOG.debug("Uploading #{carthage_dependency.version_filename}")
45
- RestClient.post(url, :version_file => File.new(carthage_dependency.version_filepath)) do |response, request, result|
46
- unless response.code == 200
47
- raise AppError.new, "Version file upload #{carthage_dependency.version_filename} failed, response:\n #{response[0..300]}"
54
+ perform_network_request do
55
+ $LOG.debug("Uploading #{carthage_dependency.version_filename}")
56
+ RestClient.post(url, :version_file => File.new(carthage_dependency.version_filepath)) do |response, request, result|
57
+ unless response.code == 200
58
+ raise AppError.new, "Version file upload #{carthage_dependency.version_filename} failed, response:\n #{response[0..300]}"
59
+ end
48
60
  end
49
61
  end
50
62
  end
@@ -52,16 +64,18 @@ class Networking
52
64
  # Archives
53
65
 
54
66
  # @return Hash with CarthageArchive and checksum or nil
55
- def download_framework_archive(carthage_dependency, framework_name, platform)
56
- url = new_framework_url(carthage_dependency, framework_name, platform)
57
- $LOG.debug("Downloading framework from #{url}")
58
- archive = RestClient.get(url) do |response, request, result|
59
- if response.code == 200
60
- archive = CarthageArchive.new(framework_name, platform)
61
- File.write(archive.archive_path, response.to_s)
62
- {:archive => archive, :checksum => response.headers[ARCHIVE_CHECKSUM_HEADER_REST_CLIENT]}
63
- else
64
- nil
67
+ def download_framework_archive(carthage_dependency, framework, platform)
68
+ url = new_framework_url(carthage_dependency, framework.name, platform)
69
+ archive = perform_network_request do
70
+ $LOG.debug("Downloading framework from #{url}")
71
+ RestClient.get(url) do |response, request, result|
72
+ if response.code == 200
73
+ archive = framework.make_archive(platform)
74
+ File.write(archive.archive_path, response.to_s)
75
+ { :archive => archive, :checksum => response.headers[ARCHIVE_CHECKSUM_HEADER_REST_CLIENT] }
76
+ else
77
+ nil
78
+ end
65
79
  end
66
80
  end
67
81
  archive
@@ -70,12 +84,14 @@ class Networking
70
84
  # @raise AppError when upload fails
71
85
  def upload_framework_archive(zipfile_name, carthage_dependency, framework_name, platform, checksum)
72
86
  url = new_framework_url(carthage_dependency, framework_name, platform)
73
- params = {:framework_file => File.new(zipfile_name)}
74
- headers = {ARCHIVE_CHECKSUM_HEADER_REST_CLIENT => checksum}
75
- $LOG.debug("Uploading framework to #{url}, headers: #{headers}")
76
- RestClient.post(url, params, headers) do |response, request, result|
77
- unless response.code == 200
78
- raise AppError.new, "Framework upload #{zipfile_name} failed, response:\n #{response[0..300]}"
87
+ params = { :framework_file => File.new(zipfile_name) }
88
+ headers = { ARCHIVE_CHECKSUM_HEADER_REST_CLIENT => checksum }
89
+ perform_network_request do
90
+ $LOG.debug("Uploading framework to #{url}, headers: #{headers}")
91
+ RestClient.post(url, params, headers) do |response, request, result|
92
+ unless response.code == 200
93
+ raise AppError.new, "Framework upload #{zipfile_name} failed, response:\n #{response[0..300]}"
94
+ end
79
95
  end
80
96
  end
81
97
  end
@@ -83,12 +99,12 @@ class Networking
83
99
  private
84
100
 
85
101
  def new_version_url
86
- new_server_url(['version'])
102
+ new_server_url(["version"])
87
103
  end
88
104
 
89
105
  def new_version_file_url(carthage_dependency)
90
106
  new_server_url([
91
- 'versions',
107
+ "versions",
92
108
  @config.xcodebuild_version,
93
109
  @config.swift_version,
94
110
  carthage_dependency.guessed_framework_basename,
@@ -99,7 +115,7 @@ class Networking
99
115
 
100
116
  def new_framework_url(carthage_dependency, framework_name, platform)
101
117
  new_server_url([
102
- 'frameworks',
118
+ "frameworks",
103
119
  @config.xcodebuild_version,
104
120
  @config.swift_version,
105
121
  carthage_dependency.guessed_framework_basename,
@@ -115,13 +131,37 @@ class Networking
115
131
  :scheme => @config.server_uri.scheme,
116
132
  :host => @config.server_uri.host,
117
133
  :port => @config.server_uri.port,
118
- :path => '/' + sanitized_path_slices.join('/'),
134
+ :path => "/" + sanitized_path_slices.join("/"),
119
135
  )
120
136
  uri.to_s
121
137
  end
122
138
 
123
139
  # Mangle identifiers for URL paths.
124
140
  def sanitized(input)
125
- input.gsub(/\//, '_')
141
+ input.gsub(/\//, "_")
142
+ end
143
+
144
+ def perform_network_request
145
+ if @is_retry_enabled
146
+ retries_remaining = 3
147
+ sleep_time_seconds = 5
148
+ begin
149
+ result = yield
150
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
151
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
152
+ if retries_remaining > 0
153
+ $LOG.warn("Network request failed - remaining retries: #{retries_remaining}, sleeping for: #{sleep_time_seconds}s, error: #{e.message}")
154
+ sleep(sleep_time_seconds)
155
+ retries_remaining -= 1
156
+ sleep_time_seconds *= 3
157
+ retry
158
+ else
159
+ raise e
160
+ end
161
+ end
162
+ result
163
+ else
164
+ yield
165
+ end
126
166
  end
127
167
  end
data/lib/server/config.ru CHANGED
@@ -1,6 +1,6 @@
1
- require 'rubygems'
2
- require 'bundler'
1
+ require "rubygems"
2
+ require "bundler"
3
3
  Bundler.require
4
4
 
5
- require './server_app.rb'
5
+ require "./server_app.rb"
6
6
  run Sinatra::Application
@@ -1,14 +1,21 @@
1
- require 'sinatra'
2
- require 'fileutils'
3
- require 'carthage_remote_cache'
4
-
5
- get '/' do
6
- "Welcome to carthage_remote_cache"
1
+ require "json"
2
+ require "sinatra"
3
+ require "fileutils"
4
+ require "carthage_remote_cache"
5
+
6
+ get "/" do
7
+ <<-eos
8
+ <html>
9
+ <p>Welcome to <strong>carthage_remote_cache</strong> (#{VERSION})</p>
10
+ <p>To browse cache contents visit <a href="/browser/">/browser/</a></p>
11
+ </html>
12
+ eos
7
13
  end
8
14
 
9
- version_path = '/version'
10
- versions_path = '/versions/:xcodebuild_version/:swift_version/:dependency_name/:version/:version_filename'
11
- frameworks_path = '/frameworks/:xcodebuild_version/:swift_version/:dependency_name/:version/:framework_name/:platform'
15
+ version_path = "/version"
16
+ versions_path = "/versions/:xcodebuild_version/:swift_version/:dependency_name/:version/:version_filename"
17
+ frameworks_path = "/frameworks/:xcodebuild_version/:swift_version/:dependency_name/:version/:framework_name/:platform"
18
+ browser_path = "/browser/*"
12
19
 
13
20
  get version_path do
14
21
  status(200)
@@ -16,13 +23,25 @@ get version_path do
16
23
  end
17
24
 
18
25
  get versions_path do
26
+ if params.key?(:platform)
27
+ begin
28
+ platforms = platform_to_symbols(params[:platform])
29
+ rescue AppError => e
30
+ status(400)
31
+ return JSON.pretty_generate({ "error" => e.message })
32
+ end
33
+ else
34
+ platforms = PLATFORMS
35
+ end
36
+
19
37
  dirname = params_to_framework_dir(params)
20
38
  filename = params[:version_filename]
21
39
  filepath = File.join(dirname, filename)
22
40
 
23
41
  if File.exist?(filepath)
24
42
  status(200)
25
- send_file(filepath)
43
+ version_file = VersionFile.new(filepath, platforms)
44
+ JSON.pretty_generate(version_file.json)
26
45
  else
27
46
  status(404)
28
47
  end
@@ -39,7 +58,7 @@ post versions_path do
39
58
  File.delete(target_filename) if File.exist?(target_filename)
40
59
 
41
60
  $LOG.info("Writing: #{target_filename}")
42
- File.open(target_filename, 'wb') do |target_file|
61
+ File.open(target_filename, "wb") do |target_file|
43
62
  target_file.write(source_file.read)
44
63
  end
45
64
 
@@ -75,7 +94,7 @@ post frameworks_path do
75
94
  File.delete(target_filename) if File.exist?(target_filename)
76
95
 
77
96
  $LOG.info("Writing: #{target_filename}")
78
- File.open(target_filename, 'wb') do |target_file|
97
+ File.open(target_filename, "wb") do |target_file|
79
98
  target_file.write(source_file.read)
80
99
  end
81
100
 
@@ -91,6 +110,44 @@ post frameworks_path do
91
110
  end
92
111
  end
93
112
 
113
+ # Full blown file browser.
114
+ get browser_path do
115
+ url_path = "/" + params["splat"][0]
116
+ path = File.join(SERVER_CACHE_DIR, url_path)
117
+
118
+ if File.file?(path)
119
+ status(200)
120
+ send_file(path)
121
+ else
122
+ html = "<html>"
123
+
124
+ # Current directory
125
+ html += "<h2>#{url_path}</h2>"
126
+
127
+ # ".." link
128
+ if url_path != "/"
129
+ parent = File.dirname(url_path)
130
+ parent += "/" if parent != "/"
131
+ html += "<p><a href=\"/browser#{parent}\">..</a></p>"
132
+ end
133
+
134
+ # Child links
135
+ for name in Dir.children(path).select { |name| name != ".DS_Store" }.sort
136
+ child_path = File.join(path, name)
137
+ html += "<p>"
138
+ if File.file?(child_path)
139
+ html += "<a href=\"#{name}\">#{name}</a> #{format_file_size(File.size(child_path))}"
140
+ else
141
+ html += "<a href=\"#{name}/\">#{name}/</a>"
142
+ end
143
+ html += " <span style=\"color:#777\">#{File.ctime(child_path).to_s}</span>"
144
+ html += "</p>"
145
+ end
146
+
147
+ html
148
+ end
149
+ end
150
+
94
151
  private
95
152
 
96
153
  def params_to_framework_dir(params)
data/lib/shell_wrapper.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'open3'
1
+ require "open3"
2
2
 
3
3
  class ShellWrapper
4
4
  # @return
data/lib/table.rb CHANGED
@@ -32,8 +32,8 @@ class Table
32
32
  end
33
33
 
34
34
  def separator_line
35
- dashes = @column_sizes.map { |size| '-' * size }
36
- '+' + dashes.join('+') + '+'
35
+ dashes = @column_sizes.map { |size| "-" * size }
36
+ "+" + dashes.join("+") + "+"
37
37
  end
38
38
 
39
39
  def header_line
@@ -41,7 +41,7 @@ class Table
41
41
  column_size = @column_sizes[index] - 1
42
42
  " %-#{column_size}.#{column_size}s" % column
43
43
  end
44
- '|' + columns.join('|') + '|'
44
+ "|" + columns.join("|") + "|"
45
45
  end
46
46
 
47
47
  def row_line(row)
@@ -53,6 +53,6 @@ class Table
53
53
  "%#{column_size}.#{column_size}s " % column
54
54
  end
55
55
  end
56
- '|' + columns.join('|') + '|'
56
+ "|" + columns.join("|") + "|"
57
57
  end
58
58
  end
data/lib/utils.rb CHANGED
@@ -15,7 +15,7 @@ end
15
15
  def quote(input)
16
16
  if input.is_a? String
17
17
  if input.empty?
18
- ''
18
+ ""
19
19
  else
20
20
  '"' + input + '"'
21
21
  end
@@ -23,7 +23,7 @@ def quote(input)
23
23
  input
24
24
  .map { |e| quote(e) }
25
25
  .select { |e| !e.empty? }
26
- .join(' ')
26
+ .join(" ")
27
27
  else
28
28
  raise AppError.new, "Unsupported type #{input}"
29
29
  end
@@ -32,13 +32,13 @@ end
32
32
  def platform_to_api_string(platform)
33
33
  case platform
34
34
  when :iOS
35
- 'iOS'
35
+ "iOS"
36
36
  when :macOS
37
- 'macOS'
37
+ "macOS"
38
38
  when :tvOS
39
- 'tvOS'
39
+ "tvOS"
40
40
  when :watchOS
41
- 'watchOS'
41
+ "watchOS"
42
42
  else
43
43
  raise AppError.new, "Unrecognized platform #{platform.inspect}"
44
44
  end
@@ -47,20 +47,34 @@ end
47
47
  def platform_to_carthage_dir_string(platform)
48
48
  case platform
49
49
  when :iOS
50
- 'iOS'
50
+ "iOS"
51
51
  when :macOS
52
- 'Mac'
52
+ "Mac"
53
53
  when :tvOS
54
- 'tvOS'
54
+ "tvOS"
55
55
  when :watchOS
56
- 'watchOS'
56
+ "watchOS"
57
57
  else
58
58
  raise AppError.new, "Unrecognized platform #{platform.inspect}"
59
59
  end
60
60
  end
61
61
 
62
+ def platform_to_symbols(string)
63
+ platforms = string.split(",").map(&:to_sym)
64
+ for platform in platforms
65
+ if !PLATFORMS.include?(platform)
66
+ raise PlatformMismatchError.new(platform)
67
+ end
68
+ end
69
+ platforms
70
+ end
71
+
62
72
  # @return string in "x.y MB" format
63
73
  def format_file_size(bytes)
64
- megabytes = bytes / 1000.0 / 1000.0
65
- "#{megabytes.round(1)} MB"
74
+ if bytes == 0
75
+ "0.0 MB"
76
+ else
77
+ megabytes = [0.1, bytes / 1000.0 / 1000.0].max
78
+ "#{megabytes.round(1)} MB"
79
+ end
66
80
  end
data/lib/version.rb CHANGED
@@ -1 +1 @@
1
- VERSION = '0.0.8'
1
+ VERSION = "0.0.11"