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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Yggdrasil
2
2
 
3
- Yggdrasil is a subversion wrapper to manage configuration files.
3
+ Yggdrasil is a subversion wrapper to manage server configurations and conditions.
4
4
 
5
5
  ## Installation
6
6
 
data/lib/yggdrasil.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require 'fileutils'
2
- require "open3"
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
- Yggdrasil::help([])
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 'status', 'stat', 'st'
44
- new.status(args[1..-1])
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
- error "Unknown subcommand: '#{args[0]}'"
53
- end
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
- # load config value from config file
137
- def read_config
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 += " --username '#{@options[:username]}' --password '#{@options[:password]}'" unless @anon_access
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 += " --username '#{@options[:username]}' --password '#{@options[:password]}'" unless @anon_access
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 += " --username '#{@options[:username]}' --password '#{@options[:password]}'" unless @anon_access
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 -q --no-auth-cache --non-interactive"
189
- cmd += " --username '#{@options[:username]}' --password '#{@options[:password]}'" unless @anon_access
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
- updates << $1 if /^.*\s(\S+)\s*$/ =~ line
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
- updates
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 method_missing(action, *args)
253
- Yggdrasil.__send__ action, *args
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
@@ -7,12 +7,12 @@ class Yggdrasil
7
7
  error "invalid arguments: #{args.join(',')}"
8
8
  end
9
9
 
10
- input_user_pass unless @anon_access
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 += " --username '#{@options[:username]}' --password '#{@options[:password]}'" unless @anon_access
15
+ cmd += username_password_options_to_read_repo
16
16
  system3 cmd
17
17
  end
18
18
  end
@@ -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
- input_user_pass
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
- puts system3("#@svn diff --no-auth-cache --non-interactive #{relative_path}")
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
- until @options.has_key?(:message) do
27
+ message = ''
28
+ unless @options.has_key?(:message)
26
29
  print "Input log message: "
27
- input = $stdin.gets
28
- @options[:message] = input.chomp
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"\