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.
Files changed (92) hide show
  1. data/Gemfile +16 -0
  2. data/README.rdoc +9 -28
  3. data/Rakefile +51 -39
  4. data/lib/right_scraper/builders/base.rb +64 -0
  5. data/lib/right_scraper/builders/filesystem.rb +96 -0
  6. data/lib/right_scraper/builders/union.rb +57 -0
  7. data/lib/right_scraper/logger.rb +102 -0
  8. data/lib/right_scraper/loggers/noisy.rb +85 -0
  9. data/lib/right_scraper/processes/ssh.rb +188 -0
  10. data/lib/right_scraper/repositories/base.rb +299 -0
  11. data/lib/right_scraper/repositories/download.rb +90 -0
  12. data/lib/right_scraper/repositories/git.rb +92 -0
  13. data/lib/right_scraper/repositories/mock.rb +70 -0
  14. data/lib/right_scraper/repositories/svn.rb +96 -0
  15. data/lib/right_scraper/resources/base.rb +70 -0
  16. data/{spec/scraper_base_spec.rb → lib/right_scraper/resources/cookbook.rb} +9 -23
  17. data/lib/right_scraper/resources/workflow.rb +55 -0
  18. data/lib/right_scraper/retrievers/base.rb +114 -0
  19. data/lib/right_scraper/retrievers/checkout.rb +79 -0
  20. data/lib/right_scraper/retrievers/download.rb +97 -0
  21. data/lib/right_scraper/retrievers/git.rb +140 -0
  22. data/lib/right_scraper/retrievers/svn.rb +87 -0
  23. data/lib/right_scraper/scanners/base.rb +111 -0
  24. data/lib/right_scraper/scanners/cookbook_manifest.rb +59 -0
  25. data/lib/right_scraper/scanners/cookbook_metadata.rb +69 -0
  26. data/lib/right_scraper/scanners/cookbook_s3_upload.rb +84 -0
  27. data/lib/right_scraper/scanners/union.rb +89 -0
  28. data/lib/right_scraper/scanners/workflow_manifest.rb +86 -0
  29. data/lib/right_scraper/scanners/workflow_metadata.rb +70 -0
  30. data/lib/right_scraper/scanners/workflow_s3_upload.rb +85 -0
  31. data/lib/right_scraper/scraper.rb +81 -57
  32. data/lib/right_scraper/scraper_logger.rb +61 -0
  33. data/lib/right_scraper/scrapers/base.rb +262 -0
  34. data/lib/right_scraper/scrapers/cookbook.rb +73 -0
  35. data/lib/right_scraper/scrapers/workflow.rb +88 -0
  36. data/lib/right_scraper/svn_client.rb +101 -0
  37. data/lib/right_scraper/version.rb +28 -0
  38. data/lib/right_scraper.rb +35 -11
  39. data/right_scraper.gemspec +26 -13
  40. data/right_scraper.rconf +13 -0
  41. data/spec/builder_spec.rb +50 -0
  42. data/spec/cookbook_helper.rb +73 -0
  43. data/spec/cookbook_manifest_spec.rb +55 -0
  44. data/spec/cookbook_s3_upload_spec.rb +152 -0
  45. data/spec/download/download_retriever_spec.rb +118 -0
  46. data/spec/download/download_retriever_spec_helper.rb +72 -0
  47. data/spec/download/download_spec.rb +130 -0
  48. data/spec/download/multi_dir_spec.rb +106 -0
  49. data/spec/download/multi_dir_spec_helper.rb +40 -0
  50. data/spec/git/cookbook_spec.rb +166 -0
  51. data/spec/git/demokey +27 -0
  52. data/spec/git/demokey.pub +1 -0
  53. data/spec/git/password_key +30 -0
  54. data/spec/git/password_key.pub +1 -0
  55. data/spec/git/repository_spec.rb +110 -0
  56. data/spec/git/retriever_spec.rb +505 -0
  57. data/spec/git/retriever_spec_helper.rb +112 -0
  58. data/spec/git/scraper_spec.rb +136 -0
  59. data/spec/git/ssh_spec.rb +170 -0
  60. data/spec/git/url_spec.rb +103 -0
  61. data/spec/logger_spec.rb +185 -0
  62. data/spec/repository_spec.rb +89 -23
  63. data/spec/{scraper_spec_helper_base.rb → retriever_spec_helper.rb} +41 -27
  64. data/spec/scanner_spec.rb +61 -0
  65. data/spec/scraper_helper.rb +96 -0
  66. data/spec/scraper_spec.rb +123 -45
  67. data/spec/spec_helper.rb +87 -14
  68. data/spec/svn/cookbook_spec.rb +97 -0
  69. data/spec/svn/multi_svn_spec.rb +64 -0
  70. data/spec/svn/multi_svn_spec_helper.rb +40 -0
  71. data/spec/svn/repository_spec.rb +72 -0
  72. data/spec/svn/retriever_spec.rb +261 -0
  73. data/spec/svn/scraper_spec.rb +90 -0
  74. data/spec/svn/{svn_scraper_spec_helper.rb → svn_retriever_spec_helper.rb} +46 -27
  75. data/spec/svn/url_spec.rb +47 -0
  76. data/spec/url_spec.rb +164 -0
  77. metadata +203 -31
  78. data/lib/right_scraper/linux/process_monitor.rb +0 -84
  79. data/lib/right_scraper/repository.rb +0 -78
  80. data/lib/right_scraper/scraper_base.rb +0 -175
  81. data/lib/right_scraper/scrapers/download_scraper.rb +0 -67
  82. data/lib/right_scraper/scrapers/git_scraper.rb +0 -283
  83. data/lib/right_scraper/scrapers/svn_scraper.rb +0 -119
  84. data/lib/right_scraper/watcher.rb +0 -158
  85. data/lib/right_scraper/win32/process_monitor.rb +0 -98
  86. data/spec/download/download_scraper_spec.rb +0 -94
  87. data/spec/git/git_scraper_spec.rb +0 -165
  88. data/spec/git/git_scraper_spec_helper.rb +0 -72
  89. data/spec/rcov.opts +0 -1
  90. data/spec/spec.opts +0 -2
  91. data/spec/svn/svn_scraper_spec.rb +0 -148
  92. data/spec/watcher_spec.rb +0 -74
@@ -0,0 +1,86 @@
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
+ require 'digest/sha1'
26
+
27
+ module RightScraper
28
+ module Scanners
29
+ # Build manifests from a filesystem.
30
+ class WorkflowManifest < Base
31
+ # Create a new manifest scanner. Does not accept any new arguments.
32
+ def initialize(*args)
33
+ super
34
+ @manifest = {}
35
+ end
36
+
37
+ # Retrieve relative workflow files positions
38
+ #
39
+ # === Parameters
40
+ # workflow(Resources::Workflow):: Workflow whose manifest is being built
41
+ def begin(workflow)
42
+ @workflow = workflow
43
+ @metadata_filename = File.basename(@workflow.metadata_path)
44
+ @definition_filename = File.basename(@workflow.definition_path)
45
+ end
46
+
47
+ # Complete a scan for the given resource.
48
+ #
49
+ # === Parameters ===
50
+ # resource(RightScraper::Resources::Base):: resource to scan
51
+ def end(resource)
52
+ resource.manifest = @manifest
53
+ @manifest = {}
54
+ end
55
+
56
+ # Notice a file during scanning.
57
+ #
58
+ # === Block ===
59
+ # Return the data for this file. We use a block because it may
60
+ # not always be necessary to read the data.
61
+ #
62
+ # === Parameters ===
63
+ # relative_position(String):: relative pathname for file from root of resource
64
+ def notice(relative_position)
65
+ if [ @metadata_filename, @definition_filename ].include?(relative_position)
66
+ @manifest[relative_position] = Digest::SHA1.hexdigest(yield)
67
+ end
68
+ end
69
+
70
+ # Notice a directory during scanning. Since the workflow definition and
71
+ # metadata live in the root directory we don't need to recurse,
72
+ # but we do need to go into the first directory (identified by
73
+ # +relative_position+ being +nil+).
74
+ #
75
+ # === Parameters
76
+ # relative_position(String):: relative pathname for the directory from root of workflow
77
+ #
78
+ # === Returns
79
+ # Boolean:: should the scanning recurse into the directory
80
+ def notice_dir(relative_position)
81
+ relative_position == nil
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,70 @@
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 'json'
25
+
26
+ module RightScraper
27
+ module Scanners
28
+ # Load workflow metadata from a filesystem.
29
+ class WorkflowMetadata < Base
30
+ # Begin a scan for the given workflow.
31
+ #
32
+ # === Parameters
33
+ # workflow(RightScraper::Resources::Workflow):: workflow to scan
34
+ def begin(workflow)
35
+ @workflow = workflow
36
+ @metadata_filename = File.basename(workflow.metadata_path)
37
+ end
38
+
39
+ # Notice a file during scanning.
40
+ #
41
+ # === Block
42
+ # Return the data for this file. We use a block because it may
43
+ # not always be necessary to read the data.
44
+ #
45
+ # === Parameters
46
+ # relative_position(String):: relative pathname for the file from root of workflow
47
+ def notice(relative_position)
48
+ if relative_position == @metadata_filename
49
+ @logger.operation(:metadata_parsing) do
50
+ @workflow.metadata = JSON.parse(yield)
51
+ end
52
+ end
53
+ end
54
+
55
+ # Notice a directory during scanning. Since the workflow definition and
56
+ # metadata live in the root directory we don't need to recurse,
57
+ # but we do need to go into the first directory (identified by
58
+ # +relative_position+ being +nil+).
59
+ #
60
+ # === Parameters
61
+ # relative_position(String):: relative pathname for the directory from root of workflow
62
+ #
63
+ # === Returns
64
+ # Boolean:: should the scanning recurse into the directory
65
+ def notice_dir(relative_position)
66
+ relative_position == nil
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,85 @@
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
+ require 'right_aws'
24
+ require 'json'
25
+
26
+ module RightScraper
27
+ module Scanners
28
+ # Upload workflow definition and metadata to an S3 bucket.
29
+ class WorkflowS3Upload < Base
30
+ # Create a new S3Upload. In addition to the options recognized
31
+ # by Scanner, this class recognizes <tt>:s3_key</tt>,
32
+ # <tt>:s3_secret</tt>, and <tt>:s3_bucket</tt> and requires all
33
+ # of those.
34
+ #
35
+ # === Options
36
+ # <tt>:s3_key</tt>:: Required. S3 access key.
37
+ # <tt>:s3_secret</tt>:: Required. S3 secret key.
38
+ # <tt>:s3_bucket</tt>:: Required. Bucket to upload workflows to.
39
+ #
40
+ # === Parameters
41
+ # options(Hash):: scanner options
42
+ def initialize(options={})
43
+ super
44
+ s3_key = options.fetch(:s3_key)
45
+ s3_secret = options.fetch(:s3_secret)
46
+ s3 = RightAws::S3.new(aws_access_key_id=s3_key,
47
+ aws_secret_access_key=s3_secret,
48
+ :logger => Logger.new)
49
+ @bucket = s3.bucket(options.fetch(:s3_bucket))
50
+ raise "Need an actual, existing S3 bucket!" if @bucket.nil?
51
+ end
52
+
53
+ # Upon ending a scan for a workflows, upload the workflows
54
+ # contents to S3.
55
+ #
56
+ # === Parameters
57
+ # workflows(RightScraper::Workflows):: Workflow to scan
58
+ def end(workflow)
59
+ @bucket.put(File.join('Workflows', workflow.resource_hash),
60
+ {
61
+ :metadata => workflow.metadata,
62
+ :manifest => workflow.manifest
63
+ }.to_json)
64
+ end
65
+
66
+ # Upload a file during scanning.
67
+ #
68
+ # === Block
69
+ # Return the data for this file. We use a block because it may
70
+ # not always be necessary to read the data.
71
+ #
72
+ # === Parameters
73
+ # relative_position(String):: relative pathname for file from root of cookbook
74
+ def notice(relative_position)
75
+ # TBD: Only uplad definition and metadata, will there be more files?
76
+ contents = yield
77
+ name = Digest::SHA1.hexdigest(contents)
78
+ path = File.join('Files', name)
79
+ unless @bucket.key(path).exists?
80
+ @bucket.put(path, contents)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -1,18 +1,18 @@
1
1
  #--
2
- # Copyright: Copyright (c) 2010 RightScale, Inc.
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
@@ -20,94 +20,118 @@
20
20
  # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
21
  # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
+ require File.expand_path(File.join(File.dirname(__FILE__), 'logger'))
23
24
 
24
- module RightScale
25
-
26
- # Hash of repository types associated with corresponding scraper class
27
- SCRAPERS = { 'git' => RightScale::GitScraper,
28
- 'svn' => RightScale::SvnScraper,
29
- 'download' => RightScale::DownloadScraper }
25
+ module RightScraper
30
26
 
31
27
  # Library main entry point. Instantiate this class and call the scrape
32
- # method to download or update a remote repository to the local disk.
28
+ # method to download or update a remote repository to the local disk and
29
+ # run a scraper on the resulting files.
33
30
  class Scraper
34
31
 
35
- # (String) Path to directory where remote repository was downloaded
36
- # Note: This will be a subfolder of the scrape directory (directory given to initializer)
37
- attr_reader :last_repo_dir
38
-
32
+ # (Array):: Scraped resources
33
+ attr_reader :resources
34
+
39
35
  # Initialize scrape destination directory
40
36
  #
41
- # === Parameters
42
- # scrape_dir(String):: Scrape destination directory
43
- # max_bytes(Integer):: Maximum size allowed for repos, -1 for no limit (default)
44
- # max_seconds(Integer):: Maximum number of seconds a single scrape operation should take, -1 for no limit (default)
45
- def initialize(scrape_dir, max_bytes = -1, max_seconds = -1)
46
- @scrape_dir = scrape_dir
47
- @max_bytes = max_bytes
48
- @max_seconds = max_seconds
49
- @scrapers = {}
37
+ # === Options
38
+ # <tt>:kind</tt>:: Type of scraper that will traverse directory for resources, one of :cookbook or :workflow
39
+ # <tt>:basedir</tt>:: Local directory where files are retrieved and scraped, use temporary directory if nil
40
+ # <tt>:max_bytes</tt>:: Maximum number of bytes to read from remote repo, unlimited if nil
41
+ # <tt>:max_seconds</tt>:: Maximum number of seconds to spend reading from remote repo, unlimited if nil
42
+ def initialize(options={})
43
+ @temporary = !options.has_key?(:basedir)
44
+ options[:basedir] ||= Dir.mktmpdir
45
+ @logger = ScraperLogger.new
46
+ @options = options.merge({:logger => @logger})
47
+ @resources = []
50
48
  end
51
49
 
52
- # Scrape given repository.
53
- # Create unique directory inside scrape directory when called for the first time.
54
- # Update content of unique directory incrementally when possible with further calls.
50
+ # Scrape given repository, depositing files into the scrape
51
+ # directory. Update content of unique directory incrementally
52
+ # when possible with further calls.
55
53
  #
56
54
  # === Parameters
57
- # repo(Hash|RightScale::Repository):: Repository to be scraped
58
- # Note: repo can either be a Hash or a RightScale::Repo instance.
59
- # See the RightScale::Repo class for valid Hash keys.
60
- # incremental(FalseClass|TrueClass):: Whether scrape should be incremental if possible (true by default)
55
+ # repo(Hash|RightScraper::Repositories::Base):: Repository to be scraped
56
+ # Note: repo can either be a Hash or a RightScraper::Repositories::Base instance.
57
+ # See the RightScraper::Repositories::Base class for valid Hash keys.
61
58
  #
62
59
  # === Block
63
60
  # If a block is given, it will be called back with progress information
64
- # the block should take two arguments:
65
- # - first argument is the string containing the info
66
- # - second argument is a boolean indicating whether to increment progress
67
- # The block is called exactly once with the increment flag set to true
61
+ # the block should take four arguments:
62
+ # - first argument is one of <tt>:begin</tt>, <tt>:commit</tt>,
63
+ # <tt>:abort</tt> which signifies what
64
+ # the scraper is trying to do and where it is when it does it
65
+ # - second argument is a symbol describing the operation being performed
66
+ # in an easy-to-match way
67
+ # - third argument is optional further explanation
68
+ # - fourth argument is the exception pending (only relevant for <tt>:abort</tt>)
68
69
  #
69
70
  # === Return
70
71
  # true:: If scrape was successful
71
- # false:: If scrape failed, call error_message for information on failure
72
+ # false:: If scrape failed, call errors for information on failure
72
73
  #
73
74
  # === Raise
74
75
  # 'Invalid repository type':: If repository type is not known
75
76
  def scrape(repo, incremental=true, &callback)
76
- repo = RightScale::Repository.from_hash(repo) if repo.is_a?(Hash)
77
- repo.repo_type = repo.repo_type.to_s # In case it's a symbol
78
- raise "Invalid repository type" unless SCRAPERS.include?(repo.repo_type)
79
- @scraper = @scrapers[repo.repo_type] ||= SCRAPERS[repo.repo_type].new(@scrape_dir, @max_bytes, @max_seconds)
80
- @scraper.scrape(repo, incremental, &callback)
81
- @last_repo_dir = @scraper.current_repo_dir
82
- @scraper.succeeded?
77
+ errorlen = errors.size
78
+ repo = RightScraper::Repositories::Base.from_hash(repo) if repo.is_a?(Hash)
79
+ @logger.callback = callback
80
+ begin
81
+ # 1. Retrieve the files
82
+ retriever = nil
83
+ @logger.operation(:retrieving, "from #{repo}") do
84
+ retriever = repo.retriever(@options)
85
+ retriever.retrieve
86
+ end
87
+
88
+ # 2. Now scrape if there is a scraper in the options
89
+ @logger.operation(:scraping, retriever.repo_dir) do
90
+ if @options[:kind]
91
+ options = @options.merge({:ignorable_paths => retriever.ignorable_paths,
92
+ :repo_dir => retriever.repo_dir,
93
+ :repository => retriever.repository})
94
+ scraper = RightScraper::Scrapers::Base.scraper(options)
95
+ @resources += scraper.scrape
96
+ end
97
+ end
98
+
99
+ # 3. Cleanup if temporary
100
+ FileUtils.remove_entry_secure(@options[:basedir]) if @temporary
101
+ rescue
102
+ # logger handles communication with the end user and appending
103
+ # to our error list, we just need to keep going.
104
+ end
105
+ @logger.callback = nil
106
+ errors.size == errorlen
83
107
  end
84
-
85
- # Retrieve directory path where repo was or would be downloaded
108
+
109
+ # Path to directory where given repo should be or was downloaded
86
110
  #
87
111
  # === Parameters
88
- # repo(Hash|RightScale::Repository):: Remote repository corresponding to local directory
112
+ # repo(Hash|RightScraper::Repositories::Base):: Remote repository corresponding to local directory
89
113
  #
90
- # === Return
91
- # repo_dir(String):: Path to local directory that corresponds to given repository
114
+ # === Return
115
+ # String:: Path to local directory that corresponds to given repository
92
116
  def repo_dir(repo)
93
- repo_dir = RightScale::ScraperBase.repo_dir(scrape_dir, repo)
117
+ RightScraper::Retrievers::Base.repo_dir(@options[:basedir], repo)
94
118
  end
95
119
 
96
- # Error messages in case of failure
97
- #
98
- # === Return
99
- # errors(Array):: Error messages or empty array if no error
120
+ # (Array):: Error messages in case of failure
100
121
  def errors
101
- errors = @scraper && @scraper.errors || []
122
+ @logger.errors
102
123
  end
103
124
 
104
- # Was scraping successful?
105
- # Call error_message to get error messages if false
125
+ # Was scraping successful?
126
+ # Call errors to get error messages if false
106
127
  #
107
128
  # === Return
108
- # succeeded(Boolean):: true if scrape finished with no error, false otherwise.
129
+ # Boolean:: true if scrape finished with no error, false otherwise.
109
130
  def succeeded?
110
- succeeded = errors.size == 0
131
+ errors.empty?
111
132
  end
133
+ alias_method :successful?, :succeeded?
134
+
112
135
  end
113
136
  end
137
+
@@ -0,0 +1,61 @@
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
+
26
+ class ScraperLogger < Logger
27
+ attr_accessor :errors
28
+ attr_accessor :callback
29
+
30
+ def add(severity, message=nil, progname=nil)
31
+ if severity >= (self.level || Logger::WARN)
32
+ if message.nil?
33
+ if block_given?
34
+ message = yield
35
+ else
36
+ message = progname
37
+ progname = self.progname
38
+ end
39
+ end
40
+ @errors << [nil, :log,
41
+ {:severity => severity,
42
+ :message => message,
43
+ :progname => progname}]
44
+ end
45
+ end
46
+
47
+ def initialize
48
+ @errors = []
49
+ end
50
+
51
+ def note_phase(phase, type, explanation, exception=nil)
52
+ @callback.call(phase, type, explanation, exception) unless @callback.nil?
53
+ super
54
+ end
55
+
56
+ def note_error(exception, type, explanation="")
57
+ @errors << [exception, type, explanation]
58
+ end
59
+ end
60
+
61
+ end