dtk-network-client 1.0.0

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +201 -0
  5. data/README.md +2 -0
  6. data/dtk-network-client.gemspec +24 -0
  7. data/lib/client/args.rb +19 -0
  8. data/lib/client/client_args.rb +23 -0
  9. data/lib/client/command/add_to_group.rb +20 -0
  10. data/lib/client/command/chmod.rb +21 -0
  11. data/lib/client/command/create_namespace.rb +19 -0
  12. data/lib/client/command/delete.rb +25 -0
  13. data/lib/client/command/delete_namespace.rb +19 -0
  14. data/lib/client/command/info.rb +32 -0
  15. data/lib/client/command/install/installer.rb +9 -0
  16. data/lib/client/command/install.rb +190 -0
  17. data/lib/client/command/list.rb +13 -0
  18. data/lib/client/command/list_namespaces.rb +10 -0
  19. data/lib/client/command/publish.rb +120 -0
  20. data/lib/client/command/pull.rb +53 -0
  21. data/lib/client/command/push.rb +63 -0
  22. data/lib/client/command/remove_from_group.rb +20 -0
  23. data/lib/client/command/unpublish.rb +27 -0
  24. data/lib/client/command/update.rb +18 -0
  25. data/lib/client/command.rb +31 -0
  26. data/lib/client/config.rb +54 -0
  27. data/lib/client/conn.rb +132 -0
  28. data/lib/client/dependency_tree/activated.rb +35 -0
  29. data/lib/client/dependency_tree/cache.rb +28 -0
  30. data/lib/client/dependency_tree/candidates.rb +19 -0
  31. data/lib/client/dependency_tree/resolver.rb +16 -0
  32. data/lib/client/dependency_tree.rb +272 -0
  33. data/lib/client/error.rb +22 -0
  34. data/lib/client/file_helper.rb +8 -0
  35. data/lib/client/git_adapter/git_gem.rb +246 -0
  36. data/lib/client/git_client.rb +136 -0
  37. data/lib/client/git_repo.rb +221 -0
  38. data/lib/client/module_dir.rb +38 -0
  39. data/lib/client/module_ref/dependency/local.rb +47 -0
  40. data/lib/client/module_ref/dependency/remote.rb +18 -0
  41. data/lib/client/module_ref/dependency.rb +21 -0
  42. data/lib/client/module_ref/version/source.rb +18 -0
  43. data/lib/client/module_ref/version.rb +87 -0
  44. data/lib/client/module_ref.rb +21 -0
  45. data/lib/client/response/response_types.rb +42 -0
  46. data/lib/client/response.rb +27 -0
  47. data/lib/client/rest_wrapper.rb +43 -0
  48. data/lib/client/s3_helper.rb +23 -0
  49. data/lib/client/session.rb +54 -0
  50. data/lib/client/storage/adapters/s3.rb +25 -0
  51. data/lib/client/storage.rb +29 -0
  52. data/lib/client/util/os_util.rb +77 -0
  53. data/lib/client/util/permissions_util.rb +12 -0
  54. data/lib/client/util/tar.rb +104 -0
  55. data/lib/client/util.rb +7 -0
  56. data/lib/client/version.rb +8 -0
  57. data/lib/dtk_network_client.rb +27 -0
  58. metadata +183 -0
@@ -0,0 +1,272 @@
1
+ require 'semverly'
2
+
3
+ module DTK::Network
4
+ module Client
5
+ class DependencyTree
6
+ require_relative('dependency_tree/activated')
7
+ require_relative('dependency_tree/cache')
8
+ require_relative('dependency_tree/candidates')
9
+
10
+ include RestWrapper
11
+ extend RestWrapper
12
+
13
+ LOCK_FILE = "dtk.module.lock"
14
+
15
+ def initialize(module_ref, opts = {})
16
+ @module_ref = module_ref
17
+ @module_directory = opts[:module_directory] || module_ref.repo_dir
18
+ @parsed_module = opts[:parsed_module]
19
+ @cache = Cache.new
20
+ @activated = Activated.new
21
+ @candidates = Candidates.new
22
+ @development_mode = opts[:development_mode]
23
+ end
24
+
25
+ def self.get_or_create(module_ref, opts = {})
26
+ content = nil
27
+ module_ref = convert_to_module_ref(module_ref) unless module_ref.is_a?(ModuleRef)
28
+ update_lock_file = opts[:update_lock_file]
29
+ yaml_content = FileHelper.get_content?("#{module_ref.repo_dir}/#{LOCK_FILE}")
30
+
31
+ if yaml_content && !update_lock_file
32
+ content = YAML.load(yaml_content)
33
+ raise_error_if_dependencies_changed!(content, opts[:parsed_module])
34
+ elsif opts[:save_to_file] || update_lock_file
35
+ content = compute_and_save_to_file(module_ref, opts)
36
+ else
37
+ content = compute(module_ref, opts)
38
+ end
39
+
40
+ ret_required_format(content, opts[:format])
41
+ end
42
+
43
+ def self.compute_and_save_to_file(module_ref, opts = {})
44
+ activated = compute(module_ref, opts)
45
+ ModuleDir.create_file_with_content("#{module_ref.repo_dir}/#{LOCK_FILE}", YAML.dump(activated.to_h))
46
+ activated
47
+ end
48
+
49
+ def self.compute(module_ref, opts = {})
50
+ new(module_ref, opts).compute
51
+ end
52
+
53
+ def compute
54
+ dependencies = (ret_dependencies || []).map do |pm_ref|
55
+ ModuleRef::Dependency.create_local_or_remote(pm_ref)
56
+ # ModuleRef::Dependency.new({ name: pm_ref['module'], namespace: pm_ref['namespace'], version: pm_ref['version'] })
57
+ end
58
+
59
+ activate_dependencies(dependencies)
60
+ @activated
61
+ end
62
+
63
+ private
64
+
65
+ def activate_dependencies(dependencies, opts = {})
66
+ dependencies.each do |dependency|
67
+ next if @activated.module_activated?(dependency)
68
+
69
+ puts "Calculating dependencies for module: #{dependency.full_name}(#{dependency.version.str_version})" if @development_mode
70
+
71
+ check_for_conflicts(dependency)
72
+
73
+ # dtkn_versions_w_deps_hash = dtkn_versions_with_dependencies(dependency)
74
+ dtkn_versions_w_deps_hash = dependency.dtkn_versions_with_dependencies
75
+ dtkn_versions_w_deps = dtkn_versions_w_deps_hash.map { |v| v['version'] }
76
+
77
+ version_obj = dependency.version
78
+ versions_in_range = version_obj.versions_in_range(dtkn_versions_w_deps)
79
+
80
+ raise "No version matching requirement '#{version_obj.full_version}'" if versions_in_range.empty?
81
+
82
+ versions_in_range.sort!
83
+ latest_version = versions_in_range.last
84
+
85
+ if dependency.is_a?(ModuleRef::Dependency::Local)
86
+ latest_version_dep = dependency
87
+ else
88
+ latest_version_dep = ModuleRef::Dependency::Remote.new({ name: dependency.name, namespace: dependency.namespace, version: latest_version })
89
+ end
90
+
91
+ @activated.add!(latest_version_dep)
92
+ @candidates.add!(dependency, versions_in_range)
93
+
94
+ dtkn_deps_of_deps = dtkn_versions_w_deps_hash.find {|dep| dep['version'].eql?(latest_version) }
95
+ add_nested_modules(dependency, dtkn_deps_of_deps)
96
+
97
+ dtkn_deps_of_deps_objs = (dtkn_deps_of_deps['dependencies'] || {}).map do |dtkn_dep|
98
+ ModuleRef::Dependency.create_local_or_remote({ name: dtkn_dep['module'], namespace: dtkn_dep['namespace'], version: dtkn_dep['version'] })
99
+ end
100
+
101
+ activate_dependencies(dtkn_deps_of_deps_objs, opts)
102
+ end
103
+ end
104
+
105
+ def ret_dependencies
106
+ if @parsed_module
107
+ (@parsed_module.val(:DependentModules) || []).map do |parsed_mr|
108
+ { 'namespace' => parsed_mr.req(:Namespace), 'module' => parsed_mr.req(:ModuleName), 'version' => parsed_mr.val(:ModuleVersion) }
109
+ end
110
+ else
111
+ response = rest_get("modules/#{@module_ref.name}/dependencies", { name: @module_ref.name, namespace: @module_ref.namespace, version: @module_ref.version.str_version })
112
+ response['dependencies']
113
+ end
114
+ end
115
+
116
+ def dtkn_versions_with_dependencies(module_ref)
117
+ response = rest_get("modules/get_versions_with_dependencies", { name: module_ref.name, namespace: module_ref.namespace })
118
+ response['versions']
119
+ end
120
+
121
+ def check_for_conflicts(dependency)
122
+ if activated_mod = @activated.existing_name?(dependency.full_name)
123
+ raise "There is already activated version '#{activated_mod[:version] || activated_mod['version']}' for module '#{dependency.full_name}' and it does not match required version '#{dependency.version.full_version}'"
124
+ end
125
+ end
126
+
127
+ def add_nested_modules(dependency, dtkn_deps_of_deps)
128
+ if activated_module = @activated[dependency.full_name]
129
+ nested_deps = {}
130
+ (dtkn_deps_of_deps['dependencies'] || []).each{ |dtkn_dep| nested_deps.merge!("#{dtkn_dep['namespace']}/#{dtkn_dep['module']}" => simplify_version(dtkn_dep['version'])) }
131
+
132
+ unless nested_deps.empty?
133
+ activated_module.key?('modules') ? activated_module['modules'].merge!(nested_deps) : activated_module.merge!('modules' => nested_deps)
134
+ end
135
+ end
136
+ end
137
+
138
+ def simplify_version(version)
139
+ if version.is_a?(Hash)
140
+ # transform custom dtk hash into ruby hash to avoid strange output in yaml file
141
+ version.to_h
142
+ else
143
+ version
144
+ end
145
+ end
146
+
147
+ def self.ret_as_module_refs(dep_modules)
148
+ dep_modules.map { |k,v| create_module_ref(k, v) }
149
+ end
150
+
151
+ def self.create_module_ref(full_name, version_hash)
152
+ namespace, name = full_name.split('/')
153
+ version = version_hash[:version] || version_hash['version']
154
+ ModuleRef.new({ namespace: namespace, name: name, version: version })
155
+ end
156
+
157
+ def self.ret_as_hash(dep_modules)
158
+ dep_modules.map { |k,v| create_module_hash(k, v) }
159
+ end
160
+
161
+ def self.create_module_hash(full_name, version_hash)
162
+ namespace, name = full_name.split('/')
163
+ version = version_hash[:version] || version_hash['version']
164
+ ret = { namespace: namespace, name: name, version: version }
165
+
166
+ if source = version_hash[:source] || version_hash['source']
167
+ ret.merge!(source: source)
168
+ end
169
+
170
+ ret
171
+ end
172
+
173
+ def self.ret_required_format(content, format)
174
+ format ||= :module_ref
175
+ case format.to_sym
176
+ when :module_ref
177
+ ret_as_module_refs(content)
178
+ when :hash
179
+ ret_as_hash(content)
180
+ else
181
+ raise Error.new("Unsupported format '#{format}'. Valid formats are '#{ValidFormats.join(', ')}'")
182
+ end
183
+ end
184
+ ValidFormats = [:module_ref, :hash]
185
+
186
+ def self.convert_to_module_ref(module_ref)
187
+ ModuleRef.new(module_ref)
188
+ end
189
+
190
+ def self.raise_error_if_dependencies_changed!(lock_content, parsed_module)
191
+ return unless parsed_module
192
+
193
+ message = "Module dependencies have been changed, please use '-u' option to update '#{LOCK_FILE}' file accordingly."
194
+ dependencies = convert_to_modules_lock_format(parsed_module.val(:DependentModules))
195
+
196
+ lock_deps = filter_out_dependencies_of_dependencies(lock_content, dependencies)
197
+ raise Error.new(message) if dependencies.size != lock_deps.size
198
+
199
+ dependencies.each do |name, value|
200
+ if matching = lock_deps[name]
201
+ module_ref_version = ModuleRef::Version.new(value['version'])
202
+ matches_version = module_ref_version.satisfied_by?(matching['version'])
203
+ matches_source = (value['source'] == matching['source'])
204
+ raise Error.new(message) unless (matches_version && matches_source)
205
+ else
206
+ raise Error.new(message)
207
+ end
208
+ end
209
+ end
210
+
211
+ def self.convert_to_modules_lock_format(dependencies = {})
212
+ modules_hash = {}
213
+
214
+ (dependencies || {}).each do |dependency|
215
+ version = dependency[:version]
216
+ source = nil
217
+
218
+ if version.is_a?(Hash)
219
+ source = version['source'] || version[:source]
220
+ if matching_source = source && source.match(/(file:)(.*)/)
221
+ source = matching_source[2]
222
+ end
223
+ version = version['version'] || version[:version]
224
+ end
225
+
226
+ namespace_name = "#{dependency[:namespace]}/#{dependency[:module_name]}"
227
+ content_hash = {'version' => version}
228
+ content_hash['source'] = source if source
229
+ modules_hash.merge!(namespace_name => content_hash)
230
+ end
231
+
232
+ modules_hash
233
+ end
234
+
235
+ def self.filter_out_dependencies_of_dependencies(lock_content, module_yaml_dependencies)
236
+ top_level_dependencies = {}
237
+ nested_dependencies = {}
238
+
239
+ lock_content.each do |lock_name, lock_value|
240
+ nested_dependencies.merge!(lock_value['modules'] || lock_value[:modules] || {})
241
+ top_level_dependencies.merge!(lock_name => {'version' => lock_value['version'], 'source' => lock_value['source']})
242
+ end
243
+
244
+ nested_dependencies.each do |nd_name, version|
245
+ source = nil
246
+
247
+ if version.is_a?(Hash)
248
+ source = version['source'] || version[:source]
249
+ version = version['version'] || version[:version]
250
+ end
251
+
252
+ if top_level_dependency = top_level_dependencies[nd_name]
253
+ module_ref_version = ModuleRef::Version.new(version)
254
+ matches_version = module_ref_version.satisfied_by?(top_level_dependency['version'])
255
+ matches_source = (source == top_level_dependency['source'])
256
+
257
+ if yaml_dep = module_yaml_dependencies[nd_name]
258
+ matches_version_new = module_ref_version.satisfied_by?(yaml_dep['version'])
259
+ matches_source_new = (source == yaml_dep['source'])
260
+ next unless (matches_version_new && matches_source_new)
261
+ end
262
+
263
+ top_level_dependencies.delete(nd_name) if (matches_version && matches_source)
264
+ end
265
+ end
266
+
267
+ top_level_dependencies
268
+ end
269
+
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,22 @@
1
+ module DTK::Network::Client
2
+ class Error < NameError
3
+ def initialize(msg = '')
4
+ if errors = msg['errors']
5
+ errors = [errors] unless errors.is_a?(Array)
6
+ error_msg = ''
7
+ # error_msg << "#{errors['code'].upcase} " if errors['code']
8
+ errors.each do |error|
9
+ if err_msg = error['message']
10
+ error_msg << "#{err_msg}\n"
11
+ elsif orig_exeption = error['original_exception']
12
+ error_msg << "#{orig_exeption}\n"
13
+ end
14
+ end
15
+ super(error_msg)
16
+ else
17
+ super(msg)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,8 @@
1
+ module DTK::Network::Client
2
+ class FileHelper
3
+ def self.get_content?(file_path)
4
+ File.open(file_path).read if file_path && File.exists?(file_path)
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,246 @@
1
+ require 'git'
2
+
3
+ module DTK::Network
4
+ module Client
5
+ class GitGem
6
+ attr_accessor :git_repo
7
+
8
+ # Monkey patch the git merge method
9
+ # to allow passing the --allow-unrelated-histories flag
10
+ # more info: http://stackoverflow.com/questions/37937984/git-refusing-to-merge-unrelated-histories
11
+ class ::Git::Base
12
+ def merge(branch, message = 'merge', opts = {})
13
+ self.lib.merge(branch, message, opts)
14
+ end
15
+
16
+ def rev_list(sha)
17
+ self.lib.rev_list(sha)
18
+ end
19
+
20
+ def name_status(branch1 = nil, branch2 = nil, opts = {})
21
+ self.lib.name_status(branch1, branch2, opts)
22
+ end
23
+ end
24
+
25
+ class ::Git::Lib
26
+ def merge(branch, message = nil, opts = {})
27
+ arr_opts = []
28
+ arr_opts << '--allow-unrelated-histories' if opts[:allow_unrelated_histories]
29
+ arr_opts << '-Xtheirs' if opts[:use_theirs]
30
+ arr_opts << '-m' << message if message
31
+ arr_opts += [branch]
32
+ command('merge', arr_opts)
33
+ end
34
+
35
+ def rev_list(sha)
36
+ arr_opts = [sha]
37
+ command('rev-list', arr_opts)
38
+ end
39
+
40
+ def name_status(branch1 = nil, branch2 = nil, opts = {})
41
+ arr_opts = []
42
+ arr_opts << '--name-status'
43
+ arr_opts << "--diff-filter=#{opts[:diff_filter]}" if opts[:diff_filter]
44
+ arr_opts << branch1 if branch1
45
+ arr_opts << branch2 if branch2
46
+
47
+ command_lines('diff', arr_opts).inject({}) do |memo, line|
48
+ status, path = line.split("\t")
49
+ memo[path] = status
50
+ memo
51
+ end
52
+ end
53
+
54
+ def command_lines(cmd, opts = [], chdir = true, redirect = '')
55
+ cmd_op = command(cmd, opts, chdir)
56
+ op = cmd_op.encode("UTF-8", "binary", {
57
+ :invalid => :replace,
58
+ :undef => :replace
59
+ })
60
+ op.split("\n")
61
+ end
62
+ end
63
+
64
+ # opts can have keys
65
+ # :branch
66
+ def initialize(repo_dir, opts = {})
67
+ @repo_dir = repo_dir
68
+ @git_repo = ::Git.init(repo_dir)
69
+ @local_branch_name = opts[:branch]
70
+ end
71
+
72
+ def self.clone(repo_url, target_path, branch)
73
+ git_base = ::Git.clone(repo_url, target_path)
74
+ begin
75
+ git_base.checkout(branch)
76
+ rescue => e
77
+ raise "The branch or tag '#{branch}' does not exist on repo '#{repo_url}'"
78
+ end
79
+ git_base
80
+ end
81
+
82
+ # opts can have keys
83
+ # :new_branch - Boolean
84
+ def checkout(branch, opts = {})
85
+ ret = @git_repo.checkout(branch, opts)
86
+ @local_branch_name = branch
87
+ ret
88
+ end
89
+
90
+ def fetch(remote = 'origin')
91
+ @git_repo.fetch(remote)
92
+ end
93
+
94
+ def add_remote(name, url)
95
+ @git_repo.remove_remote(name) if is_there_remote?(name)
96
+ @git_repo.add_remote(name, url)
97
+ end
98
+
99
+ def remove_remote(name)
100
+ @git_repo.remove_remote(name) if is_there_remote?(name)
101
+ end
102
+
103
+ def push(remote, branch, opts = {})
104
+ branch_name = current_branch ? current_branch.name : 'master'
105
+ branch_for_push = "#{branch_name}:refs/heads/#{branch || local_branch_name}"
106
+ @git_repo.push(remote, branch_for_push, opts)
107
+ end
108
+
109
+ def merge(branch_to_merge_from, opts = {})
110
+ @git_repo.merge(branch_to_merge_from, 'merge', :allow_unrelated_histories => allow_unrelated_histories?, :use_theirs => opts[:use_theirs])
111
+ end
112
+
113
+ def status
114
+ @git_repo.status
115
+ end
116
+
117
+ def changed
118
+ status.is_a?(Hash) ? status.changed().keys : status.changed().collect { |file| file.first }
119
+ end
120
+
121
+ def untracked
122
+ status.is_a?(Hash) ? status.untracked().keys : status.untracked().collect { |file| file.first }
123
+ end
124
+
125
+ def deleted
126
+ status.is_a?(Hash) ? status.deleted().keys : status.deleted().collect { |file| file.first }
127
+ end
128
+
129
+ def added
130
+ status.is_a?(Hash) ? status.added().keys : status.added().collect { |file| file.first }
131
+ end
132
+
133
+ def stage_and_commit(commit_msg = nil)
134
+ commit_msg ||= default_commit_message
135
+ add_all
136
+ begin
137
+ commit(commit_msg)
138
+ rescue
139
+ # do not raise if nothing to commit
140
+ end
141
+ end
142
+
143
+ def empty_commit(commit_msg = nil)
144
+ commit_msg ||= default_commit_message
145
+ commit(commit_msg, :allow_empty => true)
146
+ end
147
+
148
+ def reset_soft(sha)
149
+ @git_repo.reset(sha)
150
+ end
151
+
152
+ def reset_hard(sha)
153
+ @git_repo.reset_hard(sha)
154
+ end
155
+
156
+ def revparse(sha_or_string)
157
+ @git_repo.revparse(sha_or_string)
158
+ end
159
+
160
+ def rev_list(base_sha)
161
+ @git_repo.rev_list(base_sha)
162
+ end
163
+
164
+ def local_ahead(base_sha, remote_sha)
165
+ results = @git_repo.rev_list(base_sha)
166
+ !results.split("\n").grep(remote_sha).empty?
167
+ end
168
+
169
+ def stage_changes()
170
+ @git_repo.add(untracked())
171
+ @git_repo.add(added())
172
+ @git_repo.add(changed())
173
+
174
+ deleted().each do |file|
175
+ begin
176
+ @git_repo.remove(file)
177
+ rescue
178
+ # ignore this error means file has already been staged
179
+ # we cannot support status of file, in 1.8.7 so this is
180
+ # solution for that
181
+ end
182
+ end
183
+ end
184
+
185
+ # opts can have keys
186
+ # :allow_empty
187
+ def commit(commit_msg = "", opts = {})
188
+ @git_repo.commit(commit_msg, :allow_empty => opts[:allow_empty])
189
+ end
190
+
191
+ def add(*files)
192
+ @git_repo.add(files.flatten)
193
+ end
194
+
195
+ def add_all
196
+ # Cannot use '@git_repo.add(:all => true)' because this only works if pwd is base git repo
197
+ fully_qualified_repo_dir = (@repo_dir =~ /^\// ? @repo_dir : File.join(Dir.pwd, @repo_dir))
198
+ @git_repo.add(fully_qualified_repo_dir, :all => true )
199
+ end
200
+
201
+ def is_there_remote?(remote_name)
202
+ @git_repo.remotes.find { |r| r.name == remote_name }
203
+ end
204
+
205
+ def current_branch
206
+ @git_repo.branches.local.find { |b| b.current }
207
+ end
208
+
209
+ def remotes
210
+ @git_repo.remotes
211
+ end
212
+
213
+ def head_commit_sha
214
+ current_branch.gcommit.sha
215
+ end
216
+
217
+ def pull(remote, branch)
218
+ @git_repo.pull(remote, branch)
219
+ end
220
+
221
+ def diff
222
+ @git_repo.diff
223
+ end
224
+
225
+ def diff_name_status(branch_or_sha_1, branch_or_sha_2, opts = {})
226
+ @git_repo.name_status(branch_or_sha_1, branch_or_sha_2, opts)
227
+ end
228
+
229
+ def changed?
230
+ (!(changed().empty? && untracked().empty? && deleted().empty?))
231
+ end
232
+
233
+
234
+ def all_branches
235
+ @git_repo.branches
236
+ end
237
+
238
+ private
239
+
240
+ def default_commit_message
241
+ "DTK Commit from network client"
242
+ end
243
+
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,136 @@
1
+ module DTK::Network
2
+ module Client
3
+ class GitClient
4
+ require_relative('git_adapter/git_gem')
5
+
6
+ # opts can have keys
7
+ # :branch
8
+ def initialize(repo_dir, opts = {})
9
+ @repo_dir = repo_dir
10
+ @git_adapter = git_adapter_class.new(repo_dir, opts)
11
+ end
12
+
13
+ attr_reader :repo_dir
14
+
15
+ def self.clone(repo_url, target_path, branch)
16
+ git_adapter_class.clone(repo_url, target_path, branch)
17
+ end
18
+
19
+ def self.is_git_repo?(dir)
20
+ File.directory?("#{dir}/.git")
21
+ end
22
+
23
+ def add_remote(name, url)
24
+ @git_adapter.add_remote(name, url)
25
+ end
26
+
27
+ def changed?
28
+ @git_adapter.changed?
29
+ end
30
+
31
+ # opts can have keys
32
+ # :new_branch - Boolean
33
+ def checkout(branch, opts = {})
34
+ @git_adapter.checkout(branch, opts)
35
+ end
36
+
37
+ def current_branch
38
+ @git_adapter.current_branch
39
+ end
40
+
41
+ def diff
42
+ @git_adapter.diff
43
+ end
44
+
45
+ def diff_name_status(branch_or_sha_1 = nil, branch_or_sha_2 = nil, opts = {})
46
+ @git_adapter.diff_name_status(branch_or_sha_1, branch_or_sha_2, opts)
47
+ end
48
+
49
+ def fetch(remote = 'origin')
50
+ @git_adapter.fetch(remote)
51
+ end
52
+
53
+ def head_commit_sha
54
+ @git_adapter.head_commit_sha
55
+ end
56
+
57
+ def is_there_remote?(remote_name)
58
+ @git_adapter.is_there_remote?(remote_name)
59
+ end
60
+
61
+ def merge(branch_to_merge_from, opts = {})
62
+ @git_adapter.merge(branch_to_merge_from, opts)
63
+ end
64
+
65
+ def push(remote, branch, opts = {})
66
+ @git_adapter.push(remote, branch, opts)
67
+ end
68
+
69
+ def push_from_cached_branch(remote, branch, opts = {})
70
+ @git_adapter.push_from_cached_branch(remote, branch, opts)
71
+ end
72
+
73
+ def pull(remote, branch)
74
+ @git_adapter.pull(remote, branch)
75
+ end
76
+
77
+ def remotes
78
+ @git_adapter.remotes
79
+ end
80
+
81
+ def remove_remote(name)
82
+ @git_adapter.remove_remote(name)
83
+ end
84
+
85
+ def stage_and_commit(commit_msg = nil)
86
+ @git_adapter.stage_and_commit(commit_msg)
87
+ end
88
+
89
+ def empty_commit(commit_msg = nil)
90
+ @git_adapter.empty_commit(commit_msg)
91
+ end
92
+
93
+ def commit(commit_msg = "", opts = {})
94
+ @git_adapter.commit(commit_msg, opts)
95
+ end
96
+
97
+ def reset_soft(sha)
98
+ @git_adapter.reset_soft(sha)
99
+ end
100
+
101
+ def reset_hard(sha)
102
+ @git_adapter.reset_hard(sha)
103
+ end
104
+
105
+ def revparse(string)
106
+ @git_adapter.revparse(string)
107
+ end
108
+
109
+ def rev_list(base_sha)
110
+ @git_adapter.rev_list(base_sha)
111
+ end
112
+
113
+ def local_ahead(base_sha, remote_sha)
114
+ @git_adapter.local_ahead(base_sha, remote_sha)
115
+ end
116
+
117
+ def add_all
118
+ @git_adapter.add_all
119
+ end
120
+
121
+ def all_branches
122
+ @git_adapter.all_branches
123
+ end
124
+
125
+ private
126
+
127
+ def git_adapter_class
128
+ self.class.git_adapter_class
129
+ end
130
+
131
+ def self.git_adapter_class
132
+ GitGem
133
+ end
134
+ end
135
+ end
136
+ end