guard-copy 0.0.2 → 0.0.3
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/README.md +40 -1
- data/lib/guard/copy/target.rb +37 -0
- data/lib/guard/copy/version.rb +1 -1
- data/lib/guard/copy.rb +88 -53
- metadata +7 -118
data/README.md
CHANGED
@@ -36,7 +36,7 @@ guard :copy, :from => 'source', :to => 'target'
|
|
36
36
|
### Multiple Targets
|
37
37
|
|
38
38
|
``` ruby
|
39
|
-
guard :copy, :from => 'source', :to => ['t1', 't2']
|
39
|
+
guard :copy, :from => 'source', :to => ['t1', 't2']
|
40
40
|
```
|
41
41
|
|
42
42
|
### Newest Wildcard Target
|
@@ -48,6 +48,45 @@ guard :copy, :from => 'source', :to => 'target*', :glob => :newest
|
|
48
48
|
This guard will copy files from the source directory to the newest
|
49
49
|
directory starting with 'target'.
|
50
50
|
|
51
|
+
## Options
|
52
|
+
|
53
|
+
By default, Guard::Copy will copy modified and newly created files from
|
54
|
+
the directory specified by the `:from` option to that specified by the
|
55
|
+
`:to` option.
|
56
|
+
|
57
|
+
### List of available options:
|
58
|
+
|
59
|
+
``` ruby
|
60
|
+
:from => 'source' # directory to copy files from
|
61
|
+
:to => 'target' # directory or glob to copy files to; can be an array
|
62
|
+
:glob => :newest # how to handle globs; default: :all
|
63
|
+
# :newest - copy to only the newest directory
|
64
|
+
# :all - copy to all directories
|
65
|
+
:delete => true # delete files from target directories
|
66
|
+
:verbose => true # log all operations as info messages
|
67
|
+
```
|
68
|
+
|
69
|
+
## Watchers
|
70
|
+
|
71
|
+
The paths that files are ultimately copied to are generated by
|
72
|
+
substituting the `:from` portion of the changed file's path with each of
|
73
|
+
the `:to` directories. Because of this, any watchers you define will be
|
74
|
+
modified to be relative to the `:from` directory.
|
75
|
+
|
76
|
+
Therefore the following two watcher definitions are equivalent.
|
77
|
+
|
78
|
+
``` ruby
|
79
|
+
guard :copy, :from => 'source', :to => 'target' do
|
80
|
+
watch(%r{^source/.+\.js$})
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
``` ruby
|
85
|
+
guard :copy, :from => 'source', :to => 'target' do
|
86
|
+
watch(%r{^.+\.js$})
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
51
90
|
## Author
|
52
91
|
|
53
92
|
[Marc Schwieterman](https://github.com/marcisme)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Guard
|
2
|
+
class Copy
|
3
|
+
class Target
|
4
|
+
|
5
|
+
attr_reader :pattern, :options, :paths
|
6
|
+
|
7
|
+
# Initialize a new target
|
8
|
+
#
|
9
|
+
# @param [String] pattern the pattern for this target
|
10
|
+
# @option options [Symbol] glob target resolution mode, `:newest` or `:all`
|
11
|
+
#
|
12
|
+
def initialize(pattern, options = {})
|
13
|
+
raise ArgumentError, 'pattern cannot be nil' unless pattern
|
14
|
+
raise ArgumentError, 'pattern cannot be empty' if pattern.empty?
|
15
|
+
@pattern = pattern
|
16
|
+
@options = {
|
17
|
+
:glob => :all
|
18
|
+
}.merge(options)
|
19
|
+
@paths = []
|
20
|
+
end
|
21
|
+
|
22
|
+
# Resolve the target into one or more paths
|
23
|
+
#
|
24
|
+
# @return [Boolean] true if the pattern resolved to any paths
|
25
|
+
def resolve
|
26
|
+
@paths.clear
|
27
|
+
if @options[:glob] == :newest
|
28
|
+
@paths.concat(Dir[@pattern].sort_by { |f| File.mtime(f) }.last(1))
|
29
|
+
else
|
30
|
+
@paths.concat(Dir[@pattern])
|
31
|
+
end
|
32
|
+
@paths.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/guard/copy/version.rb
CHANGED
data/lib/guard/copy.rb
CHANGED
@@ -1,34 +1,51 @@
|
|
1
1
|
require 'guard'
|
2
2
|
require 'guard/guard'
|
3
|
-
require 'guard/copy/version'
|
4
3
|
require 'fileutils'
|
5
4
|
|
6
5
|
module Guard
|
7
6
|
class Copy < Guard
|
8
7
|
|
8
|
+
autoload :Target, 'guard/copy/target'
|
9
|
+
|
9
10
|
attr_reader :targets
|
10
11
|
|
11
12
|
# Initialize a Guard.
|
12
13
|
# @param [Array<Guard::Watcher>] watchers the Guard file watchers
|
13
14
|
# @param [Hash] options the custom Guard options
|
14
15
|
def initialize(watchers = [], options = {})
|
15
|
-
# watchers are currently ignored
|
16
|
-
watchers << ::Guard::Watcher.new(%r{#{options[:from]}/.*})
|
17
|
-
options[:to] = Array(options[:to]).freeze
|
18
16
|
super
|
17
|
+
if watchers.empty?
|
18
|
+
watchers << ::Guard::Watcher.new(%r{^#{options[:from]}/.*$})
|
19
|
+
else
|
20
|
+
watchers.each { |w| normalize_watcher(w, options[:from]) }
|
21
|
+
end
|
22
|
+
@targets = Array(options[:to]).map { |to| Target.new(to, options) }
|
19
23
|
end
|
20
24
|
|
21
25
|
# Call once when Guard starts. Please override initialize method to init stuff.
|
22
26
|
# @raise [:task_has_failed] when start has failed
|
23
27
|
def start
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
validate_presence_of(:from)
|
29
|
+
validate_from_is_directory
|
30
|
+
validate_presence_of(:to)
|
31
|
+
validate_to_does_not_include_from
|
32
|
+
@targets.each do |target|
|
33
|
+
unless target.resolve
|
34
|
+
UI.warning("Guard::Copy - '#{target.pattern}' does not match a valid directory")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
if target_paths.any?
|
28
38
|
UI.info("Guard::Copy will copy files from:")
|
29
39
|
UI.info(" #{options[:from]}")
|
30
40
|
UI.info("to:")
|
31
|
-
|
41
|
+
target_paths.each { |target_path| UI.info(" #{target_path}") }
|
42
|
+
|
43
|
+
if options[:delete]
|
44
|
+
UI.info("Guard::Copy will delete files removed from:")
|
45
|
+
UI.info(" #{options[:from]}")
|
46
|
+
UI.info("from:")
|
47
|
+
target_paths.each { |target_path| UI.info(" #{target_path}") }
|
48
|
+
end
|
32
49
|
end
|
33
50
|
end
|
34
51
|
|
@@ -40,55 +57,85 @@ module Guard
|
|
40
57
|
|
41
58
|
# Called on file(s) modifications that the Guard watches.
|
42
59
|
# @param [Array<String>] paths the changes files or paths
|
43
|
-
# @raise [:task_has_failed] when
|
44
|
-
def
|
45
|
-
|
46
|
-
paths
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
FileUtils.cp(from_path, to_path)
|
51
|
-
end
|
60
|
+
# @raise [:task_has_failed] when run_on_changes has failed
|
61
|
+
def run_on_changes(paths)
|
62
|
+
validate_at_least_one_target('copy')
|
63
|
+
with_all_target_paths(paths) do |from_path, to_path|
|
64
|
+
validate_to_path(to_path)
|
65
|
+
UI.info("copying to #{to_path}") if options[:verbose]
|
66
|
+
FileUtils.cp(from_path, to_path)
|
52
67
|
end
|
53
68
|
end
|
54
69
|
|
55
70
|
# Called on file(s) deletions that the Guard watches.
|
56
71
|
# @param [Array<String>] paths the deleted files or paths
|
57
|
-
# @raise [:task_has_failed] when
|
58
|
-
def
|
72
|
+
# @raise [:task_has_failed] when run_on_removals has failed
|
73
|
+
def run_on_removals(paths)
|
74
|
+
return unless options[:delete]
|
75
|
+
validate_at_least_one_target('delete')
|
76
|
+
with_all_target_paths(paths) do |_, to_path|
|
77
|
+
validate_to_file(to_path)
|
78
|
+
UI.info("deleting #{to_path}") if options[:verbose]
|
79
|
+
FileUtils.rm(to_path)
|
80
|
+
end
|
59
81
|
end
|
60
82
|
|
61
83
|
private
|
62
84
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
85
|
+
def target_paths
|
86
|
+
@targets.map { |t| t.paths }.flatten
|
87
|
+
end
|
88
|
+
|
89
|
+
def with_all_target_paths(paths)
|
90
|
+
paths.each do |from_path|
|
91
|
+
target_paths.each do |target_path|
|
92
|
+
to_path = from_path.sub(@options[:from], target_path)
|
93
|
+
yield(from_path, to_path)
|
94
|
+
end
|
67
95
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
96
|
+
end
|
97
|
+
|
98
|
+
def normalize_watcher(watcher, from)
|
99
|
+
unless watcher.pattern.source =~ %r{^\^#{from}/.*}
|
100
|
+
normalized_source = watcher.pattern.source.sub(%r{^\^?(#{from})?/?}, "^#{from}/")
|
101
|
+
UI.info('Guard::Copy is changing watcher pattern:')
|
102
|
+
UI.info(" #{watcher.pattern.source}")
|
103
|
+
UI.info('to:')
|
104
|
+
UI.info(" #{normalized_source}")
|
105
|
+
watcher.pattern = Regexp.new(normalized_source)
|
71
106
|
end
|
72
|
-
|
73
|
-
|
107
|
+
end
|
108
|
+
|
109
|
+
def validate_presence_of(option)
|
110
|
+
unless options[option]
|
111
|
+
UI.error("Guard::Copy - :#{option} option is required")
|
74
112
|
throw :task_has_failed
|
75
113
|
end
|
76
114
|
end
|
77
115
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
116
|
+
def validate_from_is_directory
|
117
|
+
path = options[:from]
|
118
|
+
unless File.directory?(path)
|
119
|
+
if File.file?(path)
|
120
|
+
UI.error("Guard::Copy - '#{path}' is a file and must be a directory")
|
121
|
+
throw :task_has_failed
|
122
|
+
else
|
123
|
+
UI.error("Guard::Copy - :from option does not contain a valid directory")
|
124
|
+
throw :task_has_failed
|
125
|
+
end
|
82
126
|
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def validate_to_does_not_include_from
|
83
130
|
if options[:to].include?(options[:from])
|
84
131
|
UI.error('Guard::Copy - :to must not include :from')
|
85
132
|
throw :task_has_failed
|
86
133
|
end
|
87
134
|
end
|
88
135
|
|
89
|
-
def
|
90
|
-
if
|
91
|
-
UI.error(
|
136
|
+
def validate_at_least_one_target(operation)
|
137
|
+
if target_paths.empty?
|
138
|
+
UI.error("Guard::Copy - cannot #{operation}, no valid :to directories")
|
92
139
|
throw :task_has_failed
|
93
140
|
end
|
94
141
|
end
|
@@ -102,23 +149,11 @@ module Guard
|
|
102
149
|
end
|
103
150
|
end
|
104
151
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
else
|
111
|
-
dirs = Dir[to]
|
112
|
-
end
|
113
|
-
if dirs.any?
|
114
|
-
#dirs.each do |dir|
|
115
|
-
#throw :task_has_failed if File.file?(dir)
|
116
|
-
#end
|
117
|
-
targets.concat(dirs)
|
118
|
-
else
|
119
|
-
UI.warning("Guard::Copy - '#{to}' does not match a valid directory")
|
120
|
-
end
|
121
|
-
end
|
152
|
+
def validate_to_file(to_file)
|
153
|
+
unless File.file?(to_file)
|
154
|
+
UI.error('Guard::Copy - cannot delete, file does not exist:')
|
155
|
+
UI.error(" #{to_file}")
|
156
|
+
throw :task_has_failed
|
122
157
|
end
|
123
158
|
end
|
124
159
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard-copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: guard
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.1.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,119 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: bundler
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 1.1.0
|
38
|
-
type: :development
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 1.1.0
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: rake
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ! '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 0.9.2
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.9.2
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: aruba
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0.4'
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0.4'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: guard-cucumber
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: '0.8'
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0.8'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: guard-rspec
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ! '>='
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: 0.7.2
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '>='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 0.7.2
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: fakefs
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ! '>='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.4.0
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ! '>='
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: 0.4.0
|
126
|
-
- !ruby/object:Gem::Dependency
|
127
|
-
name: mocha
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
|
-
requirements:
|
131
|
-
- - ! '>='
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: 0.11.4
|
134
|
-
type: :development
|
135
|
-
prerelease: false
|
136
|
-
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
|
-
requirements:
|
139
|
-
- - ! '>='
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: 0.11.4
|
29
|
+
version: 1.1.1
|
142
30
|
description: Guard::Copy automatically copies files.
|
143
31
|
email:
|
144
32
|
- marc.schwieterman@gmail.com
|
@@ -146,6 +34,7 @@ executables: []
|
|
146
34
|
extensions: []
|
147
35
|
extra_rdoc_files: []
|
148
36
|
files:
|
37
|
+
- lib/guard/copy/target.rb
|
149
38
|
- lib/guard/copy/templates/Guardfile
|
150
39
|
- lib/guard/copy/version.rb
|
151
40
|
- lib/guard/copy.rb
|
@@ -165,7 +54,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
165
54
|
version: '0'
|
166
55
|
segments:
|
167
56
|
- 0
|
168
|
-
hash:
|
57
|
+
hash: 1790192604358185863
|
169
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
59
|
none: false
|
171
60
|
requirements:
|
@@ -174,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
63
|
version: '0'
|
175
64
|
segments:
|
176
65
|
- 0
|
177
|
-
hash:
|
66
|
+
hash: 1790192604358185863
|
178
67
|
requirements: []
|
179
68
|
rubyforge_project:
|
180
69
|
rubygems_version: 1.8.24
|