right_scraper 1.0.26 → 3.0.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/Gemfile +16 -0
- data/README.rdoc +9 -28
- data/Rakefile +51 -39
- data/lib/right_scraper/builders/base.rb +64 -0
- data/lib/right_scraper/builders/filesystem.rb +96 -0
- data/lib/right_scraper/builders/union.rb +57 -0
- data/lib/right_scraper/logger.rb +102 -0
- data/lib/right_scraper/loggers/noisy.rb +85 -0
- data/lib/right_scraper/processes/ssh.rb +188 -0
- data/lib/right_scraper/repositories/base.rb +299 -0
- data/lib/right_scraper/repositories/download.rb +90 -0
- data/lib/right_scraper/repositories/git.rb +92 -0
- data/lib/right_scraper/repositories/mock.rb +70 -0
- data/lib/right_scraper/repositories/svn.rb +96 -0
- data/lib/right_scraper/resources/base.rb +70 -0
- data/{spec/scraper_base_spec.rb → lib/right_scraper/resources/cookbook.rb} +9 -23
- data/lib/right_scraper/resources/workflow.rb +55 -0
- data/lib/right_scraper/retrievers/base.rb +114 -0
- data/lib/right_scraper/retrievers/checkout.rb +79 -0
- data/lib/right_scraper/retrievers/download.rb +97 -0
- data/lib/right_scraper/retrievers/git.rb +140 -0
- data/lib/right_scraper/retrievers/svn.rb +87 -0
- data/lib/right_scraper/scanners/base.rb +111 -0
- data/lib/right_scraper/scanners/cookbook_manifest.rb +59 -0
- data/lib/right_scraper/scanners/cookbook_metadata.rb +69 -0
- data/lib/right_scraper/scanners/cookbook_s3_upload.rb +84 -0
- data/lib/right_scraper/scanners/union.rb +89 -0
- data/lib/right_scraper/scanners/workflow_manifest.rb +86 -0
- data/lib/right_scraper/scanners/workflow_metadata.rb +70 -0
- data/lib/right_scraper/scanners/workflow_s3_upload.rb +85 -0
- data/lib/right_scraper/scraper.rb +81 -57
- data/lib/right_scraper/scraper_logger.rb +61 -0
- data/lib/right_scraper/scrapers/base.rb +262 -0
- data/lib/right_scraper/scrapers/cookbook.rb +73 -0
- data/lib/right_scraper/scrapers/workflow.rb +88 -0
- data/lib/right_scraper/svn_client.rb +101 -0
- data/lib/right_scraper/version.rb +28 -0
- data/lib/right_scraper.rb +35 -11
- data/right_scraper.gemspec +26 -13
- data/right_scraper.rconf +13 -0
- data/spec/builder_spec.rb +50 -0
- data/spec/cookbook_helper.rb +73 -0
- data/spec/cookbook_manifest_spec.rb +55 -0
- data/spec/cookbook_s3_upload_spec.rb +152 -0
- data/spec/download/download_retriever_spec.rb +118 -0
- data/spec/download/download_retriever_spec_helper.rb +72 -0
- data/spec/download/download_spec.rb +130 -0
- data/spec/download/multi_dir_spec.rb +106 -0
- data/spec/download/multi_dir_spec_helper.rb +40 -0
- data/spec/git/cookbook_spec.rb +166 -0
- data/spec/git/demokey +27 -0
- data/spec/git/demokey.pub +1 -0
- data/spec/git/password_key +30 -0
- data/spec/git/password_key.pub +1 -0
- data/spec/git/repository_spec.rb +110 -0
- data/spec/git/retriever_spec.rb +505 -0
- data/spec/git/retriever_spec_helper.rb +112 -0
- data/spec/git/scraper_spec.rb +136 -0
- data/spec/git/ssh_spec.rb +170 -0
- data/spec/git/url_spec.rb +103 -0
- data/spec/logger_spec.rb +185 -0
- data/spec/repository_spec.rb +89 -23
- data/spec/{scraper_spec_helper_base.rb → retriever_spec_helper.rb} +41 -27
- data/spec/scanner_spec.rb +61 -0
- data/spec/scraper_helper.rb +96 -0
- data/spec/scraper_spec.rb +123 -45
- data/spec/spec_helper.rb +87 -14
- data/spec/svn/cookbook_spec.rb +97 -0
- data/spec/svn/multi_svn_spec.rb +64 -0
- data/spec/svn/multi_svn_spec_helper.rb +40 -0
- data/spec/svn/repository_spec.rb +72 -0
- data/spec/svn/retriever_spec.rb +261 -0
- data/spec/svn/scraper_spec.rb +90 -0
- data/spec/svn/{svn_scraper_spec_helper.rb → svn_retriever_spec_helper.rb} +46 -27
- data/spec/svn/url_spec.rb +47 -0
- data/spec/url_spec.rb +164 -0
- metadata +203 -31
- data/lib/right_scraper/linux/process_monitor.rb +0 -84
- data/lib/right_scraper/repository.rb +0 -78
- data/lib/right_scraper/scraper_base.rb +0 -175
- data/lib/right_scraper/scrapers/download_scraper.rb +0 -67
- data/lib/right_scraper/scrapers/git_scraper.rb +0 -283
- data/lib/right_scraper/scrapers/svn_scraper.rb +0 -119
- data/lib/right_scraper/watcher.rb +0 -158
- data/lib/right_scraper/win32/process_monitor.rb +0 -98
- data/spec/download/download_scraper_spec.rb +0 -94
- data/spec/git/git_scraper_spec.rb +0 -165
- data/spec/git/git_scraper_spec_helper.rb +0 -72
- data/spec/rcov.opts +0 -1
- data/spec/spec.opts +0 -2
- data/spec/svn/svn_scraper_spec.rb +0 -148
- data/spec/watcher_spec.rb +0 -74
data/Gemfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
source "http://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gem "json", "~> 1.4.5"
|
|
4
|
+
gem "blackwinter-git", "~> 1.2.7"
|
|
5
|
+
gem "libarchive", "~> 0.1.2"
|
|
6
|
+
gem "right_aws", "~> 2.0"
|
|
7
|
+
gem "process_watcher", "~> 0.3"
|
|
8
|
+
|
|
9
|
+
group :development do
|
|
10
|
+
gem "rspec", "~> 2.3"
|
|
11
|
+
gem "rake"
|
|
12
|
+
gem "flexmock"
|
|
13
|
+
gem "ruby-debug", :platform=>"ruby_18"
|
|
14
|
+
gem "ruby-debug19", :platform=>"ruby_19"
|
|
15
|
+
gem "rdoc", "~> 2.4"
|
|
16
|
+
end
|
data/README.rdoc
CHANGED
|
@@ -4,24 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
=== Synopsis
|
|
6
6
|
|
|
7
|
-
RightScraper provides a simple interface to download and keep repositories up-to-date
|
|
8
|
-
using various protocols.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- *SVN*: RightScraper will checkout then update SVN repositories
|
|
13
|
-
- *tarballs*: Includes uncompressed (.tar), gzip (.tgz, .gzip) and bzip (.bzip, .bzip2) tar files.
|
|
14
|
-
|
|
15
|
-
The scraper first inspects the local directory to see if the repo has already been scraped
|
|
16
|
-
and if so runs some basic checks before it tries to update it. Incremental updates are not
|
|
17
|
-
supported with tar files.
|
|
18
|
-
|
|
19
|
-
=== Rationale
|
|
20
|
-
|
|
21
|
-
The idea is to have many repos that need to be downloaded/kept up-to-date in a central
|
|
22
|
-
place. Point the scraper to this central place and it will take care of creating unique
|
|
23
|
-
local directories for each remote repository and keep that mapping to download changes
|
|
24
|
-
incrementally upon request.
|
|
7
|
+
RightScraper provides a simple interface to download and keep repositories up-to-date
|
|
8
|
+
using various protocols. It has been decomposed into various modules so that you
|
|
9
|
+
may specify only the functionality (and required libraries and gems) you require.
|
|
10
|
+
This gem depends on all available RightScraper modules, enabling full support at the
|
|
11
|
+
cost of requiring some systems administration work external to Ruby.
|
|
25
12
|
|
|
26
13
|
== USAGE
|
|
27
14
|
|
|
@@ -30,22 +17,16 @@ incrementally upon request.
|
|
|
30
17
|
require 'rubygems'
|
|
31
18
|
require 'right_scraper'
|
|
32
19
|
|
|
33
|
-
scraper = RightScale::Scraper.new('/tmp')
|
|
20
|
+
scraper = RightScale::Scraper.new(:basedir => '/tmp', :kind => :cookbook)
|
|
34
21
|
scraper.scrape(:type => :git, :url => 'git://github.com/rightscale/right_scraper.git')
|
|
35
22
|
|
|
36
23
|
== INSTALLATION
|
|
37
24
|
|
|
38
|
-
RightScraper can be installed by entering the following at the command
|
|
25
|
+
This module for RightScraper can be installed by entering the following at the command
|
|
26
|
+
prompt:
|
|
39
27
|
|
|
40
28
|
gem install right_scraper
|
|
41
29
|
|
|
42
|
-
== DEPENDENCIES
|
|
43
|
-
|
|
44
|
-
RightScraper relies on the following tools:
|
|
45
|
-
- git
|
|
46
|
-
- svn
|
|
47
|
-
- curl
|
|
48
|
-
|
|
49
30
|
== TESTING
|
|
50
31
|
|
|
51
32
|
Install the following RubyGems required for testing:
|
|
@@ -59,7 +40,7 @@ The build can be tested using the RSpec gem.
|
|
|
59
40
|
|
|
60
41
|
<b>RightScraper</b>
|
|
61
42
|
|
|
62
|
-
Copyright:: Copyright (c) 2010 RightScale, Inc.
|
|
43
|
+
Copyright:: Copyright (c) 2010 RightScale, Inc.
|
|
63
44
|
|
|
64
45
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
65
46
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
#--
|
|
2
|
-
# Copyright: Copyright (c) 2010 RightScale, Inc.
|
|
1
|
+
#-- -*-ruby-*-
|
|
2
|
+
# Copyright: Copyright (c) 2010-2011 RightScale, Inc.
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
5
|
# a copy of this software and associated documentation files (the
|
|
6
6
|
# 'Software'), to deal in the Software without restriction, including
|
|
7
7
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
9
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
10
|
# the following conditions:
|
|
11
11
|
#
|
|
12
12
|
# The above copyright notice and this permission notice shall be
|
|
13
13
|
# included in all copies or substantial portions of the Software.
|
|
14
14
|
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
16
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
17
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
18
|
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
@@ -22,56 +22,68 @@
|
|
|
22
22
|
#++
|
|
23
23
|
|
|
24
24
|
require 'rubygems'
|
|
25
|
+
require 'rubygems/package_task'
|
|
26
|
+
require 'bundler/setup'
|
|
27
|
+
|
|
25
28
|
require 'fileutils'
|
|
26
29
|
require 'rake'
|
|
27
|
-
require '
|
|
30
|
+
require 'rspec/core/rake_task'
|
|
31
|
+
require 'rdoc/task'
|
|
32
|
+
require 'rake/clean'
|
|
28
33
|
|
|
29
34
|
task :default => 'spec'
|
|
30
35
|
|
|
36
|
+
# == Gem packaging == #
|
|
37
|
+
|
|
38
|
+
desc "Build right_scraper gem"
|
|
39
|
+
Gem::PackageTask.new(Gem::Specification.load("right_scraper.gemspec")) do |package|
|
|
40
|
+
package.need_zip = true
|
|
41
|
+
package.need_tar = true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
CLEAN.include('pkg')
|
|
45
|
+
|
|
31
46
|
# == Unit Tests == #
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
task :specs => :spec
|
|
49
|
+
|
|
50
|
+
# == Unit Tests == #
|
|
51
|
+
|
|
52
|
+
desc 'Run unit tests'
|
|
53
|
+
RSpec::Core::RakeTask.new do |t|
|
|
54
|
+
t.pattern = 'spec/**/*_spec.rb'
|
|
55
|
+
t.rspec_opts = ["--color", "--format", "nested"]
|
|
39
56
|
end
|
|
40
57
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
namespace :spec do
|
|
59
|
+
desc "Run unit tests with RCov"
|
|
60
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
|
61
|
+
t.pattern = '*/spec/**/*_spec.rb'
|
|
62
|
+
t.rcov = true
|
|
63
|
+
t.rcov_opts = %q[--exclude "spec"]
|
|
47
64
|
end
|
|
48
|
-
end
|
|
49
65
|
|
|
50
|
-
desc "Print Specdoc for unit tests"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
66
|
+
desc "Print Specdoc for unit tests"
|
|
67
|
+
RSpec::Core::RakeTask.new(:doc) do |t|
|
|
68
|
+
t.pattern = '*/spec/**/*_spec.rb'
|
|
69
|
+
t.rspec_opts = ["--format", "documentation"]
|
|
70
|
+
end
|
|
54
71
|
end
|
|
55
72
|
|
|
56
|
-
# ==
|
|
73
|
+
# == Documentation == #
|
|
57
74
|
|
|
58
|
-
desc "
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
FileUtils.mv(Dir.glob(File.join(File.dirname(__FILE__), '*.gem')), pkg_dir)
|
|
64
|
-
end
|
|
75
|
+
desc "Generate API documentation to doc/rdocs/index.html"
|
|
76
|
+
RDoc::Task.new do |rd|
|
|
77
|
+
rd.rdoc_dir = 'doc/rdocs'
|
|
78
|
+
rd.main = 'README.rdoc'
|
|
79
|
+
rd.rdoc_files.include 'README.rdoc', 'lib/**/*.rb'
|
|
65
80
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
file = Dir["pkg/*.gem"].last
|
|
69
|
-
sh "gem install #{file}"
|
|
81
|
+
rd.options << '--all'
|
|
82
|
+
rd.options << '--diagram'
|
|
70
83
|
end
|
|
71
84
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
# == Emacs integration == #
|
|
86
|
+
desc "Rebuild TAGS file"
|
|
87
|
+
task :tags do
|
|
88
|
+
sh "rtags -R */{lib,spec}"
|
|
76
89
|
end
|
|
77
|
-
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-2011 RightScale, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'logger'))
|
|
25
|
+
|
|
26
|
+
module RightScraper
|
|
27
|
+
module Builders
|
|
28
|
+
# Base class for building additional metadata from filesystem
|
|
29
|
+
# based checkouts. Subclasses should override #go, and possibly
|
|
30
|
+
# #new if they require additional arguments.
|
|
31
|
+
#
|
|
32
|
+
# The lifecycle for a builder is as follows:
|
|
33
|
+
# - builder = Builder.new (once)
|
|
34
|
+
# - builder.go(dir, resource) (many times)
|
|
35
|
+
# - builder.finish (once)
|
|
36
|
+
class Builder
|
|
37
|
+
# Create a new Builder. Recognizes options as given. Some
|
|
38
|
+
# options may be required, others optional. This class recognizes
|
|
39
|
+
# only :logger.
|
|
40
|
+
#
|
|
41
|
+
# === Options
|
|
42
|
+
# <tt>:logger</tt>:: Optional. Logger currently being used
|
|
43
|
+
#
|
|
44
|
+
# === Parameters
|
|
45
|
+
# options(Hash):: builder options
|
|
46
|
+
def initialize(options={})
|
|
47
|
+
@logger = options.fetch(:logger, Logger.new)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Run builder for this resource.
|
|
51
|
+
#
|
|
52
|
+
# === Parameters
|
|
53
|
+
# dir(String):: directory resource exists at
|
|
54
|
+
# resource(Object):: resource instance being built
|
|
55
|
+
def go(dir, resource)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Notification that all scans for this repository have
|
|
59
|
+
# completed.
|
|
60
|
+
def finish
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-2011 RightScale, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'base'))
|
|
25
|
+
|
|
26
|
+
module RightScraper
|
|
27
|
+
module Builders
|
|
28
|
+
# Build metadata by scanning the filesystem.
|
|
29
|
+
class Filesystem < Builder
|
|
30
|
+
|
|
31
|
+
# Create a new filesystem scanner. In addition to the options
|
|
32
|
+
# recognized by Builder, this class recognizes <tt>:retriever</tt> and
|
|
33
|
+
# <tt>:scanner</tt>.
|
|
34
|
+
#
|
|
35
|
+
# === Options
|
|
36
|
+
# <tt>:scanner</tt>:: Required. Scanner currently being used
|
|
37
|
+
# <tt>:ignorable_paths</tt>:: Ignore directories whose name belong to this list
|
|
38
|
+
#
|
|
39
|
+
# === Parameters
|
|
40
|
+
# options(Hash):: scraper options
|
|
41
|
+
def initialize(options={})
|
|
42
|
+
super
|
|
43
|
+
@scanner = options.fetch(:scanner)
|
|
44
|
+
@ignorable_paths = options[:ignorable_paths]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Tell the scanner we're done.
|
|
48
|
+
def finish
|
|
49
|
+
super
|
|
50
|
+
@scanner.finish
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Run builder for this resource.
|
|
54
|
+
#
|
|
55
|
+
# === Parameters
|
|
56
|
+
# dir(String):: directory resource exists at
|
|
57
|
+
# resource(Object):: resource instance being built
|
|
58
|
+
def go(dir, resource)
|
|
59
|
+
@logger.operation(:scanning_filesystem, "rooted at #{dir}") do
|
|
60
|
+
@scanner.begin(resource)
|
|
61
|
+
maybe_scan(Dir.new(dir), nil)
|
|
62
|
+
@scanner.end(resource)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def maybe_scan(directory, position)
|
|
67
|
+
if @scanner.notice_dir(position)
|
|
68
|
+
scan(directory, position)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Scan the contents of directory.
|
|
73
|
+
#
|
|
74
|
+
# === Parameters
|
|
75
|
+
# directory(Dir):: directory to scan
|
|
76
|
+
# position(String):: relative pathname for _directory_ from root of resource
|
|
77
|
+
def scan(directory, position)
|
|
78
|
+
directory.each do |entry|
|
|
79
|
+
next if entry == '.' || entry == '..'
|
|
80
|
+
next if @ignorable_paths && @ignorable_paths.include?(entry)
|
|
81
|
+
|
|
82
|
+
fullpath = File.join(directory.path, entry)
|
|
83
|
+
relative_position = position ? File.join(position, entry) : entry
|
|
84
|
+
|
|
85
|
+
if File.directory?(fullpath)
|
|
86
|
+
maybe_scan(Dir.new(fullpath), relative_position)
|
|
87
|
+
else
|
|
88
|
+
@scanner.notice(relative_position) do
|
|
89
|
+
open(fullpath) {|f| f.read}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-2011 RightScale, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
module RightScraper
|
|
25
|
+
module Builders
|
|
26
|
+
# Union builder, to permit running multiple builders in sequence
|
|
27
|
+
# with the same interface as running one.
|
|
28
|
+
class Union
|
|
29
|
+
# (Array) subcomponents of this union
|
|
30
|
+
attr_reader :subbuilders
|
|
31
|
+
|
|
32
|
+
# Create a new union builder. Recognizes no new options.
|
|
33
|
+
#
|
|
34
|
+
# === Parameters
|
|
35
|
+
# classes(List):: List of Builder classes to run
|
|
36
|
+
# options(Hash):: options to initialize each Builder with
|
|
37
|
+
def initialize(classes, options={})
|
|
38
|
+
@subbuilders = classes.map {|klass| klass.new(options)}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Run each builder for this resource.
|
|
42
|
+
#
|
|
43
|
+
# === Parameters
|
|
44
|
+
# dir(String):: directory resource exists at
|
|
45
|
+
# resource(RightScraper::Resources::Base):: resource instance being built
|
|
46
|
+
def go(dir, resource)
|
|
47
|
+
@subbuilders.each {|builder| builder.go(dir, resource)}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Notify subbuilders that all scans for this repository have
|
|
51
|
+
# completed.
|
|
52
|
+
def finish
|
|
53
|
+
@subbuilders.each {|builder| builder.finish}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-2011 RightScale, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require 'logger'
|
|
25
|
+
|
|
26
|
+
module RightScraper
|
|
27
|
+
# Very simplistic logger for scraper operations.
|
|
28
|
+
class Logger < ::Logger
|
|
29
|
+
# If no arguments, create a Logger that logs to nothing.
|
|
30
|
+
# Otherwise pass the arguments on to ::Logger.
|
|
31
|
+
def initialize(*args)
|
|
32
|
+
if args.empty?
|
|
33
|
+
super('/dev/null')
|
|
34
|
+
self.level = ::Logger::ERROR
|
|
35
|
+
else
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
@exceptional = false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# (RightScraper::Repositories::Base) Repository currently being examined.
|
|
42
|
+
attr_writer :repository
|
|
43
|
+
|
|
44
|
+
# Begin an operation that merits logging. Will call #note_error
|
|
45
|
+
# if an exception is raised during the operation.
|
|
46
|
+
#
|
|
47
|
+
# === Parameters
|
|
48
|
+
# type(Symbol):: operation type identifier
|
|
49
|
+
# explanation(String):: optional explanation
|
|
50
|
+
def operation(type, explanation="")
|
|
51
|
+
begin
|
|
52
|
+
note_phase(:begin, type, explanation)
|
|
53
|
+
result = yield
|
|
54
|
+
note_phase(:commit, type, explanation)
|
|
55
|
+
result
|
|
56
|
+
rescue
|
|
57
|
+
note_phase(:abort, type, explanation, $!)
|
|
58
|
+
raise
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Note an event to the log. In this base class this calls
|
|
63
|
+
# note_error when an error occurs, but subclasses will presumably
|
|
64
|
+
# want to override it.
|
|
65
|
+
#
|
|
66
|
+
# === Parameters
|
|
67
|
+
# phase(Symbol):: phase of operation; one of :begin, :commit, :abort
|
|
68
|
+
# type(Symbol):: operation type identifier
|
|
69
|
+
# explanation(String):: explanation of operation
|
|
70
|
+
# exception(Exception):: optional exception (only if +phase+ is :abort)
|
|
71
|
+
def note_phase(phase, type, explanation, exception=nil)
|
|
72
|
+
case phase
|
|
73
|
+
when :begin then @exceptional = false
|
|
74
|
+
when :abort then
|
|
75
|
+
unless @exceptional
|
|
76
|
+
note_error(exception, type, explanation)
|
|
77
|
+
@exceptional = true
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Log an error, with the given exception and explanation of what
|
|
83
|
+
# was going on.
|
|
84
|
+
#
|
|
85
|
+
# === Parameters
|
|
86
|
+
# exception(Exception):: exception raised
|
|
87
|
+
# type(Symbol):: operation type identifier
|
|
88
|
+
# explanation(String):: optional explanation
|
|
89
|
+
def note_error(exception, type, explanation="")
|
|
90
|
+
error("Saw #{exception} during #{type}#{maybe_explain(explanation)}")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
protected
|
|
94
|
+
def maybe_explain(explanation)
|
|
95
|
+
if explanation.nil? || explanation.empty?
|
|
96
|
+
""
|
|
97
|
+
else
|
|
98
|
+
": #{explanation}"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010 RightScale, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'logger'))
|
|
25
|
+
|
|
26
|
+
module RightScraper
|
|
27
|
+
module Loggers
|
|
28
|
+
# A very noisy logger, useful for debugging.
|
|
29
|
+
class NoisyLogger < Logger
|
|
30
|
+
# Initialize the logger, setting the current operation depth to 1.
|
|
31
|
+
def initialize(*args)
|
|
32
|
+
super
|
|
33
|
+
@pending = []
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Note an event to the log, including a visual indicator of how
|
|
37
|
+
# many nested operations are currently pending.
|
|
38
|
+
#
|
|
39
|
+
# === Parameters
|
|
40
|
+
# phase(Symbol):: phase of operation; one of :begin, :commit, :abort
|
|
41
|
+
# type(Symbol):: operation type identifier
|
|
42
|
+
# explanation(String):: explanation of operation
|
|
43
|
+
# exception(Exception):: optional exception (only if +phase+ is :abort)
|
|
44
|
+
def note_phase(phase, type, explanation, exception=nil)
|
|
45
|
+
if phase == :begin
|
|
46
|
+
@pending.push [type, explanation]
|
|
47
|
+
end
|
|
48
|
+
super
|
|
49
|
+
debug("#{depth_str} #{phase} #{immediate_context}")
|
|
50
|
+
unless phase == :begin
|
|
51
|
+
@pending.pop
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def note_error(exception, type, explanation="")
|
|
56
|
+
recordedtype, recordedexplanation = @pending[-1]
|
|
57
|
+
if recordedtype != type || recordedexplanation != explanation
|
|
58
|
+
@pending.push [type, explanation]
|
|
59
|
+
end
|
|
60
|
+
error("Saw #{exception} during #{context}")
|
|
61
|
+
if recordedtype != type || recordedexplanation != explanation
|
|
62
|
+
@pending.pop
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
def depth_str
|
|
68
|
+
'>' * @pending.size
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def context
|
|
72
|
+
@pending.reverse.map {|pair| contextify(pair)}.join(" in ")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def immediate_context
|
|
76
|
+
contextify(@pending[-1])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def contextify(pair)
|
|
80
|
+
type, explanation = pair
|
|
81
|
+
"#{type}#{maybe_explain(explanation)}"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|