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.
- 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
|