carthage_remote_cache 0.0.4 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 419b8edd1e39136269db80965bcffb2fe4e6207f7b83459e549a37f4beac9f7c
4
- data.tar.gz: 0c83197b67a7e6b5ef504a1811a533a082c98152e07315414d346eb97049a9fc
3
+ metadata.gz: 76eb34fe905eb5fce02802b6b3d7a764b144cc4ab20b6f67d2068215c6605811
4
+ data.tar.gz: ce2786ceae18cdc95d4c21360044b21838f839879d5a69f883d7b8c8d2040f15
5
5
  SHA512:
6
- metadata.gz: 5b4aaad19ca7a53f5ce85fa801c22fe019c66a3281ecb6d239516d8d0c94418201b1974d149ff44fc2e22b6a5085227f9280680b0aef1bc0700ea480fa4a1310
7
- data.tar.gz: 5fd1d49c2c75c9ffa64fc36cad248ee4cb670abab779f821582cdfc8b656ba175ece52608a6017022d2ffabd1997bda53c442229d14b876041f557929396bbc9
6
+ metadata.gz: a128b2d782cee56f2ddfc018a8f4e4e3275dd87b1337d6420861ee376edd0ea468655739951667768855721d0f91a7176a4102a4f20a2cc92e363e617bebe2d8
7
+ data.tar.gz: ffead6c5c29416ed7d12e2fdbd26f465127deedb80fb3af261904de35b2a22245a9302427081ff5e86585e2426db4a4444bbac57680e0726b7b3d2d9809f2e8d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- carthage_remote_cache (0.0.4)
4
+ carthage_remote_cache (0.0.5)
5
5
  concurrent-ruby (~> 1.0.5)
6
6
  rack (~> 2.0.4)
7
7
  rest-client (~> 2.0.2)
data/lib/api.rb CHANGED
@@ -22,17 +22,30 @@ class API
22
22
  archive.create_archive(@shell, carthage_dependency.should_include_dsym)
23
23
  archive_size = archive.archive_size
24
24
  begin
25
- @networking.upload_framework_archive(archive.archive_path, carthage_dependency, framework_name, platform)
25
+ checksum = crc32(archive.archive_path)
26
+ @networking.upload_framework_archive(archive.archive_path, carthage_dependency, framework_name, platform, checksum)
26
27
  ensure
27
28
  archive.delete_archive
28
29
  end
29
30
  archive_size
30
31
  end
31
32
 
32
- # @return zip archive size in Bytes or nil if archive download failed
33
+ # @return zip archive size in Bytes
34
+ # @raise AppError if download or checksum validation fails
33
35
  def download_and_unpack_archive(carthage_dependency, framework_name, platform)
34
- archive = @networking.download_framework_archive(carthage_dependency, framework_name, platform)
35
- return nil if archive.nil?
36
+ result = @networking.download_framework_archive(carthage_dependency, framework_name, platform)
37
+ if result.nil?
38
+ raise AppError.new, "Failed to download framework #{carthage_dependency} – #{framework_name} (#{platform}). Please `upload` the framework first."
39
+ end
40
+
41
+ archive = result[:archive]
42
+ remote_checksum = result[:checksum]
43
+ local_checksum = crc32(archive.archive_path)
44
+
45
+ if local_checksum != remote_checksum
46
+ raise AppError.new, checksum_error_message(archive.archive_path, remote_checksum, local_checksum)
47
+ end
48
+
36
49
  archive_size = archive.archive_size
37
50
  begin
38
51
  $LOG.debug("Downloaded #{archive.archive_path}")
@@ -42,4 +55,14 @@ class API
42
55
  end
43
56
  archive_size
44
57
  end
58
+
59
+ private
60
+
61
+ def checksum_error_message(path, remote, local)
62
+ <<~EOS
63
+ Checksums for '#{path}' do not match:
64
+ Remote: #{remote}
65
+ Local: #{local}
66
+ EOS
67
+ end
45
68
  end
@@ -6,6 +6,7 @@ require 'carthage_archive'
6
6
  require 'carthage_dependency'
7
7
  require 'constants'
8
8
  require 'configuration'
9
+ require 'crc32'
9
10
  require 'errors'
10
11
  require 'log'
11
12
  require 'networking'
@@ -72,12 +72,8 @@ class DownloadCommand
72
72
  version_file.frameworks_by_platform.each do |platform, framework_names|
73
73
  for framework_name in framework_names
74
74
  archive_size = @api.download_and_unpack_archive(carthage_dependency, framework_name, platform)
75
- if archive_size.nil?
76
- raise AppError.new, "Failed to download framework #{carthage_dependency} – #{framework_name} (#{platform}). Please `upload` the framework first."
77
- else
78
- @number_of_downloaded_archives += 1
79
- @total_archive_size += archive_size
80
- end
75
+ @number_of_downloaded_archives += 1
76
+ @total_archive_size += archive_size
81
77
  end
82
78
  end
83
79
  version_file.move_to_build_dir
data/lib/constants.rb CHANGED
@@ -6,3 +6,7 @@ THREAD_POOL_SIZE = 8
6
6
 
7
7
  SERVER_DEFAULT_PORT = 9292
8
8
  SERVER_CACHE_DIR = File.join(Dir.home, '.carthagerc_server')
9
+
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'
data/lib/crc32.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'digest'
2
+ require 'zlib'
3
+
4
+ class Digest::CRC32 < Digest::Class
5
+ include Digest::Instance
6
+
7
+ def initialize
8
+ reset
9
+ end
10
+
11
+ def reset
12
+ @crc32 = 0
13
+ end
14
+
15
+ def update(str)
16
+ @crc32 = Zlib.crc32(str, @crc32)
17
+ end
18
+
19
+ def finish
20
+ [@crc32].pack('N')
21
+ end
22
+ end
data/lib/errors.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  # Common type for all carthage_remote_cache Errors.
2
2
  class AppError < StandardError; end
3
3
 
4
+ class CmdError < StandardError
5
+ attr_reader :command
6
+
7
+ def initialize(command)
8
+ @command = command
9
+ end
10
+ end
11
+
4
12
  class MultipleErrorsError < AppError
5
13
  def initialize(errors)
6
14
  @errors = errors
data/lib/networking.rb CHANGED
@@ -8,6 +8,7 @@ class Networking
8
8
 
9
9
  # Version Files
10
10
 
11
+ # @return VersionFile or nil
11
12
  def download_version_file(carthage_dependency)
12
13
  url = new_version_file_url(carthage_dependency)
13
14
  $LOG.debug("Downloading version file from #{url}")
@@ -22,14 +23,20 @@ class Networking
22
23
  version_file
23
24
  end
24
25
 
26
+ # @raise AppError on upload failure
25
27
  def upload_version_file(carthage_dependency)
26
28
  url = new_version_file_url(carthage_dependency)
27
29
  $LOG.debug("Uploading #{carthage_dependency.version_filename}")
28
- RestClient.post(url, :version_file => File.new(carthage_dependency.version_filepath))
30
+ RestClient.post(url, :version_file => File.new(carthage_dependency.version_filepath)) do |response, request, result|
31
+ unless response.code == 200
32
+ raise AppError.new, "Version file upload #{carthage_dependency.version_filename} failed, response:\n #{response[0..300]}"
33
+ end
34
+ end
29
35
  end
30
36
 
31
37
  # Archives
32
38
 
39
+ # @return Hash with CarthageArchive and checksum or nil
33
40
  def download_framework_archive(carthage_dependency, framework_name, platform)
34
41
  url = new_framework_url(carthage_dependency, framework_name, platform)
35
42
  $LOG.debug("Downloading framework from #{url}")
@@ -37,7 +44,7 @@ class Networking
37
44
  if response.code == 200
38
45
  archive = CarthageArchive.new(framework_name, platform)
39
46
  File.write(archive.archive_path, response.to_s)
40
- archive
47
+ {:archive => archive, :checksum => response.headers[ARCHIVE_CHECKSUM_HEADER_REST_CLIENT]}
41
48
  else
42
49
  nil
43
50
  end
@@ -45,10 +52,17 @@ class Networking
45
52
  archive
46
53
  end
47
54
 
48
- def upload_framework_archive(zipfile_name, carthage_dependency, framework_name, platform)
55
+ # @raise AppError when upload fails
56
+ def upload_framework_archive(zipfile_name, carthage_dependency, framework_name, platform, checksum)
49
57
  url = new_framework_url(carthage_dependency, framework_name, platform)
50
- $LOG.debug("Uploading framework to #{url}")
51
- RestClient.post(url, :framework_file => File.new(zipfile_name))
58
+ params = {:framework_file => File.new(zipfile_name)}
59
+ headers = {ARCHIVE_CHECKSUM_HEADER_REST_CLIENT => checksum}
60
+ $LOG.debug("Uploading framework to #{url}, headers: #{headers}")
61
+ RestClient.post(url, params, headers) do |response, request, result|
62
+ unless response.code == 200
63
+ raise AppError.new, "Framework upload #{zipfile_name} failed, response:\n #{response[0..300]}"
64
+ end
65
+ end
52
66
  end
53
67
 
54
68
  private
@@ -47,15 +47,18 @@ get frameworks_path do
47
47
  filename = File.join(dirname, archive.archive_filename)
48
48
 
49
49
  if File.exist?(filename)
50
+ headers[ARCHIVE_CHECKSUM_HEADER_SINATRA_OUT] = crc32(filename)
50
51
  status(200)
51
52
  send_file(filename)
52
53
  else
53
54
  status(404)
55
+ "Missing framework archive at '#{filename}'"
54
56
  end
55
57
  end
56
58
 
57
59
  # Upload framework archive. Overwrites already cached archive if exists.
58
60
  post frameworks_path do
61
+ expected_checksum = request.env[ARCHIVE_CHECKSUM_HEADER_SINATRA_IN]
59
62
  filename = params[:framework_file][:filename]
60
63
  source_file = params[:framework_file][:tempfile]
61
64
 
@@ -70,7 +73,16 @@ post frameworks_path do
70
73
  target_file.write(source_file.read)
71
74
  end
72
75
 
73
- status(200)
76
+ checksum = crc32(target_filename)
77
+ if checksum == expected_checksum
78
+ status(200)
79
+ else
80
+ File.delete(target_filename)
81
+ message = "Checksums for '#{target_filename}' don't match. Expected '#{expected_checksum}', got '#{checksum}'"
82
+ $LOG.error(message)
83
+ status(500)
84
+ message
85
+ end
74
86
  end
75
87
 
76
88
  private
data/lib/shell_wrapper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'open3'
2
+
1
3
  class ShellWrapper
2
4
  # @return
3
5
  # Xcode 9.2
@@ -29,4 +31,17 @@ class ShellWrapper
29
31
  def unpack(archive_path)
30
32
  sh("unzip -o #{quote archive_path}")
31
33
  end
34
+
35
+ private
36
+
37
+ # @return command output if successful
38
+ # @raise CmdError
39
+ def sh(command)
40
+ stdout, stderr, status = Open3.capture3(command)
41
+ if status.success?
42
+ stdout.strip
43
+ else
44
+ raise CmdError.new(command), "Command '#{command}' failed, error output:\n#{stderr.strip}"
45
+ end
46
+ end
32
47
  end
data/lib/utils.rb CHANGED
@@ -1,19 +1,15 @@
1
- # Execute arbitrary system command.
2
- # @return command output, bails on failure
3
- def sh(cmd)
4
- output = `#{cmd}`
5
- bail("Command `#{cmd}` failed!") unless $?.success?
6
- output.strip
7
- end
8
-
9
- # Exits Ruby process, only to be called:
10
- # 1. If sh / system calls fail
11
- # 2. From top level `carthagerc` script
1
+ # Exits Ruby process, only to be called from top level `carthagerc` script
12
2
  def bail(message, code = 1)
13
3
  $stderr.puts(message.strip + "\n")
14
4
  Process.exit(code)
15
5
  end
16
6
 
7
+ def crc32(filename)
8
+ checksum = Digest::CRC32.file(filename).hexdigest
9
+ $LOG.debug("CRC32 checksum for '#{filename}': #{checksum}")
10
+ checksum
11
+ end
12
+
17
13
  # Quote command line arguments with double quotes.
18
14
  # Useful for file paths with spaces.
19
15
  def quote(input)
data/lib/version.rb CHANGED
@@ -1 +1 @@
1
- VERSION = '0.0.4'
1
+ VERSION = '0.0.5'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carthage_remote_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juraj Blahunka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-08 00:00:00.000000000 Z
11
+ date: 2018-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -212,6 +212,7 @@ files:
212
212
  - lib/commands/upload_command.rb
213
213
  - lib/configuration.rb
214
214
  - lib/constants.rb
215
+ - lib/crc32.rb
215
216
  - lib/errors.rb
216
217
  - lib/log.rb
217
218
  - lib/networking.rb