yggdrasil 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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"\