* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / un.rb
blob3dcdbede4aa8f4d79b6401ba36fdcde3a92d8cb4
1
2 # = un.rb
3
4 # Copyright (c) 2003 WATANABE Hirofumi <eban@ruby-lang.org>
5
6 # This program is free software.
7 # You can distribute/modify this program under the same terms of Ruby.
8
9 # == Utilities to replace common UNIX commands in Makefiles etc
11 # == SYNOPSIS
13 #   ruby -run -e cp -- [OPTION] SOURCE DEST
14 #   ruby -run -e ln -- [OPTION] TARGET LINK_NAME
15 #   ruby -run -e mv -- [OPTION] SOURCE DEST
16 #   ruby -run -e rm -- [OPTION] FILE
17 #   ruby -run -e mkdir -- [OPTION] DIRS
18 #   ruby -run -e rmdir -- [OPTION] DIRS
19 #   ruby -run -e install -- [OPTION] SOURCE DEST
20 #   ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE
21 #   ruby -run -e touch -- [OPTION] FILE
22 #   ruby -run -e wait_writable -- [OPTION] FILE
23 #   ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
24 #   ruby -run -e help [COMMAND]
26 require "fileutils"
27 require "optparse"
29 module FileUtils
30 #  @fileutils_label = ""
31   @fileutils_output = $stdout
32 end
34 def setup(options = "", *long_options)
35   opt_hash = {}
36   argv = []
37   OptionParser.new do |o|
38     options.scan(/.:?/) do |s|
39       opt_name = s.delete(":").intern
40       o.on("-" + s.tr(":", " ")) do |val|
41         opt_hash[opt_name] = val
42       end
43     end
44     long_options.each do |s|
45       opt_name = s[/\A(?:--)?([^\s=]+)/, 1].intern
46       o.on(s.sub(/\A(?!--)/, '--')) do |val|
47         opt_hash[opt_name] = val
48       end
49     end
50     o.on("-v") do opt_hash[:verbose] = true end
51     o.order!(ARGV) do |x|
52       if /[*?\[{]/ =~ x
53         argv.concat(Dir[x])
54       else
55         argv << x
56       end
57     end
58   end
59   yield argv, opt_hash
60 end
63 # Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY
65 #   ruby -run -e cp -- [OPTION] SOURCE DEST
67 #   -p          preserve file attributes if possible
68 #   -r          copy recursively
69 #   -v          verbose
72 def cp
73   setup("pr") do |argv, options|
74     cmd = "cp"
75     cmd += "_r" if options.delete :r
76     options[:preserve] = true if options.delete :p
77     dest = argv.pop
78     argv = argv[0] if argv.size == 1
79     FileUtils.send cmd, argv, dest, options
80   end
81 end
84 # Create a link to the specified TARGET with LINK_NAME.
86 #   ruby -run -e ln -- [OPTION] TARGET LINK_NAME
88 #   -s          make symbolic links instead of hard links
89 #   -f          remove existing destination files
90 #   -v          verbose
93 def ln
94   setup("sf") do |argv, options|
95     cmd = "ln"
96     cmd += "_s" if options.delete :s
97     options[:force] = true if options.delete :f
98     dest = argv.pop
99     argv = argv[0] if argv.size == 1
100     FileUtils.send cmd, argv, dest, options
101   end
105 # Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
107 #   ruby -run -e mv -- [OPTION] SOURCE DEST
109 #   -v          verbose
112 def mv
113   setup do |argv, options|
114     dest = argv.pop
115     argv = argv[0] if argv.size == 1
116     FileUtils.mv argv, dest, options
117   end
121 # Remove the FILE
123 #   ruby -run -e rm -- [OPTION] FILE
125 #   -f          ignore nonexistent files
126 #   -r          remove the contents of directories recursively
127 #   -v          verbose
130 def rm
131   setup("fr") do |argv, options|
132     cmd = "rm"
133     cmd += "_r" if options.delete :r
134     options[:force] = true if options.delete :f
135     FileUtils.send cmd, argv, options
136   end
140 # Create the DIR, if they do not already exist.
142 #   ruby -run -e mkdir -- [OPTION] DIR
144 #   -p          no error if existing, make parent directories as needed
145 #   -v          verbose
148 def mkdir
149   setup("p") do |argv, options|
150     cmd = "mkdir"
151     cmd += "_p" if options.delete :p
152     FileUtils.send cmd, argv, options
153   end
157 # Remove the DIR.
159 #   ruby -run -e rmdir -- [OPTION] DIR
161 #   -v          verbose
164 def rmdir
165   setup do |argv, options|
166     FileUtils.rmdir argv, options
167   end
171 # Copy SOURCE to DEST.
173 #   ruby -run -e install -- [OPTION] SOURCE DEST
175 #   -p          apply access/modification times of SOURCE files to
176 #               corresponding destination files
177 #   -m          set permission mode (as in chmod), instead of 0755
178 #   -v          verbose
181 def install
182   setup("pm:") do |argv, options|
183     options[:mode] = (mode = options.delete :m) ? mode.oct : 0755
184     options[:preserve] = true if options.delete :p
185     dest = argv.pop
186     argv = argv[0] if argv.size == 1
187     FileUtils.install argv, dest, options
188   end
192 # Change the mode of each FILE to OCTAL-MODE.
194 #   ruby -run -e chmod -- [OPTION] OCTAL-MODE FILE
196 #   -v          verbose
199 def chmod
200   setup do |argv, options|
201     mode = argv.shift.oct
202     FileUtils.chmod mode, argv, options
203   end
207 # Update the access and modification times of each FILE to the current time.
209 #   ruby -run -e touch -- [OPTION] FILE
211 #   -v          verbose
214 def touch
215   setup do |argv, options|
216     FileUtils.touch argv, options
217   end
221 # Wait until the file becomes writable.
223 #   ruby -run -e wait_writable -- [OPTION] FILE
225 #   -n RETRY    count to retry
226 #   -w SEC      each wait time in seconds
227 #   -v          verbose
230 def wait_writable
231   setup("n:w:v") do |argv, options|
232     verbose = options[:verbose]
233     n = options[:n] and n = Integer(n)
234     wait = (wait = options[:w]) ? Float(wait) : 0.2
235     argv.each do |file|
236       begin
237         open(file, "r+b")
238       rescue Errno::ENOENT
239         break
240       rescue Errno::EACCES => e
241         raise if n and (n -= 1) <= 0
242         puts e
243         STDOUT.flush
244         sleep wait
245         retry
246       end
247     end
248   end
252 # Create makefile using mkmf.
254 #   ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
256 #   -d ARGS     run dir_config
257 #   -h ARGS     run have_header
258 #   -l ARGS     run have_library
259 #   -f ARGS     run have_func
260 #   -v ARGS     run have_var
261 #   -t ARGS     run have_type
262 #   -m ARGS     run have_macro
263 #   -c ARGS     run have_const
264 #   --vendor    install to vendor_ruby
267 def mkmf
268   setup("d:h:l:f:v:t:m:c:", "vendor") do |argv, options|
269     require 'mkmf'
270     opt = options[:d] and opt.split(/:/).each {|n| dir_config(*n.split(/,/))}
271     opt = options[:h] and opt.split(/:/).each {|n| have_header(*n.split(/,/))}
272     opt = options[:l] and opt.split(/:/).each {|n| have_library(*n.split(/,/))}
273     opt = options[:f] and opt.split(/:/).each {|n| have_func(*n.split(/,/))}
274     opt = options[:v] and opt.split(/:/).each {|n| have_var(*n.split(/,/))}
275     opt = options[:t] and opt.split(/:/).each {|n| have_type(*n.split(/,/))}
276     opt = options[:m] and opt.split(/:/).each {|n| have_macro(*n.split(/,/))}
277     opt = options[:c] and opt.split(/:/).each {|n| have_const(*n.split(/,/))}
278     $configure_args["--vendor"] = true if options[:vendor]
279     create_makefile(*argv)
280   end
284 # Display help message.
286 #   ruby -run -e help [COMMAND]
289 def help
290   setup do |argv,|
291     all = argv.empty?
292     open(__FILE__) do |me|
293       while me.gets("##\n")
294         if help = me.gets("\n\n")
295           if all or argv.delete help[/-e \w+/].sub(/-e /, "")
296             print help.gsub(/^# ?/, "")
297           end
298         end
299       end
300     end
301   end