tripwire 1.1.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/.gitignore +1 -0
- data/History.txt +6 -0
- data/Manifest.txt +14 -0
- data/README.txt +56 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/bin/tripwire +10 -0
- data/lib/tripwire.rb +8 -0
- data/lib/tripwire/cli.rb +46 -0
- data/lib/tripwire/runner.rb +30 -0
- data/lib/tripwire/scanner.rb +58 -0
- data/spec/scanner_spec.rb +76 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +3 -0
- data/tripwire.gemspec +60 -0
- metadata +79 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
= tripwire
|
2
|
+
|
3
|
+
http://github.com/brendan/tripwire
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Tripwire is a simple tool for watching a set of files/folders for changes
|
8
|
+
and then triggering a shell command to execute when a change occurs.
|
9
|
+
|
10
|
+
It was written because I love the concepts behind autotest and rstakeout
|
11
|
+
but the difference is that it will watch for the addition of files and
|
12
|
+
subfolders where those tools only seemed to register a set of files at
|
13
|
+
startup and never seemed to pick up on when you created new ones.
|
14
|
+
|
15
|
+
Tripwire uses very simple Dir.glob-ing
|
16
|
+
|
17
|
+
== FEATURES/PROBLEMS:
|
18
|
+
|
19
|
+
* FIX (list of features or problems)
|
20
|
+
|
21
|
+
== SYNOPSIS:
|
22
|
+
|
23
|
+
FIX (code sample of usage)
|
24
|
+
|
25
|
+
== REQUIREMENTS:
|
26
|
+
|
27
|
+
* FIX (list of requirements)
|
28
|
+
|
29
|
+
== INSTALL:
|
30
|
+
|
31
|
+
sudo gem install brendan-tripwire
|
32
|
+
|
33
|
+
== LICENSE:
|
34
|
+
|
35
|
+
(The MIT License)
|
36
|
+
|
37
|
+
Copyright (c) 2009 FIX
|
38
|
+
|
39
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
40
|
+
a copy of this software and associated documentation files (the
|
41
|
+
'Software'), to deal in the Software without restriction, including
|
42
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
43
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
44
|
+
permit persons to whom the Software is furnished to do so, subject to
|
45
|
+
the following conditions:
|
46
|
+
|
47
|
+
The above copyright notice and this permission notice shall be
|
48
|
+
included in all copies or substantial portions of the Software.
|
49
|
+
|
50
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
51
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
52
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
53
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
54
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
55
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
56
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gem|
|
6
|
+
gem.name = "tripwire"
|
7
|
+
gem.summary = "Executes a shell command every time file/folder changes"
|
8
|
+
gem.description = "Similar to rstakeout and autotest except more options"
|
9
|
+
gem.email = "brendan@usergenic.com"
|
10
|
+
gem.homepage = "http://github.com/brendan/tripwire"
|
11
|
+
gem.authors = ["Brendan Baldwin"]
|
12
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
13
|
+
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'spec/rake/spectask'
|
20
|
+
|
21
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
+
spec.libs << 'lib' << 'spec'
|
23
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
+
spec.rcov = true
|
30
|
+
end
|
31
|
+
|
32
|
+
task :spec => :check_dependencies
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.0
|
data/bin/tripwire
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# This file needs to be readable and executable by all.
|
4
|
+
|
5
|
+
me = __FILE__
|
6
|
+
me = File.readlink(me) while(File.symlink?(me))
|
7
|
+
require File.expand_path(File.join(File.dirname(me), "..", "lib","tripwire"))
|
8
|
+
require 'tripwire/cli'
|
9
|
+
|
10
|
+
Tripwire::CLI.new(ARGV)
|
data/lib/tripwire.rb
ADDED
data/lib/tripwire/cli.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'tripwire/runner'
|
3
|
+
|
4
|
+
module Tripwire
|
5
|
+
class CLI
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def initialize(args)
|
10
|
+
|
11
|
+
trap('INT') do
|
12
|
+
puts "\nQuitting..."
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
|
16
|
+
scanner = Tripwire::Scanner.new
|
17
|
+
recursive = true
|
18
|
+
delay = 1
|
19
|
+
option_parser = OptionParser.new do |opt|
|
20
|
+
opt.banner = "Usage: tripwire [options] <command> <filespec>+"
|
21
|
+
opt.on("-e","--exclude <pattern>", String, "a pattern defining files/folders to ignore") do |e|
|
22
|
+
scanner.exclude_patterns << e
|
23
|
+
end
|
24
|
+
opt.on("-d","--delay <seconds>", Integer, "number of seconds between each scan (defaults to 1)") do |d|
|
25
|
+
delay = d
|
26
|
+
end
|
27
|
+
opt.on("-q","--quiet", "suppresses output") do
|
28
|
+
scanner.quiet = true
|
29
|
+
end
|
30
|
+
opt.on("-n","--non-recursive", "tells tripwire *not* to scan folders recursively") do
|
31
|
+
recursive = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
option_parser.parse!(args)
|
36
|
+
|
37
|
+
command = args.shift
|
38
|
+
args.map!{|arg| File.directory?(arg) ? "#{arg}/**/*" : arg} if recursive
|
39
|
+
scanner.scan_patterns.concat(args)
|
40
|
+
runner = Tripwire::Runner.new(scanner, command, :delay => delay)
|
41
|
+
runner.run! rescue puts "#{$!}\n(type tripwire -h for help)"
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Tripwire
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
attr_accessor :scanner
|
5
|
+
attr_accessor :command
|
6
|
+
attr_accessor :delay
|
7
|
+
|
8
|
+
def run!
|
9
|
+
raise "No command specified. Please specify a command to run." if !command
|
10
|
+
raise "No files/folders specified. Please specify files/patterns to scan." if scanner.scan_patterns.empty?
|
11
|
+
original_quiet = scanner.quiet
|
12
|
+
scanner.quiet = true
|
13
|
+
scanner.scan # do this because we don't care about the initial updates collection
|
14
|
+
scanner.quiet = original_quiet
|
15
|
+
loop do
|
16
|
+
sleep delay
|
17
|
+
system(command) unless scanner.scan.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def initialize(scanner, command, options={})
|
24
|
+
self.scanner = scanner
|
25
|
+
self.command = command
|
26
|
+
self.delay = options[:delay] || 1
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Tripwire
|
2
|
+
class Scanner
|
3
|
+
attr_accessor :exclude_patterns
|
4
|
+
attr_accessor :scan_patterns
|
5
|
+
attr_accessor :scanned_files
|
6
|
+
attr_accessor :scanned_file_mtimes
|
7
|
+
attr_accessor :updates
|
8
|
+
attr_accessor :quiet
|
9
|
+
|
10
|
+
def scan
|
11
|
+
updates.clear
|
12
|
+
files = scan_patterns.map {|scan_pattern| Dir.glob(scan_pattern) }.flatten.uniq
|
13
|
+
exclude_list = exclude_patterns.map {|exclude_pattern| Dir.glob(exclude_pattern) }.flatten
|
14
|
+
files -= exclude_list
|
15
|
+
excluded_folders = exclude_list.select {|item| File.directory?(item) }
|
16
|
+
excluded_folders.each do |folder|
|
17
|
+
regexp = /^#{Regexp.escape(folder)}\//
|
18
|
+
files -= files.select {|file| file.match(regexp)}
|
19
|
+
end
|
20
|
+
files.each do |file|
|
21
|
+
mtime = File.mtime(file)
|
22
|
+
previous_mtime = scanned_file_mtimes[file]
|
23
|
+
if mtime != previous_mtime
|
24
|
+
if !previous_mtime
|
25
|
+
updates << "A #{file}"
|
26
|
+
else
|
27
|
+
updates << "M #{file}"
|
28
|
+
end
|
29
|
+
scanned_file_mtimes[file] = mtime
|
30
|
+
end
|
31
|
+
end
|
32
|
+
missing_files = scanned_files - files
|
33
|
+
missing_files.each do |file|
|
34
|
+
scanned_file_mtimes.delete(file)
|
35
|
+
updates << "D #{file}"
|
36
|
+
end
|
37
|
+
self.scanned_files.replace(files)
|
38
|
+
puts updates unless quiet
|
39
|
+
updates
|
40
|
+
end
|
41
|
+
|
42
|
+
def tripped?
|
43
|
+
!updates.empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
self.exclude_patterns = []
|
50
|
+
self.scan_patterns = []
|
51
|
+
self.scanned_files = []
|
52
|
+
self.scanned_file_mtimes = {}
|
53
|
+
self.updates = []
|
54
|
+
self.quiet = false
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),"spec_helper")
|
2
|
+
|
3
|
+
describe "A Tripwire Scanner" do
|
4
|
+
|
5
|
+
attr_accessor :scanner
|
6
|
+
|
7
|
+
temp = File.join(File.dirname(__FILE__),"../temp")
|
8
|
+
|
9
|
+
define_method :clear_temp_folder do
|
10
|
+
Dir.glob("#{temp}/**/*").sort.reverse.each do |item|
|
11
|
+
File.file?(item) ? File.delete(item) : Dir.delete(item)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
clear_temp_folder
|
17
|
+
self.scanner = Tripwire::Scanner.new
|
18
|
+
scanner.quiet = true
|
19
|
+
scanner.scan_patterns << "#{temp}/**/*"
|
20
|
+
end
|
21
|
+
|
22
|
+
after :all do
|
23
|
+
clear_temp_folder
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should detect that a folder is added to a watched folder" do
|
27
|
+
Dir.mkdir("#{temp}/subfolder")
|
28
|
+
scanner.scan.should_not be_empty
|
29
|
+
scanner.scan.should be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should detect that a file is added to a watched folder" do
|
33
|
+
scanner.scan.should be_empty
|
34
|
+
File.open("#{temp}/testfile", "w") {}
|
35
|
+
scanner.scan.should_not be_empty
|
36
|
+
scanner.scan.should be_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should detect that a watched file is modified" do
|
40
|
+
scanner.scan.should be_empty
|
41
|
+
File.open("#{temp}/testfile", "w") {}
|
42
|
+
scanner.scan.should_not be_empty
|
43
|
+
scanner.scan.should be_empty
|
44
|
+
sleep 1
|
45
|
+
File.open("#{temp}/testfile", "w") {|f| f.write("something")}
|
46
|
+
scanner.scan.should_not be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should detect that a watched file is deleted" do
|
50
|
+
scanner.scan.should be_empty
|
51
|
+
File.open("#{temp}/testfile", "w") {}
|
52
|
+
scanner.scan.should_not be_empty
|
53
|
+
scanner.scan.should be_empty
|
54
|
+
File.delete("#{temp}/testfile")
|
55
|
+
scanner.scan.should_not be_empty
|
56
|
+
scanner.scan.should be_empty
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not watch a file matching an exclude pattern" do
|
60
|
+
scanner.exclude_patterns << "#{temp}/**/irrelevant"
|
61
|
+
scanner.scan.should be_empty
|
62
|
+
File.open("#{temp}/irrelevant", "w") {}
|
63
|
+
scanner.scan.should be_empty
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not watch a folder matching an exclude pattern" do
|
67
|
+
scanner.exclude_patterns << "#{temp}/**/irrelevant"
|
68
|
+
scanner.scan.should be_empty
|
69
|
+
Dir.mkdir("#{temp}/irrelevant")
|
70
|
+
scanner.scan.should be_empty
|
71
|
+
File.open("#{temp}/irrelevant/testfile", "w") {}
|
72
|
+
scanner.scan.should be_empty
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
data/tripwire.gemspec
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{tripwire}
|
8
|
+
s.version = "1.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brendan Baldwin"]
|
12
|
+
s.date = %q{2010-01-09}
|
13
|
+
s.default_executable = %q{tripwire}
|
14
|
+
s.description = %q{Similar to rstakeout and autotest except more options}
|
15
|
+
s.email = %q{brendan@usergenic.com}
|
16
|
+
s.executables = ["tripwire"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"README.txt"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gitignore",
|
22
|
+
"History.txt",
|
23
|
+
"Manifest.txt",
|
24
|
+
"README.txt",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"bin/tripwire",
|
28
|
+
"lib/tripwire.rb",
|
29
|
+
"lib/tripwire/cli.rb",
|
30
|
+
"lib/tripwire/runner.rb",
|
31
|
+
"lib/tripwire/scanner.rb",
|
32
|
+
"spec/scanner_spec.rb",
|
33
|
+
"spec/spec.opts",
|
34
|
+
"spec/spec_helper.rb",
|
35
|
+
"tripwire.gemspec"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://github.com/brendan/tripwire}
|
38
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.3.5}
|
41
|
+
s.summary = %q{Executes a shell command every time file/folder changes}
|
42
|
+
s.test_files = [
|
43
|
+
"spec/scanner_spec.rb",
|
44
|
+
"spec/spec_helper.rb"
|
45
|
+
]
|
46
|
+
|
47
|
+
if s.respond_to? :specification_version then
|
48
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
49
|
+
s.specification_version = 3
|
50
|
+
|
51
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
52
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tripwire
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brendan Baldwin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-09 00:00:00 -08:00
|
13
|
+
default_executable: tripwire
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
description: Similar to rstakeout and autotest except more options
|
26
|
+
email: brendan@usergenic.com
|
27
|
+
executables:
|
28
|
+
- tripwire
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.txt
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- History.txt
|
36
|
+
- Manifest.txt
|
37
|
+
- README.txt
|
38
|
+
- Rakefile
|
39
|
+
- VERSION
|
40
|
+
- bin/tripwire
|
41
|
+
- lib/tripwire.rb
|
42
|
+
- lib/tripwire/cli.rb
|
43
|
+
- lib/tripwire/runner.rb
|
44
|
+
- lib/tripwire/scanner.rb
|
45
|
+
- spec/scanner_spec.rb
|
46
|
+
- spec/spec.opts
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
- tripwire.gemspec
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/brendan/tripwire
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options:
|
55
|
+
- --charset=UTF-8
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Executes a shell command every time file/folder changes
|
77
|
+
test_files:
|
78
|
+
- spec/scanner_spec.rb
|
79
|
+
- spec/spec_helper.rb
|