elliottcable-echoe 3.1.2 → 3.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/CHANGELOG +3 -1
  2. data/Manifest +1 -93
  3. data/Rakefile +1 -2
  4. data/echoe.gemspec +7 -7
  5. data/lib/echoe.rb +50 -22
  6. data/lib/echoe/net.rb +7 -0
  7. data/lib/echoe/platform.rb +27 -25
  8. data/vendor/rake/lib/rake/contrib/sshpublisher.rb +0 -4
  9. metadata +7 -96
  10. data/vendor/rake/CHANGES +0 -400
  11. data/vendor/rake/README +0 -285
  12. data/vendor/rake/Rakefile +0 -418
  13. data/vendor/rake/TODO +0 -20
  14. data/vendor/rake/bin/rake +0 -31
  15. data/vendor/rake/doc/example/Rakefile1 +0 -38
  16. data/vendor/rake/doc/example/Rakefile2 +0 -35
  17. data/vendor/rake/doc/example/a.c +0 -6
  18. data/vendor/rake/doc/example/b.c +0 -6
  19. data/vendor/rake/doc/example/main.c +0 -11
  20. data/vendor/rake/doc/glossary.rdoc +0 -51
  21. data/vendor/rake/doc/jamis.rb +0 -591
  22. data/vendor/rake/doc/proto_rake.rdoc +0 -127
  23. data/vendor/rake/doc/rake.1.gz +0 -0
  24. data/vendor/rake/doc/rakefile.rdoc +0 -534
  25. data/vendor/rake/doc/rational.rdoc +0 -151
  26. data/vendor/rake/doc/release_notes/rake-0.4.14.rdoc +0 -23
  27. data/vendor/rake/doc/release_notes/rake-0.4.15.rdoc +0 -35
  28. data/vendor/rake/doc/release_notes/rake-0.5.0.rdoc +0 -53
  29. data/vendor/rake/doc/release_notes/rake-0.5.3.rdoc +0 -78
  30. data/vendor/rake/doc/release_notes/rake-0.5.4.rdoc +0 -46
  31. data/vendor/rake/doc/release_notes/rake-0.6.0.rdoc +0 -141
  32. data/vendor/rake/doc/release_notes/rake-0.7.0.rdoc +0 -119
  33. data/vendor/rake/doc/release_notes/rake-0.7.1.rdoc +0 -59
  34. data/vendor/rake/doc/release_notes/rake-0.7.2.rdoc +0 -121
  35. data/vendor/rake/doc/release_notes/rake-0.7.3.rdoc +0 -47
  36. data/vendor/rake/doc/release_notes/rake-0.8.0.rdoc +0 -114
  37. data/vendor/rake/doc/release_notes/rake-0.8.2.rdoc +0 -165
  38. data/vendor/rake/doc/release_notes/rake-0.8.3.rdoc +0 -112
  39. data/vendor/rake/install.rb +0 -88
  40. data/vendor/rake/lib/rake.rb +0 -2468
  41. data/vendor/rake/lib/rake/classic_namespace.rb +0 -8
  42. data/vendor/rake/lib/rake/clean.rb +0 -33
  43. data/vendor/rake/lib/rake/gempackagetask.rb +0 -103
  44. data/vendor/rake/lib/rake/loaders/makefile.rb +0 -35
  45. data/vendor/rake/lib/rake/packagetask.rb +0 -185
  46. data/vendor/rake/lib/rake/rake_test_loader.rb +0 -5
  47. data/vendor/rake/lib/rake/rdoctask.rb +0 -147
  48. data/vendor/rake/lib/rake/ruby182_test_unit_fix.rb +0 -23
  49. data/vendor/rake/lib/rake/runtest.rb +0 -23
  50. data/vendor/rake/lib/rake/tasklib.rb +0 -23
  51. data/vendor/rake/lib/rake/testtask.rb +0 -161
  52. data/vendor/rake/lib/rake/win32.rb +0 -54
  53. data/vendor/rake/test/capture_stdout.rb +0 -26
  54. data/vendor/rake/test/check_expansion.rb +0 -5
  55. data/vendor/rake/test/contrib/test_sys.rb +0 -47
  56. data/vendor/rake/test/data/chains/Rakefile +0 -15
  57. data/vendor/rake/test/data/default/Rakefile +0 -19
  58. data/vendor/rake/test/data/dryrun/Rakefile +0 -22
  59. data/vendor/rake/test/data/file_creation_task/Rakefile +0 -33
  60. data/vendor/rake/test/data/imports/Rakefile +0 -19
  61. data/vendor/rake/test/data/imports/deps.mf +0 -1
  62. data/vendor/rake/test/data/multidesc/Rakefile +0 -17
  63. data/vendor/rake/test/data/namespace/Rakefile +0 -57
  64. data/vendor/rake/test/data/rakelib/test1.rb +0 -3
  65. data/vendor/rake/test/data/rbext/rakefile.rb +0 -3
  66. data/vendor/rake/test/data/sample.mf +0 -12
  67. data/vendor/rake/test/data/statusreturn/Rakefile +0 -8
  68. data/vendor/rake/test/data/unittest/Rakefile +0 -1
  69. data/vendor/rake/test/filecreation.rb +0 -32
  70. data/vendor/rake/test/functional.rb +0 -15
  71. data/vendor/rake/test/in_environment.rb +0 -30
  72. data/vendor/rake/test/rake_test_setup.rb +0 -10
  73. data/vendor/rake/test/reqfile.rb +0 -3
  74. data/vendor/rake/test/reqfile2.rb +0 -3
  75. data/vendor/rake/test/session_functional.rb +0 -337
  76. data/vendor/rake/test/shellcommand.rb +0 -3
  77. data/vendor/rake/test/test_application.rb +0 -694
  78. data/vendor/rake/test/test_clean.rb +0 -14
  79. data/vendor/rake/test/test_definitions.rb +0 -82
  80. data/vendor/rake/test/test_earlytime.rb +0 -35
  81. data/vendor/rake/test/test_extension.rb +0 -63
  82. data/vendor/rake/test/test_file_creation_task.rb +0 -62
  83. data/vendor/rake/test/test_file_task.rb +0 -139
  84. data/vendor/rake/test/test_filelist.rb +0 -618
  85. data/vendor/rake/test/test_fileutils.rb +0 -250
  86. data/vendor/rake/test/test_ftp.rb +0 -59
  87. data/vendor/rake/test/test_invocation_chain.rb +0 -75
  88. data/vendor/rake/test/test_makefile_loader.rb +0 -25
  89. data/vendor/rake/test/test_multitask.rb +0 -45
  90. data/vendor/rake/test/test_namespace.rb +0 -36
  91. data/vendor/rake/test/test_package_task.rb +0 -116
  92. data/vendor/rake/test/test_pathmap.rb +0 -209
  93. data/vendor/rake/test/test_rake.rb +0 -41
  94. data/vendor/rake/test/test_require.rb +0 -33
  95. data/vendor/rake/test/test_rules.rb +0 -347
  96. data/vendor/rake/test/test_task_arguments.rb +0 -89
  97. data/vendor/rake/test/test_task_manager.rb +0 -170
  98. data/vendor/rake/test/test_tasklib.rb +0 -12
  99. data/vendor/rake/test/test_tasks.rb +0 -371
  100. data/vendor/rake/test/test_test_task.rb +0 -75
  101. data/vendor/rake/test/test_top_level_functions.rb +0 -84
  102. data/vendor/rake/test/test_win32.rb +0 -57
@@ -1,165 +0,0 @@
1
- = Rake 0.8.2 Released
2
-
3
- Rake version 0.8.2 is a new release of rake that includes a number of
4
- new features and numerous bug fixes.
5
-
6
- == Changes
7
-
8
- === New Features in Version 0.8.2
9
-
10
- * Switched from getoptlong to optparse (patches supplied by Edwin
11
- Pratomo).
12
-
13
- * The -T option will now attempt to dynamically sense the size of the
14
- terminal. The -T output will only self-truncate if the output is a
15
- tty. However, if RAKE_COLUMNS is explicitly set, it will be honored
16
- in any case. (Patch provided by Gavin Stark).
17
-
18
- * The following public methods have been added to rake task objects:
19
-
20
- * task.clear -- Clear both the prerequisites and actions of the
21
- target rake task.
22
- * task.clear_prerequisites -- Clear all the existing prerequisites
23
- from the target rake task.
24
- * task.clear_actions -- Clear all the existing actions from the
25
- target rake task.
26
- * task.reenable -- Re-enable a task, allowing its actions to be
27
- executed again if the task is invoked.
28
-
29
- * Changed RDoc test task to have no default template. This makes it
30
- easier for the tempate to pick up the template from the environment.
31
-
32
- * Default values for task arguments can easily be specified with the
33
- :with_defaults method. (Idea for default argument merging supplied
34
- by (Adam Q. Salter)
35
-
36
- === Bug Fixes in Version 0.8.2
37
-
38
- * Fixed bug in package task so that it will include the subdir
39
- directory in the package for testing. (Bug found by Adam Majer)
40
-
41
- * Fixed filename dependency order bug in test_inspect_pending and
42
- test_to_s_pending. (Bug found by Adam Majer)
43
-
44
- * Fixed check for file utils options to make them immune to the
45
- symbol/string differences. (Patch supplied by Edwin Pratomo)
46
-
47
- * Fixed bug with rules involving multiple source, where only the first
48
- dependency of a rule has any effect (Patch supplied by Emanuel
49
- Inderm�hle)
50
-
51
- * FileList#clone and FileList#dup have better sematics w.r.t. taint
52
- and freeze.
53
-
54
- * Changed from using Mutex to Monitor. Evidently Mutex causes thread
55
- join errors when Ruby is compiled with -disable-pthreads. (Patch
56
- supplied by Ittay Dror)
57
-
58
- * Fixed bug in makefile parser that had problems with extra spaces in
59
- file task names. (Patch supplied by Ittay Dror)
60
-
61
- == Other changes in Version 0.8.2
62
-
63
- * Added ENV var to rake's own Rakefile to prevent OS X from including
64
- extended attribute junk in the rake package tar file. (Bug found by
65
- Adam Majer)
66
-
67
- * Added a performance patch for reading large makefile dependency
68
- files. (Patch supplied by Ittay Dror)
69
-
70
- == What is Rake
71
-
72
- Rake is a build tool similar to the make program in many ways. But
73
- instead of cryptic make recipes, Rake uses standard Ruby code to
74
- declare tasks and dependencies. You have the full power of a modern
75
- scripting language built right into your build tool.
76
-
77
- == Availability
78
-
79
- The easiest way to get and install rake is via RubyGems ...
80
-
81
- gem install rake (you may need root/admin privileges)
82
-
83
- Otherwise, you can get it from the more traditional places:
84
-
85
- Home Page:: http://rake.rubyforge.org/
86
- Download:: http://rubyforge.org/project/showfiles.php?group_id=50
87
-
88
- == Task Argument Examples
89
-
90
- Prior to version 0.8.0, rake was only able to handle command line
91
- arguments of the form NAME=VALUE that were passed into Rake via the
92
- ENV hash. Many folks had asked for some kind of simple command line
93
- arguments, perhaps using "--" to separate regular task names from
94
- argument values on the command line. The problem is that there was no
95
- easy way to associate positional arguments on the command line with
96
- different tasks. Suppose both tasks :a and :b expect a command line
97
- argument: does the first value go with :a? What if :b is run first?
98
- Should it then get the first command line argument.
99
-
100
- Rake 0.8.0 solves this problem by explicitly passing values directly
101
- to the tasks that need them. For example, if I had a release task
102
- that required a version number, I could say:
103
-
104
- rake release[0.8.2]
105
-
106
- And the string "0.8.2" will be passed to the :release task. Multiple
107
- arguments can be passed by separating them with a comma, for example:
108
-
109
- rake name[john,doe]
110
-
111
- Just a few words of caution. The rake task name and its arguments
112
- need to be a single command line argument to rake. This generally
113
- means no spaces. If spaces are needed, then the entire rake +
114
- argument string should be quoted. Something like this:
115
-
116
- rake "name[billy bob, smith]"
117
-
118
- (Quoting rules vary between operating systems and shells, so make sure
119
- you consult the proper docs for your OS/shell).
120
-
121
- === Tasks that Expect Parameters
122
-
123
- Parameters are only given to tasks that are setup to expect them. In
124
- order to handle named parameters, the task declaration syntax for
125
- tasks has been extended slightly.
126
-
127
- For example, a task that needs a first name and last name might be
128
- declared as:
129
-
130
- task :name, :first_name, :last_name
131
-
132
- The first argument is still the name of the task (:name in this case).
133
- The next to argumements are the names of the parameters expected by
134
- :name (:first_name and :last_name in the example).
135
-
136
- To access the values of the paramters, the block defining the task
137
- behaviour can now accept a second parameter:
138
-
139
- task :name, :first_name, :last_name do |t, args|
140
- puts "First name is #{args.first_name}"
141
- puts "Last name is #{args.last_name}"
142
- end
143
-
144
- The first argument of the block "t" is always bound to the current
145
- task object. The second argument "args" is an open-struct like object
146
- that allows access to the task arguments. Extra command line
147
- arguments to a task are ignored. Missing command line arguments are
148
- given the nil value.
149
-
150
- == Thanks
151
-
152
- As usual, it was input from users that drove a alot of these changes. The
153
- following people either contributed patches, made suggestions or made
154
- otherwise helpful comments. Thanks to ...
155
-
156
- * Edwin Pratomo
157
- * Gavin Stark
158
- * Adam Q. Salter
159
- * Adam Majer
160
- * Emanuel Inderm�hle
161
- * Ittay Dror
162
- * Bheeshmar Redheendran (for spending an afternoon with me debugging
163
- windows issues)
164
-
165
- -- Jim Weirich
@@ -1,112 +0,0 @@
1
- = Rake 0.8.3 Released
2
-
3
- Rake version 0.8.3 is a bug-fix release of rake.
4
-
5
- == Changes
6
-
7
- === Bug Fixes in Version 0.8.3
8
-
9
- * Enhanced the system directory detection in windows. We now check
10
- HOMEDRIVE/HOMEPATH and USERPROFILE if APPDATA isn't found. (Patch
11
- supplied by James Tucker). Rake no long aborts if it can't find the
12
- directory.
13
-
14
- * Added fix to handle ruby installations in directories with spaces in
15
- their name.
16
-
17
- == What is Rake
18
-
19
- Rake is a build tool similar to the make program in many ways. But
20
- instead of cryptic make recipes, Rake uses standard Ruby code to
21
- declare tasks and dependencies. You have the full power of a modern
22
- scripting language built right into your build tool.
23
-
24
- == Availability
25
-
26
- The easiest way to get and install rake is via RubyGems ...
27
-
28
- gem install rake (you may need root/admin privileges)
29
-
30
- Otherwise, you can get it from the more traditional places:
31
-
32
- Home Page:: http://rake.rubyforge.org/
33
- Download:: http://rubyforge.org/project/showfiles.php?group_id=50
34
-
35
- == Task Argument Examples
36
-
37
- Prior to version 0.8.0, rake was only able to handle command line
38
- arguments of the form NAME=VALUE that were passed into Rake via the
39
- ENV hash. Many folks had asked for some kind of simple command line
40
- arguments, perhaps using "--" to separate regular task names from
41
- argument values on the command line. The problem is that there was no
42
- easy way to associate positional arguments on the command line with
43
- different tasks. Suppose both tasks :a and :b expect a command line
44
- argument: does the first value go with :a? What if :b is run first?
45
- Should it then get the first command line argument.
46
-
47
- Rake 0.8.0 solves this problem by explicitly passing values directly
48
- to the tasks that need them. For example, if I had a release task
49
- that required a version number, I could say:
50
-
51
- rake release[0.8.3]
52
-
53
- And the string "0.8.3" will be passed to the :release task. Multiple
54
- arguments can be passed by separating them with a comma, for example:
55
-
56
- rake name[john,doe]
57
-
58
- Just a few words of caution. The rake task name and its arguments
59
- need to be a single command line argument to rake. This generally
60
- means no spaces. If spaces are needed, then the entire rake +
61
- argument string should be quoted. Something like this:
62
-
63
- rake "name[billy bob, smith]"
64
-
65
- (Quoting rules vary between operating systems and shells, so make sure
66
- you consult the proper docs for your OS/shell).
67
-
68
- === Tasks that Expect Parameters
69
-
70
- Parameters are only given to tasks that are setup to expect them. In
71
- order to handle named parameters, the task declaration syntax for
72
- tasks has been extended slightly.
73
-
74
- For example, a task that needs a first name and last name might be
75
- declared as:
76
-
77
- task :name, :first_name, :last_name
78
-
79
- The first argument is still the name of the task (:name in this case).
80
- The next to argumements are the names of the parameters expected by
81
- :name (:first_name and :last_name in the example).
82
-
83
- To access the values of the paramters, the block defining the task
84
- behaviour can now accept a second parameter:
85
-
86
- task :name, :first_name, :last_name do |t, args|
87
- puts "First name is #{args.first_name}"
88
- puts "Last name is #{args.last_name}"
89
- end
90
-
91
- The first argument of the block "t" is always bound to the current
92
- task object. The second argument "args" is an open-struct like object
93
- that allows access to the task arguments. Extra command line
94
- arguments to a task are ignored. Missing command line arguments are
95
- given the nil value.
96
-
97
- == Thanks
98
-
99
- As usual, it was input from users that drove a alot of these changes. The
100
- following people either contributed patches, made suggestions or made
101
- otherwise helpful comments. Thanks to ...
102
-
103
- * Edwin Pratomo
104
- * Gavin Stark
105
- * Adam Q. Salter
106
- * Adam Majer
107
- * Emanuel Inderm�hle
108
- * Ittay Dror
109
- * Bheeshmar Redheendran (for spending an afternoon with me debugging
110
- windows issues)
111
-
112
- -- Jim Weirich
@@ -1,88 +0,0 @@
1
- require 'rbconfig'
2
- require 'find'
3
- require 'ftools'
4
-
5
- include Config
6
-
7
- $ruby = CONFIG['ruby_install_name']
8
-
9
- ##
10
- # Install a binary file. We patch in on the way through to
11
- # insert a #! line. If this is a Unix install, we name
12
- # the command (for example) 'rake' and let the shebang line
13
- # handle running it. Under windows, we add a '.rb' extension
14
- # and let file associations to their stuff
15
- #
16
-
17
- def installBIN(from, opfile)
18
-
19
- tmp_dir = nil
20
- for t in [".", "/tmp", "c:/temp", $bindir]
21
- stat = File.stat(t) rescue next
22
- if stat.directory? and stat.writable?
23
- tmp_dir = t
24
- break
25
- end
26
- end
27
-
28
- fail "Cannot find a temporary directory" unless tmp_dir
29
- tmp_file = File.join(tmp_dir, "_tmp")
30
-
31
- File.open(from) do |ip|
32
- File.open(tmp_file, "w") do |op|
33
- ruby = File.join($realbindir, $ruby)
34
- op.puts "#!#{ruby} -w"
35
- op.write ip.read
36
- end
37
- end
38
-
39
- opfile += ".rb" if CONFIG["target_os"] =~ /mswin/i
40
- File::install(tmp_file, File.join($bindir, opfile), 0755, true)
41
- File::unlink(tmp_file)
42
- end
43
-
44
- $sitedir = CONFIG["sitelibdir"]
45
- unless $sitedir
46
- version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
47
- $libdir = File.join(CONFIG["libdir"], "ruby", version)
48
- $sitedir = $:.find {|x| x =~ /site_ruby/}
49
- if !$sitedir
50
- $sitedir = File.join($libdir, "site_ruby")
51
- elsif $sitedir !~ Regexp.quote(version)
52
- $sitedir = File.join($sitedir, version)
53
- end
54
- end
55
-
56
- $bindir = CONFIG["bindir"]
57
-
58
- $realbindir = $bindir
59
-
60
- bindir = CONFIG["bindir"]
61
- if (destdir = ENV['DESTDIR'])
62
- $bindir = destdir + $bindir
63
- $sitedir = destdir + $sitedir
64
-
65
- File::makedirs($bindir)
66
- File::makedirs($sitedir)
67
- end
68
-
69
- rake_dest = File.join($sitedir, "rake")
70
- File::makedirs(rake_dest, true)
71
- File::chmod(0755, rake_dest)
72
-
73
- # The library files
74
-
75
- files = Dir.chdir('lib') { Dir['**/*.rb'] }
76
-
77
- for fn in files
78
- fn_dir = File.dirname(fn)
79
- target_dir = File.join($sitedir, fn_dir)
80
- if ! File.exist?(target_dir)
81
- File.makedirs(target_dir)
82
- end
83
- File::install(File.join('lib', fn), File.join($sitedir, fn), 0644, true)
84
- end
85
-
86
- # and the executable
87
-
88
- installBIN("bin/rake", "rake")
@@ -1,2468 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #--
4
-
5
- # Copyright (c) 2003, 2004, 2005, 2006, 2007 Jim Weirich
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the "Software"), to
9
- # deal in the Software without restriction, including without limitation the
10
- # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
- # sell copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in
15
- # all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
- # IN THE SOFTWARE.
24
- #++
25
- #
26
- # = Rake -- Ruby Make
27
- #
28
- # This is the main file for the Rake application. Normally it is referenced
29
- # as a library via a require statement, but it can be distributed
30
- # independently as an application.
31
-
32
- RAKEVERSION = '0.8.3'
33
-
34
- require 'rbconfig'
35
- require 'fileutils'
36
- require 'singleton'
37
- require 'monitor'
38
- require 'optparse'
39
- require 'ostruct'
40
-
41
- require 'rake/win32'
42
-
43
- ######################################################################
44
- # Rake extensions to Module.
45
- #
46
- class Module
47
- # Check for an existing method in the current class before extending. IF
48
- # the method already exists, then a warning is printed and the extension is
49
- # not added. Otherwise the block is yielded and any definitions in the
50
- # block will take effect.
51
- #
52
- # Usage:
53
- #
54
- # class String
55
- # rake_extension("xyz") do
56
- # def xyz
57
- # ...
58
- # end
59
- # end
60
- # end
61
- #
62
- def rake_extension(method)
63
- if instance_methods.include?(method.to_s) || instance_methods.include?(method.to_sym)
64
- $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
65
- else
66
- yield
67
- end
68
- end
69
- end # module Module
70
-
71
-
72
- ######################################################################
73
- # User defined methods to be added to String.
74
- #
75
- class String
76
- rake_extension("ext") do
77
- # Replace the file extension with +newext+. If there is no extenson on
78
- # the string, append the new extension to the end. If the new extension
79
- # is not given, or is the empty string, remove any existing extension.
80
- #
81
- # +ext+ is a user added method for the String class.
82
- def ext(newext='')
83
- return self.dup if ['.', '..'].include? self
84
- if newext != ''
85
- newext = (newext =~ /^\./) ? newext : ("." + newext)
86
- end
87
- dup.sub!(%r(([^/\\])\.[^./\\]*$)) { $1 + newext } || self + newext
88
- end
89
- end
90
-
91
- rake_extension("pathmap") do
92
- # Explode a path into individual components. Used by +pathmap+.
93
- def pathmap_explode
94
- head, tail = File.split(self)
95
- return [self] if head == self
96
- return [tail] if head == '.' || tail == '/'
97
- return [head, tail] if head == '/'
98
- return head.pathmap_explode + [tail]
99
- end
100
- protected :pathmap_explode
101
-
102
- # Extract a partial path from the path. Include +n+ directories from the
103
- # front end (left hand side) if +n+ is positive. Include |+n+|
104
- # directories from the back end (right hand side) if +n+ is negative.
105
- def pathmap_partial(n)
106
- dirs = File.dirname(self).pathmap_explode
107
- partial_dirs =
108
- if n > 0
109
- dirs[0...n]
110
- elsif n < 0
111
- dirs.reverse[0...-n].reverse
112
- else
113
- "."
114
- end
115
- File.join(partial_dirs)
116
- end
117
- protected :pathmap_partial
118
-
119
- # Preform the pathmap replacement operations on the given path. The
120
- # patterns take the form 'pat1,rep1;pat2,rep2...'.
121
- def pathmap_replace(patterns, &block)
122
- result = self
123
- patterns.split(';').each do |pair|
124
- pattern, replacement = pair.split(',')
125
- pattern = Regexp.new(pattern)
126
- if replacement == '*' && block_given?
127
- result = result.sub(pattern, &block)
128
- elsif replacement
129
- result = result.sub(pattern, replacement)
130
- else
131
- result = result.sub(pattern, '')
132
- end
133
- end
134
- result
135
- end
136
- protected :pathmap_replace
137
-
138
- # Map the path according to the given specification. The specification
139
- # controls the details of the mapping. The following special patterns are
140
- # recognized:
141
- #
142
- # * <b>%p</b> -- The complete path.
143
- # * <b>%f</b> -- The base file name of the path, with its file extension,
144
- # but without any directories.
145
- # * <b>%n</b> -- The file name of the path without its file extension.
146
- # * <b>%d</b> -- The directory list of the path.
147
- # * <b>%x</b> -- The file extension of the path. An empty string if there
148
- # is no extension.
149
- # * <b>%X</b> -- Everything *but* the file extension.
150
- # * <b>%s</b> -- The alternate file separater if defined, otherwise use
151
- # the standard file separator.
152
- # * <b>%%</b> -- A percent sign.
153
- #
154
- # The %d specifier can also have a numeric prefix (e.g. '%2d'). If the
155
- # number is positive, only return (up to) +n+ directories in the path,
156
- # starting from the left hand side. If +n+ is negative, return (up to)
157
- # |+n+| directories from the right hand side of the path.
158
- #
159
- # Examples:
160
- #
161
- # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
162
- # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
163
- #
164
- # Also the %d, %p, $f, $n, %x, and %X operators can take a
165
- # pattern/replacement argument to perform simple string substititions on a
166
- # particular part of the path. The pattern and replacement are speparated
167
- # by a comma and are enclosed by curly braces. The replacement spec comes
168
- # after the % character but before the operator letter. (e.g.
169
- # "%{old,new}d"). Muliple replacement specs should be separated by
170
- # semi-colons (e.g. "%{old,new;src,bin}d").
171
- #
172
- # Regular expressions may be used for the pattern, and back refs may be
173
- # used in the replacement text. Curly braces, commas and semi-colons are
174
- # excluded from both the pattern and replacement text (let's keep parsing
175
- # reasonable).
176
- #
177
- # For example:
178
- #
179
- # "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class")
180
- #
181
- # returns:
182
- #
183
- # "bin/org/onestepback/proj/A.class"
184
- #
185
- # If the replacement text is '*', then a block may be provided to perform
186
- # some arbitrary calculation for the replacement.
187
- #
188
- # For example:
189
- #
190
- # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
191
- # ext.downcase
192
- # }
193
- #
194
- # Returns:
195
- #
196
- # "/path/to/file.txt"
197
- #
198
- def pathmap(spec=nil, &block)
199
- return self if spec.nil?
200
- result = ''
201
- spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
202
- case frag
203
- when '%f'
204
- result << File.basename(self)
205
- when '%n'
206
- result << File.basename(self).ext
207
- when '%d'
208
- result << File.dirname(self)
209
- when '%x'
210
- result << $1 if self =~ /[^\/](\.[^.]+)$/
211
- when '%X'
212
- if self =~ /^(.*[^\/])(\.[^.]+)$/
213
- result << $1
214
- else
215
- result << self
216
- end
217
- when '%p'
218
- result << self
219
- when '%s'
220
- result << (File::ALT_SEPARATOR || File::SEPARATOR)
221
- when '%-'
222
- # do nothing
223
- when '%%'
224
- result << "%"
225
- when /%(-?\d+)d/
226
- result << pathmap_partial($1.to_i)
227
- when /^%\{([^}]*)\}(\d*[dpfnxX])/
228
- patterns, operator = $1, $2
229
- result << pathmap('%' + operator).pathmap_replace(patterns, &block)
230
- when /^%/
231
- fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
232
- else
233
- result << frag
234
- end
235
- end
236
- result
237
- end
238
- end
239
- end # class String
240
-
241
- ##############################################################################
242
- module Rake
243
-
244
- # Errors -----------------------------------------------------------
245
-
246
- # Error indicating an ill-formed task declaration.
247
- class TaskArgumentError < ArgumentError
248
- end
249
-
250
- # Error indicating a recursion overflow error in task selection.
251
- class RuleRecursionOverflowError < StandardError
252
- def initialize(*args)
253
- super
254
- @targets = []
255
- end
256
-
257
- def add_target(target)
258
- @targets << target
259
- end
260
-
261
- def message
262
- super + ": [" + @targets.reverse.join(' => ') + "]"
263
- end
264
- end
265
-
266
- # --------------------------------------------------------------------------
267
- # Rake module singleton methods.
268
- #
269
- class << self
270
- # Current Rake Application
271
- def application
272
- @application ||= Rake::Application.new
273
- end
274
-
275
- # Set the current Rake application object.
276
- def application=(app)
277
- @application = app
278
- end
279
-
280
- # Return the original directory where the Rake application was started.
281
- def original_dir
282
- application.original_dir
283
- end
284
-
285
- end
286
-
287
- # ##########################################################################
288
- # Mixin for creating easily cloned objects.
289
- #
290
- module Cloneable
291
- # Clone an object by making a new object and setting all the instance
292
- # variables to the same values.
293
- def dup
294
- sibling = self.class.new
295
- instance_variables.each do |ivar|
296
- value = self.instance_variable_get(ivar)
297
- new_value = value.clone rescue value
298
- sibling.instance_variable_set(ivar, new_value)
299
- end
300
- sibling.taint if tainted?
301
- sibling
302
- end
303
-
304
- def clone
305
- sibling = dup
306
- sibling.freeze if frozen?
307
- sibling
308
- end
309
- end
310
-
311
- ####################################################################
312
- # TaskAguments manage the arguments passed to a task.
313
- #
314
- class TaskArguments
315
- include Enumerable
316
-
317
- attr_reader :names
318
-
319
- # Create a TaskArgument object with a list of named arguments
320
- # (given by :names) and a set of associated values (given by
321
- # :values). :parent is the parent argument object.
322
- def initialize(names, values, parent=nil)
323
- @names = names
324
- @parent = parent
325
- @hash = {}
326
- names.each_with_index { |name, i|
327
- @hash[name.to_sym] = values[i] unless values[i].nil?
328
- }
329
- end
330
-
331
- # Create a new argument scope using the prerequisite argument
332
- # names.
333
- def new_scope(names)
334
- values = names.collect { |n| self[n] }
335
- self.class.new(names, values, self)
336
- end
337
-
338
- # Find an argument value by name or index.
339
- def [](index)
340
- lookup(index.to_sym)
341
- end
342
-
343
- # Specify a hash of default values for task arguments. Use the
344
- # defaults only if there is no specific value for the given
345
- # argument.
346
- def with_defaults(defaults)
347
- @hash = defaults.merge(@hash)
348
- end
349
-
350
- def each(&block)
351
- @hash.each(&block)
352
- end
353
-
354
- def method_missing(sym, *args, &block)
355
- lookup(sym.to_sym)
356
- end
357
-
358
- def to_hash
359
- @hash
360
- end
361
-
362
- def to_s
363
- @hash.inspect
364
- end
365
-
366
- def inspect
367
- to_s
368
- end
369
-
370
- protected
371
-
372
- def lookup(name)
373
- if @hash.has_key?(name)
374
- @hash[name]
375
- elsif ENV.has_key?(name.to_s)
376
- ENV[name.to_s]
377
- elsif ENV.has_key?(name.to_s.upcase)
378
- ENV[name.to_s.upcase]
379
- elsif @parent
380
- @parent.lookup(name)
381
- end
382
- end
383
- end
384
-
385
- EMPTY_TASK_ARGS = TaskArguments.new([], [])
386
-
387
- ####################################################################
388
- # InvocationChain tracks the chain of task invocations to detect
389
- # circular dependencies.
390
- class InvocationChain
391
- def initialize(value, tail)
392
- @value = value
393
- @tail = tail
394
- end
395
-
396
- def member?(obj)
397
- @value == obj || @tail.member?(obj)
398
- end
399
-
400
- def append(value)
401
- if member?(value)
402
- fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
403
- end
404
- self.class.new(value, self)
405
- end
406
-
407
- def to_s
408
- "#{prefix}#{@value}"
409
- end
410
-
411
- def self.append(value, chain)
412
- chain.append(value)
413
- end
414
-
415
- private
416
-
417
- def prefix
418
- "#{@tail.to_s} => "
419
- end
420
-
421
- class EmptyInvocationChain
422
- def member?(obj)
423
- false
424
- end
425
- def append(value)
426
- InvocationChain.new(value, self)
427
- end
428
- def to_s
429
- "TOP"
430
- end
431
- end
432
-
433
- EMPTY = EmptyInvocationChain.new
434
-
435
- end # class InvocationChain
436
-
437
- end # module Rake
438
-
439
- module Rake
440
-
441
- # #########################################################################
442
- # A Task is the basic unit of work in a Rakefile. Tasks have associated
443
- # actions (possibly more than one) and a list of prerequisites. When
444
- # invoked, a task will first ensure that all of its prerequisites have an
445
- # opportunity to run and then it will execute its own actions.
446
- #
447
- # Tasks are not usually created directly using the new method, but rather
448
- # use the +file+ and +task+ convenience methods.
449
- #
450
- class Task
451
- # List of prerequisites for a task.
452
- attr_reader :prerequisites
453
-
454
- # List of actions attached to a task.
455
- attr_reader :actions
456
-
457
- # Application owning this task.
458
- attr_accessor :application
459
-
460
- # Comment for this task. Restricted to a single line of no more than 50
461
- # characters.
462
- attr_reader :comment
463
-
464
- # Full text of the (possibly multi-line) comment.
465
- attr_reader :full_comment
466
-
467
- # Array of nested namespaces names used for task lookup by this task.
468
- attr_reader :scope
469
-
470
- # Return task name
471
- def to_s
472
- name
473
- end
474
-
475
- def inspect
476
- "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
477
- end
478
-
479
- # List of sources for task.
480
- attr_writer :sources
481
- def sources
482
- @sources ||= []
483
- end
484
-
485
- # First source from a rule (nil if no sources)
486
- def source
487
- @sources.first if defined?(@sources)
488
- end
489
-
490
- # Create a task named +task_name+ with no actions or prerequisites. Use
491
- # +enhance+ to add actions and prerequisites.
492
- def initialize(task_name, app)
493
- @name = task_name.to_s
494
- @prerequisites = []
495
- @actions = []
496
- @already_invoked = false
497
- @full_comment = nil
498
- @comment = nil
499
- @lock = Monitor.new
500
- @application = app
501
- @scope = app.current_scope
502
- @arg_names = nil
503
- end
504
-
505
- # Enhance a task with prerequisites or actions. Returns self.
506
- def enhance(deps=nil, &block)
507
- @prerequisites |= deps if deps
508
- @actions << block if block_given?
509
- self
510
- end
511
-
512
- # Name of the task, including any namespace qualifiers.
513
- def name
514
- @name.to_s
515
- end
516
-
517
- # Name of task with argument list description.
518
- def name_with_args # :nodoc:
519
- if arg_description
520
- "#{name}#{arg_description}"
521
- else
522
- name
523
- end
524
- end
525
-
526
- # Argument description (nil if none).
527
- def arg_description # :nodoc:
528
- @arg_names ? "[#{(arg_names || []).join(',')}]" : nil
529
- end
530
-
531
- # Name of arguments for this task.
532
- def arg_names
533
- @arg_names || []
534
- end
535
-
536
- # Reenable the task, allowing its tasks to be executed if the task
537
- # is invoked again.
538
- def reenable
539
- @already_invoked = false
540
- end
541
-
542
- # Clear the existing prerequisites and actions of a rake task.
543
- def clear
544
- clear_prerequisites
545
- clear_actions
546
- self
547
- end
548
-
549
- # Clear the existing prerequisites of a rake task.
550
- def clear_prerequisites
551
- prerequisites.clear
552
- self
553
- end
554
-
555
- # Clear the existing actions on a rake task.
556
- def clear_actions
557
- actions.clear
558
- self
559
- end
560
-
561
- # Invoke the task if it is needed. Prerequites are invoked first.
562
- def invoke(*args)
563
- task_args = TaskArguments.new(arg_names, args)
564
- invoke_with_call_chain(task_args, InvocationChain::EMPTY)
565
- end
566
-
567
- # Same as invoke, but explicitly pass a call chain to detect
568
- # circular dependencies.
569
- def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
570
- new_chain = InvocationChain.append(self, invocation_chain)
571
- @lock.synchronize do
572
- if application.options.trace
573
- puts "** Invoke #{name} #{format_trace_flags}"
574
- end
575
- return if @already_invoked
576
- @already_invoked = true
577
- invoke_prerequisites(task_args, new_chain)
578
- execute(task_args) if needed?
579
- end
580
- end
581
- protected :invoke_with_call_chain
582
-
583
- # Invoke all the prerequisites of a task.
584
- def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
585
- @prerequisites.each { |n|
586
- prereq = application[n, @scope]
587
- prereq_args = task_args.new_scope(prereq.arg_names)
588
- prereq.invoke_with_call_chain(prereq_args, invocation_chain)
589
- }
590
- end
591
-
592
- # Format the trace flags for display.
593
- def format_trace_flags
594
- flags = []
595
- flags << "first_time" unless @already_invoked
596
- flags << "not_needed" unless needed?
597
- flags.empty? ? "" : "(" + flags.join(", ") + ")"
598
- end
599
- private :format_trace_flags
600
-
601
- # Execute the actions associated with this task.
602
- def execute(args=nil)
603
- args ||= EMPTY_TASK_ARGS
604
- if application.options.dryrun
605
- puts "** Execute (dry run) #{name}"
606
- return
607
- end
608
- if application.options.trace
609
- puts "** Execute #{name}"
610
- end
611
- application.enhance_with_matching_rule(name) if @actions.empty?
612
- @actions.each do |act|
613
- case act.arity
614
- when 1
615
- act.call(self)
616
- else
617
- act.call(self, args)
618
- end
619
- end
620
- end
621
-
622
- # Is this task needed?
623
- def needed?
624
- true
625
- end
626
-
627
- # Timestamp for this task. Basic tasks return the current time for their
628
- # time stamp. Other tasks can be more sophisticated.
629
- def timestamp
630
- @prerequisites.collect { |p| application[p].timestamp }.max || Time.now
631
- end
632
-
633
- # Add a description to the task. The description can consist of an option
634
- # argument list (enclosed brackets) and an optional comment.
635
- def add_description(description)
636
- return if ! description
637
- comment = description.strip
638
- add_comment(comment) if comment && ! comment.empty?
639
- end
640
-
641
- # Writing to the comment attribute is the same as adding a description.
642
- def comment=(description)
643
- add_description(description)
644
- end
645
-
646
- # Add a comment to the task. If a comment alread exists, separate
647
- # the new comment with " / ".
648
- def add_comment(comment)
649
- if @full_comment
650
- @full_comment << " / "
651
- else
652
- @full_comment = ''
653
- end
654
- @full_comment << comment
655
- if @full_comment =~ /\A([^.]+?\.)( |$)/
656
- @comment = $1
657
- else
658
- @comment = @full_comment
659
- end
660
- end
661
- private :add_comment
662
-
663
- # Set the names of the arguments for this task. +args+ should be
664
- # an array of symbols, one for each argument name.
665
- def set_arg_names(args)
666
- @arg_names = args.map { |a| a.to_sym }
667
- end
668
-
669
- # Return a string describing the internal state of a task. Useful for
670
- # debugging.
671
- def investigation
672
- result = "------------------------------\n"
673
- result << "Investigating #{name}\n"
674
- result << "class: #{self.class}\n"
675
- result << "task needed: #{needed?}\n"
676
- result << "timestamp: #{timestamp}\n"
677
- result << "pre-requisites: \n"
678
- prereqs = @prerequisites.collect {|name| application[name]}
679
- prereqs.sort! {|a,b| a.timestamp <=> b.timestamp}
680
- prereqs.each do |p|
681
- result << "--#{p.name} (#{p.timestamp})\n"
682
- end
683
- latest_prereq = @prerequisites.collect{|n| application[n].timestamp}.max
684
- result << "latest-prerequisite time: #{latest_prereq}\n"
685
- result << "................................\n\n"
686
- return result
687
- end
688
-
689
- # ----------------------------------------------------------------
690
- # Rake Module Methods
691
- #
692
- class << self
693
-
694
- # Clear the task list. This cause rake to immediately forget all the
695
- # tasks that have been assigned. (Normally used in the unit tests.)
696
- def clear
697
- Rake.application.clear
698
- end
699
-
700
- # List of all defined tasks.
701
- def tasks
702
- Rake.application.tasks
703
- end
704
-
705
- # Return a task with the given name. If the task is not currently
706
- # known, try to synthesize one from the defined rules. If no rules are
707
- # found, but an existing file matches the task name, assume it is a file
708
- # task with no dependencies or actions.
709
- def [](task_name)
710
- Rake.application[task_name]
711
- end
712
-
713
- # TRUE if the task name is already defined.
714
- def task_defined?(task_name)
715
- Rake.application.lookup(task_name) != nil
716
- end
717
-
718
- # Define a task given +args+ and an option block. If a rule with the
719
- # given name already exists, the prerequisites and actions are added to
720
- # the existing task. Returns the defined task.
721
- def define_task(*args, &block)
722
- Rake.application.define_task(self, *args, &block)
723
- end
724
-
725
- # Define a rule for synthesizing tasks.
726
- def create_rule(*args, &block)
727
- Rake.application.create_rule(*args, &block)
728
- end
729
-
730
- # Apply the scope to the task name according to the rules for
731
- # this kind of task. Generic tasks will accept the scope as
732
- # part of the name.
733
- def scope_name(scope, task_name)
734
- (scope + [task_name]).join(':')
735
- end
736
-
737
- end # class << Rake::Task
738
- end # class Rake::Task
739
-
740
-
741
- # #########################################################################
742
- # A FileTask is a task that includes time based dependencies. If any of a
743
- # FileTask's prerequisites have a timestamp that is later than the file
744
- # represented by this task, then the file must be rebuilt (using the
745
- # supplied actions).
746
- #
747
- class FileTask < Task
748
-
749
- # Is this file task needed? Yes if it doesn't exist, or if its time stamp
750
- # is out of date.
751
- def needed?
752
- return true unless File.exist?(name)
753
- return true if out_of_date?(timestamp)
754
- false
755
- end
756
-
757
- # Time stamp for file task.
758
- def timestamp
759
- if File.exist?(name)
760
- File.mtime(name.to_s)
761
- else
762
- Rake::EARLY
763
- end
764
- end
765
-
766
- private
767
-
768
- # Are there any prerequisites with a later time than the given time stamp?
769
- def out_of_date?(stamp)
770
- @prerequisites.any? { |n| application[n].timestamp > stamp}
771
- end
772
-
773
- # ----------------------------------------------------------------
774
- # Task class methods.
775
- #
776
- class << self
777
- # Apply the scope to the task name according to the rules for this kind
778
- # of task. File based tasks ignore the scope when creating the name.
779
- def scope_name(scope, task_name)
780
- task_name
781
- end
782
- end
783
- end # class Rake::FileTask
784
-
785
- # #########################################################################
786
- # A FileCreationTask is a file task that when used as a dependency will be
787
- # needed if and only if the file has not been created. Once created, it is
788
- # not re-triggered if any of its dependencies are newer, nor does trigger
789
- # any rebuilds of tasks that depend on it whenever it is updated.
790
- #
791
- class FileCreationTask < FileTask
792
- # Is this file task needed? Yes if it doesn't exist.
793
- def needed?
794
- ! File.exist?(name)
795
- end
796
-
797
- # Time stamp for file creation task. This time stamp is earlier
798
- # than any other time stamp.
799
- def timestamp
800
- Rake::EARLY
801
- end
802
- end
803
-
804
- # #########################################################################
805
- # Same as a regular task, but the immediate prerequisites are done in
806
- # parallel using Ruby threads.
807
- #
808
- class MultiTask < Task
809
- def invoke_prerequisites(args, invocation_chain)
810
- threads = @prerequisites.collect { |p|
811
- Thread.new(p) { |r| application[r].invoke_with_call_chain(args, invocation_chain) }
812
- }
813
- threads.each { |t| t.join }
814
- end
815
- end
816
- end # module Rake
817
-
818
- # ###########################################################################
819
- # Task Definition Functions ...
820
-
821
- # Declare a basic task.
822
- #
823
- # Example:
824
- # task :clobber => [:clean] do
825
- # rm_rf "html"
826
- # end
827
- #
828
- def task(*args, &block)
829
- Rake::Task.define_task(*args, &block)
830
- end
831
-
832
-
833
- # Declare a file task.
834
- #
835
- # Example:
836
- # file "config.cfg" => ["config.template"] do
837
- # open("config.cfg", "w") do |outfile|
838
- # open("config.template") do |infile|
839
- # while line = infile.gets
840
- # outfile.puts line
841
- # end
842
- # end
843
- # end
844
- # end
845
- #
846
- def file(*args, &block)
847
- Rake::FileTask.define_task(*args, &block)
848
- end
849
-
850
- # Declare a file creation task.
851
- # (Mainly used for the directory command).
852
- def file_create(args, &block)
853
- Rake::FileCreationTask.define_task(args, &block)
854
- end
855
-
856
- # Declare a set of files tasks to create the given directories on demand.
857
- #
858
- # Example:
859
- # directory "testdata/doc"
860
- #
861
- def directory(dir)
862
- Rake.each_dir_parent(dir) do |d|
863
- file_create d do |t|
864
- mkdir_p t.name if ! File.exist?(t.name)
865
- end
866
- end
867
- end
868
-
869
- # Declare a task that performs its prerequisites in parallel. Multitasks does
870
- # *not* guarantee that its prerequisites will execute in any given order
871
- # (which is obvious when you think about it)
872
- #
873
- # Example:
874
- # multitask :deploy => [:deploy_gem, :deploy_rdoc]
875
- #
876
- def multitask(args, &block)
877
- Rake::MultiTask.define_task(args, &block)
878
- end
879
-
880
- # Create a new rake namespace and use it for evaluating the given block.
881
- # Returns a NameSpace object that can be used to lookup tasks defined in the
882
- # namespace.
883
- #
884
- # E.g.
885
- #
886
- # ns = namespace "nested" do
887
- # task :run
888
- # end
889
- # task_run = ns[:run] # find :run in the given namespace.
890
- #
891
- def namespace(name=nil, &block)
892
- Rake.application.in_namespace(name, &block)
893
- end
894
-
895
- # Declare a rule for auto-tasks.
896
- #
897
- # Example:
898
- # rule '.o' => '.c' do |t|
899
- # sh %{cc -o #{t.name} #{t.source}}
900
- # end
901
- #
902
- def rule(*args, &block)
903
- Rake::Task.create_rule(*args, &block)
904
- end
905
-
906
- # Describe the next rake task.
907
- #
908
- # Example:
909
- # desc "Run the Unit Tests"
910
- # task :test => [:build]
911
- # runtests
912
- # end
913
- #
914
- def desc(description)
915
- Rake.application.last_description = description
916
- end
917
-
918
- # Import the partial Rakefiles +fn+. Imported files are loaded _after_ the
919
- # current file is completely loaded. This allows the import statement to
920
- # appear anywhere in the importing file, and yet allowing the imported files
921
- # to depend on objects defined in the importing file.
922
- #
923
- # A common use of the import statement is to include files containing
924
- # dependency declarations.
925
- #
926
- # See also the --rakelibdir command line option.
927
- #
928
- # Example:
929
- # import ".depend", "my_rules"
930
- #
931
- def import(*fns)
932
- fns.each do |fn|
933
- Rake.application.add_import(fn)
934
- end
935
- end
936
-
937
- # ###########################################################################
938
- # This a FileUtils extension that defines several additional commands to be
939
- # added to the FileUtils utility functions.
940
- #
941
- module FileUtils
942
- RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']).
943
- sub(/.*\s.*/m, '"\&"')
944
-
945
- OPT_TABLE['sh'] = %w(noop verbose)
946
- OPT_TABLE['ruby'] = %w(noop verbose)
947
-
948
- # Run the system command +cmd+. If multiple arguments are given the command
949
- # is not run with the shell (same semantics as Kernel::exec and
950
- # Kernel::system).
951
- #
952
- # Example:
953
- # sh %{ls -ltr}
954
- #
955
- # sh 'ls', 'file with spaces'
956
- #
957
- # # check exit status after command runs
958
- # sh %{grep pattern file} do |ok, res|
959
- # if ! ok
960
- # puts "pattern not found (status = #{res.exitstatus})"
961
- # end
962
- # end
963
- #
964
- def sh(*cmd, &block)
965
- options = (Hash === cmd.last) ? cmd.pop : {}
966
- unless block_given?
967
- show_command = cmd.join(" ")
968
- show_command = show_command[0,42] + "..."
969
- # TODO code application logic heref show_command.length > 45
970
- block = lambda { |ok, status|
971
- ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
972
- }
973
- end
974
- if RakeFileUtils.verbose_flag == :default
975
- options[:verbose] = false
976
- else
977
- options[:verbose] ||= RakeFileUtils.verbose_flag
978
- end
979
- options[:noop] ||= RakeFileUtils.nowrite_flag
980
- rake_check_options options, :noop, :verbose
981
- rake_output_message cmd.join(" ") if options[:verbose]
982
- unless options[:noop]
983
- res = rake_system(*cmd)
984
- block.call(res, $?)
985
- end
986
- end
987
-
988
- def rake_system(*cmd)
989
- if Rake::Win32.windows?
990
- Rake::Win32.rake_system(*cmd)
991
- else
992
- system(*cmd)
993
- end
994
- end
995
- private :rake_system
996
-
997
- # Run a Ruby interpreter with the given arguments.
998
- #
999
- # Example:
1000
- # ruby %{-pe '$_.upcase!' <README}
1001
- #
1002
- def ruby(*args,&block)
1003
- options = (Hash === args.last) ? args.pop : {}
1004
- if args.length > 1 then
1005
- sh(*([RUBY] + args + [options]), &block)
1006
- else
1007
- sh("#{RUBY} #{args.first}", options, &block)
1008
- end
1009
- end
1010
-
1011
- LN_SUPPORTED = [true]
1012
-
1013
- # Attempt to do a normal file link, but fall back to a copy if the link
1014
- # fails.
1015
- def safe_ln(*args)
1016
- unless LN_SUPPORTED[0]
1017
- cp(*args)
1018
- else
1019
- begin
1020
- ln(*args)
1021
- rescue StandardError, NotImplementedError => ex
1022
- LN_SUPPORTED[0] = false
1023
- cp(*args)
1024
- end
1025
- end
1026
- end
1027
-
1028
- # Split a file path into individual directory names.
1029
- #
1030
- # Example:
1031
- # split_all("a/b/c") => ['a', 'b', 'c']
1032
- #
1033
- def split_all(path)
1034
- head, tail = File.split(path)
1035
- return [tail] if head == '.' || tail == '/'
1036
- return [head, tail] if head == '/'
1037
- return split_all(head) + [tail]
1038
- end
1039
- end
1040
-
1041
- # ###########################################################################
1042
- # RakeFileUtils provides a custom version of the FileUtils methods that
1043
- # respond to the <tt>verbose</tt> and <tt>nowrite</tt> commands.
1044
- #
1045
- module RakeFileUtils
1046
- include FileUtils
1047
-
1048
- class << self
1049
- attr_accessor :verbose_flag, :nowrite_flag
1050
- end
1051
- RakeFileUtils.verbose_flag = :default
1052
- RakeFileUtils.nowrite_flag = false
1053
-
1054
- $fileutils_verbose = true
1055
- $fileutils_nowrite = false
1056
-
1057
- FileUtils::OPT_TABLE.each do |name, opts|
1058
- default_options = []
1059
- if opts.include?(:verbose) || opts.include?("verbose")
1060
- default_options << ':verbose => RakeFileUtils.verbose_flag'
1061
- end
1062
- if opts.include?(:noop) || opts.include?("noop")
1063
- default_options << ':noop => RakeFileUtils.nowrite_flag'
1064
- end
1065
-
1066
- next if default_options.empty?
1067
- module_eval(<<-EOS, __FILE__, __LINE__ + 1)
1068
- def #{name}( *args, &block )
1069
- super(
1070
- *rake_merge_option(args,
1071
- #{default_options.join(', ')}
1072
- ), &block)
1073
- end
1074
- EOS
1075
- end
1076
-
1077
- # Get/set the verbose flag controlling output from the FileUtils utilities.
1078
- # If verbose is true, then the utility method is echoed to standard output.
1079
- #
1080
- # Examples:
1081
- # verbose # return the current value of the verbose flag
1082
- # verbose(v) # set the verbose flag to _v_.
1083
- # verbose(v) { code } # Execute code with the verbose flag set temporarily to _v_.
1084
- # # Return to the original value when code is done.
1085
- def verbose(value=nil)
1086
- oldvalue = RakeFileUtils.verbose_flag
1087
- RakeFileUtils.verbose_flag = value unless value.nil?
1088
- if block_given?
1089
- begin
1090
- yield
1091
- ensure
1092
- RakeFileUtils.verbose_flag = oldvalue
1093
- end
1094
- end
1095
- RakeFileUtils.verbose_flag
1096
- end
1097
-
1098
- # Get/set the nowrite flag controlling output from the FileUtils utilities.
1099
- # If verbose is true, then the utility method is echoed to standard output.
1100
- #
1101
- # Examples:
1102
- # nowrite # return the current value of the nowrite flag
1103
- # nowrite(v) # set the nowrite flag to _v_.
1104
- # nowrite(v) { code } # Execute code with the nowrite flag set temporarily to _v_.
1105
- # # Return to the original value when code is done.
1106
- def nowrite(value=nil)
1107
- oldvalue = RakeFileUtils.nowrite_flag
1108
- RakeFileUtils.nowrite_flag = value unless value.nil?
1109
- if block_given?
1110
- begin
1111
- yield
1112
- ensure
1113
- RakeFileUtils.nowrite_flag = oldvalue
1114
- end
1115
- end
1116
- oldvalue
1117
- end
1118
-
1119
- # Use this function to prevent protentially destructive ruby code from
1120
- # running when the :nowrite flag is set.
1121
- #
1122
- # Example:
1123
- #
1124
- # when_writing("Building Project") do
1125
- # project.build
1126
- # end
1127
- #
1128
- # The following code will build the project under normal conditions. If the
1129
- # nowrite(true) flag is set, then the example will print:
1130
- # DRYRUN: Building Project
1131
- # instead of actually building the project.
1132
- #
1133
- def when_writing(msg=nil)
1134
- if RakeFileUtils.nowrite_flag
1135
- puts "DRYRUN: #{msg}" if msg
1136
- else
1137
- yield
1138
- end
1139
- end
1140
-
1141
- # Merge the given options with the default values.
1142
- def rake_merge_option(args, defaults)
1143
- if Hash === args.last
1144
- defaults.update(args.last)
1145
- args.pop
1146
- end
1147
- args.push defaults
1148
- args
1149
- end
1150
- private :rake_merge_option
1151
-
1152
- # Send the message to the default rake output (which is $stderr).
1153
- def rake_output_message(message)
1154
- $stderr.puts(message)
1155
- end
1156
- private :rake_output_message
1157
-
1158
- # Check that the options do not contain options not listed in +optdecl+. An
1159
- # ArgumentError exception is thrown if non-declared options are found.
1160
- def rake_check_options(options, *optdecl)
1161
- h = options.dup
1162
- optdecl.each do |name|
1163
- h.delete name
1164
- end
1165
- raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
1166
- end
1167
- private :rake_check_options
1168
-
1169
- extend self
1170
- end
1171
-
1172
- # ###########################################################################
1173
- # Include the FileUtils file manipulation functions in the top level module,
1174
- # but mark them private so that they don't unintentionally define methods on
1175
- # other objects.
1176
-
1177
- include RakeFileUtils
1178
- private(*FileUtils.instance_methods(false))
1179
- private(*RakeFileUtils.instance_methods(false))
1180
-
1181
- ######################################################################
1182
- module Rake
1183
-
1184
- # #########################################################################
1185
- # A FileList is essentially an array with a few helper methods defined to
1186
- # make file manipulation a bit easier.
1187
- #
1188
- # FileLists are lazy. When given a list of glob patterns for possible files
1189
- # to be included in the file list, instead of searching the file structures
1190
- # to find the files, a FileList holds the pattern for latter use.
1191
- #
1192
- # This allows us to define a number of FileList to match any number of
1193
- # files, but only search out the actual files when then FileList itself is
1194
- # actually used. The key is that the first time an element of the
1195
- # FileList/Array is requested, the pending patterns are resolved into a real
1196
- # list of file names.
1197
- #
1198
- class FileList
1199
-
1200
- include Cloneable
1201
-
1202
- # == Method Delegation
1203
- #
1204
- # The lazy evaluation magic of FileLists happens by implementing all the
1205
- # array specific methods to call +resolve+ before delegating the heavy
1206
- # lifting to an embedded array object (@items).
1207
- #
1208
- # In addition, there are two kinds of delegation calls. The regular kind
1209
- # delegates to the @items array and returns the result directly. Well,
1210
- # almost directly. It checks if the returned value is the @items object
1211
- # itself, and if so will return the FileList object instead.
1212
- #
1213
- # The second kind of delegation call is used in methods that normally
1214
- # return a new Array object. We want to capture the return value of these
1215
- # methods and wrap them in a new FileList object. We enumerate these
1216
- # methods in the +SPECIAL_RETURN+ list below.
1217
-
1218
- # List of array methods (that are not in +Object+) that need to be
1219
- # delegated.
1220
- ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
1221
-
1222
- # List of additional methods that must be delegated.
1223
- MUST_DEFINE = %w[to_a inspect]
1224
-
1225
- # List of methods that should not be delegated here (we define special
1226
- # versions of them explicitly below).
1227
- MUST_NOT_DEFINE = %w[to_a to_ary partition *]
1228
-
1229
- # List of delegated methods that return new array values which need
1230
- # wrapping.
1231
- SPECIAL_RETURN = %w[
1232
- map collect sort sort_by select find_all reject grep
1233
- compact flatten uniq values_at
1234
- + - & |
1235
- ]
1236
-
1237
- DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
1238
-
1239
- # Now do the delegation.
1240
- DELEGATING_METHODS.each_with_index do |sym, i|
1241
- if SPECIAL_RETURN.include?(sym)
1242
- ln = __LINE__+1
1243
- class_eval %{
1244
- def #{sym}(*args, &block)
1245
- resolve
1246
- result = @items.send(:#{sym}, *args, &block)
1247
- FileList.new.import(result)
1248
- end
1249
- }, __FILE__, ln
1250
- else
1251
- ln = __LINE__+1
1252
- class_eval %{
1253
- def #{sym}(*args, &block)
1254
- resolve
1255
- result = @items.send(:#{sym}, *args, &block)
1256
- result.object_id == @items.object_id ? self : result
1257
- end
1258
- }, __FILE__, ln
1259
- end
1260
- end
1261
-
1262
- # Create a file list from the globbable patterns given. If you wish to
1263
- # perform multiple includes or excludes at object build time, use the
1264
- # "yield self" pattern.
1265
- #
1266
- # Example:
1267
- # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')
1268
- #
1269
- # pkg_files = FileList.new('lib/**/*') do |fl|
1270
- # fl.exclude(/\bCVS\b/)
1271
- # end
1272
- #
1273
- def initialize(*patterns)
1274
- @pending_add = []
1275
- @pending = false
1276
- @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
1277
- @exclude_procs = DEFAULT_IGNORE_PROCS.dup
1278
- @exclude_re = nil
1279
- @items = []
1280
- patterns.each { |pattern| include(pattern) }
1281
- yield self if block_given?
1282
- end
1283
-
1284
- # Add file names defined by glob patterns to the file list. If an array
1285
- # is given, add each element of the array.
1286
- #
1287
- # Example:
1288
- # file_list.include("*.java", "*.cfg")
1289
- # file_list.include %w( math.c lib.h *.o )
1290
- #
1291
- def include(*filenames)
1292
- # TODO: check for pending
1293
- filenames.each do |fn|
1294
- if fn.respond_to? :to_ary
1295
- include(*fn.to_ary)
1296
- else
1297
- @pending_add << fn
1298
- end
1299
- end
1300
- @pending = true
1301
- self
1302
- end
1303
- alias :add :include
1304
-
1305
- # Register a list of file name patterns that should be excluded from the
1306
- # list. Patterns may be regular expressions, glob patterns or regular
1307
- # strings. In addition, a block given to exclude will remove entries that
1308
- # return true when given to the block.
1309
- #
1310
- # Note that glob patterns are expanded against the file system. If a file
1311
- # is explicitly added to a file list, but does not exist in the file
1312
- # system, then an glob pattern in the exclude list will not exclude the
1313
- # file.
1314
- #
1315
- # Examples:
1316
- # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
1317
- # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c']
1318
- #
1319
- # If "a.c" is a file, then ...
1320
- # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']
1321
- #
1322
- # If "a.c" is not a file, then ...
1323
- # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']
1324
- #
1325
- def exclude(*patterns, &block)
1326
- patterns.each do |pat|
1327
- @exclude_patterns << pat
1328
- end
1329
- if block_given?
1330
- @exclude_procs << block
1331
- end
1332
- resolve_exclude if ! @pending
1333
- self
1334
- end
1335
-
1336
-
1337
- # Clear all the exclude patterns so that we exclude nothing.
1338
- def clear_exclude
1339
- @exclude_patterns = []
1340
- @exclude_procs = []
1341
- calculate_exclude_regexp if ! @pending
1342
- self
1343
- end
1344
-
1345
- # Define equality.
1346
- def ==(array)
1347
- to_ary == array
1348
- end
1349
-
1350
- # Return the internal array object.
1351
- def to_a
1352
- resolve
1353
- @items
1354
- end
1355
-
1356
- # Return the internal array object.
1357
- def to_ary
1358
- to_a
1359
- end
1360
-
1361
- # Lie about our class.
1362
- def is_a?(klass)
1363
- klass == Array || super(klass)
1364
- end
1365
- alias kind_of? is_a?
1366
-
1367
- # Redefine * to return either a string or a new file list.
1368
- def *(other)
1369
- result = @items * other
1370
- case result
1371
- when Array
1372
- FileList.new.import(result)
1373
- else
1374
- result
1375
- end
1376
- end
1377
-
1378
- # Resolve all the pending adds now.
1379
- def resolve
1380
- if @pending
1381
- @pending = false
1382
- @pending_add.each do |fn| resolve_add(fn) end
1383
- @pending_add = []
1384
- resolve_exclude
1385
- end
1386
- self
1387
- end
1388
-
1389
- def calculate_exclude_regexp
1390
- ignores = []
1391
- @exclude_patterns.each do |pat|
1392
- case pat
1393
- when Regexp
1394
- ignores << pat
1395
- when /[*?]/
1396
- Dir[pat].each do |p| ignores << p end
1397
- else
1398
- ignores << Regexp.quote(pat)
1399
- end
1400
- end
1401
- if ignores.empty?
1402
- @exclude_re = /^$/
1403
- else
1404
- re_str = ignores.collect { |p| "(" + p.to_s + ")" }.join("|")
1405
- @exclude_re = Regexp.new(re_str)
1406
- end
1407
- end
1408
-
1409
- def resolve_add(fn)
1410
- case fn
1411
- when %r{[*?\[\{]}
1412
- add_matching(fn)
1413
- else
1414
- self << fn
1415
- end
1416
- end
1417
- private :resolve_add
1418
-
1419
- def resolve_exclude
1420
- calculate_exclude_regexp
1421
- reject! { |fn| exclude?(fn) }
1422
- self
1423
- end
1424
- private :resolve_exclude
1425
-
1426
- # Return a new FileList with the results of running +sub+ against each
1427
- # element of the oringal list.
1428
- #
1429
- # Example:
1430
- # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
1431
- #
1432
- def sub(pat, rep)
1433
- inject(FileList.new) { |res, fn| res << fn.sub(pat,rep) }
1434
- end
1435
-
1436
- # Return a new FileList with the results of running +gsub+ against each
1437
- # element of the original list.
1438
- #
1439
- # Example:
1440
- # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\")
1441
- # => ['lib\\test\\file', 'x\\y']
1442
- #
1443
- def gsub(pat, rep)
1444
- inject(FileList.new) { |res, fn| res << fn.gsub(pat,rep) }
1445
- end
1446
-
1447
- # Same as +sub+ except that the oringal file list is modified.
1448
- def sub!(pat, rep)
1449
- each_with_index { |fn, i| self[i] = fn.sub(pat,rep) }
1450
- self
1451
- end
1452
-
1453
- # Same as +gsub+ except that the original file list is modified.
1454
- def gsub!(pat, rep)
1455
- each_with_index { |fn, i| self[i] = fn.gsub(pat,rep) }
1456
- self
1457
- end
1458
-
1459
- # Apply the pathmap spec to each of the included file names, returning a
1460
- # new file list with the modified paths. (See String#pathmap for
1461
- # details.)
1462
- def pathmap(spec=nil)
1463
- collect { |fn| fn.pathmap(spec) }
1464
- end
1465
-
1466
- # Return a new array with <tt>String#ext</tt> method applied to each
1467
- # member of the array.
1468
- #
1469
- # This method is a shortcut for:
1470
- #
1471
- # array.collect { |item| item.ext(newext) }
1472
- #
1473
- # +ext+ is a user added method for the Array class.
1474
- def ext(newext='')
1475
- collect { |fn| fn.ext(newext) }
1476
- end
1477
-
1478
-
1479
- # Grep each of the files in the filelist using the given pattern. If a
1480
- # block is given, call the block on each matching line, passing the file
1481
- # name, line number, and the matching line of text. If no block is given,
1482
- # a standard emac style file:linenumber:line message will be printed to
1483
- # standard out.
1484
- def egrep(pattern)
1485
- each do |fn|
1486
- open(fn) do |inf|
1487
- count = 0
1488
- inf.each do |line|
1489
- count += 1
1490
- if pattern.match(line)
1491
- if block_given?
1492
- yield fn, count, line
1493
- else
1494
- puts "#{fn}:#{count}:#{line}"
1495
- end
1496
- end
1497
- end
1498
- end
1499
- end
1500
- end
1501
-
1502
- # Return a new file list that only contains file names from the current
1503
- # file list that exist on the file system.
1504
- def existing
1505
- select { |fn| File.exist?(fn) }
1506
- end
1507
-
1508
- # Modify the current file list so that it contains only file name that
1509
- # exist on the file system.
1510
- def existing!
1511
- resolve
1512
- @items = @items.select { |fn| File.exist?(fn) }
1513
- self
1514
- end
1515
-
1516
- # FileList version of partition. Needed because the nested arrays should
1517
- # be FileLists in this version.
1518
- def partition(&block) # :nodoc:
1519
- resolve
1520
- result = @items.partition(&block)
1521
- [
1522
- FileList.new.import(result[0]),
1523
- FileList.new.import(result[1]),
1524
- ]
1525
- end
1526
-
1527
- # Convert a FileList to a string by joining all elements with a space.
1528
- def to_s
1529
- resolve
1530
- self.join(' ')
1531
- end
1532
-
1533
- # Add matching glob patterns.
1534
- def add_matching(pattern)
1535
- Dir[pattern].each do |fn|
1536
- self << fn unless exclude?(fn)
1537
- end
1538
- end
1539
- private :add_matching
1540
-
1541
- # Should the given file name be excluded?
1542
- def exclude?(fn)
1543
- calculate_exclude_regexp unless @exclude_re
1544
- fn =~ @exclude_re || @exclude_procs.any? { |p| p.call(fn) }
1545
- end
1546
-
1547
- DEFAULT_IGNORE_PATTERNS = [
1548
- /(^|[\/\\])CVS([\/\\]|$)/,
1549
- /(^|[\/\\])\.svn([\/\\]|$)/,
1550
- /\.bak$/,
1551
- /~$/
1552
- ]
1553
- DEFAULT_IGNORE_PROCS = [
1554
- proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
1555
- ]
1556
- # @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
1557
-
1558
- def import(array)
1559
- @items = array
1560
- self
1561
- end
1562
-
1563
- class << self
1564
- # Create a new file list including the files listed. Similar to:
1565
- #
1566
- # FileList.new(*args)
1567
- def [](*args)
1568
- new(*args)
1569
- end
1570
- end
1571
- end # FileList
1572
- end
1573
-
1574
- module Rake
1575
- class << self
1576
-
1577
- # Yield each file or directory component.
1578
- def each_dir_parent(dir) # :nodoc:
1579
- old_length = nil
1580
- while dir != '.' && dir.length != old_length
1581
- yield(dir)
1582
- old_length = dir.length
1583
- dir = File.dirname(dir)
1584
- end
1585
- end
1586
- end
1587
- end # module Rake
1588
-
1589
- # Alias FileList to be available at the top level.
1590
- FileList = Rake::FileList
1591
-
1592
- # ###########################################################################
1593
- module Rake
1594
-
1595
- # Default Rakefile loader used by +import+.
1596
- class DefaultLoader
1597
- def load(fn)
1598
- Kernel.load(File.expand_path(fn))
1599
- end
1600
- end
1601
-
1602
- # EarlyTime is a fake timestamp that occurs _before_ any other time value.
1603
- class EarlyTime
1604
- include Comparable
1605
- include Singleton
1606
-
1607
- def <=>(other)
1608
- -1
1609
- end
1610
-
1611
- def to_s
1612
- "<EARLY TIME>"
1613
- end
1614
- end
1615
-
1616
- EARLY = EarlyTime.instance
1617
- end # module Rake
1618
-
1619
- # ###########################################################################
1620
- # Extensions to time to allow comparisons with an early time class.
1621
- #
1622
- class Time
1623
- alias rake_original_time_compare :<=>
1624
- def <=>(other)
1625
- if Rake::EarlyTime === other
1626
- - other.<=>(self)
1627
- else
1628
- rake_original_time_compare(other)
1629
- end
1630
- end
1631
- end # class Time
1632
-
1633
- module Rake
1634
-
1635
- ####################################################################
1636
- # The NameSpace class will lookup task names in the the scope
1637
- # defined by a +namespace+ command.
1638
- #
1639
- class NameSpace
1640
-
1641
- # Create a namespace lookup object using the given task manager
1642
- # and the list of scopes.
1643
- def initialize(task_manager, scope_list)
1644
- @task_manager = task_manager
1645
- @scope = scope_list.dup
1646
- end
1647
-
1648
- # Lookup a task named +name+ in the namespace.
1649
- def [](name)
1650
- @task_manager.lookup(name, @scope)
1651
- end
1652
-
1653
- # Return the list of tasks defined in this namespace.
1654
- def tasks
1655
- @task_manager.tasks
1656
- end
1657
- end # NameSpace
1658
-
1659
-
1660
- ####################################################################
1661
- # The TaskManager module is a mixin for managing tasks.
1662
- module TaskManager
1663
- # Track the last comment made in the Rakefile.
1664
- attr_accessor :last_description
1665
- alias :last_comment :last_description # Backwards compatibility
1666
-
1667
- def initialize
1668
- super
1669
- @tasks = Hash.new
1670
- @rules = Array.new
1671
- @scope = Array.new
1672
- @last_description = nil
1673
- end
1674
-
1675
- def create_rule(*args, &block)
1676
- pattern, arg_names, deps = resolve_args(args)
1677
- pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
1678
- @rules << [pattern, deps, block]
1679
- end
1680
-
1681
- def define_task(task_class, *args, &block)
1682
- task_name, arg_names, deps = resolve_args(args)
1683
- task_name = task_class.scope_name(@scope, task_name)
1684
- deps = [deps] unless deps.respond_to?(:to_ary)
1685
- deps = deps.collect {|d| d.to_s }
1686
- task = intern(task_class, task_name)
1687
- task.set_arg_names(arg_names) unless arg_names.empty?
1688
- task.add_description(@last_description)
1689
- @last_description = nil
1690
- task.enhance(deps, &block)
1691
- task
1692
- end
1693
-
1694
- # Lookup a task. Return an existing task if found, otherwise
1695
- # create a task of the current type.
1696
- def intern(task_class, task_name)
1697
- @tasks[task_name.to_s] ||= task_class.new(task_name, self)
1698
- end
1699
-
1700
- # Find a matching task for +task_name+.
1701
- def [](task_name, scopes=nil)
1702
- task_name = task_name.to_s
1703
- self.lookup(task_name, scopes) or
1704
- enhance_with_matching_rule(task_name) or
1705
- synthesize_file_task(task_name) or
1706
- fail "Don't know how to build task '#{task_name}'"
1707
- end
1708
-
1709
- def synthesize_file_task(task_name)
1710
- return nil unless File.exist?(task_name)
1711
- define_task(Rake::FileTask, task_name)
1712
- end
1713
-
1714
- # Resolve the arguments for a task/rule. Returns a triplet of
1715
- # [task_name, arg_name_list, prerequisites].
1716
- def resolve_args(args)
1717
- if args.last.is_a?(Hash)
1718
- deps = args.pop
1719
- resolve_args_with_dependencies(args, deps)
1720
- else
1721
- resolve_args_without_dependencies(args)
1722
- end
1723
- end
1724
-
1725
- # Resolve task arguments for a task or rule when there are no
1726
- # dependencies declared.
1727
- #
1728
- # The patterns recognized by this argument resolving function are:
1729
- #
1730
- # task :t
1731
- # task :t, [:a]
1732
- # task :t, :a (deprecated)
1733
- #
1734
- def resolve_args_without_dependencies(args)
1735
- task_name = args.shift
1736
- if args.size == 1 && args.first.respond_to?(:to_ary)
1737
- arg_names = args.first.to_ary
1738
- else
1739
- arg_names = args
1740
- end
1741
- [task_name, arg_names, []]
1742
- end
1743
- private :resolve_args_without_dependencies
1744
-
1745
- # Resolve task arguments for a task or rule when there are
1746
- # dependencies declared.
1747
- #
1748
- # The patterns recognized by this argument resolving function are:
1749
- #
1750
- # task :t => [:d]
1751
- # task :t, [a] => [:d]
1752
- # task :t, :needs => [:d] (deprecated)
1753
- # task :t, :a, :needs => [:d] (deprecated)
1754
- #
1755
- def resolve_args_with_dependencies(args, hash) # :nodoc:
1756
- fail "Task Argument Error" if hash.size != 1
1757
- key, value = hash.map { |k, v| [k,v] }.first
1758
- if args.empty?
1759
- task_name = key
1760
- arg_names = []
1761
- deps = value
1762
- elsif key == :needs
1763
- task_name = args.shift
1764
- arg_names = args
1765
- deps = value
1766
- else
1767
- task_name = args.shift
1768
- arg_names = key
1769
- deps = value
1770
- end
1771
- deps = [deps] unless deps.respond_to?(:to_ary)
1772
- [task_name, arg_names, deps]
1773
- end
1774
- private :resolve_args_with_dependencies
1775
-
1776
- # If a rule can be found that matches the task name, enhance the
1777
- # task with the prerequisites and actions from the rule. Set the
1778
- # source attribute of the task appropriately for the rule. Return
1779
- # the enhanced task or nil of no rule was found.
1780
- def enhance_with_matching_rule(task_name, level=0)
1781
- fail Rake::RuleRecursionOverflowError,
1782
- "Rule Recursion Too Deep" if level >= 16
1783
- @rules.each do |pattern, extensions, block|
1784
- if md = pattern.match(task_name)
1785
- task = attempt_rule(task_name, extensions, block, level)
1786
- return task if task
1787
- end
1788
- end
1789
- nil
1790
- rescue Rake::RuleRecursionOverflowError => ex
1791
- ex.add_target(task_name)
1792
- fail ex
1793
- end
1794
-
1795
- # List of all defined tasks in this application.
1796
- def tasks
1797
- @tasks.values.sort_by { |t| t.name }
1798
- end
1799
-
1800
- # Clear all tasks in this application.
1801
- def clear
1802
- @tasks.clear
1803
- @rules.clear
1804
- end
1805
-
1806
- # Lookup a task, using scope and the scope hints in the task name.
1807
- # This method performs straight lookups without trying to
1808
- # synthesize file tasks or rules. Special scope names (e.g. '^')
1809
- # are recognized. If no scope argument is supplied, use the
1810
- # current scope. Return nil if the task cannot be found.
1811
- def lookup(task_name, initial_scope=nil)
1812
- initial_scope ||= @scope
1813
- task_name = task_name.to_s
1814
- if task_name =~ /^rake:/
1815
- scopes = []
1816
- task_name = task_name.sub(/^rake:/, '')
1817
- elsif task_name =~ /^(\^+)/
1818
- scopes = initial_scope[0, initial_scope.size - $1.size]
1819
- task_name = task_name.sub(/^(\^+)/, '')
1820
- else
1821
- scopes = initial_scope
1822
- end
1823
- lookup_in_scope(task_name, scopes)
1824
- end
1825
-
1826
- # Lookup the task name
1827
- def lookup_in_scope(name, scope)
1828
- n = scope.size
1829
- while n >= 0
1830
- tn = (scope[0,n] + [name]).join(':')
1831
- task = @tasks[tn]
1832
- return task if task
1833
- n -= 1
1834
- end
1835
- nil
1836
- end
1837
- private :lookup_in_scope
1838
-
1839
- # Return the list of scope names currently active in the task
1840
- # manager.
1841
- def current_scope
1842
- @scope.dup
1843
- end
1844
-
1845
- # Evaluate the block in a nested namespace named +name+. Create
1846
- # an anonymous namespace if +name+ is nil.
1847
- def in_namespace(name)
1848
- name ||= generate_name
1849
- @scope.push(name)
1850
- ns = NameSpace.new(self, @scope)
1851
- yield(ns)
1852
- ns
1853
- ensure
1854
- @scope.pop
1855
- end
1856
-
1857
- private
1858
-
1859
- # Generate an anonymous namespace name.
1860
- def generate_name
1861
- @seed ||= 0
1862
- @seed += 1
1863
- "_anon_#{@seed}"
1864
- end
1865
-
1866
- def trace_rule(level, message)
1867
- puts "#{" "*level}#{message}" if Rake.application.options.trace_rules
1868
- end
1869
-
1870
- # Attempt to create a rule given the list of prerequisites.
1871
- def attempt_rule(task_name, extensions, block, level)
1872
- sources = make_sources(task_name, extensions)
1873
- prereqs = sources.collect { |source|
1874
- trace_rule level, "Attempting Rule #{task_name} => #{source}"
1875
- if File.exist?(source) || Rake::Task.task_defined?(source)
1876
- trace_rule level, "(#{task_name} => #{source} ... EXIST)"
1877
- source
1878
- elsif parent = enhance_with_matching_rule(source, level+1)
1879
- trace_rule level, "(#{task_name} => #{source} ... ENHANCE)"
1880
- parent.name
1881
- else
1882
- trace_rule level, "(#{task_name} => #{source} ... FAIL)"
1883
- return nil
1884
- end
1885
- }
1886
- task = FileTask.define_task({task_name => prereqs}, &block)
1887
- task.sources = prereqs
1888
- task
1889
- end
1890
-
1891
- # Make a list of sources from the list of file name extensions /
1892
- # translation procs.
1893
- def make_sources(task_name, extensions)
1894
- extensions.collect { |ext|
1895
- case ext
1896
- when /%/
1897
- task_name.pathmap(ext)
1898
- when %r{/}
1899
- ext
1900
- when /^\./
1901
- task_name.ext(ext)
1902
- when String
1903
- ext
1904
- when Proc
1905
- if ext.arity == 1
1906
- ext.call(task_name)
1907
- else
1908
- ext.call
1909
- end
1910
- else
1911
- fail "Don't know how to handle rule dependent: #{ext.inspect}"
1912
- end
1913
- }.flatten
1914
- end
1915
-
1916
- end # TaskManager
1917
-
1918
- ######################################################################
1919
- # Rake main application object. When invoking +rake+ from the
1920
- # command line, a Rake::Application object is created and run.
1921
- #
1922
- class Application
1923
- include TaskManager
1924
-
1925
- # The name of the application (typically 'rake')
1926
- attr_reader :name
1927
-
1928
- # The original directory where rake was invoked.
1929
- attr_reader :original_dir
1930
-
1931
- # Name of the actual rakefile used.
1932
- attr_reader :rakefile
1933
-
1934
- # List of the top level task names (task names from the command line).
1935
- attr_reader :top_level_tasks
1936
-
1937
- DEFAULT_RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
1938
-
1939
- # Initialize a Rake::Application object.
1940
- def initialize
1941
- super
1942
- @name = 'rake'
1943
- @rakefiles = DEFAULT_RAKEFILES.dup
1944
- @rakefile = nil
1945
- @pending_imports = []
1946
- @imported = []
1947
- @loaders = {}
1948
- @default_loader = Rake::DefaultLoader.new
1949
- @original_dir = Dir.pwd
1950
- @top_level_tasks = []
1951
- add_loader('rb', DefaultLoader.new)
1952
- add_loader('rf', DefaultLoader.new)
1953
- add_loader('rake', DefaultLoader.new)
1954
- @tty_output = STDOUT.tty?
1955
- end
1956
-
1957
- # Run the Rake application. The run method performs the following three steps:
1958
- #
1959
- # * Initialize the command line options (+init+).
1960
- # * Define the tasks (+load_rakefile+).
1961
- # * Run the top level tasks (+run_tasks+).
1962
- #
1963
- # If you wish to build a custom rake command, you should call +init+ on your
1964
- # application. The define any tasks. Finally, call +top_level+ to run your top
1965
- # level tasks.
1966
- def run
1967
- standard_exception_handling do
1968
- init
1969
- load_rakefile
1970
- top_level
1971
- end
1972
- end
1973
-
1974
- # Initialize the command line parameters and app name.
1975
- def init(app_name='rake')
1976
- standard_exception_handling do
1977
- @name = app_name
1978
- collect_tasks handle_options
1979
- end
1980
- end
1981
-
1982
- # Find the rakefile and then load it and any pending imports.
1983
- def load_rakefile
1984
- standard_exception_handling do
1985
- raw_load_rakefile
1986
- end
1987
- end
1988
-
1989
- # Run the top level tasks of a Rake application.
1990
- def top_level
1991
- standard_exception_handling do
1992
- if options.show_tasks
1993
- display_tasks_and_comments
1994
- elsif options.show_prereqs
1995
- display_prerequisites
1996
- else
1997
- top_level_tasks.each { |task_name| invoke_task(task_name) }
1998
- end
1999
- end
2000
- end
2001
-
2002
- # Add a loader to handle imported files ending in the extension
2003
- # +ext+.
2004
- def add_loader(ext, loader)
2005
- ext = ".#{ext}" unless ext =~ /^\./
2006
- @loaders[ext] = loader
2007
- end
2008
-
2009
- # Application options from the command line
2010
- def options
2011
- @options ||= OpenStruct.new
2012
- end
2013
-
2014
- # private ----------------------------------------------------------------
2015
-
2016
- def invoke_task(task_string)
2017
- name, args = parse_task_string(task_string)
2018
- t = self[name]
2019
- t.invoke(*args)
2020
- end
2021
-
2022
- def parse_task_string(string)
2023
- if string =~ /^([^\[]+)(\[(.*)\])$/
2024
- name = $1
2025
- args = $3.split(/\s*,\s*/)
2026
- else
2027
- name = string
2028
- args = []
2029
- end
2030
- [name, args]
2031
- end
2032
-
2033
- # Provide standard execption handling for the given block.
2034
- def standard_exception_handling
2035
- begin
2036
- yield
2037
- rescue SystemExit => ex
2038
- # Exit silently with current status
2039
- exit(ex.status)
2040
- rescue SystemExit, OptionParser::InvalidOption => ex
2041
- # Exit silently
2042
- exit(1)
2043
- rescue Exception => ex
2044
- # Exit with error message
2045
- $stderr.puts "rake aborted!"
2046
- $stderr.puts ex.message
2047
- if options.trace
2048
- $stderr.puts ex.backtrace.join("\n")
2049
- else
2050
- $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
2051
- $stderr.puts "(See full trace by running task with --trace)"
2052
- end
2053
- exit(1)
2054
- end
2055
- end
2056
-
2057
- # True if one of the files in RAKEFILES is in the current directory.
2058
- # If a match is found, it is copied into @rakefile.
2059
- def have_rakefile
2060
- @rakefiles.each do |fn|
2061
- if File.exist?(fn) || fn == ''
2062
- return fn
2063
- end
2064
- end
2065
- return nil
2066
- end
2067
-
2068
- # True if we are outputting to TTY, false otherwise
2069
- def tty_output?
2070
- @tty_output
2071
- end
2072
-
2073
- # Override the detected TTY output state (mostly for testing)
2074
- def tty_output=( tty_output_state )
2075
- @tty_output = tty_output_state
2076
- end
2077
-
2078
- # We will truncate output if we are outputting to a TTY or if we've been
2079
- # given an explicit column width to honor
2080
- def truncate_output?
2081
- tty_output? || ENV['RAKE_COLUMNS']
2082
- end
2083
-
2084
- # Display the tasks and dependencies.
2085
- def display_tasks_and_comments
2086
- displayable_tasks = tasks.select { |t|
2087
- t.comment && t.name =~ options.show_task_pattern
2088
- }
2089
- if options.full_description
2090
- displayable_tasks.each do |t|
2091
- puts "rake #{t.name_with_args}"
2092
- t.full_comment.split("\n").each do |line|
2093
- puts " #{line}"
2094
- end
2095
- puts
2096
- end
2097
- else
2098
- width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
2099
- max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
2100
- displayable_tasks.each do |t|
2101
- printf "#{name} %-#{width}s # %s\n",
2102
- t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
2103
- end
2104
- end
2105
- end
2106
-
2107
- def terminal_width
2108
- if ENV['RAKE_COLUMNS']
2109
- result = ENV['RAKE_COLUMNS'].to_i
2110
- else
2111
- result = unix? ? dynamic_width : 80
2112
- end
2113
- (result < 10) ? 80 : result
2114
- rescue
2115
- 80
2116
- end
2117
-
2118
- # Calculate the dynamic width of the
2119
- def dynamic_width
2120
- @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
2121
- end
2122
-
2123
- def dynamic_width_stty
2124
- %x{stty size 2>/dev/null}.split[1].to_i
2125
- end
2126
-
2127
- def dynamic_width_tput
2128
- %x{tput cols 2>/dev/null}.to_i
2129
- end
2130
-
2131
- def unix?
2132
- RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
2133
- end
2134
-
2135
- def windows?
2136
- Win32.windows?
2137
- end
2138
-
2139
- def truncate(string, width)
2140
- if string.length <= width
2141
- string
2142
- else
2143
- ( string[0, width-3] || "" ) + "..."
2144
- end
2145
- end
2146
-
2147
- # Display the tasks and prerequisites
2148
- def display_prerequisites
2149
- tasks.each do |t|
2150
- puts "rake #{t.name}"
2151
- t.prerequisites.each { |pre| puts " #{pre}" }
2152
- end
2153
- end
2154
-
2155
- # A list of all the standard options used in rake, suitable for
2156
- # passing to OptionParser.
2157
- def standard_rake_options
2158
- [
2159
- ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
2160
- lambda { |value|
2161
- require 'rake/classic_namespace'
2162
- options.classic_namespace = true
2163
- }
2164
- ],
2165
- ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
2166
- lambda { |value|
2167
- options.show_tasks = true
2168
- options.full_description = true
2169
- options.show_task_pattern = Regexp.new(value || '')
2170
- }
2171
- ],
2172
- ['--dry-run', '-n', "Do a dry run without executing actions.",
2173
- lambda { |value|
2174
- verbose(true)
2175
- nowrite(true)
2176
- options.dryrun = true
2177
- options.trace = true
2178
- }
2179
- ],
2180
- ['--execute', '-e CODE', "Execute some Ruby code and exit.",
2181
- lambda { |value|
2182
- eval(value)
2183
- exit
2184
- }
2185
- ],
2186
- ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.",
2187
- lambda { |value|
2188
- puts eval(value)
2189
- exit
2190
- }
2191
- ],
2192
- ['--execute-continue', '-E CODE',
2193
- "Execute some Ruby code, then continue with normal task processing.",
2194
- lambda { |value| eval(value) }
2195
- ],
2196
- ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
2197
- lambda { |value| $:.push(value) }
2198
- ],
2199
- ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
2200
- lambda { |value| options.show_prereqs = true }
2201
- ],
2202
- ['--quiet', '-q', "Do not log messages to standard output.",
2203
- lambda { |value| verbose(false) }
2204
- ],
2205
- ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
2206
- lambda { |value|
2207
- value ||= ''
2208
- @rakefiles.clear
2209
- @rakefiles << value
2210
- }
2211
- ],
2212
- ['--rakelibdir', '--rakelib', '-R RAKELIBDIR',
2213
- "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')",
2214
- lambda { |value| options.rakelib = value.split(':') }
2215
- ],
2216
- ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
2217
- lambda { |value|
2218
- begin
2219
- require value
2220
- rescue LoadError => ex
2221
- begin
2222
- rake_require value
2223
- rescue LoadError => ex2
2224
- raise ex
2225
- end
2226
- end
2227
- }
2228
- ],
2229
- ['--rules', "Trace the rules resolution.",
2230
- lambda { |value| options.trace_rules = true }
2231
- ],
2232
- ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
2233
- lambda { |value| options.nosearch = true }
2234
- ],
2235
- ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
2236
- lambda { |value|
2237
- verbose(false)
2238
- options.silent = true
2239
- }
2240
- ],
2241
- ['--system', '-g',
2242
- "Using system wide (global) rakefiles (usually '~/.rake/*.rake').",
2243
- lambda { |value| options.load_system = true }
2244
- ],
2245
- ['--no-system', '--nosystem', '-G',
2246
- "Use standard project Rakefile search paths, ignore system wide rakefiles.",
2247
- lambda { |value| options.ignore_system = true }
2248
- ],
2249
- ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
2250
- lambda { |value|
2251
- options.show_tasks = true
2252
- options.show_task_pattern = Regexp.new(value || '')
2253
- options.full_description = false
2254
- }
2255
- ],
2256
- ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
2257
- lambda { |value|
2258
- options.trace = true
2259
- verbose(true)
2260
- }
2261
- ],
2262
- ['--verbose', '-v', "Log message to standard output (default).",
2263
- lambda { |value| verbose(true) }
2264
- ],
2265
- ['--version', '-V', "Display the program version.",
2266
- lambda { |value|
2267
- puts "rake, version #{RAKEVERSION}"
2268
- exit
2269
- }
2270
- ]
2271
- ]
2272
- end
2273
-
2274
- # Read and handle the command line options.
2275
- def handle_options
2276
- options.rakelib = ['rakelib']
2277
-
2278
- opts = OptionParser.new
2279
- opts.banner = "rake [-f rakefile] {options} targets..."
2280
- opts.separator ""
2281
- opts.separator "Options are ..."
2282
-
2283
- opts.on_tail("-h", "--help", "-H", "Display this help message.") do
2284
- puts opts
2285
- exit
2286
- end
2287
-
2288
- standard_rake_options.each { |args| opts.on(*args) }
2289
- parsed_argv = opts.parse(ARGV)
2290
-
2291
- # If class namespaces are requested, set the global options
2292
- # according to the values in the options structure.
2293
- if options.classic_namespace
2294
- $show_tasks = options.show_tasks
2295
- $show_prereqs = options.show_prereqs
2296
- $trace = options.trace
2297
- $dryrun = options.dryrun
2298
- $silent = options.silent
2299
- end
2300
- parsed_argv
2301
- end
2302
-
2303
- # Similar to the regular Ruby +require+ command, but will check
2304
- # for *.rake files in addition to *.rb files.
2305
- def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
2306
- return false if loaded.include?(file_name)
2307
- paths.each do |path|
2308
- fn = file_name + ".rake"
2309
- full_path = File.join(path, fn)
2310
- if File.exist?(full_path)
2311
- load full_path
2312
- loaded << fn
2313
- return true
2314
- end
2315
- end
2316
- fail LoadError, "Can't find #{file_name}"
2317
- end
2318
-
2319
- def find_rakefile_location
2320
- here = Dir.pwd
2321
- while ! (fn = have_rakefile)
2322
- Dir.chdir("..")
2323
- if Dir.pwd == here || options.nosearch
2324
- return nil
2325
- end
2326
- here = Dir.pwd
2327
- end
2328
- [fn, here]
2329
- ensure
2330
- Dir.chdir(Rake.original_dir)
2331
- end
2332
-
2333
- def raw_load_rakefile # :nodoc:
2334
- rakefile, location = find_rakefile_location
2335
- if (! options.ignore_system) &&
2336
- (options.load_system || rakefile.nil?) &&
2337
- system_dir && File.directory?(system_dir)
2338
- puts "(in #{Dir.pwd})" unless options.silent
2339
- glob("#{system_dir}/*.rake") do |name|
2340
- add_import name
2341
- end
2342
- else
2343
- fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if
2344
- rakefile.nil?
2345
- @rakefile = rakefile
2346
- Dir.chdir(location)
2347
- puts "(in #{Dir.pwd})" unless options.silent
2348
- $rakefile = @rakefile if options.classic_namespace
2349
- load File.expand_path(@rakefile) if @rakefile && @rakefile != ''
2350
- options.rakelib.each do |rlib|
2351
- glob("#{rlib}/*.rake") do |name|
2352
- add_import name
2353
- end
2354
- end
2355
- end
2356
- load_imports
2357
- end
2358
-
2359
- def glob(path, &block)
2360
- Dir[path.gsub("\\", '/')].each(&block)
2361
- end
2362
- private :glob
2363
-
2364
- # The directory path containing the system wide rakefiles.
2365
- def system_dir
2366
- @system_dir ||=
2367
- begin
2368
- if ENV['RAKE_SYSTEM']
2369
- ENV['RAKE_SYSTEM']
2370
- elsif Win32.windows?
2371
- Win32.win32_system_dir
2372
- else
2373
- standard_system_dir
2374
- end
2375
- end
2376
- end
2377
-
2378
- # The standard directory containing system wide rake files.
2379
- def standard_system_dir #:nodoc:
2380
- File.join(File.expand_path('~'), '.rake')
2381
- end
2382
- private :standard_system_dir
2383
-
2384
- # Collect the list of tasks on the command line. If no tasks are
2385
- # given, return a list containing only the default task.
2386
- # Environmental assignments are processed at this time as well.
2387
- def collect_tasks(argv)
2388
- @top_level_tasks = []
2389
- argv.each do |arg|
2390
- if arg =~ /^(\w+)=(.*)$/
2391
- ENV[$1] = $2
2392
- else
2393
- @top_level_tasks << arg unless arg =~ /^-/
2394
- end
2395
- end
2396
- @top_level_tasks.push("default") if @top_level_tasks.size == 0
2397
- end
2398
-
2399
- # Add a file to the list of files to be imported.
2400
- def add_import(fn)
2401
- @pending_imports << fn
2402
- end
2403
-
2404
- # Load the pending list of imported files.
2405
- def load_imports
2406
- while fn = @pending_imports.shift
2407
- next if @imported.member?(fn)
2408
- if fn_task = lookup(fn)
2409
- fn_task.invoke
2410
- end
2411
- ext = File.extname(fn)
2412
- loader = @loaders[ext] || @default_loader
2413
- loader.load(fn)
2414
- @imported << fn
2415
- end
2416
- end
2417
-
2418
- # Warn about deprecated use of top level constant names.
2419
- def const_warning(const_name)
2420
- @const_warning ||= false
2421
- if ! @const_warning
2422
- $stderr.puts %{WARNING: Deprecated reference to top-level constant '#{const_name}' } +
2423
- %{found at: #{rakefile_location}} # '
2424
- $stderr.puts %{ Use --classic-namespace on rake command}
2425
- $stderr.puts %{ or 'require "rake/classic_namespace"' in Rakefile}
2426
- end
2427
- @const_warning = true
2428
- end
2429
-
2430
- def rakefile_location
2431
- begin
2432
- fail
2433
- rescue RuntimeError => ex
2434
- ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
2435
- end
2436
- end
2437
- end
2438
- end
2439
-
2440
-
2441
- class Module
2442
- # Rename the original handler to make it available.
2443
- alias :rake_original_const_missing :const_missing
2444
-
2445
- # Check for deprecated uses of top level (i.e. in Object) uses of
2446
- # Rake class names. If someone tries to reference the constant
2447
- # name, display a warning and return the proper object. Using the
2448
- # --classic-namespace command line option will define these
2449
- # constants in Object and avoid this handler.
2450
- def const_missing(const_name)
2451
- case const_name
2452
- when :Task
2453
- Rake.application.const_warning(const_name)
2454
- Rake::Task
2455
- when :FileTask
2456
- Rake.application.const_warning(const_name)
2457
- Rake::FileTask
2458
- when :FileCreationTask
2459
- Rake.application.const_warning(const_name)
2460
- Rake::FileCreationTask
2461
- when :RakeApp
2462
- Rake.application.const_warning(const_name)
2463
- Rake::Application
2464
- else
2465
- rake_original_const_missing(const_name)
2466
- end
2467
- end
2468
- end