ratch 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.ruby +99 -0
- data/COPYING +203 -21
- data/History.rdoc +35 -0
- data/License.txt +204 -0
- data/README.rdoc +113 -0
- data/Version +1 -0
- data/bin/ludo +16 -0
- data/bin/ratch +1 -8
- data/lib/ratch.rb +28 -0
- data/lib/ratch.yml +99 -0
- data/lib/ratch/batch.rb +500 -0
- data/lib/ratch/console.rb +199 -0
- data/lib/ratch/core_ext.rb +1 -4
- data/lib/ratch/core_ext/facets.rb +15 -1
- data/lib/ratch/core_ext/filetest.rb +29 -0
- data/lib/ratch/core_ext/{string.rb → to_actual_filename.rb} +0 -23
- data/lib/ratch/core_ext/to_console.rb +30 -12
- data/lib/ratch/core_ext/{object.rb → to_yamlfrag.rb} +1 -0
- data/lib/ratch/core_ext/unfold_paragraphs.rb +27 -0
- data/lib/ratch/file_list.rb +411 -0
- data/lib/ratch/script.rb +99 -5
- data/lib/ratch/script/help.rb +84 -0
- data/lib/ratch/shell.rb +783 -0
- data/lib/ratch/system.rb +15 -0
- data/lib/ratch/utils/cli.rb +49 -0
- data/lib/ratch/utils/config.rb +52 -0
- data/lib/ratch/{emailer.rb → utils/email.rb} +43 -6
- data/lib/ratch/utils/ftp.rb +134 -0
- data/lib/ratch/utils/pom.rb +22 -0
- data/lib/ratch/utils/rdoc.rb +48 -0
- data/lib/ratch/utils/tar.rb +88 -0
- data/lib/ratch/utils/xdg.rb +39 -0
- data/lib/ratch/utils/zlib.rb +54 -0
- data/spec/01_shell.rdoc +198 -0
- data/spec/02_script.rdoc +34 -0
- data/spec/03_batch.rdoc +71 -0
- data/spec/04_system.rdoc +3 -0
- data/spec/applique/array.rb +8 -0
- data/spec/applique/setup.rb +20 -0
- data/test/case_batch.rb +63 -0
- data/test/case_shell.rb +46 -0
- data/test/core_ext/case_pathname.rb +361 -0
- data/test/helper.rb +4 -0
- data/test/utils/case_cli.rb +6 -0
- data/test/utils/case_config.rb +12 -0
- data/test/utils/case_email.rb +10 -0
- data/test/utils/case_ftp.rb +6 -0
- data/test/utils/case_pom.rb +17 -0
- data/test/utils/case_rdoc.rb +23 -0
- data/test/utils/case_tar.rb +6 -0
- data/test/utils/case_zlib.rb +11 -0
- data/test/utils/fixtures/pom_sample/Profile +4 -0
- data/test/utils/fixtures/rdoc_sample/README.rdoc +4 -0
- data/test/utils/fixtures/rdoc_sample/lib/rdoc_sample/rdoc_sample.rb +9 -0
- metadata +139 -82
- data/HISTORY +0 -6
- data/MANIFEST +0 -53
- data/NEWS +0 -12
- data/README +0 -87
- data/VERSION +0 -1
- data/demo/tryme-task.ratch +0 -12
- data/demo/tryme1.ratch +0 -6
- data/doc/log/basic_stats/index.html +0 -39
- data/doc/log/notes.xml +0 -18
- data/doc/log/stats.log +0 -14
- data/doc/log/syntax.log +0 -0
- data/doc/log/testunit.log +0 -156
- data/lib/ratch/commandline.rb +0 -16
- data/lib/ratch/core_ext/pathname.rb +0 -38
- data/lib/ratch/dsl.rb +0 -420
- data/lib/ratch/index.rb +0 -4
- data/lib/ratch/io.rb +0 -116
- data/lib/ratch/plugin.rb +0 -65
- data/lib/ratch/service.rb +0 -33
- data/lib/ratch/task.rb +0 -249
- data/lib/ratch/task2.rb +0 -298
- data/meta/abstract +0 -4
- data/meta/author +0 -1
- data/meta/contact +0 -1
- data/meta/homepage +0 -1
- data/meta/name +0 -1
- data/meta/requires +0 -4
- data/meta/summary +0 -1
- data/test/README +0 -1
- data/test/test_helper.rb +0 -4
- data/test/test_task.rb +0 -46
data/README.rdoc
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
= Ratch
|
2
|
+
|
3
|
+
Ruby-based Batch Scripts
|
4
|
+
|
5
|
+
|
6
|
+
== Introduction
|
7
|
+
|
8
|
+
Ratch is Ruby-based DSL for building batch scripts. It's intent
|
9
|
+
is to ease the burden of batch script writers by supplementing
|
10
|
+
the standard ruby environment to be more conducive to the needs
|
11
|
+
of batch scripting.
|
12
|
+
|
13
|
+
In addition to using Ratch to write stand-alone batch scripts,
|
14
|
+
it makes a very powerful library for other applications that
|
15
|
+
require batch-like functionality. In general any program that
|
16
|
+
access the file system extensively could benefit from it's use.
|
17
|
+
|
18
|
+
|
19
|
+
== Resources
|
20
|
+
|
21
|
+
* home: http://rubyworks.github.com/ratch
|
22
|
+
* code: http://github.com/rubyworks/ratch
|
23
|
+
* talk: http://googlegroups.com/
|
24
|
+
|
25
|
+
== Usage
|
26
|
+
|
27
|
+
=== Batch Scripting
|
28
|
+
|
29
|
+
To use for your own scripts, simply add a bang line.
|
30
|
+
|
31
|
+
#!/usr/bin/env ratch
|
32
|
+
|
33
|
+
On Windows, of course, you will want to associate the .ratch extension
|
34
|
+
name to the ratch executable instead.
|
35
|
+
|
36
|
+
=== As a Library
|
37
|
+
|
38
|
+
To use Ratch as a library, require 'ratch' and create an instance of
|
39
|
+
Ratch::Shell.
|
40
|
+
|
41
|
+
If you wish to extend Ratch::Shell for your application, it is recommend
|
42
|
+
that you either subclass Ratch::Shell, e.g.
|
43
|
+
|
44
|
+
require 'ratch'
|
45
|
+
|
46
|
+
class MyClass < Ratch::Shell
|
47
|
+
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
Or delegate to a Ratch::Shell instance, e.g.
|
52
|
+
|
53
|
+
require 'ratch'
|
54
|
+
|
55
|
+
class MyClass
|
56
|
+
|
57
|
+
def initialize(path)
|
58
|
+
@shell = Ratch::Shell.new(path)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
For details on all the functionality Ratch provides, please refer to
|
64
|
+
the API documentation.
|
65
|
+
|
66
|
+
|
67
|
+
== Bonus Feature
|
68
|
+
|
69
|
+
Ratch also includes the `ludo` command, which stands for "lookup and do".
|
70
|
+
It will ascend up the directory tree searching for a matching executable
|
71
|
+
script. If it finds one it will execute the script relative the currently
|
72
|
+
ascended directory.
|
73
|
+
|
74
|
+
|
75
|
+
== Installation
|
76
|
+
|
77
|
+
Standard installation procedure apply.
|
78
|
+
|
79
|
+
$ gem install ratch
|
80
|
+
|
81
|
+
or manually using Setup.rb
|
82
|
+
|
83
|
+
$ tar -xzf ratch-1.0.0.tgz
|
84
|
+
$ cd ratch-1.0.0
|
85
|
+
$ setup.rb
|
86
|
+
|
87
|
+
|
88
|
+
== Development
|
89
|
+
|
90
|
+
Ratch is hosted on GitHub.
|
91
|
+
|
92
|
+
To pull the 'ratch' repository anonymously, use:
|
93
|
+
|
94
|
+
git clone git://github.com/rubyworks/ratch.git
|
95
|
+
|
96
|
+
|
97
|
+
== Copying
|
98
|
+
|
99
|
+
Copyright (c) 2008 Thomas Sawyer
|
100
|
+
|
101
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
102
|
+
you may not use this program except in compliance with the License.
|
103
|
+
You may obtain a copy of the License at
|
104
|
+
|
105
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
106
|
+
|
107
|
+
Unless required by applicable law or agreed to in writing, software
|
108
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
109
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
110
|
+
See the License for the specific language governing permissions and
|
111
|
+
limitations under the License.
|
112
|
+
|
113
|
+
|
data/Version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.2.0
|
data/bin/ludo
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#! /usr/bin/ruby1.8
|
2
|
+
|
3
|
+
# for FileTest.root?
|
4
|
+
require 'facets/filetest'
|
5
|
+
|
6
|
+
name = ARGV[0]
|
7
|
+
|
8
|
+
if name
|
9
|
+
Dir.chdir '..' until FileTest.executable?(name) or FileTest.root?(Dir.pwd)
|
10
|
+
if FileTest.executable?( name )
|
11
|
+
system name
|
12
|
+
end
|
13
|
+
else
|
14
|
+
puts "Script #{name} not found."
|
15
|
+
end
|
16
|
+
|
data/bin/ratch
CHANGED
data/lib/ratch.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Ratch
|
2
|
+
# Access to project metadata.
|
3
|
+
def self.metadata
|
4
|
+
@metadata ||= (
|
5
|
+
require 'yaml'
|
6
|
+
YAML.load(File.dirname(__FILE__) + '/ratch.yml')
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Access to project metadata via constants.
|
11
|
+
def self.const_missing(name)
|
12
|
+
metadata[name.to_s.downcase] || super(name)
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: Only here b/c of issue with Ruby 1.8.x.
|
16
|
+
VERSION = metadata['version']
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'ratch/script'
|
20
|
+
|
21
|
+
# Load utility extension modules.
|
22
|
+
require 'ratch/utils/cli'
|
23
|
+
require 'ratch/utils/pom'
|
24
|
+
require 'ratch/utils/rdoc'
|
25
|
+
#require 'ratch/utils/email'
|
26
|
+
#require 'ratch/utils/tar'
|
27
|
+
#require 'ratch/utils/zlib'
|
28
|
+
|
data/lib/ratch.yml
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
---
|
2
|
+
name: ratch
|
3
|
+
spec_version: 1.0.0
|
4
|
+
repositories:
|
5
|
+
public: git://github.com/rubyworks/ratch.git
|
6
|
+
title: Ratch
|
7
|
+
contact: trans <transfire@gmail.com>
|
8
|
+
requires:
|
9
|
+
- group: []
|
10
|
+
|
11
|
+
name: facets
|
12
|
+
version: 2.9.1+
|
13
|
+
- group: []
|
14
|
+
|
15
|
+
name: minitar
|
16
|
+
version: 0.5.3+
|
17
|
+
- group:
|
18
|
+
- test
|
19
|
+
name: ko
|
20
|
+
version: 1.2.0~
|
21
|
+
- group:
|
22
|
+
- test
|
23
|
+
name: qed
|
24
|
+
version: 0+
|
25
|
+
- group:
|
26
|
+
- build
|
27
|
+
name: syckle
|
28
|
+
version: 0+
|
29
|
+
resources:
|
30
|
+
code: http://github.org/rubyworks/ratch
|
31
|
+
mail: http://groups.gooogle.com/group/rubyworks-mailinglist
|
32
|
+
home: http://rubyworks.github.org/ratch
|
33
|
+
manifest:
|
34
|
+
- .ruby
|
35
|
+
- bin/ludo
|
36
|
+
- bin/ratch
|
37
|
+
- lib/ratch/batch.rb
|
38
|
+
- lib/ratch/console.rb
|
39
|
+
- lib/ratch/core_ext/facets.rb
|
40
|
+
- lib/ratch/core_ext/filetest.rb
|
41
|
+
- lib/ratch/core_ext/to_actual_filename.rb
|
42
|
+
- lib/ratch/core_ext/to_console.rb
|
43
|
+
- lib/ratch/core_ext/to_list.rb
|
44
|
+
- lib/ratch/core_ext/to_yamlfrag.rb
|
45
|
+
- lib/ratch/core_ext/unfold_paragraphs.rb
|
46
|
+
- lib/ratch/core_ext.rb
|
47
|
+
- lib/ratch/file_list.rb
|
48
|
+
- lib/ratch/script/help.rb
|
49
|
+
- lib/ratch/script.rb
|
50
|
+
- lib/ratch/shell.rb
|
51
|
+
- lib/ratch/system.rb
|
52
|
+
- lib/ratch/utils/cli.rb
|
53
|
+
- lib/ratch/utils/config.rb
|
54
|
+
- lib/ratch/utils/email.rb
|
55
|
+
- lib/ratch/utils/ftp.rb
|
56
|
+
- lib/ratch/utils/pom.rb
|
57
|
+
- lib/ratch/utils/rdoc.rb
|
58
|
+
- lib/ratch/utils/tar.rb
|
59
|
+
- lib/ratch/utils/xdg.rb
|
60
|
+
- lib/ratch/utils/zlib.rb
|
61
|
+
- lib/ratch.rb
|
62
|
+
- lib/ratch.yml
|
63
|
+
- man/ratch.1
|
64
|
+
- spec/01_shell.rdoc
|
65
|
+
- spec/02_script.rdoc
|
66
|
+
- spec/03_batch.rdoc
|
67
|
+
- spec/04_system.rdoc
|
68
|
+
- spec/applique/array.rb
|
69
|
+
- spec/applique/setup.rb
|
70
|
+
- test/case_batch.rb
|
71
|
+
- test/case_shell.rb
|
72
|
+
- test/core_ext/case_pathname.rb
|
73
|
+
- test/helper.rb
|
74
|
+
- test/utils/case_cli.rb
|
75
|
+
- test/utils/case_config.rb
|
76
|
+
- test/utils/case_email.rb
|
77
|
+
- test/utils/case_ftp.rb
|
78
|
+
- test/utils/case_pom.rb
|
79
|
+
- test/utils/case_rdoc.rb
|
80
|
+
- test/utils/case_tar.rb
|
81
|
+
- test/utils/case_zlib.rb
|
82
|
+
- test/utils/fixtures/pom_sample/Profile
|
83
|
+
- test/utils/fixtures/rdoc_sample/README.rdoc
|
84
|
+
- test/utils/fixtures/rdoc_sample/lib/rdoc_sample/rdoc_sample.rb
|
85
|
+
- README.rdoc
|
86
|
+
- History.rdoc
|
87
|
+
- Version
|
88
|
+
- License.txt
|
89
|
+
- COPYING
|
90
|
+
version: 1.2.0
|
91
|
+
licenses:
|
92
|
+
- Apache 2.0
|
93
|
+
copyright: Copyright (c) 2009 Thomas Sawyer
|
94
|
+
description: Ratch is a Ruby-based batch scripting language. It's a DSL over regular Ruby to make the life of the batch script writter easier.
|
95
|
+
summary: Ruby-based Batch Scripting
|
96
|
+
organization: RubyWorks
|
97
|
+
authors:
|
98
|
+
- Trans <transfire@gmail.com>
|
99
|
+
created: 2009-09-22
|
data/lib/ratch/batch.rb
ADDED
@@ -0,0 +1,500 @@
|
|
1
|
+
require 'ratch/core_ext'
|
2
|
+
require 'ratch/file_list'
|
3
|
+
|
4
|
+
module Ratch
|
5
|
+
|
6
|
+
# Proccess a list of files in batch.
|
7
|
+
#
|
8
|
+
# The Batch interface mimics the Shell class in most respects.
|
9
|
+
#
|
10
|
+
# TODO: Should FileList use Pathname, or only in Batch?
|
11
|
+
class Batch
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
#
|
15
|
+
def self.[](*patterns)
|
16
|
+
new('.', *patterns)
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
def initialize(local, *patterns)
|
21
|
+
@local = Pathname.new(local)
|
22
|
+
@options = (Hash === patterns.last ? patterns.pop : {}).rekey(&:to_sym)
|
23
|
+
|
24
|
+
@file_list = FileList.all
|
25
|
+
|
26
|
+
patterns.each do |pattern|
|
27
|
+
if @local == Pathname.new('.')
|
28
|
+
@file_list.add(pattern)
|
29
|
+
else
|
30
|
+
@file_list.add(File.join(local,pattern))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
attr :local
|
37
|
+
|
38
|
+
# Returns the the underlying FileList object.
|
39
|
+
def file_list
|
40
|
+
@file_list
|
41
|
+
end
|
42
|
+
|
43
|
+
# Iterate over pathnames.
|
44
|
+
def each(&block)
|
45
|
+
@file_list.each{ |file| block.call(Pathname.new(file)) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the Integer size of the list of files.
|
49
|
+
def size
|
50
|
+
@file_list.size
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the list of files as Pathname objects.
|
54
|
+
def to_a
|
55
|
+
@file_list.map{ |file| Pathname.new(file) }
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return the list of files as Pathname objects.
|
59
|
+
alias_method :pathnames, :to_a
|
60
|
+
|
61
|
+
# Returns the list of files as Strings, rather than Pathname objects.
|
62
|
+
def list
|
63
|
+
@file_list.to_a
|
64
|
+
end
|
65
|
+
alias_method :filenames, :list
|
66
|
+
|
67
|
+
# Returns an Array of file paths relative to +local+.
|
68
|
+
def entries
|
69
|
+
map{ |entry| entry.sub(local.to_s+'/','') }
|
70
|
+
end
|
71
|
+
|
72
|
+
# Limit list to files.
|
73
|
+
def file!
|
74
|
+
@file_list = @file_list.select{ |f| File.file?(f) }
|
75
|
+
end
|
76
|
+
|
77
|
+
# Limit list to directories.
|
78
|
+
def directory!
|
79
|
+
@file_list = @file_list.select{ |f| File.directory?(f) }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Limit list to selection block.
|
83
|
+
def select!(&block)
|
84
|
+
#@file_list = FileList.all(*to_a.select{ |f| block.call(f) })
|
85
|
+
@file_list = @file_list.select{ |f| block.call(f) }
|
86
|
+
end
|
87
|
+
|
88
|
+
#############
|
89
|
+
# FileTest #
|
90
|
+
#############
|
91
|
+
|
92
|
+
# This is called #size in FileTest but must be renamed to
|
93
|
+
# avoid the clash with the Enumerable mixin.
|
94
|
+
def byte_size
|
95
|
+
inject(0){ |sum, path| sum + FileTest.size(path) }
|
96
|
+
end
|
97
|
+
|
98
|
+
# An alias for #byte_size.
|
99
|
+
alias_method :size?, :byte_size
|
100
|
+
|
101
|
+
def directory? ; all?{ |path| FileTest.directory?(path) } ; end
|
102
|
+
def symlink? ; all?{ |path| FileTest.symlink?(path) } ; end
|
103
|
+
def readable? ; all?{ |path| FileTest.readable?(path) } ; end
|
104
|
+
def chardev? ; all?{ |path| FileTest.chardev?(path) } ; end
|
105
|
+
def exist? ; all?{ |path| FileTest.exist?(path) } ; end
|
106
|
+
def exists? ; all?{ |path| FileTest.exists?(path) } ; end
|
107
|
+
def zero? ; all?{ |path| FileTest.zero?(path) } ; end
|
108
|
+
def pipe? ; all?{ |path| FileTest.pipe?(path) } ; end
|
109
|
+
def file? ; all?{ |path| FileTest.file?(path) } ; end
|
110
|
+
def sticky? ; all?{ |path| FileTest.sticky?(path) } ; end
|
111
|
+
def blockdev? ; all?{ |path| FileTest.blockdev?(path) } ; end
|
112
|
+
def grpowned? ; all?{ |path| FileTest.grpowned?(path) } ; end
|
113
|
+
def setgid? ; all?{ |path| FileTest.setgid?(path) } ; end
|
114
|
+
def setuid? ; all?{ |path| FileTest.setuid?(path) } ; end
|
115
|
+
def socket? ; all?{ |path| FileTest.socket?(path) } ; end
|
116
|
+
def owned? ; all?{ |path| FileTest.owned?(path) } ; end
|
117
|
+
def writable? ; all?{ |path| FileTest.writable?(path) } ; end
|
118
|
+
def executable? ; all?{ |path| FileTest.executable?(path) } ; end
|
119
|
+
def safe? ; all?{ |path| FileTest.safe?(path) } ; end
|
120
|
+
|
121
|
+
# TODO: Will this work since all paths are localized?
|
122
|
+
def relative? ; all?{ |path| FileTest.relative?(path) } ; end
|
123
|
+
def absolute? ; all?{ |path| FileTest.absolute?(path) } ; end
|
124
|
+
|
125
|
+
def writable_real? ; all?{ |path| FileTest.writable_real?(path) } ; end
|
126
|
+
def executable_real? ; all?{ |path| FileTest.executable_real?(path) } ; end
|
127
|
+
def readable_real? ; all?{ |path| FileTest.readable_real?(path) } ; end
|
128
|
+
|
129
|
+
alias_method :dir?, :directory?
|
130
|
+
|
131
|
+
def identical?(other)
|
132
|
+
all?{ |path| FileTest.identical?(path, other) }
|
133
|
+
end
|
134
|
+
|
135
|
+
# TODO: Really?
|
136
|
+
alias_method :compare_file, :identical?
|
137
|
+
alias_method :cmp, :identical?
|
138
|
+
|
139
|
+
|
140
|
+
#############
|
141
|
+
# FileUtils #
|
142
|
+
#############
|
143
|
+
|
144
|
+
# Low-level Methods Omitted
|
145
|
+
# -------------------------
|
146
|
+
# getwd -> pwd
|
147
|
+
# compare_file -> cmp
|
148
|
+
# remove_file -> rm
|
149
|
+
# copy_file -> cp
|
150
|
+
# remove_dir -> rmdir
|
151
|
+
# safe_unlink -> rm_f
|
152
|
+
# makedirs -> mkdir_p
|
153
|
+
# rmtree -> rm_rf
|
154
|
+
# copy_stream
|
155
|
+
# remove_entry
|
156
|
+
# copy_entry
|
157
|
+
# remove_entry_secure
|
158
|
+
# compare_stream
|
159
|
+
|
160
|
+
# Present working directory.
|
161
|
+
# TODO: Does this make sense?
|
162
|
+
def pwd
|
163
|
+
@local
|
164
|
+
end
|
165
|
+
|
166
|
+
# Make a directory for every entry.
|
167
|
+
def mkdir(options={})
|
168
|
+
list.each do |dir|
|
169
|
+
if File.exist?(dir)
|
170
|
+
raise Errno::EEXIST, "File exists - #{dir}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
list.map{ |dir| fileutils.mkdir(dir, options) }
|
174
|
+
end
|
175
|
+
|
176
|
+
# Make a directory for every entry.
|
177
|
+
def mkdir_p(options={})
|
178
|
+
list.each do |dir|
|
179
|
+
if File.exist?(dir) && !File.directory?(dir)
|
180
|
+
raise Errno::EEXIST, "File exists - #{dir}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
list.map{ |dir| fileutils.mkdir_p(dir, options) }
|
184
|
+
end
|
185
|
+
alias_method :mkpath, :mkdir_p
|
186
|
+
|
187
|
+
# Remove every directory.
|
188
|
+
def rmdir(options={})
|
189
|
+
list.map{ |dir| fileutils.rmdir(dir, options) }
|
190
|
+
end
|
191
|
+
|
192
|
+
# ln(list, destdir, options={})
|
193
|
+
def ln(dir, options={})
|
194
|
+
#src = list.to_a
|
195
|
+
#new = localize(new)
|
196
|
+
fileutils.ln(list, dir, options)
|
197
|
+
end
|
198
|
+
alias_method :link, :ln
|
199
|
+
|
200
|
+
# ln_s(list, destdir, options={})
|
201
|
+
def ln_s(dir, options={})
|
202
|
+
#src = list.to_a
|
203
|
+
#new = localize(new)
|
204
|
+
fileutils.ln_s(list, dir, options)
|
205
|
+
end
|
206
|
+
alias_method :symlink, :ln_s
|
207
|
+
|
208
|
+
def ln_sf(dir, options={})
|
209
|
+
#src = list.to_a
|
210
|
+
#new = localize(new)
|
211
|
+
fileutils.ln_sf(list, dir, options)
|
212
|
+
end
|
213
|
+
|
214
|
+
# cp(list, dir, options={})
|
215
|
+
def cp(dir, options={})
|
216
|
+
#src = list.to_a
|
217
|
+
#dest = localize(dest)
|
218
|
+
fileutils.cp(list, dir, options)
|
219
|
+
end
|
220
|
+
alias_method :copy, :cp
|
221
|
+
|
222
|
+
# cp_r(list, dir, options={})
|
223
|
+
def cp_r(dir, options={})
|
224
|
+
#src = list.to_a
|
225
|
+
#dest = localize(dest)
|
226
|
+
fileutils.cp_r(list, dir, options)
|
227
|
+
end
|
228
|
+
|
229
|
+
# mv(list, dir, options={})
|
230
|
+
def mv(dir, options={})
|
231
|
+
#src = list.to_a
|
232
|
+
#dest = localize(dest)
|
233
|
+
fileutils.mv(list, dir, options)
|
234
|
+
end
|
235
|
+
alias_method :move, :mv
|
236
|
+
|
237
|
+
#
|
238
|
+
def rm(options={})
|
239
|
+
list = list.to_a
|
240
|
+
fileutils.rm(list, options)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Alias for #rm.
|
244
|
+
alias_method :remove, :rm
|
245
|
+
|
246
|
+
# Remove, recursively removing the contents of directories.
|
247
|
+
def rm_r(options={})
|
248
|
+
#list = list.to_a
|
249
|
+
fileutils.rm_r(list, options)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Remove, with force option.
|
253
|
+
def rm_f(options={})
|
254
|
+
#list = list.to_a
|
255
|
+
fileutils.rm_f(list, options)
|
256
|
+
end
|
257
|
+
|
258
|
+
# Remove with force option, recursively removing the contents of directories.
|
259
|
+
def rm_rf(options={})
|
260
|
+
#list = list.to_a
|
261
|
+
fileutils.rm_rf(list, options)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Install files to a directory with given mode. Unlike #cp, this will
|
265
|
+
# not copy the file if an up-to-date copy already exists.
|
266
|
+
def install(dir, mode, options={})
|
267
|
+
#src = list.to_a
|
268
|
+
#dest = localize(dest)
|
269
|
+
fileutils.install(list, dir, mode, options)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Change mode of files.
|
273
|
+
def chmod(mode, options={})
|
274
|
+
#list = list.to_a
|
275
|
+
fileutils.chmod(mode, list, options)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Change mode of files, following directories recursively.
|
279
|
+
def chmod_r(mode, options={})
|
280
|
+
#list = list.to_a
|
281
|
+
fileutils.chmod_r(mode, list, options)
|
282
|
+
end
|
283
|
+
#alias_method :chmod_R, :chmod_r
|
284
|
+
|
285
|
+
# Change owner of files.
|
286
|
+
def chown(user, group, options={})
|
287
|
+
#list = list.to_a
|
288
|
+
fileutils.chown(user, group, list, options)
|
289
|
+
end
|
290
|
+
|
291
|
+
# Change owner of files, following directories recursively.
|
292
|
+
def chown_r(user, group, options={})
|
293
|
+
#list = list.to_a
|
294
|
+
fileutils.chown_r(user, group, list, options)
|
295
|
+
end
|
296
|
+
#alias_method :chown_R, :chown_r
|
297
|
+
|
298
|
+
# Touch each file.
|
299
|
+
def touch(options={})
|
300
|
+
#list = list.to_a
|
301
|
+
fileutils.touch(list, options)
|
302
|
+
end
|
303
|
+
|
304
|
+
# Stage files. This is like #install but uses hardlinks.
|
305
|
+
def stage(dir)
|
306
|
+
#dir = localize(directory)
|
307
|
+
#files = localize(files)
|
308
|
+
#list = list.to_a
|
309
|
+
fileutils.stage(dir, local, list)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Convenient alias for #map_mv.
|
313
|
+
def rename(options={}, &block)
|
314
|
+
map_mv(options, &block)
|
315
|
+
end
|
316
|
+
|
317
|
+
# Rename the list of files in batch, using a block to determine the new
|
318
|
+
# names. If the block returns nil, the file will not be renamed.
|
319
|
+
#
|
320
|
+
# This is similar to #mv, but allows for detailed control over the renaming.
|
321
|
+
#
|
322
|
+
# Unlike the other `map_*` methods, this changes the Batch list in-place,
|
323
|
+
# since the files renamed no loner exist.
|
324
|
+
#
|
325
|
+
# Returns the changed FileList instance.
|
326
|
+
def map_mv(options={}, &block)
|
327
|
+
@file_list = map_send(:mv, options={}, &block)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Hard link the list of files in batch, using a block to determine the new
|
331
|
+
# names. If the block returns nil, the file will not be linked.
|
332
|
+
#
|
333
|
+
# This is similar to #ln, but allows for detailed control over the link names.
|
334
|
+
def map_ln(options={}, &block)
|
335
|
+
map_send(:ln, options={}, &block)
|
336
|
+
end
|
337
|
+
|
338
|
+
# Soft link the list of files in batch, using a block to determine the new
|
339
|
+
# names. If the block returns nil, the file will not be linked.
|
340
|
+
#
|
341
|
+
# This is similar to #ln_s, but allows for detailed control over the link names.
|
342
|
+
def map_ln_s(options={}, &block)
|
343
|
+
map_send(:ln_s, options={}, &block)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Force soft linking of the list of files in batch, using a block to
|
347
|
+
# determine the new names. If the block returns nil, the file will not
|
348
|
+
# be linked.
|
349
|
+
#
|
350
|
+
# This is similar to #ln_sf, but allows for detailed control over the
|
351
|
+
# link names.
|
352
|
+
def map_ln_sf(options={}, &block)
|
353
|
+
map_send(:ln_sf, options={}, &block)
|
354
|
+
end
|
355
|
+
|
356
|
+
# Copy the list of files in batch, using a block to determine the new
|
357
|
+
# file names. If the block returns nil, the file will not be copied.
|
358
|
+
#
|
359
|
+
# This is similar to #cp, but allows for detailed control over the new
|
360
|
+
# file names.
|
361
|
+
def map_cp(options={}, &block)
|
362
|
+
map_send(:cp, options={}, &block)
|
363
|
+
end
|
364
|
+
|
365
|
+
# Copy the list of files recursively in batch, using a block to determine
|
366
|
+
# the new file names. If the block returns nil, the file will not be copied.
|
367
|
+
#
|
368
|
+
# This is similar to #cp_r, but allows for detailed control over the new
|
369
|
+
# file names.
|
370
|
+
def map_cp_r(options={}, &block)
|
371
|
+
map_send(:cp_r, options={}, &block)
|
372
|
+
end
|
373
|
+
|
374
|
+
# # Force copy the list of files recursively in batch, using a block to
|
375
|
+
# # determine the new file names. If the block returns nil, the file will not
|
376
|
+
# # be copied.
|
377
|
+
# #
|
378
|
+
# # This is similar to #cp_rf, but allows for detailed control over the new
|
379
|
+
# # file names.
|
380
|
+
# def map_cp_rf(options={}, &block)
|
381
|
+
# map_send(:cp_rf, options={}, &block)
|
382
|
+
# end
|
383
|
+
|
384
|
+
private
|
385
|
+
|
386
|
+
SAFE_METHODS = [:ln]
|
387
|
+
|
388
|
+
# Generic name mapping procedure which can be used for any
|
389
|
+
# FileUtils method that has a `src, dest` interface.
|
390
|
+
#--
|
391
|
+
# TODO: Make public?
|
392
|
+
#++
|
393
|
+
def map_send(method, options={}, &block)
|
394
|
+
|
395
|
+
map = {}
|
396
|
+
list.each do |file|
|
397
|
+
if dest = block.call(file)
|
398
|
+
map[file] = dest
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
if options[:safe] or !options[:force] or SAFE_METHODS.include?(method)
|
403
|
+
ensure_safe(map)
|
404
|
+
end
|
405
|
+
|
406
|
+
map.each do |src, dest|
|
407
|
+
fileutils.__send__(method, src, dest, options)
|
408
|
+
end
|
409
|
+
FileList.all(*map.values)
|
410
|
+
end
|
411
|
+
|
412
|
+
# Given a map of source to destination, this method ensures
|
413
|
+
# a FileUtils operation can is "safe" --that the destination does not
|
414
|
+
# yet and exist and/or the source and destination are compatible.
|
415
|
+
# If nota file rrror is raised.
|
416
|
+
def ensure_safe(map)
|
417
|
+
map.each do |src, dest|
|
418
|
+
raise unless File.exist?(src)
|
419
|
+
if File.directory?(src)
|
420
|
+
if File.directory?(dest)
|
421
|
+
new_map = {}
|
422
|
+
Dir.entries(src).each do |e|
|
423
|
+
next if e == '.' or e == '..'
|
424
|
+
new_map[File.join(src, e)] = File.join(dest, e)
|
425
|
+
end
|
426
|
+
ensure_safe_destination(new_map)
|
427
|
+
else
|
428
|
+
raise Errno::EISDIR, "Is a directory - #{src}"
|
429
|
+
end
|
430
|
+
else
|
431
|
+
if File.directory?(dest)
|
432
|
+
check = File.join(dest, src)
|
433
|
+
if File.exist?(check)
|
434
|
+
raise Errno::EEXIST, "File exists - #{check}"
|
435
|
+
end
|
436
|
+
else
|
437
|
+
raise Errno::EEXIST, "File exists - #{dest}" if File.exist?(dest)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
public
|
444
|
+
|
445
|
+
# An intergrated glob like method that takes a set of include globs,
|
446
|
+
# exclude globs and ignore globs to produce a collection of paths.
|
447
|
+
#
|
448
|
+
# Ignore_globs differ from exclude_globs in that they match by
|
449
|
+
# the basename of the path rather than the whole pathname.
|
450
|
+
#
|
451
|
+
#def amass(include_globs, exclude_globs=[], ignore_globs=[])
|
452
|
+
# locally do
|
453
|
+
# fileutils.amass(include_globs, exclude_globs, ignore_globs)
|
454
|
+
# end
|
455
|
+
#end
|
456
|
+
|
457
|
+
# Is +path+ out-of-date in comparsion to all files in batch.
|
458
|
+
def outofdate?(path)
|
459
|
+
fileutils.outofdate?(path, to_a)
|
460
|
+
end
|
461
|
+
|
462
|
+
# Is +path+ up-to-date in comparsion to all files in batch.
|
463
|
+
def uptodate?(path)
|
464
|
+
fileutils.uptodate?(path, to_a)
|
465
|
+
end
|
466
|
+
|
467
|
+
#
|
468
|
+
def noop?
|
469
|
+
@options[:noop] or @options[:dryrun]
|
470
|
+
end
|
471
|
+
|
472
|
+
#
|
473
|
+
def verbose?
|
474
|
+
@options[:verbose] or @options[:dryrun]
|
475
|
+
end
|
476
|
+
|
477
|
+
#
|
478
|
+
def dryrun?
|
479
|
+
noop? && verbose?
|
480
|
+
end
|
481
|
+
|
482
|
+
private
|
483
|
+
|
484
|
+
# Returns FileUtils module based on mode.
|
485
|
+
def fileutils
|
486
|
+
if dryrun?
|
487
|
+
::FileUtils::DryRun
|
488
|
+
elsif noop?
|
489
|
+
::FileUtils::Noop
|
490
|
+
elsif verbose?
|
491
|
+
::FileUtils::Verbose
|
492
|
+
else
|
493
|
+
::FileUtils
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
end
|
500
|
+
|