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.
@@ -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,3 @@
1
+ module CarthageCacheRes
2
+ DESCRIPTION = "A tool that allows to cache Carthage/Build folder in Amazon S3."
3
+ 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,11 @@
1
+ module CarthageCacheRes
2
+
3
+ class ShellCommandExecutor
4
+
5
+ def execute(command)
6
+ `#{command}`
7
+ end
8
+
9
+ end
10
+
11
+ 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