automateit 0.70923
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -0
- data/CHANGES.txt +100 -0
- data/Hoe.rake +35 -0
- data/Manifest.txt +111 -0
- data/README.txt +44 -0
- data/Rakefile +284 -0
- data/TESTING.txt +57 -0
- data/TODO.txt +26 -0
- data/TUTORIAL.txt +390 -0
- data/bin/ai +3 -0
- data/bin/aifield +82 -0
- data/bin/aitag +128 -0
- data/bin/automateit +117 -0
- data/docs/friendly_errors.txt +50 -0
- data/docs/previews.txt +86 -0
- data/env.sh +4 -0
- data/examples/basic/Rakefile +26 -0
- data/examples/basic/config/automateit_env.rb +16 -0
- data/examples/basic/config/fields.yml +3 -0
- data/examples/basic/config/tags.yml +13 -0
- data/examples/basic/dist/README.txt +9 -0
- data/examples/basic/dist/myapp_server.erb +30 -0
- data/examples/basic/install.log +15 -0
- data/examples/basic/lib/README.txt +10 -0
- data/examples/basic/recipes/README.txt +4 -0
- data/examples/basic/recipes/install.rb +53 -0
- data/examples/basic/recipes/uninstall.rb +6 -0
- data/gpl.txt +674 -0
- data/lib/automateit.rb +66 -0
- data/lib/automateit/account_manager.rb +106 -0
- data/lib/automateit/account_manager/linux.rb +171 -0
- data/lib/automateit/account_manager/passwd.rb +69 -0
- data/lib/automateit/account_manager/portable.rb +136 -0
- data/lib/automateit/address_manager.rb +165 -0
- data/lib/automateit/address_manager/linux.rb +80 -0
- data/lib/automateit/address_manager/portable.rb +37 -0
- data/lib/automateit/cli.rb +80 -0
- data/lib/automateit/common.rb +65 -0
- data/lib/automateit/constants.rb +33 -0
- data/lib/automateit/edit_manager.rb +292 -0
- data/lib/automateit/error.rb +10 -0
- data/lib/automateit/field_manager.rb +103 -0
- data/lib/automateit/interpreter.rb +641 -0
- data/lib/automateit/package_manager.rb +242 -0
- data/lib/automateit/package_manager/apt.rb +63 -0
- data/lib/automateit/package_manager/egg.rb +64 -0
- data/lib/automateit/package_manager/gem.rb +179 -0
- data/lib/automateit/package_manager/portage.rb +69 -0
- data/lib/automateit/package_manager/yum.rb +65 -0
- data/lib/automateit/platform_manager.rb +47 -0
- data/lib/automateit/platform_manager/darwin.rb +30 -0
- data/lib/automateit/platform_manager/debian.rb +26 -0
- data/lib/automateit/platform_manager/freebsd.rb +25 -0
- data/lib/automateit/platform_manager/gentoo.rb +26 -0
- data/lib/automateit/platform_manager/lsb.rb +40 -0
- data/lib/automateit/platform_manager/struct.rb +78 -0
- data/lib/automateit/platform_manager/uname.rb +29 -0
- data/lib/automateit/platform_manager/windows.rb +33 -0
- data/lib/automateit/plugin.rb +7 -0
- data/lib/automateit/plugin/base.rb +32 -0
- data/lib/automateit/plugin/driver.rb +218 -0
- data/lib/automateit/plugin/manager.rb +232 -0
- data/lib/automateit/project.rb +460 -0
- data/lib/automateit/root.rb +14 -0
- data/lib/automateit/service_manager.rb +79 -0
- data/lib/automateit/service_manager/chkconfig.rb +39 -0
- data/lib/automateit/service_manager/rc_update.rb +37 -0
- data/lib/automateit/service_manager/sysv.rb +126 -0
- data/lib/automateit/service_manager/update_rcd.rb +35 -0
- data/lib/automateit/shell_manager.rb +261 -0
- data/lib/automateit/shell_manager/base_link.rb +67 -0
- data/lib/automateit/shell_manager/link.rb +24 -0
- data/lib/automateit/shell_manager/portable.rb +421 -0
- data/lib/automateit/shell_manager/symlink.rb +32 -0
- data/lib/automateit/shell_manager/which.rb +25 -0
- data/lib/automateit/tag_manager.rb +63 -0
- data/lib/automateit/tag_manager/struct.rb +101 -0
- data/lib/automateit/tag_manager/tag_parser.rb +91 -0
- data/lib/automateit/tag_manager/yaml.rb +29 -0
- data/lib/automateit/template_manager.rb +55 -0
- data/lib/automateit/template_manager/base.rb +172 -0
- data/lib/automateit/template_manager/erb.rb +17 -0
- data/lib/ext/metaclass.rb +17 -0
- data/lib/ext/object.rb +18 -0
- data/lib/hashcache.rb +22 -0
- data/lib/helpful_erb.rb +63 -0
- data/lib/nested_error.rb +33 -0
- data/lib/queued_logger.rb +68 -0
- data/lib/tempster.rb +239 -0
- data/misc/index_gem_repository.rb +303 -0
- data/misc/setup_egg.rb +12 -0
- data/misc/setup_gem_dependencies.sh +7 -0
- data/misc/setup_rubygems.sh +21 -0
- data/misc/which.cmd +6 -0
- data/spec/extras/automateit_service_sysv_test +50 -0
- data/spec/extras/scratch.rb +15 -0
- data/spec/extras/simple_recipe.rb +8 -0
- data/spec/integration/account_manager_spec.rb +218 -0
- data/spec/integration/address_manager_linux_spec.rb +119 -0
- data/spec/integration/address_manager_portable_spec.rb +30 -0
- data/spec/integration/cli_spec.rb +215 -0
- data/spec/integration/examples_spec.rb +54 -0
- data/spec/integration/examples_spec_editor.rb +71 -0
- data/spec/integration/package_manager_spec.rb +104 -0
- data/spec/integration/platform_manager_spec.rb +69 -0
- data/spec/integration/service_manager_sysv_spec.rb +115 -0
- data/spec/integration/shell_manager_spec.rb +471 -0
- data/spec/integration/template_manager_erb_spec.rb +31 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/unit/edit_manager_spec.rb +162 -0
- data/spec/unit/field_manager_spec.rb +79 -0
- data/spec/unit/hashcache_spec.rb +28 -0
- data/spec/unit/interpreter_spec.rb +98 -0
- data/spec/unit/platform_manager_spec.rb +44 -0
- data/spec/unit/plugins_spec.rb +253 -0
- data/spec/unit/tag_manager_spec.rb +189 -0
- data/spec/unit/template_manager_erb_spec.rb +137 -0
- metadata +249 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
# == ShellManager::BaseLink
|
2
|
+
#
|
3
|
+
# An abstract ShellManager driver used by drivers that provide either hard or
|
4
|
+
# symbolic links.
|
5
|
+
class AutomateIt::ShellManager::BaseLink < AutomateIt::ShellManager::BaseDriver
|
6
|
+
abstract_driver
|
7
|
+
|
8
|
+
# See ShellManager#ln
|
9
|
+
def _ln(sources, target, opts={})
|
10
|
+
kind = \
|
11
|
+
if opts[:symbolic] and opts[:force]
|
12
|
+
:ln_sf
|
13
|
+
elsif opts[:symbolic]
|
14
|
+
:ln_s
|
15
|
+
else
|
16
|
+
:ln
|
17
|
+
end
|
18
|
+
|
19
|
+
missing = []
|
20
|
+
sources = [sources].flatten
|
21
|
+
|
22
|
+
if kind == :ln
|
23
|
+
raise TypeError.new("source for hard link must be a String") unless sources.size == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
for source in sources
|
27
|
+
peer = File.directory?(target) ? File.join(target, File.basename(source)) : target
|
28
|
+
begin
|
29
|
+
peer_stat = File.stat(peer)
|
30
|
+
source_stat = File.stat(source)
|
31
|
+
|
32
|
+
if peer_stat.ino == source_stat.ino
|
33
|
+
next
|
34
|
+
elsif kind == :ln
|
35
|
+
missing << source
|
36
|
+
elsif Pathname.new(peer).realpath != Pathname.new(source).realpath
|
37
|
+
# It's either :ln_s or :ln_sf
|
38
|
+
missing << source
|
39
|
+
end
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
# File doesn't exist, so obviously missing
|
42
|
+
missing << source
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return false if missing.empty?
|
46
|
+
|
47
|
+
log.debug(PNOTE+"_ln(%s, %s, %s) # => %s" % [kind, sources.inspect, target.inspect, missing.inspect])
|
48
|
+
missing = missing.first if missing.size == 1
|
49
|
+
|
50
|
+
displayed = "ln"
|
51
|
+
if opts[:symbolic] and opts[:force]
|
52
|
+
displayed << " -sf"
|
53
|
+
else
|
54
|
+
displayed << " -s" if opts[:symbolic]
|
55
|
+
displayed << " -f" if opts[:force]
|
56
|
+
end
|
57
|
+
|
58
|
+
if kind == :ln
|
59
|
+
log.info(PEXEC+"#{displayed} #{missing} #{target}")
|
60
|
+
FileUtils.ln(missing, target, _fileutils_opts) && missing
|
61
|
+
else
|
62
|
+
log.info(PEXEC+"#{displayed} #{String === missing ? missing : missing.join(' ')} #{target}")
|
63
|
+
FileUtils.send(kind, missing, target, _fileutils_opts) && missing
|
64
|
+
end
|
65
|
+
return missing
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# == ShellManager::Link
|
2
|
+
#
|
3
|
+
# A ShellManager driver providing access to the hard link +ln+ command found on
|
4
|
+
# Unix-like systems.
|
5
|
+
class AutomateIt::ShellManager::Link < AutomateIt::ShellManager::BaseLink
|
6
|
+
depends_on :callbacks => [lambda{
|
7
|
+
RUBY_PLATFORM !~ /mswin/i and File.respond_to?(:link)
|
8
|
+
}]
|
9
|
+
|
10
|
+
def suitability(method, *args) # :nodoc:
|
11
|
+
# Level must be higher than Portable
|
12
|
+
return available? ? 2 : 0
|
13
|
+
end
|
14
|
+
|
15
|
+
# See ShellManager#provides_link?
|
16
|
+
def provides_link?
|
17
|
+
available? ? true : false
|
18
|
+
end
|
19
|
+
|
20
|
+
# See ShellManager#ln
|
21
|
+
def ln(*args)
|
22
|
+
_ln(*args)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,421 @@
|
|
1
|
+
# == ShellManager::Portable
|
2
|
+
#
|
3
|
+
# Pure-Ruby, portable driver for ShellManager provides Unix-like shell
|
4
|
+
# commands for manipulating files and executing commands.
|
5
|
+
#
|
6
|
+
# It does not provide commands for:
|
7
|
+
# * #which
|
8
|
+
# * #which!
|
9
|
+
class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
|
10
|
+
depends_on :nothing
|
11
|
+
|
12
|
+
def suitability(method, *args) # :nodoc:
|
13
|
+
return available? ? 1 : 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def broken?
|
17
|
+
RUBY_PLATFORM =~ /mswin|java/
|
18
|
+
end
|
19
|
+
private :broken?
|
20
|
+
|
21
|
+
def provides_mode?
|
22
|
+
! broken?
|
23
|
+
end
|
24
|
+
|
25
|
+
def provides_ownership?
|
26
|
+
! broken?
|
27
|
+
end
|
28
|
+
|
29
|
+
#...[ Custom commands ].................................................
|
30
|
+
|
31
|
+
# See ShellManager#sh
|
32
|
+
def sh(*commands)
|
33
|
+
args, opts = args_and_opts(*commands)
|
34
|
+
log.info(PEXEC+"#{args.join(' ')}")
|
35
|
+
return writing? ? system(*args) : true
|
36
|
+
end
|
37
|
+
|
38
|
+
def _mktemp_helper(kind, name=nil, opts={}, &block)
|
39
|
+
# Tempster takes care of rethrowing exceptions
|
40
|
+
opts[:name] = name || "automateit_temp"
|
41
|
+
opts[:message_callback] = lambda{|msg| log.info(PEXEC+msg)}
|
42
|
+
opts[:noop] = interpreter.preview?
|
43
|
+
::Tempster.send(kind, opts, &block)
|
44
|
+
end
|
45
|
+
private :_mktemp_helper
|
46
|
+
|
47
|
+
# See ShellManager#mktemp
|
48
|
+
def mktemp(name=nil, &block)
|
49
|
+
_mktemp_helper(:mktemp, name, &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# See ShellManager#mktempdir
|
53
|
+
def mktempdir(name=nil, &block)
|
54
|
+
_mktemp_helper(:mktempdir, name, &block)
|
55
|
+
end
|
56
|
+
|
57
|
+
# See ShellManager#mktempdircd
|
58
|
+
def mktempdircd(name=nil, &block)
|
59
|
+
_mktemp_helper(:mktempdircd, name, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
# See ShellManager#umask
|
63
|
+
def umask(mode=nil, &block)
|
64
|
+
if mode
|
65
|
+
old = File::umask
|
66
|
+
File::umask(mode)
|
67
|
+
if block
|
68
|
+
begin
|
69
|
+
block.call
|
70
|
+
rescue Exception => e
|
71
|
+
raise e
|
72
|
+
ensure
|
73
|
+
File::umask(old)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
else
|
77
|
+
File::umask
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#...[ FileUtils wrappers ]...............................................
|
82
|
+
|
83
|
+
# See ShellManager#cd
|
84
|
+
def cd(dir, opts={}, &block)
|
85
|
+
if block
|
86
|
+
log.enqueue(:info, PEXEC+(block ? "pushd" : "cd")+" "+dir)
|
87
|
+
begin
|
88
|
+
if writing? or File.directory?(dir)
|
89
|
+
FileUtils.cd(dir, &block)
|
90
|
+
else
|
91
|
+
begin
|
92
|
+
block.call(true)
|
93
|
+
rescue Exception => e
|
94
|
+
raise e
|
95
|
+
end
|
96
|
+
end
|
97
|
+
rescue Exception => e
|
98
|
+
raise e
|
99
|
+
ensure
|
100
|
+
log.dequeue(:info, PEXEC+"popd # => #{pwd}")
|
101
|
+
end
|
102
|
+
else
|
103
|
+
FileUtils.cd(dir) if writing?
|
104
|
+
end
|
105
|
+
return dir
|
106
|
+
end
|
107
|
+
|
108
|
+
# See ShellManager#pwd
|
109
|
+
def pwd()
|
110
|
+
return FileUtils.pwd()
|
111
|
+
end
|
112
|
+
|
113
|
+
# See ShellManager#mkdir
|
114
|
+
def mkdir(dirs, opts={}, &block)
|
115
|
+
_replace_owner_with_user(opts)
|
116
|
+
kind = opts[:parents] ? :mkdir_p : :mkdir
|
117
|
+
missing = [dirs].flatten.select{|dir| ! File.directory?(dir)}
|
118
|
+
result = false
|
119
|
+
if missing.empty? and not block
|
120
|
+
chperm(opts) if opts[:user] or opts[:group] or opts[:mode]
|
121
|
+
return result
|
122
|
+
end
|
123
|
+
unless missing.empty?
|
124
|
+
cmd = kind.to_s.gsub(/_/, ' -')
|
125
|
+
log.info(PEXEC+"#{cmd} #{missing.join(" ")}")
|
126
|
+
result = [FileUtils.send(kind, missing, _fileutils_opts)].flatten
|
127
|
+
end
|
128
|
+
if block
|
129
|
+
if missing.size > 1
|
130
|
+
raise ArgumentError.new(
|
131
|
+
"can only use a block if you mkdir a single directory")
|
132
|
+
end
|
133
|
+
dir = [dirs].flatten.first
|
134
|
+
cd(dir) do
|
135
|
+
block.call(result)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
chperm(opts) if opts[:user] or opts[:group] or opts[:mode]
|
139
|
+
return missing
|
140
|
+
end
|
141
|
+
|
142
|
+
# See ShellManager#mkdir_p
|
143
|
+
def mkdir_p(dirs, opts={}, &block)
|
144
|
+
mkdir(dirs, {:parents => true}.merge(opts), &block)
|
145
|
+
end
|
146
|
+
|
147
|
+
# See ShellManager#rmdir
|
148
|
+
def rmdir(dirs)
|
149
|
+
present = [dirs].flatten.select{|dir| File.directory?(dir)}
|
150
|
+
return false if present.empty?
|
151
|
+
log.info(PEXEC+"rmdir #{String === dirs ? dirs : dirs.join(' ')}")
|
152
|
+
FileUtils.rmdir(present, _fileutils_opts)
|
153
|
+
return present
|
154
|
+
end
|
155
|
+
|
156
|
+
# See ShellManager#install
|
157
|
+
def install(source, target, mode=nil)
|
158
|
+
cp_rv = nil
|
159
|
+
chmod_rv = nil
|
160
|
+
log.silence(Logger::WARN) do
|
161
|
+
cp_rv = cp(source, target)
|
162
|
+
chmod_rv = chmod(mode, target) if mode
|
163
|
+
end
|
164
|
+
|
165
|
+
return false unless cp_rv or chmod_rv
|
166
|
+
|
167
|
+
log.info(PEXEC+"install%s %s %s" %
|
168
|
+
[mode ? ' -m 0%o' % mode : '', source, target])
|
169
|
+
return source
|
170
|
+
end
|
171
|
+
|
172
|
+
# See ShellManager#cp
|
173
|
+
def cp(sources, target, opts={})
|
174
|
+
# TODO ShellManager::Portable#cp -- rather funky, needs a code review
|
175
|
+
fu_opts = _fileutils_opts
|
176
|
+
for opt in [:noop, :verbose]
|
177
|
+
opt = opt.to_sym
|
178
|
+
fu_opts[opt] = opts[opt] if opts[opt]
|
179
|
+
end
|
180
|
+
#fu_opts[:verbose] = true
|
181
|
+
fu_opts_with_preserve = {:preserve => opts[:preserve]}.merge(fu_opts)
|
182
|
+
|
183
|
+
changed = []
|
184
|
+
sources_a = [sources].flatten
|
185
|
+
sources_a.each do |parent|
|
186
|
+
Find.find(parent) do |child|
|
187
|
+
source_fn = File.directory?(child) ? child+"/" : child
|
188
|
+
target_dir = File.directory?(target)
|
189
|
+
target_fn = \
|
190
|
+
if target_dir
|
191
|
+
#File.join(target, source_fn.match(/#{parent}\/?(.*)$/)[1])
|
192
|
+
File.join(target, source_fn)
|
193
|
+
else
|
194
|
+
target
|
195
|
+
end
|
196
|
+
log.debug(PNOTE+"comparing %s => %s" % [source_fn, target_fn])
|
197
|
+
source_st = File.stat(source_fn)
|
198
|
+
is_copy = false
|
199
|
+
begin
|
200
|
+
begin
|
201
|
+
target_st = File.stat(target_fn)
|
202
|
+
|
203
|
+
unless target_dir
|
204
|
+
# Is the file obviously different?
|
205
|
+
if source_st.file?
|
206
|
+
for kind in %w(size mtime)
|
207
|
+
next if kind == "mtime" and ! opts[:preserve]
|
208
|
+
unless source_st.send(kind) == target_st.send(kind)
|
209
|
+
log.debug(PNOTE+"%s not same %s" % [target_fn, kind])
|
210
|
+
raise EOFError.new
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
unless FileUtils.identical?(source_fn, target_fn)
|
215
|
+
log.debug(PNOTE+"%s not identical" % target_fn)
|
216
|
+
raise EOFError.new
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# File just needs to be altered
|
221
|
+
if opts[:preserve]
|
222
|
+
unless source_st.mode == target_st.mode
|
223
|
+
changed << child
|
224
|
+
log.debug(PNOTE+"%s not same mode" % target_fn)
|
225
|
+
chmod(source_st.mode, target_fn, fu_opts)
|
226
|
+
end
|
227
|
+
unless source_st.uid == target_st.uid and source_st.gid == target_st.gid
|
228
|
+
changed << child
|
229
|
+
log.debug(PNOTE+"%s not same uid/gid" % target_fn)
|
230
|
+
chown(source_st.uid, source_st.gid, target_fn, fu_opts)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
rescue EOFError
|
235
|
+
changed << child
|
236
|
+
is_copy = true
|
237
|
+
end
|
238
|
+
rescue Errno::ENOENT
|
239
|
+
changed << child
|
240
|
+
log.debug(PNOTE+"%s not present" % target_fn)
|
241
|
+
is_copy = true
|
242
|
+
end
|
243
|
+
if is_copy
|
244
|
+
log.info(PEXEC+"cp%s %s %s" % [opts[:recursive] ? ' -r' : '', source_fn, target_fn])
|
245
|
+
## puts "fo %s" % fu_opts.inspect
|
246
|
+
## puts "fowp %s" % fu_opts_with_preserve.inspect
|
247
|
+
FileUtils.cp_r(source_fn, target_fn, fu_opts_with_preserve)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
result = \
|
253
|
+
if changed.empty?
|
254
|
+
false
|
255
|
+
else
|
256
|
+
if sources_a.size == 1
|
257
|
+
changed.first
|
258
|
+
else
|
259
|
+
changed.uniq
|
260
|
+
end
|
261
|
+
end
|
262
|
+
return result
|
263
|
+
end
|
264
|
+
|
265
|
+
# See ShellManager#cp_r
|
266
|
+
def cp_r(sources, target, opts={})
|
267
|
+
cp(sources, target, {:recursive => true}.merge(opts))
|
268
|
+
end
|
269
|
+
|
270
|
+
# See ShellManager#cp_R
|
271
|
+
def cp_R(*args)
|
272
|
+
cp_r(*args)
|
273
|
+
end
|
274
|
+
|
275
|
+
# See ShellManager#mv
|
276
|
+
def mv(sources, target)
|
277
|
+
present = [sources].flatten.select{|entry| File.exists?(entry)}
|
278
|
+
return false if present.empty?
|
279
|
+
present = present.first if present.size == 1
|
280
|
+
FileUtils.mv(present, target, _fileutils_opts) && present
|
281
|
+
return present
|
282
|
+
end
|
283
|
+
|
284
|
+
# See ShellManager#rm
|
285
|
+
def rm(targets, opts={})
|
286
|
+
kind = \
|
287
|
+
if opts[:recursive] and opts[:force]
|
288
|
+
:rm_rf
|
289
|
+
elsif opts[:recursive]
|
290
|
+
:rm_r
|
291
|
+
else
|
292
|
+
:rm
|
293
|
+
end
|
294
|
+
present = [targets].flatten.select{|entry| File.exists?(entry)}
|
295
|
+
return false if present.empty?
|
296
|
+
present = present.first if present.size == 0
|
297
|
+
log.info(PEXEC+"#{kind} #{String === present ? present : present.join(' ')}")
|
298
|
+
FileUtils.send(kind, present, _fileutils_opts)
|
299
|
+
return present
|
300
|
+
end
|
301
|
+
|
302
|
+
# See ShellManager#rm_r
|
303
|
+
def rm_r(targets, opts={})
|
304
|
+
rm(targets, {:recursive => true}.merge(opts))
|
305
|
+
end
|
306
|
+
|
307
|
+
# See ShellManager#rm_rf
|
308
|
+
def rm_rf(targets, opts={})
|
309
|
+
rm(targets, {:recursive => true, :force => true}.merge(opts))
|
310
|
+
end
|
311
|
+
|
312
|
+
FILE_MASK = 0100000
|
313
|
+
DIRECTORY_MASK = 040000
|
314
|
+
|
315
|
+
# See ShellManager#chperm
|
316
|
+
def chperm(targets, opts={})
|
317
|
+
_replace_owner_with_user(opts)
|
318
|
+
user = \
|
319
|
+
if opts[:user]
|
320
|
+
opts[:user] = opts[:user].to_s if opts[:user].is_a?(Symbol)
|
321
|
+
if opts[:user].is_a?(String)
|
322
|
+
begin
|
323
|
+
Etc.getpwnam(opts[:user]).uid
|
324
|
+
rescue ArgumentError
|
325
|
+
:not_present
|
326
|
+
end
|
327
|
+
else
|
328
|
+
opts[:user]
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
group = \
|
333
|
+
if opts[:group]
|
334
|
+
opts[:group] = opts[:group].to_s if opts[:group].is_a?(Symbol)
|
335
|
+
if opts[:group].is_a?(String)
|
336
|
+
begin
|
337
|
+
Etc.getgrnam(opts[:group]).gid
|
338
|
+
rescue ArgumentError
|
339
|
+
:not_present
|
340
|
+
end
|
341
|
+
else
|
342
|
+
opts[:group]
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
modified_entries = []
|
347
|
+
Find.find(*targets) do |path|
|
348
|
+
modified = false
|
349
|
+
stat = writing? || File.exists?(path) ? File.stat(path) : nil
|
350
|
+
if opts[:mode]
|
351
|
+
# TODO ShellManager::Portable#chperm -- process chmod symbolic strings, e.g., [ugoa...][[+-=][rwxXstugo...]...][,...]
|
352
|
+
mode = opts[:mode] | (stat.directory? ? DIRECTORY_MASK : FILE_MASK) if stat
|
353
|
+
unless stat and (mode ^ stat.mode).zero?
|
354
|
+
modified = true
|
355
|
+
File.chmod(mode, path) if writing?
|
356
|
+
end
|
357
|
+
end
|
358
|
+
if user and (not stat or user != stat.uid)
|
359
|
+
modified = true
|
360
|
+
File.chown(user, nil, path) if writing?
|
361
|
+
end
|
362
|
+
if group and (not stat or group != stat.gid)
|
363
|
+
modified = true
|
364
|
+
File.chown(nil, group, path) if writing?
|
365
|
+
end
|
366
|
+
modified_entries << path if modified
|
367
|
+
Find.prune if not opts[:recursive] and File.directory?(path)
|
368
|
+
end
|
369
|
+
|
370
|
+
return false if modified_entries.empty?
|
371
|
+
|
372
|
+
display_entries = opts[:details] ? modified_entries : targets
|
373
|
+
display_entries = [display_entries].flatten
|
374
|
+
|
375
|
+
if opts[:mode]
|
376
|
+
msg = "chmod"
|
377
|
+
msg << " -R" if opts[:recursive]
|
378
|
+
msg << " 0%o" % opts[:mode] if opts[:mode]
|
379
|
+
msg << " " << display_entries.join(' ')
|
380
|
+
log.info(PEXEC+msg)
|
381
|
+
end
|
382
|
+
if opts[:user] or opts[:group]
|
383
|
+
msg = "chown"
|
384
|
+
msg << " -R" if opts[:recursive]
|
385
|
+
msg << " %s" % opts[:user] if opts[:user]
|
386
|
+
msg << ":" if opts[:user] and opts[:group]
|
387
|
+
msg << " " unless opts[:user] and opts[:group]
|
388
|
+
msg << "%s" % opts[:group] if opts[:group]
|
389
|
+
msg << " " << display_entries.join(' ')
|
390
|
+
log.info(PEXEC+msg)
|
391
|
+
end
|
392
|
+
return targets.is_a?(String) ? modified_entries.first : modified_entries
|
393
|
+
end
|
394
|
+
|
395
|
+
# See ShellManager#chmod
|
396
|
+
def chmod(mode, targets, opts={})
|
397
|
+
chperm(targets, {:mode => mode}.merge(opts))
|
398
|
+
end
|
399
|
+
|
400
|
+
# See ShellManager#chmod_R
|
401
|
+
def chmod_R(mode, targets, opts={})
|
402
|
+
chmod(mode, targets, {:recursive => true}.merge(opts))
|
403
|
+
end
|
404
|
+
|
405
|
+
# See ShellManager#chown
|
406
|
+
def chown(user, group, targets, opts={})
|
407
|
+
chperm(targets, {:user => user, :group => group}.merge(opts))
|
408
|
+
end
|
409
|
+
|
410
|
+
# See ShellManager#chown_R
|
411
|
+
def chown_R(user, group, targets, opts={})
|
412
|
+
chown(user, group, targets, {:recursive => true}.merge(opts))
|
413
|
+
end
|
414
|
+
|
415
|
+
# See ShellManager#touch
|
416
|
+
def touch(targets)
|
417
|
+
log.info(PEXEC+"touch #{String === targets ? targets : targets.join(' ')}")
|
418
|
+
FileUtils.touch(targets, _fileutils_opts)
|
419
|
+
return targets
|
420
|
+
end
|
421
|
+
end
|