1require 'rake/file_utils'
2
3module Rake
4  #
5  # FileUtilsExt provides a custom version of the FileUtils methods
6  # that respond to the <tt>verbose</tt> and <tt>nowrite</tt>
7  # commands.
8  #
9  module FileUtilsExt
10    include FileUtils
11
12    class << self
13      attr_accessor :verbose_flag, :nowrite_flag
14    end
15
16    DEFAULT = Object.new
17
18    FileUtilsExt.verbose_flag = DEFAULT
19    FileUtilsExt.nowrite_flag = false
20
21    $fileutils_verbose = true
22    $fileutils_nowrite = false
23
24    FileUtils.commands.each do |name|
25      opts = FileUtils.options_of name
26      default_options = []
27      if opts.include?("verbose")
28        default_options << ':verbose => FileUtilsExt.verbose_flag'
29      end
30      if opts.include?("noop")
31        default_options << ':noop => FileUtilsExt.nowrite_flag'
32      end
33
34      next if default_options.empty?
35      module_eval(<<-EOS, __FILE__, __LINE__ + 1)
36      def #{name}( *args, &block )
37        super(
38          *rake_merge_option(args,
39            #{default_options.join(', ')}
40            ), &block)
41      end
42      EOS
43    end
44
45    # Get/set the verbose flag controlling output from the FileUtils
46    # utilities.  If verbose is true, then the utility method is
47    # echoed to standard output.
48    #
49    # Examples:
50    #    verbose              # return the current value of the
51    #                         # verbose flag
52    #    verbose(v)           # set the verbose flag to _v_.
53    #    verbose(v) { code }  # Execute code with the verbose flag set
54    #                         # temporarily to _v_.  Return to the
55    #                         # original value when code is done.
56    def verbose(value=nil)
57      oldvalue = FileUtilsExt.verbose_flag
58      FileUtilsExt.verbose_flag = value unless value.nil?
59      if block_given?
60        begin
61          yield
62        ensure
63          FileUtilsExt.verbose_flag = oldvalue
64        end
65      end
66      FileUtilsExt.verbose_flag
67    end
68
69    # Get/set the nowrite flag controlling output from the FileUtils
70    # utilities.  If verbose is true, then the utility method is
71    # echoed to standard output.
72    #
73    # Examples:
74    #    nowrite              # return the current value of the
75    #                         # nowrite flag
76    #    nowrite(v)           # set the nowrite flag to _v_.
77    #    nowrite(v) { code }  # Execute code with the nowrite flag set
78    #                         # temporarily to _v_. Return to the
79    #                         # original value when code is done.
80    def nowrite(value=nil)
81      oldvalue = FileUtilsExt.nowrite_flag
82      FileUtilsExt.nowrite_flag = value unless value.nil?
83      if block_given?
84        begin
85          yield
86        ensure
87          FileUtilsExt.nowrite_flag = oldvalue
88        end
89      end
90      oldvalue
91    end
92
93    # Use this function to prevent potentially destructive ruby code
94    # from running when the :nowrite flag is set.
95    #
96    # Example:
97    #
98    #   when_writing("Building Project") do
99    #     project.build
100    #   end
101    #
102    # The following code will build the project under normal
103    # conditions. If the nowrite(true) flag is set, then the example
104    # will print:
105    #
106    #      DRYRUN: Building Project
107    #
108    # instead of actually building the project.
109    #
110    def when_writing(msg=nil)
111      if FileUtilsExt.nowrite_flag
112        $stderr.puts "DRYRUN: #{msg}" if msg
113      else
114        yield
115      end
116    end
117
118    # Merge the given options with the default values.
119    def rake_merge_option(args, defaults)
120      if Hash === args.last
121        defaults.update(args.last)
122        args.pop
123      end
124      args.push defaults
125      args
126    end
127
128    # Send the message to the default rake output (which is $stderr).
129    def rake_output_message(message)
130      $stderr.puts(message)
131    end
132
133    # Check that the options do not contain options not listed in
134    # +optdecl+.  An ArgumentError exception is thrown if non-declared
135    # options are found.
136    def rake_check_options(options, *optdecl)
137      h = options.dup
138      optdecl.each do |name|
139        h.delete name
140      end
141      raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
142    end
143
144    extend self
145  end
146end
147