right_scraper 3.0.4 → 3.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -8
- data/README.rdoc +3 -1
- data/lib/right_scraper/logger.rb +2 -2
- data/lib/right_scraper/processes/ssh.rb +103 -71
- data/lib/right_scraper/resources/cookbook.rb +35 -2
- data/lib/right_scraper/retrievers/checkout.rb +3 -3
- data/lib/right_scraper/retrievers/download.rb +81 -18
- data/lib/right_scraper/retrievers/git.rb +37 -3
- data/lib/right_scraper/retrievers/svn.rb +7 -16
- data/lib/right_scraper/scanners/cookbook_manifest.rb +2 -2
- data/lib/right_scraper/scanners/cookbook_s3_upload.rb +8 -7
- data/lib/right_scraper/scraper.rb +4 -4
- data/lib/right_scraper/svn_client.rb +73 -11
- data/right_scraper.gemspec +18 -18
- data/right_scraper.rconf +1 -1
- data/spec/cookbook_manifest_spec.rb +43 -5
- data/spec/cookbook_s3_upload_spec.rb +8 -3
- data/spec/download/download_spec.rb +3 -5
- data/spec/git/cookbook_spec.rb +6 -7
- data/spec/git/retriever_spec.rb +5 -5
- data/spec/git/scraper_spec.rb +16 -1
- data/spec/git/ssh_spec.rb +5 -2
- data/spec/retriever_spec_helper.rb +2 -2
- data/spec/scraper_helper.rb +0 -10
- data/spec/spec_helper.rb +5 -5
- data/spec/svn/cookbook_spec.rb +5 -6
- data/spec/svn/svn_retriever_spec_helper.rb +5 -6
- metadata +60 -48
data/Gemfile
CHANGED
@@ -1,15 +1,14 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
gem
|
6
|
-
|
7
|
-
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
gem 'right_popen', :git => 'git@github.com:rightscale/right_popen.git',
|
6
|
+
:branch => "master"
|
7
|
+
|
8
|
+
gem 'right_support', '2.7'
|
8
9
|
|
9
10
|
group :development do
|
10
|
-
gem "rspec", "~> 2.3"
|
11
11
|
gem "rake", "0.8.7"
|
12
|
-
gem "flexmock"
|
13
12
|
gem "ruby-debug", :platform=>"ruby_18"
|
14
13
|
gem "ruby-debug19", :platform=>"ruby_19"
|
15
14
|
gem "rdoc", "~> 2.4"
|
data/README.rdoc
CHANGED
@@ -10,6 +10,8 @@ may specify only the functionality (and required libraries and gems) you require
|
|
10
10
|
This gem depends on all available RightScraper modules, enabling full support at the
|
11
11
|
cost of requiring some systems administration work external to Ruby.
|
12
12
|
|
13
|
+
Maintained by the RightScale Teal Team
|
14
|
+
|
13
15
|
== USAGE
|
14
16
|
|
15
17
|
=== Simple Example
|
@@ -17,7 +19,7 @@ cost of requiring some systems administration work external to Ruby.
|
|
17
19
|
require 'rubygems'
|
18
20
|
require 'right_scraper'
|
19
21
|
|
20
|
-
scraper =
|
22
|
+
scraper = RightScraper::Scraper.new(:basedir => '/tmp', :kind => :cookbook)
|
21
23
|
scraper.scrape(:type => :git, :url => 'git://github.com/rightscale/right_scraper.git')
|
22
24
|
|
23
25
|
== INSTALLATION
|
data/lib/right_scraper/logger.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright: Copyright (c) 2010 RightScale, Inc.
|
2
|
+
# Copyright: Copyright (c) 2010-2013 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
|
@@ -20,14 +20,19 @@
|
|
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
|
+
|
23
24
|
require 'tempfile'
|
24
|
-
require 'process_watcher'
|
25
25
|
require 'tmpdir'
|
26
|
+
require 'right_popen'
|
27
|
+
require 'right_popen/safe_output_buffer'
|
26
28
|
|
27
29
|
module RightScraper
|
28
30
|
module Processes
|
29
31
|
# Manage a dedicated SSH agent.
|
30
32
|
class SSHAgent
|
33
|
+
|
34
|
+
class SSHAgentError < Exception; end
|
35
|
+
|
31
36
|
def initialize
|
32
37
|
@display = ENV['DISPLAY']
|
33
38
|
@askpass = ENV['SSH_ASKPASS']
|
@@ -46,26 +51,31 @@ module RightScraper
|
|
46
51
|
ENV['HOME'] = "/dev/null"
|
47
52
|
@dir = Dir.mktmpdir
|
48
53
|
@socketfile = File.join(@dir, "agent")
|
49
|
-
@
|
50
|
-
@
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
@process = nil
|
55
|
+
@interupted_to_close = false
|
56
|
+
@ssh_agent_output = ::RightScale::RightPopen::SafeOutputBuffer.new
|
57
|
+
cmd = ['ssh-agent', '-a', @socketfile, '-d']
|
58
|
+
::RightScale::RightPopen.popen3_sync(
|
59
|
+
cmd,
|
60
|
+
:target => self,
|
61
|
+
:inherit_io => true, # avoid killing any rails connection
|
62
|
+
:watch_handler => :watch_ssh_agent,
|
63
|
+
:stderr_handler => :output_ssh_agent,
|
64
|
+
:stdout_handler => :output_ssh_agent,
|
65
|
+
:timeout_handler => :timeout_ssh_agent,
|
66
|
+
:exit_handler => :exit_ssh_agent,
|
67
|
+
:timeout_seconds => 10)
|
68
|
+
if @process
|
69
|
+
ENV['SSH_AGENT_PID'] = @process.pid.to_s
|
70
|
+
ENV['SSH_AUTH_SOCK'] = @socketfile
|
58
71
|
end
|
59
|
-
ENV['SSH_AGENT_PID'] = @pid.to_s
|
60
|
-
ENV['SSH_AUTH_SOCK'] = @socketfile
|
61
72
|
end
|
62
73
|
|
63
74
|
# Close the connection to the SSH agent, and restore +ENV+.
|
64
75
|
def close
|
65
76
|
begin
|
66
77
|
FileUtils.remove_entry_secure @dir
|
67
|
-
lay_to_rest
|
68
|
-
@monitor.cleanup if @monitor
|
78
|
+
lay_to_rest
|
69
79
|
ensure
|
70
80
|
setvar 'SSH_AGENT_PID', @agentpid
|
71
81
|
setvar 'DISPLAY', @display
|
@@ -75,71 +85,35 @@ module RightScraper
|
|
75
85
|
end
|
76
86
|
end
|
77
87
|
|
78
|
-
|
79
|
-
|
80
|
-
# SIGKILL instead. In any case, the process will die. The
|
81
|
-
# status information is accessible in $?.
|
82
|
-
#
|
83
|
-
# === Parameters
|
84
|
-
# pid(Fixnum):: pid of process to kill
|
85
|
-
# timeout(Fixnum):: time in seconds to wait before forcing
|
86
|
-
# process to die. Defaults to 10 seconds.
|
87
|
-
def lay_to_rest(pid, timeout=10)
|
88
|
-
#refuse to kill ourselves, or to pass a bad arg to Process.kill
|
89
|
-
return 0 unless pid.is_a?(Integer) && pid > 0
|
90
|
-
|
91
|
-
Process.kill('TERM', pid)
|
92
|
-
time_waited = 0
|
93
|
-
loop do
|
94
|
-
if time_waited >= timeout
|
95
|
-
Process.kill('KILL', pid)
|
96
|
-
# can't waitpid here, because the ssh-agent isn't our
|
97
|
-
# child. Still, after SIGKILL it will die and init will
|
98
|
-
# reap it, so continue
|
99
|
-
return
|
100
|
-
end
|
101
|
-
# still can't waitpid here, so we see if it's still alive
|
102
|
-
return unless still_alive?(pid)
|
103
|
-
sleep 1
|
104
|
-
time_waited += 1
|
105
|
-
end
|
88
|
+
def output_ssh_agent(data)
|
89
|
+
@ssh_agent_output.safe_buffer_data(data)
|
106
90
|
end
|
107
91
|
|
108
|
-
#
|
109
|
-
# the 0 signal and checking for an exception.
|
92
|
+
# abandons watch when socket file appears
|
110
93
|
#
|
111
|
-
#
|
112
|
-
|
113
|
-
|
114
|
-
# === Return
|
115
|
-
# Boolean:: true if process is still alive
|
116
|
-
def still_alive?(pid)
|
117
|
-
begin
|
118
|
-
Process.kill(0, pid)
|
94
|
+
# @return [TrueClass|FalseClass] true to continue watch, false to abandon
|
95
|
+
def watch_ssh_agent(process)
|
96
|
+
if @interupted_to_close
|
119
97
|
true
|
120
|
-
|
121
|
-
|
98
|
+
else
|
99
|
+
@process = process
|
100
|
+
!::File.exists?(@socketfile)
|
122
101
|
end
|
123
102
|
end
|
124
103
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
if value.nil?
|
136
|
-
ENV.delete(key)
|
137
|
-
else
|
138
|
-
ENV[key] = value
|
104
|
+
def timeout_ssh_agent
|
105
|
+
unless @interupted_to_close
|
106
|
+
raise SSHAgentError, 'Timed out waiting for ssh-agent control socket to appear'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def exit_ssh_agent(status)
|
111
|
+
unless @interupted_to_close || status.success?
|
112
|
+
@ssh_agent_output.safe_buffer_data("Exit code = #{status.exitstatus}")
|
113
|
+
raise SSHAgentError, "ssh-agent failed: #{@ssh_agent_output.display_text}"
|
139
114
|
end
|
140
115
|
true
|
141
116
|
end
|
142
|
-
private :setvar
|
143
117
|
|
144
118
|
# Add the given key data to the ssh agent.
|
145
119
|
#
|
@@ -162,7 +136,33 @@ module RightScraper
|
|
162
136
|
# === Parameters
|
163
137
|
# file(String):: file containing key data
|
164
138
|
def add_keyfile(file)
|
165
|
-
|
139
|
+
@ssh_add_output = ::RightScale::RightPopen::SafeOutputBuffer.new
|
140
|
+
cmd = ['ssh-add', file]
|
141
|
+
::RightScale::RightPopen.popen3_sync(
|
142
|
+
cmd,
|
143
|
+
:target => self,
|
144
|
+
:inherit_io => true, # avoid killing any rails connection
|
145
|
+
:stderr_handler => :output_ssh_add,
|
146
|
+
:stdout_handler => :output_ssh_add,
|
147
|
+
:timeout_handler => :timeout_ssh_add,
|
148
|
+
:exit_handler => :exit_ssh_add,
|
149
|
+
:timeout_seconds => 10)
|
150
|
+
end
|
151
|
+
|
152
|
+
def output_ssh_add(data)
|
153
|
+
@ssh_add_output.safe_buffer_data(data)
|
154
|
+
end
|
155
|
+
|
156
|
+
def timeout_ssh_add
|
157
|
+
raise SSHAgentError, 'ssh-add timed out'
|
158
|
+
end
|
159
|
+
|
160
|
+
def exit_ssh_add(status)
|
161
|
+
unless status.success?
|
162
|
+
@ssh_add_output.safe_buffer_data("Exit code = #{status.exitstatus}")
|
163
|
+
raise SSHAgentError, "ssh-add failed: #{@ssh_add_output.display_text}"
|
164
|
+
end
|
165
|
+
true
|
166
166
|
end
|
167
167
|
|
168
168
|
# Execute the block in a new ssh agent.
|
@@ -183,6 +183,38 @@ module RightScraper
|
|
183
183
|
agent.close
|
184
184
|
end
|
185
185
|
end
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
def lay_to_rest
|
190
|
+
if @process
|
191
|
+
if @process.interrupt
|
192
|
+
@interupted_to_close = true
|
193
|
+
@process.sync_exit_with_target
|
194
|
+
else
|
195
|
+
@process.safe_close_io
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Set an environment variable to a value. If +value+ is nil,
|
201
|
+
# delete the variable instead.
|
202
|
+
#
|
203
|
+
# === Parameters
|
204
|
+
# key(String):: environment variable name
|
205
|
+
# value(String or nil):: proposed new value
|
206
|
+
#
|
207
|
+
# === Return
|
208
|
+
# true
|
209
|
+
def setvar(key, value)
|
210
|
+
if value.nil?
|
211
|
+
ENV.delete(key)
|
212
|
+
else
|
213
|
+
ENV[key] = value
|
214
|
+
end
|
215
|
+
true
|
216
|
+
end
|
217
|
+
|
186
218
|
end
|
187
219
|
end
|
188
220
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright: Copyright (c) 2010-
|
2
|
+
# Copyright: Copyright (c) 2010-2012 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
|
@@ -21,12 +21,45 @@
|
|
21
21
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
+
require 'digest/md5'
|
25
|
+
require 'json'
|
26
|
+
require 'right_support'
|
27
|
+
|
24
28
|
module RightScraper
|
25
29
|
|
26
30
|
module Resources
|
27
31
|
|
28
32
|
class Cookbook < Base
|
29
|
-
end
|
30
33
|
|
34
|
+
EMPTY_MANIFEST_JSON = ::JSON.dump(:manifest => {}).freeze
|
35
|
+
|
36
|
+
def manifest=(value)
|
37
|
+
@manifest_json = nil
|
38
|
+
@resource_hash = nil
|
39
|
+
@manifest = value
|
40
|
+
end
|
41
|
+
|
42
|
+
def manifest_json
|
43
|
+
unless @manifest_json
|
44
|
+
if manifest && !manifest.empty?
|
45
|
+
# note that we are preserving the :manifest key at the root only to
|
46
|
+
# avoid having to change how the manifest is interpreted by Repose.
|
47
|
+
manifest_hash = { :manifest => manifest }
|
48
|
+
@manifest_json = ::RightSupport::Data::HashTools.deep_sorted_json(manifest_hash, pretty=true).freeze
|
49
|
+
else
|
50
|
+
@manifest_json = EMPTY_MANIFEST_JSON
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@manifest_json
|
54
|
+
end
|
55
|
+
|
56
|
+
def resource_hash
|
57
|
+
unless @resource_hash
|
58
|
+
@resource_hash = ::Digest::MD5.hexdigest(manifest_json).freeze
|
59
|
+
end
|
60
|
+
@resource_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
31
64
|
end
|
32
65
|
end
|
@@ -40,9 +40,9 @@ module RightScraper
|
|
40
40
|
@logger.operation(:updating) do
|
41
41
|
do_update
|
42
42
|
end
|
43
|
-
rescue
|
44
|
-
@logger.note_error(
|
45
|
-
FileUtils.remove_entry_secure
|
43
|
+
rescue Exception => e
|
44
|
+
@logger.note_error(e, :updating, "switching to using checkout")
|
45
|
+
FileUtils.remove_entry_secure basedir
|
46
46
|
@logger.operation(:checkout) do
|
47
47
|
do_checkout
|
48
48
|
end
|
@@ -20,9 +20,11 @@
|
|
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
|
-
|
23
|
+
|
24
24
|
require 'tempfile'
|
25
25
|
require 'digest/sha1'
|
26
|
+
require 'right_popen'
|
27
|
+
require 'right_popen/safe_output_buffer'
|
26
28
|
|
27
29
|
module RightScraper
|
28
30
|
module Retrievers
|
@@ -30,6 +32,8 @@ module RightScraper
|
|
30
32
|
# somewhere. Uses command line curl and command line tar.
|
31
33
|
class Download < Base
|
32
34
|
|
35
|
+
class DownloadError < Exception; end
|
36
|
+
|
33
37
|
@@available = false
|
34
38
|
|
35
39
|
# Determines if downloader is available.
|
@@ -54,32 +58,48 @@ module RightScraper
|
|
54
58
|
|
55
59
|
# Directory used to download tarballs
|
56
60
|
def workdir
|
57
|
-
File.join(@
|
58
|
-
end
|
59
|
-
|
60
|
-
# Path to directory where files are retrieved
|
61
|
-
def repo_dir
|
62
|
-
File.join(workdir, "archive")
|
61
|
+
@workdir ||= ::File.join(::File.dirname(@repo_dir), 'download')
|
63
62
|
end
|
64
63
|
|
65
64
|
# Download tarball and unpack it
|
66
65
|
def retrieve
|
67
66
|
raise RetrieverError.new("download retriever is unavailable") unless available?
|
67
|
+
FileUtils.remove_entry_secure @repo_dir if File.exists?(@repo_dir)
|
68
68
|
FileUtils.remove_entry_secure workdir if File.exists?(workdir)
|
69
|
-
FileUtils.mkdir_p repo_dir
|
69
|
+
FileUtils.mkdir_p @repo_dir
|
70
|
+
FileUtils.mkdir_p workdir
|
70
71
|
file = File.join(workdir, "package")
|
71
72
|
|
72
73
|
@logger.operation(:downloading) do
|
73
74
|
credential_command = if @repository.first_credential && @repository.second_credential
|
74
|
-
[
|
75
|
+
['-u', "#{@repository.first_credential}:#{@repository.second_credential}"]
|
75
76
|
else
|
76
77
|
[]
|
77
78
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
@output = ::RightScale::RightPopen::SafeOutputBuffer.new
|
80
|
+
@cmd = [
|
81
|
+
'curl',
|
82
|
+
'--silent', '--show-error', '--location', '--fail',
|
83
|
+
'--location-trusted', '-o', file, credential_command,
|
84
|
+
@repository.url
|
85
|
+
].flatten
|
86
|
+
begin
|
87
|
+
::RightScale::RightPopen.popen3_sync(
|
88
|
+
@cmd,
|
89
|
+
:target => self,
|
90
|
+
:pid_handler => :pid_download,
|
91
|
+
:timeout_handler => :timeout_download,
|
92
|
+
:size_limit_handler => :size_limit_download,
|
93
|
+
:exit_handler => :exit_download,
|
94
|
+
:stderr_handler => :output_download,
|
95
|
+
:stdout_handler => :output_download,
|
96
|
+
:inherit_io => true, # avoid killing any rails connection
|
97
|
+
:watch_directory => workdir,
|
98
|
+
:size_limit_bytes => @max_bytes,
|
99
|
+
:timeout_seconds => @max_seconds)
|
100
|
+
rescue Exception => e
|
101
|
+
@logger.note_phase(:abort, :running_command, 'curl', e)
|
102
|
+
raise
|
83
103
|
end
|
84
104
|
end
|
85
105
|
|
@@ -94,15 +114,58 @@ module RightScraper
|
|
94
114
|
else
|
95
115
|
extraction = "xf"
|
96
116
|
end
|
97
|
-
Dir.chdir(repo_dir) do
|
98
|
-
|
99
|
-
|
100
|
-
|
117
|
+
Dir.chdir(@repo_dir) do
|
118
|
+
@output = ::RightScale::RightPopen::SafeOutputBuffer.new
|
119
|
+
@cmd = ['tar', extraction, file]
|
120
|
+
begin
|
121
|
+
::RightScale::RightPopen.popen3_sync(
|
122
|
+
@cmd,
|
123
|
+
:target => self,
|
124
|
+
:pid_handler => :pid_download,
|
125
|
+
:timeout_handler => :timeout_download,
|
126
|
+
:size_limit_handler => :size_limit_download,
|
127
|
+
:exit_handler => :exit_download,
|
128
|
+
:stderr_handler => :output_download,
|
129
|
+
:stdout_handler => :output_download,
|
130
|
+
:inherit_io => true, # avoid killing any rails connection
|
131
|
+
:watch_directory => @repo_dir,
|
132
|
+
:size_limit_bytes => @max_bytes,
|
133
|
+
:timeout_seconds => @max_seconds)
|
134
|
+
rescue Exception => e
|
135
|
+
@logger.note_phase(:abort, :running_command, @cmd.first, e)
|
136
|
+
raise
|
101
137
|
end
|
102
138
|
end
|
103
139
|
end
|
104
140
|
end
|
105
141
|
|
142
|
+
def pid_download(pid)
|
143
|
+
@logger.note_phase(:begin, :running_command, @cmd.first)
|
144
|
+
true
|
145
|
+
end
|
146
|
+
|
147
|
+
def output_download(data)
|
148
|
+
@output.safe_buffer_data(data)
|
149
|
+
end
|
150
|
+
|
151
|
+
def timeout_download
|
152
|
+
raise DownloadError, "Downloader timed out"
|
153
|
+
end
|
154
|
+
|
155
|
+
def size_limit_download
|
156
|
+
raise DownloadError, "Downloader exceeded size limit"
|
157
|
+
end
|
158
|
+
|
159
|
+
def exit_download(status)
|
160
|
+
unless status.success?
|
161
|
+
@output.safe_buffer_data("Exit code = #{status.exitstatus}")
|
162
|
+
raise DownloadError, "Downloader failed: #{@output.display_text}"
|
163
|
+
end
|
164
|
+
@logger.note_phase(:commit, :running_command, @cmd.first)
|
165
|
+
true
|
166
|
+
end
|
167
|
+
|
168
|
+
|
106
169
|
# Amend @repository with the tag information from the downloaded
|
107
170
|
# file.
|
108
171
|
#
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright: Copyright (c) 2010-
|
2
|
+
# Copyright: Copyright (c) 2010-2013 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
|
@@ -23,6 +23,35 @@
|
|
23
23
|
|
24
24
|
require 'tmpdir'
|
25
25
|
|
26
|
+
# TEAL FIX: figure out a way to do this monkey-patch without always rquiring the
|
27
|
+
# blackwinter gem and/or create a rightscale-git fork with this fix.
|
28
|
+
#
|
29
|
+
# ADDENDUM: we can't unconditionally require the git gem because git is not
|
30
|
+
# always available.
|
31
|
+
begin
|
32
|
+
require 'git'
|
33
|
+
require 'git/lib'
|
34
|
+
|
35
|
+
module Git
|
36
|
+
class Lib
|
37
|
+
# Monkey patch to blackwinter-git that strips ANSI escape sequences
|
38
|
+
# from command output to avoid confusing the parser.
|
39
|
+
def run_command_with_color_stripping(git_cmd, &block)
|
40
|
+
out = run_command_without_color_stripping(git_cmd, &block)
|
41
|
+
out.gsub!(/\e\[[^m]*m/, '')
|
42
|
+
out
|
43
|
+
end
|
44
|
+
|
45
|
+
unless self.methods.include?('run_command_without_color_stripping')
|
46
|
+
alias :run_command_without_color_stripping :run_command
|
47
|
+
alias :run_command :run_command_with_color_stripping
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
rescue ::Git::GitExecuteError
|
52
|
+
# silently ignore git gem's failed attempt to execute git on load.
|
53
|
+
end
|
54
|
+
|
26
55
|
module RightScraper
|
27
56
|
module Retrievers
|
28
57
|
# Retriever for resources stored in a git repository.
|
@@ -33,7 +62,6 @@ module RightScraper
|
|
33
62
|
def available?
|
34
63
|
unless @@available
|
35
64
|
begin
|
36
|
-
require 'git'
|
37
65
|
# note that require 'git' does the same version check on load but
|
38
66
|
# we don't want to assume any particular implementation.
|
39
67
|
#
|
@@ -95,7 +123,13 @@ module RightScraper
|
|
95
123
|
def do_update
|
96
124
|
git = ::Git.open(@repo_dir)
|
97
125
|
do_fetch(git)
|
98
|
-
|
126
|
+
@logger.operation(:cleanup, "ensure no untracked files in #{@repo_dir}") do
|
127
|
+
git.reset_hard
|
128
|
+
Dir.chdir(@repo_dir) do
|
129
|
+
# ignore outcome; there is no way to record 'warnings'
|
130
|
+
system("git clean -f")
|
131
|
+
end
|
132
|
+
end
|
99
133
|
do_checkout_revision(git)
|
100
134
|
do_update_tag(git)
|
101
135
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright: Copyright (c) 2010-
|
2
|
+
# Copyright: Copyright (c) 2010-2013 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
|
@@ -22,8 +22,6 @@
|
|
22
22
|
#++
|
23
23
|
require File.join(File.dirname(__FILE__), '..', 'svn_client')
|
24
24
|
|
25
|
-
require 'process_watcher'
|
26
|
-
|
27
25
|
module RightScraper
|
28
26
|
module Retrievers
|
29
27
|
# Retriever for svn repositories
|
@@ -37,17 +35,10 @@ module RightScraper
|
|
37
35
|
def available?
|
38
36
|
unless @@available
|
39
37
|
begin
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
if $?.success?
|
45
|
-
@@available = true
|
46
|
-
else
|
47
|
-
raise RetrieverError, "\"#{cmd}\" exited with #{$?.exitstatus}"
|
48
|
-
end
|
49
|
-
rescue
|
50
|
-
@logger.note_error($!, :available, "svn retriever is unavailable")
|
38
|
+
calculate_version
|
39
|
+
@@available = true
|
40
|
+
rescue SvnClientError => e
|
41
|
+
@logger.note_error(e, :available, "svn retriever is unavailable")
|
51
42
|
end
|
52
43
|
end
|
53
44
|
@@available
|
@@ -81,8 +72,8 @@ module RightScraper
|
|
81
72
|
# pick out the first tag.
|
82
73
|
def do_update_tag
|
83
74
|
@repository = @repository.clone
|
84
|
-
|
85
|
-
|
75
|
+
lines = run_svn_with_buffered_output("log", "-r", 'HEAD')
|
76
|
+
lines.each do |line|
|
86
77
|
if line =~ /^r(\d+)/
|
87
78
|
@repository.tag = $1
|
88
79
|
break
|
@@ -22,7 +22,7 @@
|
|
22
22
|
#++
|
23
23
|
|
24
24
|
require File.expand_path(File.join(File.dirname(__FILE__), 'base'))
|
25
|
-
require 'digest/
|
25
|
+
require 'digest/md5'
|
26
26
|
|
27
27
|
module RightScraper
|
28
28
|
module Scanners
|
@@ -52,7 +52,7 @@ module RightScraper
|
|
52
52
|
# === Parameters ===
|
53
53
|
# relative_position(String):: relative pathname for file from root of resource
|
54
54
|
def notice(relative_position)
|
55
|
-
@manifest[relative_position] = Digest::
|
55
|
+
@manifest[relative_position] = Digest::MD5.hexdigest(yield)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright: Copyright (c) 2010-
|
2
|
+
# Copyright: Copyright (c) 2010-2012 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
|
@@ -22,6 +22,7 @@
|
|
22
22
|
#++
|
23
23
|
require 'right_aws'
|
24
24
|
require 'json'
|
25
|
+
require 'digest/md5'
|
25
26
|
|
26
27
|
module RightScraper
|
27
28
|
module Scanners
|
@@ -56,11 +57,11 @@ module RightScraper
|
|
56
57
|
# === Parameters
|
57
58
|
# cookbook(RightScraper::Cookbook):: cookbook to scan
|
58
59
|
def end(cookbook)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
path = File.join('Cooks', cookbook.resource_hash)
|
61
|
+
unless @bucket.key(path).exists?
|
62
|
+
contents = cookbook.manifest_json
|
63
|
+
@bucket.put(path, contents)
|
64
|
+
end
|
64
65
|
end
|
65
66
|
|
66
67
|
# Upload a file during scanning.
|
@@ -73,7 +74,7 @@ module RightScraper
|
|
73
74
|
# relative_position(String):: relative pathname for file from root of cookbook
|
74
75
|
def notice(relative_position)
|
75
76
|
contents = yield
|
76
|
-
name = Digest::
|
77
|
+
name = Digest::MD5.hexdigest(contents)
|
77
78
|
path = File.join('Files', name)
|
78
79
|
unless @bucket.key(path).exists?
|
79
80
|
@bucket.put(path, contents)
|