yggdrasil 0.0.5 → 0.0.6
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.
- data/README.md +1 -1
- data/lib/yggdrasil.rb +97 -113
- data/lib/yggdrasil/add.rb +1 -1
- data/lib/yggdrasil/check.rb +65 -0
- data/lib/yggdrasil/cleanup.rb +2 -2
- data/lib/yggdrasil/commit.rb +19 -5
- data/lib/yggdrasil/diff.rb +2 -3
- data/lib/yggdrasil/help.rb +87 -27
- data/lib/yggdrasil/init.rb +56 -20
- data/lib/yggdrasil/list.rb +2 -3
- data/lib/yggdrasil/log.rb +2 -2
- data/lib/yggdrasil/revert.rb +4 -4
- data/lib/yggdrasil/status.rb +2 -2
- data/lib/yggdrasil/update.rb +7 -5
- data/lib/yggdrasil/version.rb +3 -4
- data/lib/yggdrasil_common.rb +102 -0
- data/lib/yggdrasil_server.rb +77 -0
- data/lib/yggdrasil_server/get_repo.rb +6 -0
- data/lib/yggdrasil_server/get_ro_id_pw.rb +9 -0
- data/lib/yggdrasil_server/init_server.rb +62 -0
- data/lib/yggdrasil_server/put_result.rb +16 -0
- data/lib/yggdrasil_server/results.rb +30 -0
- data/spec/check_spec.rb +145 -0
- data/spec/commit_spec.rb +18 -2
- data/spec/help_spec.rb +83 -6
- data/spec/init_server_spec.rb +82 -0
- data/spec/init_spec.rb +46 -1
- data/spec/list_spec.rb +5 -1
- data/spec/results_spec.rb +66 -0
- data/spec/server_spec.rb +158 -0
- metadata +21 -5
data/README.md
CHANGED
data/lib/yggdrasil.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
|
2
|
+
|
3
|
+
require "yggdrasil_common"
|
4
|
+
require "yggdrasil_server"
|
5
|
+
|
3
6
|
require "yggdrasil/version"
|
4
7
|
require "yggdrasil/help"
|
5
8
|
require "yggdrasil/init"
|
@@ -12,6 +15,7 @@ require "yggdrasil/log"
|
|
12
15
|
require "yggdrasil/status"
|
13
16
|
require "yggdrasil/update"
|
14
17
|
require "yggdrasil/revert"
|
18
|
+
require "yggdrasil/check"
|
15
19
|
|
16
20
|
class Yggdrasil
|
17
21
|
|
@@ -20,12 +24,14 @@ class Yggdrasil
|
|
20
24
|
ENV['LANG'] = 'en_US.UTF-8'
|
21
25
|
|
22
26
|
if args.size == 0
|
23
|
-
|
27
|
+
new(false).help([])
|
24
28
|
return
|
25
29
|
end
|
26
30
|
case args[0]
|
27
31
|
when 'add'
|
28
32
|
new.add(args[1..-1])
|
33
|
+
when 'check', 'c'
|
34
|
+
new.check(args[1..-1])
|
29
35
|
when 'cleanup'
|
30
36
|
new.cleanup(args[1..-1])
|
31
37
|
when 'commit', 'ci'
|
@@ -33,139 +39,64 @@ class Yggdrasil
|
|
33
39
|
when 'diff', 'di'
|
34
40
|
new.diff(args[1..-1])
|
35
41
|
when 'help', 'h', '?'
|
36
|
-
help(args[1..-1])
|
42
|
+
new(false).help(args[1..-1])
|
37
43
|
when 'init'
|
38
44
|
new(false).init(args[1..-1])
|
45
|
+
when 'init-server'
|
46
|
+
YggdrasilServer.new(false).init_server(args[1..-1])
|
39
47
|
when 'list', 'ls'
|
40
48
|
new.list(args[1..-1])
|
41
49
|
when 'log'
|
42
50
|
new.log(args[1..-1])
|
43
|
-
when '
|
44
|
-
new.
|
51
|
+
when 'results'
|
52
|
+
YggdrasilServer.new.results(args[1..-1])
|
45
53
|
when 'revert'
|
46
54
|
new.revert(args[1..-1])
|
55
|
+
when 'server'
|
56
|
+
YggdrasilServer.new.server(args[1..-1])
|
57
|
+
when 'status', 'stat', 'st'
|
58
|
+
new.status(args[1..-1])
|
47
59
|
when 'update'
|
48
60
|
new.update(args[1..-1])
|
49
61
|
when 'version', '--version'
|
50
|
-
version
|
62
|
+
new(false).version
|
51
63
|
else
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
# @param [String] cmd
|
57
|
-
def Yggdrasil.system3(cmd, err_exit=true)
|
58
|
-
out = `#{cmd} 2>&1`
|
59
|
-
stat = $?
|
60
|
-
|
61
|
-
unless stat.success?
|
62
|
-
return nil unless err_exit
|
63
|
-
$stderr.puts "#{CMD} error: command failure: #{cmd}"
|
64
|
-
$stderr.puts "command output:"
|
65
|
-
$stderr.puts out
|
66
|
-
exit stat.exitstatus
|
67
|
-
end
|
68
|
-
return out
|
69
|
-
end
|
70
|
-
|
71
|
-
protected
|
72
|
-
# @param [String] msg
|
73
|
-
def Yggdrasil.error(msg)
|
74
|
-
$stderr.puts "#{CMD} error: #{msg}"
|
75
|
-
$stderr.puts
|
76
|
-
exit 1
|
77
|
-
end
|
78
|
-
|
79
|
-
def parse_options(args, valid_params)
|
80
|
-
valid_params['--debug'] = :debug? # common
|
81
|
-
@options ||= Hash.new
|
82
|
-
pos = 0
|
83
|
-
while args.size > pos
|
84
|
-
if valid_params.has_key?(args[pos])
|
85
|
-
option_note = args[pos]
|
86
|
-
option_key = valid_params[option_note]
|
87
|
-
args = args[0...pos]+args[pos+1..-1]
|
88
|
-
if option_key.to_s[-1] == '?'
|
89
|
-
@options[option_key] = true
|
90
|
-
else
|
91
|
-
error "Not enough arguments provided: #{option_note}" unless args.size > pos
|
92
|
-
option_value = args[pos].dup
|
93
|
-
args = args[0...pos]+args[pos+1..-1]
|
94
|
-
@options[option_key] = option_value
|
95
|
-
end
|
96
|
-
next
|
97
|
-
end
|
98
|
-
pos += 1
|
99
|
-
end
|
100
|
-
args
|
101
|
-
end
|
102
|
-
|
103
|
-
def input_user_pass
|
104
|
-
until @options.has_key?(:username) do
|
105
|
-
error "Can't get username or password" if @options.has_key?(:non_interactive?)
|
106
|
-
print "Input svn username: "
|
107
|
-
input = $stdin.gets
|
108
|
-
@options[:username] = input.chomp
|
109
|
-
end
|
110
|
-
until @options.has_key?(:password) do
|
111
|
-
error "Can't get username or password" if @options.has_key?(:non_interactive?)
|
112
|
-
print "Input svn password: "
|
113
|
-
#input = `sh -c 'read -s hoge;echo $hoge'`
|
114
|
-
system3 'stty -echo', false
|
115
|
-
input = $stdin.gets
|
116
|
-
system3 'stty echo', false
|
117
|
-
puts
|
118
|
-
@options[:password] = input.chomp
|
64
|
+
$stderr .puts "Unknown subcommand: '#{args[0]}'"
|
65
|
+
exit 1
|
119
66
|
end
|
120
67
|
end
|
121
68
|
|
122
69
|
def initialize(exist_config = true)
|
70
|
+
@base_cmd = File::basename($0)
|
123
71
|
@current_dir = `readlink -f .`.chomp
|
124
72
|
@config_dir = "#{ENV["HOME"]}/.yggdrasil"
|
125
73
|
@config_file = "#@config_dir/config"
|
126
74
|
@mirror_dir = "#@config_dir/mirror"
|
75
|
+
@checker_dir = "#@config_dir/checker"
|
76
|
+
@checker_result_dir = "#@config_dir/checker_result"
|
127
77
|
|
128
78
|
return unless exist_config
|
129
|
-
configs = read_config
|
130
|
-
ENV["PATH"] = configs[:path]
|
131
|
-
@svn = configs[:svn]
|
132
|
-
@repo = configs[:repo]
|
79
|
+
configs = read_config(@config_file)
|
80
|
+
error "need 'path' in config file" unless (ENV["PATH"] = configs[:path])
|
81
|
+
error "need 'svn' in config file" unless (@svn = configs[:svn])
|
82
|
+
error "need 'repo' in config file" unless (@repo = configs[:repo])
|
133
83
|
@anon_access = (configs[:anon_access] == 'read')
|
84
|
+
@options ||= Hash.new
|
85
|
+
@options[:server] = configs[:server] if configs.has_key?(:server)
|
134
86
|
end
|
135
87
|
|
136
|
-
|
137
|
-
|
138
|
-
configs = Hash.new
|
139
|
-
begin
|
140
|
-
File.open(@config_file) do |file|
|
141
|
-
l = 0
|
142
|
-
while (line = file.gets)
|
143
|
-
l += 1
|
144
|
-
next if /^\s*#.*$/ =~ line # comment line
|
145
|
-
if /^\s*(\S+)\s*=\s*(\S+).*$/ =~ line
|
146
|
-
key, val = $1, $2
|
147
|
-
key.gsub!(/-/, '_')
|
148
|
-
configs[key.to_sym] = val
|
149
|
-
else
|
150
|
-
error "syntax error. :#@config_file(#{l})"
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
rescue
|
155
|
-
error "can not open config file: #@config_file"
|
156
|
-
end
|
157
|
-
configs
|
158
|
-
end
|
88
|
+
protected
|
89
|
+
include YggdrasilCommon
|
159
90
|
|
160
91
|
def sync_mirror
|
161
92
|
updates = Array.new
|
162
93
|
FileUtils.cd @mirror_dir do
|
163
94
|
cmd = "#@svn ls #@repo -R --no-auth-cache --non-interactive"
|
164
|
-
cmd +=
|
95
|
+
cmd += username_password_options_to_read_repo
|
165
96
|
out = system3(cmd)
|
166
97
|
files = out.split(/\n/)
|
167
98
|
cmd = "#@svn status -q --no-auth-cache --non-interactive"
|
168
|
-
cmd +=
|
99
|
+
cmd += username_password_options_to_read_repo
|
169
100
|
out = system3(cmd)
|
170
101
|
out.split(/\n/).each do |line|
|
171
102
|
files << $1 if /^.*\s(\S+)\s*$/ =~ line
|
@@ -179,17 +110,20 @@ class Yggdrasil
|
|
179
110
|
elsif File.file?("/#{file}")
|
180
111
|
if !File.exist?("#@mirror_dir/#{file}")
|
181
112
|
cmd = "#@svn revert #{file}"
|
182
|
-
cmd +=
|
113
|
+
cmd += username_password_options_to_read_repo
|
183
114
|
system3 cmd
|
184
115
|
end
|
185
116
|
FileUtils.copy_file "/#{file}", "#@mirror_dir/#{file}"
|
186
117
|
end
|
187
118
|
end
|
188
|
-
cmd = "#@svn status -
|
189
|
-
cmd +=
|
119
|
+
cmd = "#@svn status -qu --no-auth-cache --non-interactive"
|
120
|
+
cmd += username_password_options_to_read_repo
|
190
121
|
out = system3(cmd)
|
191
122
|
out.split(/\n/).each do |line|
|
192
|
-
|
123
|
+
next if /^Status against revision/ =~ line
|
124
|
+
if /^(.).*\s(\S+)\s*$/ =~ line
|
125
|
+
updates << [$1, $2]
|
126
|
+
end
|
193
127
|
end
|
194
128
|
end
|
195
129
|
updates
|
@@ -214,14 +148,14 @@ class Yggdrasil
|
|
214
148
|
cond = '^'+target_relatives.join('|^') # make reg exp
|
215
149
|
matched_updates = Array.new
|
216
150
|
updates.each do |update|
|
217
|
-
matched_updates << update if update.match(cond)
|
151
|
+
matched_updates << update if update[1].match(cond)
|
218
152
|
end
|
219
153
|
|
220
154
|
# search parent updates of matched updates
|
221
155
|
parents = Array.new
|
222
156
|
updates.each do |update|
|
223
157
|
matched_updates.each do |matched_update|
|
224
|
-
parents << update if matched_update.match("^#{update}/")
|
158
|
+
parents << update if matched_update[1].match("^#{update[1]}/")
|
225
159
|
end
|
226
160
|
end
|
227
161
|
matched_updates += parents
|
@@ -232,7 +166,7 @@ class Yggdrasil
|
|
232
166
|
until @options.has_key?(:non_interactive?)
|
233
167
|
puts
|
234
168
|
(0...updates.size).each do |i|
|
235
|
-
puts "#{i}:#{updates[i]}"
|
169
|
+
puts "#{i}:#{updates[i][0]} #{updates[i][1]}"
|
236
170
|
end
|
237
171
|
print "OK? [Y|n|<num to diff>]:"
|
238
172
|
res = $stdin.gets
|
@@ -242,14 +176,64 @@ class Yggdrasil
|
|
242
176
|
break if res == 'Y'
|
243
177
|
next unless updates[res.to_i]
|
244
178
|
if /^\d+$/ =~ res
|
245
|
-
yield updates[res.to_i]
|
179
|
+
yield updates[res.to_i][1]
|
246
180
|
end
|
247
181
|
end
|
248
182
|
# res == 'Y'
|
249
|
-
|
183
|
+
confirmed_updates = Array.new
|
184
|
+
updates.each do |e|
|
185
|
+
confirmed_updates << e[1]
|
186
|
+
end
|
187
|
+
confirmed_updates.sort.uniq
|
250
188
|
end
|
251
189
|
|
252
|
-
def
|
253
|
-
|
190
|
+
def username_password_options_to_read_repo
|
191
|
+
if @options.has_key?(:ro_password)
|
192
|
+
" --username #{@options[:ro_username]} --password #{@options[:ro_password]}"
|
193
|
+
else
|
194
|
+
""
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def get_user_pass_if_need_to_read_repo
|
199
|
+
unless @anon_access
|
200
|
+
get_server_config if !@options.has_key?(:ro_username) && @options.has_key?(:server)
|
201
|
+
input_user_pass unless @options.has_key?(:ro_password)
|
202
|
+
end
|
203
|
+
@options[:ro_username] = @options[:username] if @options.has_key?(:username)
|
204
|
+
@options[:ro_password] = @options[:password] if @options.has_key?(:password)
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_server_config(need_repo = false)
|
208
|
+
if /^(.+):(\d+)$/ =~ @options[:server]
|
209
|
+
host = $1
|
210
|
+
port = $2
|
211
|
+
|
212
|
+
if need_repo
|
213
|
+
# get repo
|
214
|
+
sock = TCPSocket.open(host, port)
|
215
|
+
error "can not connect to server: #{host}:#{port}" if sock.nil?
|
216
|
+
sock.puts "get_repo"
|
217
|
+
rcv = sock.gets
|
218
|
+
error "can not get repo from server" if rcv.nil?
|
219
|
+
@options[:repo] = rcv.chomp
|
220
|
+
sock.close
|
221
|
+
end
|
222
|
+
|
223
|
+
#get read-only username/password
|
224
|
+
sock = TCPSocket.open(host, port)
|
225
|
+
error "can not connect to server: #{host}:#{port}" if sock.nil?
|
226
|
+
sock.puts("get_ro_id_pw")
|
227
|
+
username = sock.gets
|
228
|
+
unless username.nil?
|
229
|
+
@options[:ro_username] = username.chomp
|
230
|
+
password = sock.gets
|
231
|
+
error "can not get ro_password" if password.nil?
|
232
|
+
@options[:ro_password] = password.chomp
|
233
|
+
end
|
234
|
+
sock.close
|
235
|
+
else
|
236
|
+
error "invalid host:port '#{@options[:server]}'"
|
237
|
+
end
|
254
238
|
end
|
255
239
|
end
|
data/lib/yggdrasil/add.rb
CHANGED
@@ -13,7 +13,7 @@ class Yggdrasil
|
|
13
13
|
file_path_parts.each do |part|
|
14
14
|
mirror_path += "/#{part}"
|
15
15
|
next if File.exist?(mirror_path)
|
16
|
-
if part.equal?(file_path_parts[-1])
|
16
|
+
if part.equal?(file_path_parts[-1]) && File.file?(file_path)
|
17
17
|
FileUtils.copy file_path, mirror_path
|
18
18
|
else
|
19
19
|
Dir.mkdir mirror_path
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'find'
|
2
|
+
|
3
|
+
class Yggdrasil
|
4
|
+
|
5
|
+
def check(args)
|
6
|
+
args = parse_options(args,
|
7
|
+
{'--username'=>:username, '--password'=>:password,
|
8
|
+
'--non-interactive'=>:non_interactive?})
|
9
|
+
if args.size != 0
|
10
|
+
error "invalid arguments: #{args.join(',')}"
|
11
|
+
end
|
12
|
+
|
13
|
+
# execute checker
|
14
|
+
`rm -rf #@checker_result_dir`
|
15
|
+
Dir.mkdir @checker_result_dir, 0755
|
16
|
+
Find.find(@checker_dir).each do |file|
|
17
|
+
if File.file?(file) && File.executable?(file)
|
18
|
+
if file =~ %r{^#@checker_dir(.*)$}
|
19
|
+
file_body = $1
|
20
|
+
system3("#{file} > #@checker_result_dir#{file_body}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# add checker result
|
26
|
+
result_files = Array.new
|
27
|
+
Find.find(@checker_result_dir) {|f| result_files << f}
|
28
|
+
stdout = $stdout
|
29
|
+
$stdout = StringIO.new
|
30
|
+
add result_files
|
31
|
+
$stdout = stdout
|
32
|
+
|
33
|
+
get_user_pass_if_need_to_read_repo
|
34
|
+
sync_mirror
|
35
|
+
|
36
|
+
cmd_arg = "#@svn status -qu --no-auth-cache --non-interactive"
|
37
|
+
cmd_arg += username_password_options_to_read_repo
|
38
|
+
check_result = String.new
|
39
|
+
FileUtils.cd @mirror_dir do
|
40
|
+
check_result = system3(cmd_arg)
|
41
|
+
end
|
42
|
+
check_result.gsub!(/^Status against revision:.*\n/, '')
|
43
|
+
check_result.chomp!
|
44
|
+
if check_result != ""
|
45
|
+
check_result << "\n\n"
|
46
|
+
cmd_arg = "#@svn diff --no-auth-cache --non-interactive -r HEAD"
|
47
|
+
cmd_arg += username_password_options_to_read_repo
|
48
|
+
FileUtils.cd @mirror_dir do
|
49
|
+
check_result << system3(cmd_arg)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
puts check_result
|
53
|
+
|
54
|
+
if /^(.+):(\d+)$/ =~ @options[:server]
|
55
|
+
host = $1
|
56
|
+
port = $2
|
57
|
+
# put check_result to server
|
58
|
+
sock = TCPSocket.open(host, port)
|
59
|
+
error "can not connect to server: #{host}:#{port}" if sock.nil?
|
60
|
+
sock.puts "put_result #{Socket.gethostname}"
|
61
|
+
sock.puts check_result
|
62
|
+
sock.close
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/yggdrasil/cleanup.rb
CHANGED
@@ -7,12 +7,12 @@ class Yggdrasil
|
|
7
7
|
error "invalid arguments: #{args.join(',')}"
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
get_user_pass_if_need_to_read_repo
|
11
11
|
|
12
12
|
system3 "rm -rf #@mirror_dir"
|
13
13
|
|
14
14
|
cmd = "#@svn checkout --no-auth-cache --non-interactive #@repo #@mirror_dir"
|
15
|
-
cmd +=
|
15
|
+
cmd += username_password_options_to_read_repo
|
16
16
|
system3 cmd
|
17
17
|
end
|
18
18
|
end
|
data/lib/yggdrasil/commit.rb
CHANGED
@@ -5,7 +5,7 @@ class Yggdrasil
|
|
5
5
|
target_paths = parse_options(args,
|
6
6
|
{'--username'=>:username, '--password'=>:password,
|
7
7
|
'-m'=>:message, '--message'=>:message, '--non-interactive'=>:non_interactive?})
|
8
|
-
|
8
|
+
get_user_pass_if_need_to_read_repo
|
9
9
|
|
10
10
|
updates = sync_mirror
|
11
11
|
matched_updates = select_updates(updates, target_paths)
|
@@ -16,18 +16,32 @@ class Yggdrasil
|
|
16
16
|
|
17
17
|
confirmed_updates = confirm_updates(matched_updates) do |relative_path|
|
18
18
|
FileUtils.cd @mirror_dir do
|
19
|
-
|
19
|
+
cmd = "#@svn diff --no-auth-cache --non-interactive #{relative_path}"
|
20
|
+
cmd += username_password_options_to_read_repo
|
21
|
+
puts system3(cmd)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
return unless confirmed_updates
|
23
25
|
return if confirmed_updates.size == 0
|
24
26
|
|
25
|
-
|
27
|
+
message = ''
|
28
|
+
unless @options.has_key?(:message)
|
26
29
|
print "Input log message: "
|
27
|
-
|
28
|
-
|
30
|
+
loop do
|
31
|
+
input = $stdin.gets
|
32
|
+
error "can not input log message" unless input
|
33
|
+
input.chomp!
|
34
|
+
if input =~ /^(.*)\\$/
|
35
|
+
message += $1+"\n"
|
36
|
+
else
|
37
|
+
message += input
|
38
|
+
@options[:message] = message
|
39
|
+
break
|
40
|
+
end
|
41
|
+
end
|
29
42
|
end
|
30
43
|
|
44
|
+
input_user_pass
|
31
45
|
FileUtils.cd @mirror_dir do
|
32
46
|
puts system3 "#@svn commit -m '#{@options[:message]}'"\
|
33
47
|
" --no-auth-cache --non-interactive"\
|