carthage_cache_res 0.9.1
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +17 -0
- data/CODEOWNERS +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +216 -0
- data/Rakefile +12 -0
- data/bin/console +11 -0
- data/bin/setup +7 -0
- data/carthage_cache_res.gemspec +43 -0
- data/exe/carthage_cache_res +107 -0
- data/lib/carthage_cache_res.rb +22 -0
- data/lib/carthage_cache_res/application.rb +93 -0
- data/lib/carthage_cache_res/archive_builder.rb +57 -0
- data/lib/carthage_cache_res/archive_installer.rb +53 -0
- data/lib/carthage_cache_res/archiver.rb +24 -0
- data/lib/carthage_cache_res/build_collector.rb +86 -0
- data/lib/carthage_cache_res/carthage_cache_lock.rb +28 -0
- data/lib/carthage_cache_res/carthage_resolved_file.rb +49 -0
- data/lib/carthage_cache_res/configuration.rb +122 -0
- data/lib/carthage_cache_res/configuration_validator.rb +134 -0
- data/lib/carthage_cache_res/configurator.rb +79 -0
- data/lib/carthage_cache_res/configurator_wizard.rb +49 -0
- data/lib/carthage_cache_res/description.rb +3 -0
- data/lib/carthage_cache_res/project.rb +66 -0
- data/lib/carthage_cache_res/repository.rb +58 -0
- data/lib/carthage_cache_res/shell_command_executor.rb +11 -0
- data/lib/carthage_cache_res/swift_version_resolver.rb +17 -0
- data/lib/carthage_cache_res/terminal.rb +25 -0
- data/lib/carthage_cache_res/version.rb +3 -0
- metadata +212 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module CarthageCacheRes
|
2
|
+
|
3
|
+
class MissingConfigurationKey < Struct.new(:keyname, :solution)
|
4
|
+
|
5
|
+
def self.missing_bucket_name
|
6
|
+
solution = "You need to specify the AWS S3 bucket to be used.\n" \
|
7
|
+
"You can either pass the '--bucket-name' option or " \
|
8
|
+
" add ':bucket_name: YOUR_BUCKET_NAME' to " \
|
9
|
+
".carthage_cache_res.yml file.\nYou can also run " \
|
10
|
+
"'carthage_cache_res config' to generate the config file."
|
11
|
+
self.new(:bucket_name, solution)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.missing_aws_key(keyname, name)
|
15
|
+
solution = "You need to specify the AWS #{name} to be used.\n" \
|
16
|
+
"You can either define a environmental variable " \
|
17
|
+
"AWS_REGION or add ':#{keyname}: YOUR_KEY_VALUE' " \
|
18
|
+
"under the :aws_s3_client_options: key in the " \
|
19
|
+
".carthage_cache_res.yml file.\nYou can also run " \
|
20
|
+
"'carthage_cache_res config' to generate the config file."
|
21
|
+
self.new("aws_s3_client_options.#{keyname}", solution)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.missing_aws_region
|
25
|
+
missing_aws_key("region", "region")
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.missing_aws_access_key_id
|
29
|
+
missing_aws_key("access_key_id", "access key ID")
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.missing_aws_secret_access_key
|
33
|
+
missing_aws_key("secret_access_key", "secret access key")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class ValidationResult
|
39
|
+
|
40
|
+
def self.valid
|
41
|
+
self.new(nil)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.invalid(error)
|
45
|
+
self.new(error)
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_reader :error
|
49
|
+
|
50
|
+
def initialize(error)
|
51
|
+
@error = error
|
52
|
+
end
|
53
|
+
|
54
|
+
def valid?
|
55
|
+
@error == nil
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class ConfigurationValidator
|
61
|
+
|
62
|
+
attr_reader :config
|
63
|
+
|
64
|
+
def initialize(config)
|
65
|
+
@config = config
|
66
|
+
end
|
67
|
+
|
68
|
+
def valid?
|
69
|
+
validate.valid?
|
70
|
+
end
|
71
|
+
|
72
|
+
def read_only?
|
73
|
+
(config.aws_access_key_id.nil? || config.aws_secret_access_key.nil?) && config.aws_profile.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate
|
77
|
+
return missing_bucket_name unless has_bucket_name?
|
78
|
+
return missing_aws_region unless has_aws_region?
|
79
|
+
|
80
|
+
return missing_aws_access_key_id if is_missing_aws_access_key_id?
|
81
|
+
return missing_aws_secret_access_key if is_missing_aws_secret_access_key?
|
82
|
+
|
83
|
+
ValidationResult.valid
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def is_missing_aws_access_key_id?
|
89
|
+
!has_aws_profile? && !has_aws_access_key_id? && has_aws_secret_access_key?
|
90
|
+
end
|
91
|
+
|
92
|
+
def is_missing_aws_secret_access_key?
|
93
|
+
!has_aws_profile? && has_aws_access_key_id? && !has_aws_secret_access_key?
|
94
|
+
end
|
95
|
+
|
96
|
+
def has_bucket_name?
|
97
|
+
config.bucket_name
|
98
|
+
end
|
99
|
+
|
100
|
+
def has_aws_region?
|
101
|
+
config.aws_region
|
102
|
+
end
|
103
|
+
|
104
|
+
def has_aws_access_key_id?
|
105
|
+
config.aws_access_key_id
|
106
|
+
end
|
107
|
+
|
108
|
+
def has_aws_secret_access_key?
|
109
|
+
config.aws_secret_access_key
|
110
|
+
end
|
111
|
+
|
112
|
+
def has_aws_profile?
|
113
|
+
config.aws_profile
|
114
|
+
end
|
115
|
+
|
116
|
+
def missing_bucket_name
|
117
|
+
ValidationResult.invalid(MissingConfigurationKey.missing_bucket_name)
|
118
|
+
end
|
119
|
+
|
120
|
+
def missing_aws_region
|
121
|
+
ValidationResult.invalid(MissingConfigurationKey.missing_aws_region)
|
122
|
+
end
|
123
|
+
|
124
|
+
def missing_aws_access_key_id
|
125
|
+
ValidationResult.invalid(MissingConfigurationKey.missing_aws_access_key_id)
|
126
|
+
end
|
127
|
+
|
128
|
+
def missing_aws_secret_access_key
|
129
|
+
ValidationResult.invalid(MissingConfigurationKey.missing_aws_secret_access_key)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module CarthageCacheRes
|
4
|
+
|
5
|
+
class Configurator
|
6
|
+
|
7
|
+
CONFIG_FILE_NAME = ".carthage_cache_res.yml"
|
8
|
+
|
9
|
+
attr_reader :config_file_path
|
10
|
+
attr_reader :base_config
|
11
|
+
attr_reader :terminal
|
12
|
+
|
13
|
+
def initialize(terminal, project_path, base_config = {})
|
14
|
+
@config_file_path = File.join(project_path, CONFIG_FILE_NAME)
|
15
|
+
@base_config = merge_config(base_config)
|
16
|
+
@terminal = terminal
|
17
|
+
end
|
18
|
+
|
19
|
+
def config
|
20
|
+
@config ||= load_config!
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_config(config)
|
24
|
+
raise "Invalid configuration" unless config.valid?
|
25
|
+
File.open(config_file_path, 'w') { |f| f.write config.to_yaml }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def config_file_exist?
|
31
|
+
File.exist?(config_file_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_config!
|
35
|
+
config = load_config
|
36
|
+
validate!(config)
|
37
|
+
config
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_config
|
41
|
+
if config_file_exist?
|
42
|
+
config = Configuration.parse(File.read(config_file_path))
|
43
|
+
config = base_config.merge(config)
|
44
|
+
else
|
45
|
+
base_config
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate!(config)
|
50
|
+
validator = ConfigurationValidator.new(config)
|
51
|
+
result = validator.validate
|
52
|
+
unless result.valid?
|
53
|
+
terminal.error "error: #{result.error.solution}"
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_nil_keys(hash)
|
59
|
+
hash.inject({}) do |new_hash, (k,v)|
|
60
|
+
unless v.nil? || (v.respond_to?(:empty?) && v.empty?)
|
61
|
+
if v.class == Hash
|
62
|
+
cleaned_hashed = remove_nil_keys(v)
|
63
|
+
new_hash[k] = cleaned_hashed unless cleaned_hashed.empty?
|
64
|
+
else
|
65
|
+
new_hash[k] = v
|
66
|
+
end
|
67
|
+
end
|
68
|
+
new_hash
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def merge_config(config)
|
73
|
+
new_config = Configuration.default.hash_object.merge(config)
|
74
|
+
Configuration.new(remove_nil_keys(new_config))
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module CarthageCacheRes
|
2
|
+
|
3
|
+
class ConfiguratorWizard
|
4
|
+
|
5
|
+
def initialize(ask_proc, password_proc)
|
6
|
+
@ask_proc = ask_proc
|
7
|
+
@password_proc = password_proc
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
config = Configuration.new
|
12
|
+
config.bucket_name = ask("What is the Amazon S3 bucket name?", ENV["CARTHAGE_CACHE_DEFAULT_BUCKET_NAME"])
|
13
|
+
config.archive_base_path = ask("What base path do you want to use as archive's prefix? (default none)", nil)
|
14
|
+
config.prune_on_publish = confirm("Do you want to prune unused framework when publishing?")
|
15
|
+
config.aws_region = ask("What is the Amazon S3 region?")
|
16
|
+
config.aws_access_key_id = password("What is the AWS access key?")
|
17
|
+
config.aws_secret_access_key = password(" What is the AWS secret access key?")
|
18
|
+
config.aws_session_token = ask("What is the AWS session token (optional)?", nil, "*")
|
19
|
+
config
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def ask(message, default_value = nil, mask = nil)
|
25
|
+
message = "#{message} [#{default_value}]" if default_value
|
26
|
+
if mask
|
27
|
+
answer = @ask_proc.call(message) { |q| q.echo = mask }
|
28
|
+
else
|
29
|
+
answer = @ask_proc.call(message)
|
30
|
+
end
|
31
|
+
|
32
|
+
if answer.empty?
|
33
|
+
default_value
|
34
|
+
else
|
35
|
+
answer
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def confirm(message)
|
40
|
+
ask("#{message} [N/y]", 'N').downcase == 'y'
|
41
|
+
end
|
42
|
+
|
43
|
+
def password(message)
|
44
|
+
@password_proc.call(message)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CarthageCacheRes
|
2
|
+
|
3
|
+
class Project
|
4
|
+
|
5
|
+
attr_reader :cartfile
|
6
|
+
attr_reader :project_path
|
7
|
+
attr_reader :archive_base_path
|
8
|
+
attr_reader :cache_dir_name
|
9
|
+
attr_reader :terminal
|
10
|
+
attr_reader :tmpdir_base_path
|
11
|
+
|
12
|
+
def initialize(project_path, cache_dir_name, archive_base_path, terminal, tmpdir, swift_version_resolver = SwiftVersionResolver.new)
|
13
|
+
@project_path = project_path
|
14
|
+
@cache_dir_name = cache_dir_name
|
15
|
+
@archive_base_path = archive_base_path
|
16
|
+
@terminal = terminal
|
17
|
+
@tmpdir_base_path = tmpdir
|
18
|
+
@cartfile = CartfileResolvedFile.new(cartfile_resolved_path, terminal, swift_version_resolver)
|
19
|
+
end
|
20
|
+
|
21
|
+
def archive_filename
|
22
|
+
@archive_filename ||= "#{archive_key}.zip"
|
23
|
+
end
|
24
|
+
|
25
|
+
def archive_path
|
26
|
+
if @archive_base_path.nil?
|
27
|
+
@archive_path ||= archive_filename
|
28
|
+
else
|
29
|
+
@archive_path ||= File.join(archive_base_path, archive_filename)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def archive_key
|
34
|
+
cartfile.digest
|
35
|
+
end
|
36
|
+
|
37
|
+
def tmpdir
|
38
|
+
@tmpdir ||= create_tmpdir
|
39
|
+
end
|
40
|
+
|
41
|
+
def carthage_build_directory
|
42
|
+
@carthage_build_directory ||= File.join(project_path, "Carthage", "Build")
|
43
|
+
end
|
44
|
+
|
45
|
+
def all_frameworks
|
46
|
+
cartfile.frameworks
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def cartfile_resolved_path
|
52
|
+
@carfile_resolved_path ||= File.join(project_path, "Cartfile.resolved")
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_tmpdir
|
56
|
+
dir = File.join(tmpdir_base_path, cache_dir_name)
|
57
|
+
unless File.exist?(dir)
|
58
|
+
terminal.vputs "Creating carthage cache directory at '#{dir}'."
|
59
|
+
FileUtils.mkdir_p(dir)
|
60
|
+
end
|
61
|
+
dir
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
|
3
|
+
module CarthageCacheRes
|
4
|
+
|
5
|
+
class AWSRepository
|
6
|
+
|
7
|
+
attr_reader :client
|
8
|
+
attr_reader :bucket_name
|
9
|
+
|
10
|
+
def initialize(bucket_name, client_options = {})
|
11
|
+
@client = ::Aws::S3::Client.new(client_options)
|
12
|
+
@bucket_name = bucket_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def archive_exist?(archive_filename)
|
16
|
+
::Aws::S3::Object.new(bucket_name, archive_filename, client: client).exists?
|
17
|
+
end
|
18
|
+
|
19
|
+
def download(archive_filename, destination_path)
|
20
|
+
resp = client.get_object(
|
21
|
+
response_target: destination_path,
|
22
|
+
bucket: bucket_name,
|
23
|
+
key: archive_filename)
|
24
|
+
end
|
25
|
+
|
26
|
+
def upload(archive_filename, archive_path)
|
27
|
+
File.open(archive_path, 'rb') do |file|
|
28
|
+
client.put_object(bucket: bucket_name, key: archive_filename, body: file)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class HTTPRepository
|
35
|
+
|
36
|
+
attr_reader :base_url
|
37
|
+
|
38
|
+
def initialize(bucket_name, client_options = {})
|
39
|
+
region = client_options[:region]
|
40
|
+
bucket_name = bucket_name
|
41
|
+
@base_url = "https://s3-#{region}.amazonaws.com/#{bucket_name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def archive_exist?(archive_filename)
|
45
|
+
system "wget", "--method=HEAD", "#{base_url}/#{archive_filename}", "-q"
|
46
|
+
end
|
47
|
+
|
48
|
+
def download(archive_filename, destination_path)
|
49
|
+
system "wget", "--output-document=#{destination_path}", "#{base_url}/#{archive_filename}", "-q"
|
50
|
+
end
|
51
|
+
|
52
|
+
def upload(archive_filename, archive_path)
|
53
|
+
raise "carthage_cache_res is working in read-only mode. Please configure AWS credentials first"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module CarthageCacheRes
|
2
|
+
|
3
|
+
class SwiftVersionResolver
|
4
|
+
|
5
|
+
def initialize(executor = ShellCommandExecutor.new)
|
6
|
+
@executor = executor
|
7
|
+
end
|
8
|
+
|
9
|
+
def swift_version
|
10
|
+
output = @executor.execute('xcrun swift -version').chomp
|
11
|
+
version_string = /(\d+\.)?(\d+\.)?(\d+)/.match(output).to_s
|
12
|
+
Gem::Version.new(version_string)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module CarthageCacheRes
|
2
|
+
|
3
|
+
class Terminal
|
4
|
+
|
5
|
+
attr_reader :verbose
|
6
|
+
|
7
|
+
def initialize(verbose = false)
|
8
|
+
@verbose = verbose
|
9
|
+
end
|
10
|
+
|
11
|
+
def puts(message)
|
12
|
+
Kernel.puts(message)
|
13
|
+
end
|
14
|
+
|
15
|
+
def vputs(message)
|
16
|
+
puts(message) if verbose
|
17
|
+
end
|
18
|
+
|
19
|
+
def error(message)
|
20
|
+
STDERR.puts(message)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|