dtk-network-client 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/Gemfile +2 -0
- data/LICENSE +201 -0
- data/README.md +2 -0
- data/dtk-network-client.gemspec +24 -0
- data/lib/client/args.rb +19 -0
- data/lib/client/client_args.rb +23 -0
- data/lib/client/command/add_to_group.rb +20 -0
- data/lib/client/command/chmod.rb +21 -0
- data/lib/client/command/create_namespace.rb +19 -0
- data/lib/client/command/delete.rb +25 -0
- data/lib/client/command/delete_namespace.rb +19 -0
- data/lib/client/command/info.rb +32 -0
- data/lib/client/command/install/installer.rb +9 -0
- data/lib/client/command/install.rb +190 -0
- data/lib/client/command/list.rb +13 -0
- data/lib/client/command/list_namespaces.rb +10 -0
- data/lib/client/command/publish.rb +120 -0
- data/lib/client/command/pull.rb +53 -0
- data/lib/client/command/push.rb +63 -0
- data/lib/client/command/remove_from_group.rb +20 -0
- data/lib/client/command/unpublish.rb +27 -0
- data/lib/client/command/update.rb +18 -0
- data/lib/client/command.rb +31 -0
- data/lib/client/config.rb +54 -0
- data/lib/client/conn.rb +132 -0
- data/lib/client/dependency_tree/activated.rb +35 -0
- data/lib/client/dependency_tree/cache.rb +28 -0
- data/lib/client/dependency_tree/candidates.rb +19 -0
- data/lib/client/dependency_tree/resolver.rb +16 -0
- data/lib/client/dependency_tree.rb +272 -0
- data/lib/client/error.rb +22 -0
- data/lib/client/file_helper.rb +8 -0
- data/lib/client/git_adapter/git_gem.rb +246 -0
- data/lib/client/git_client.rb +136 -0
- data/lib/client/git_repo.rb +221 -0
- data/lib/client/module_dir.rb +38 -0
- data/lib/client/module_ref/dependency/local.rb +47 -0
- data/lib/client/module_ref/dependency/remote.rb +18 -0
- data/lib/client/module_ref/dependency.rb +21 -0
- data/lib/client/module_ref/version/source.rb +18 -0
- data/lib/client/module_ref/version.rb +87 -0
- data/lib/client/module_ref.rb +21 -0
- data/lib/client/response/response_types.rb +42 -0
- data/lib/client/response.rb +27 -0
- data/lib/client/rest_wrapper.rb +43 -0
- data/lib/client/s3_helper.rb +23 -0
- data/lib/client/session.rb +54 -0
- data/lib/client/storage/adapters/s3.rb +25 -0
- data/lib/client/storage.rb +29 -0
- data/lib/client/util/os_util.rb +77 -0
- data/lib/client/util/permissions_util.rb +12 -0
- data/lib/client/util/tar.rb +104 -0
- data/lib/client/util.rb +7 -0
- data/lib/client/version.rb +8 -0
- data/lib/dtk_network_client.rb +27 -0
- 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
|
data/lib/client/error.rb
ADDED
@@ -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,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
|