buzzville 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 buzzware
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ = buzzville
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 buzzware. See LICENSE for details.
@@ -0,0 +1,64 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "buzzville"
8
+ gem.summary = %Q{Capistrano recipes and ruby code relating to deployment}
9
+ gem.description = %Q{Capistrano recipes and ruby code relating to deployment}
10
+ gem.email = "contact@buzzware.com.au"
11
+ gem.homepage = "http://github.com/buzzware/buzzville"
12
+ gem.authors = ["buzzware"]
13
+ gem.rubyforge_project = "buzzware"
14
+ gem.add_dependency('buzzcore', '>= 0.2.5')
15
+ gem.add_dependency('yore', '>= 0.0.5')
16
+ gem.add_dependency('cmdparse', '>= 2.0.2')
17
+ gem.add_development_dependency "thoughtbot-shoulda"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::RubyforgeTasks.new do |rubyforge|
21
+ rubyforge.doc_task = "rdoc"
22
+ end
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
25
+ end
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/*_test.rb'
39
+ test.verbose = true
40
+ end
41
+ rescue LoadError
42
+ task :rcov do
43
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
44
+ end
45
+ end
46
+
47
+ task :test => :check_dependencies
48
+
49
+ task :default => :test
50
+
51
+ require 'rake/rdoctask'
52
+ Rake::RDocTask.new do |rdoc|
53
+ if File.exist?('VERSION')
54
+ version = File.read('VERSION')
55
+ else
56
+ version = ""
57
+ end
58
+
59
+ rdoc.rdoc_dir = 'rdoc'
60
+ rdoc.title = "buzzville #{version}"
61
+ rdoc.rdoc_files.include('README*')
62
+ rdoc.rdoc_files.include('lib/**/*.rb')
63
+ end
64
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.3
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
2
+ <Project
3
+ Version="10.0"
4
+ VendorName="SlickEdit"
5
+ WorkingDir=".">
6
+ <Config
7
+ Name="Release"
8
+ OutputFile=""
9
+ CompilerConfigName="Latest Version">
10
+ <Menu>
11
+ <Target
12
+ Name="Compile"
13
+ MenuCaption="&amp;Compile"
14
+ CaptureOutputWith="ProcessBuffer"
15
+ SaveOption="SaveCurrent"
16
+ RunFromDir="%rw">
17
+ <Exec/>
18
+ </Target>
19
+ <Target
20
+ Name="Build"
21
+ MenuCaption="&amp;Build"
22
+ CaptureOutputWith="ProcessBuffer"
23
+ SaveOption="SaveWorkspaceFiles"
24
+ RunFromDir="%rw">
25
+ <Exec/>
26
+ </Target>
27
+ <Target
28
+ Name="Rebuild"
29
+ MenuCaption="&amp;Rebuild"
30
+ CaptureOutputWith="ProcessBuffer"
31
+ SaveOption="SaveWorkspaceFiles"
32
+ RunFromDir="%rw">
33
+ <Exec/>
34
+ </Target>
35
+ <Target
36
+ Name="Debug"
37
+ MenuCaption="&amp;Debug"
38
+ SaveOption="SaveNone"
39
+ RunFromDir="%rw">
40
+ <Exec/>
41
+ </Target>
42
+ <Target
43
+ Name="Execute"
44
+ MenuCaption="E&amp;xecute"
45
+ SaveOption="SaveNone"
46
+ RunFromDir="%rw"
47
+ CaptureOutputWith="ProcessBuffer"
48
+ ClearProcessBuffer="1">
49
+ <Exec CmdLine="source actions.sh execute"/>
50
+ </Target>
51
+ </Menu>
52
+ </Config>
53
+ <CustomFolders>
54
+ <Folder
55
+ Name="Source Files"
56
+ Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl"/>
57
+ <Folder
58
+ Name="Header Files"
59
+ Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if"/>
60
+ <Folder
61
+ Name="Resource Files"
62
+ Filters="*.ico;*.cur;*.dlg"/>
63
+ <Folder
64
+ Name="Bitmaps"
65
+ Filters="*.bmp"/>
66
+ <Folder
67
+ Name="Other Files"
68
+ Filters="">
69
+ </Folder>
70
+ </CustomFolders>
71
+ <Files AutoFolders="DirectoryView">
72
+ <Folder Name="lib">
73
+ <F
74
+ N="lib/*"
75
+ Recurse="1"
76
+ Refilter="0"
77
+ Excludes=""/>
78
+ </Folder>
79
+ <Folder Name="test">
80
+ <F
81
+ N="test/*"
82
+ Recurse="0"
83
+ Refilter="0"
84
+ Excludes=".svn/"/>
85
+ </Folder>
86
+ <F N="buzzville.gemspec"/>
87
+ <F N="History.txt"/>
88
+ <F N="Manifest.txt"/>
89
+ <F N="PostInstall.txt"/>
90
+ <F N="Rakefile"/>
91
+ <F N="README.rdoc"/>
92
+ </Files>
93
+ </Project>
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
2
+ <Project
3
+ Version="10.0"
4
+ VendorName="SlickEdit"
5
+ WorkingDir=".">
6
+ <Config
7
+ Name="Release"
8
+ OutputFile=""
9
+ CompilerConfigName="Latest Version">
10
+ <Menu>
11
+ <Target
12
+ Name="Compile"
13
+ MenuCaption="&amp;Compile"
14
+ CaptureOutputWith="ProcessBuffer"
15
+ SaveOption="SaveCurrent"
16
+ RunFromDir="%rw">
17
+ <Exec/>
18
+ </Target>
19
+ <Target
20
+ Name="Build"
21
+ MenuCaption="&amp;Build"
22
+ CaptureOutputWith="ProcessBuffer"
23
+ SaveOption="SaveWorkspaceFiles"
24
+ RunFromDir="%rw">
25
+ <Exec/>
26
+ </Target>
27
+ <Target
28
+ Name="Rebuild"
29
+ MenuCaption="&amp;Rebuild"
30
+ CaptureOutputWith="ProcessBuffer"
31
+ SaveOption="SaveWorkspaceFiles"
32
+ RunFromDir="%rw">
33
+ <Exec/>
34
+ </Target>
35
+ <Target
36
+ Name="Debug"
37
+ MenuCaption="&amp;Debug"
38
+ SaveOption="SaveNone"
39
+ RunFromDir="%rw">
40
+ <Exec/>
41
+ </Target>
42
+ <Target
43
+ Name="Execute"
44
+ MenuCaption="E&amp;xecute"
45
+ SaveOption="SaveNone"
46
+ RunFromDir="%rw"
47
+ CaptureOutputWith="ProcessBuffer"
48
+ ClearProcessBuffer="1">
49
+ <Exec CmdLine="source actions.sh execute"/>
50
+ </Target>
51
+ </Menu>
52
+ </Config>
53
+ <CustomFolders>
54
+ <Folder
55
+ Name="Source Files"
56
+ Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl"/>
57
+ <Folder
58
+ Name="Header Files"
59
+ Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if"/>
60
+ <Folder
61
+ Name="Resource Files"
62
+ Filters="*.ico;*.cur;*.dlg"/>
63
+ <Folder
64
+ Name="Bitmaps"
65
+ Filters="*.bmp"/>
66
+ <Folder
67
+ Name="Other Files"
68
+ Filters="">
69
+ </Folder>
70
+ </CustomFolders>
71
+ <Files AutoFolders="DirectoryView">
72
+ <Folder Name="lib">
73
+ <F
74
+ N="lib/*"
75
+ Recurse="1"
76
+ Refilter="0"
77
+ Excludes=""/>
78
+ </Folder>
79
+ <Folder Name="test">
80
+ <F
81
+ N="test/*"
82
+ Recurse="0"
83
+ Refilter="0"
84
+ Excludes=".svn/"/>
85
+ </Folder>
86
+ <F N="buzzcore.gemspec"/>
87
+ <F N="History.txt"/>
88
+ <F N="Manifest.txt"/>
89
+ <F N="PostInstall.txt"/>
90
+ <F N="Rakefile"/>
91
+ <F N="README.rdoc"/>
92
+ </Files>
93
+ </Project>
@@ -0,0 +1,4 @@
1
+
2
+ Dir.chdir(File.dirname(__FILE__)) { Dir['buzzville/*'] }.each {|f| require f }
3
+
4
+
@@ -0,0 +1,323 @@
1
+ # use "extend CapUtils" inside a task to use this
2
+ require 'buzzcore/misc_utils'
3
+ require 'buzzcore/string_utils'
4
+ require 'buzzcore/xml_utils'
5
+ require 'buzzcore/shell_extras'
6
+ require 'net/ssh'
7
+ require 'net/sftp'
8
+
9
+ module CapUtils
10
+
11
+ # upload the given local file to the remote server and set the given mode.
12
+ # 0644 is the default mode
13
+ #
14
+ # Unix file modes :
15
+ # 4: read
16
+ # 2: write
17
+ # 1: execute
18
+ # 0[owner][group][other]
19
+ def upload_file(aLocalFilePath,aRemoteFilePath,aMode = 0644)
20
+ puts "* uploading #{aLocalFilePath} to #{aRemoteFilePath}"
21
+ s = nil
22
+ File.open(aLocalFilePath, "rb") { |f| s = f.read }
23
+ put(s,aRemoteFilePath,:mode => aMode)
24
+ end
25
+
26
+ def render_template_file(aTemplateFile,aXmlConfig,aOutputFile,aMoreConfig=nil)
27
+ template = MiscUtils.string_from_file(aTemplateFile)
28
+ values = XmlUtils.read_config_values(aXmlConfig)
29
+ values = values ? values.merge(aMoreConfig || {}) : aMoreConfig
30
+ result = StringUtils.render_template(template, values)
31
+ MiscUtils.string_to_file(result, aOutputFile)
32
+ end
33
+
34
+ def get_ip
35
+ run "ifconfig eth0 |grep \"inet addr\"" do |channel,stream,data|
36
+ return data.scan(/inet addr:([0-9.]+)/).flatten.pop
37
+ end
38
+ end
39
+
40
+ # check if file exists. Relies on remote ruby
41
+ def remote_file_exists?(aPath)
42
+ remote_ruby("puts File.exists?('#{aPath}').to_s")=="true\n"
43
+ end
44
+
45
+ def remote_ruby(aRubyString)
46
+ run 'ruby -e "'+aRubyString+'"' do |channel,stream,data|
47
+ return data
48
+ end
49
+ end
50
+
51
+ def sudo_run(aString)
52
+ # as = fetch(:runner, "app")
53
+ # via = fetch(:run_method, :sudo)
54
+ # invoke_command(aString, :via => via, :as => as)
55
+ # if aUseSudo
56
+ # run "sudo "+aString
57
+ # else
58
+ run aString
59
+ # end
60
+ end
61
+
62
+ def upload_file_anywhere(aSourceFile,aDestHost,aDestUser,aDestPassword,aDestFile,aDestPort=22)
63
+ Net::SSH.start(aDestHost, aDestUser, {:port => aDestPort, :password => aDestPassword, :verbose =>Logger::DEBUG}) do |ssh|
64
+ File.open(aSourceFile, "rb") { |f| ssh.sftp.upload!(f, aDestFile) }
65
+ end
66
+ end
67
+
68
+ def branch_name_from_svn_url(aURL)
69
+ prot_domain = (aURL.scan(/[^:]+:\/\/[^\/]+\//)).first
70
+ without_domain = aURL[prot_domain.length..-1]
71
+ return 'trunk' if without_domain =~ /^trunk\//
72
+ return (without_domain.scan(/branches\/(.+?)(\/|$)/)).flatten.first
73
+ end
74
+
75
+ # give block with |aText,aStream,aState| that returns response or nil
76
+ def run_respond(aCommand)
77
+ run(aCommand) do |ch,stream,text|
78
+ ch[:state] ||= { :channel => ch }
79
+ output = yield(text,stream,ch[:state])
80
+ ch.send_data(output) if output
81
+ end
82
+ end
83
+
84
+ # pass prompt to user, and return their response
85
+ def run_prompt(aCommand)
86
+ run_respond aCommand do |text,stream,state|
87
+ Capistrano::CLI.password_prompt(text)+"\n"
88
+ end
89
+ end
90
+
91
+ def ensure_link(aTo,aFrom,aDir=nil,aUserGroup=nil,aSudo='')
92
+ cmd = []
93
+ cmd << "cd #{aDir}" if aDir
94
+ cmd << "#{sudo} rm -rf #{aFrom}"
95
+ cmd << "#{sudo} ln -sf #{aTo} #{aFrom}"
96
+ cmd << "#{sudo} chown -h #{aUserGroup} #{aFrom}" if aUserGroup
97
+ run cmd.join(' && ')
98
+ end
99
+
100
+
101
+ def file_exists?(path)
102
+ result = nil
103
+ run "if [[ -e #{path} ]]; then echo 'true'; else echo 'false'; fi", :shell => false do |ch,stream,text|
104
+ result = (text.strip! == 'true')
105
+ end
106
+ result
107
+ end
108
+
109
+ # Used in deployment to maintain folder contents between deployments.
110
+ # Normally the shared path exists and will be linked into the release.
111
+ # If it doesn't exist and the release path does, it will be moved into the shared path
112
+ # aFolder eg. "vendor/extensions/design"
113
+ # aSharedFolder eg. "design"
114
+ def preserve_folder(aReleaseFolder,aSharedFolder)
115
+ aReleaseFolder = File.join(release_path,aReleaseFolder)
116
+ aSharedFolder = File.join(shared_path,aSharedFolder)
117
+ release_exists = file_exists?(aReleaseFolder)
118
+ shared_exists = file_exists?(aSharedFolder)
119
+ if shared_exists
120
+ run "rm -rf #{aReleaseFolder}" if release_exists
121
+ else
122
+ run "mv #{aReleaseFolder} #{aSharedFolder}" if release_exists
123
+ end
124
+ ensure_link("#{aSharedFolder}","#{aReleaseFolder}",nil,"#{user}:#{apache_user}")
125
+ end
126
+
127
+ def select_target_file(aFile)
128
+ ext = MiscUtils.file_extension(aFile,false)
129
+ no_ext = MiscUtils.file_no_extension(aFile,false)
130
+ dir = File.dirname(aFile)
131
+ run "#{sudo} mv -f #{no_ext}.#{target}.#{ext} #{aFile}"
132
+ run "#{sudo} rm -f #{no_ext}.*.#{ext}"
133
+ end
134
+
135
+ def shell(aCommandline,&aBlock)
136
+ result = block_given? ? POpen4::shell(aCommandline,nil,nil,&aBlock) : POpen4::shell(aCommandline)
137
+ return result[:stdout]
138
+ end
139
+
140
+ def run_local(aString)
141
+ `#{aString}`
142
+ end
143
+
144
+
145
+ def run_for_all(aCommand,aPath,aFilesOrDirs,aPattern=nil,aInvertPattern=false,aSudo=true)
146
+ #run "#{sudo} find . -wholename '*/.svn' -prune -o -type d -print0 |xargs -0 #{sudo} chmod 750"
147
+ #sudo find . -type f -exec echo {} \;
148
+ cmd = []
149
+ cmd << "sudo" if aSudo
150
+ cmd << "find #{aPath}"
151
+ cmd << "-wholename '#{aPattern}'" if aPattern
152
+ cmd << "-prune -o" if aInvertPattern
153
+ cmd << case aFilesOrDirs.to_s[0,1]
154
+ when 'f' then '-type f'
155
+ when 'd' then '-type d'
156
+ else ''
157
+ end
158
+ cmd << "-exec"
159
+ cmd << aCommand
160
+ cmd << '{} \;'
161
+ cmd = cmd.join(' ')
162
+ run cmd
163
+ end
164
+
165
+ #run_for_all("chmod g+s #{File.expand_path(dir,public_dir)}",public_dir,:dirs)
166
+
167
+ def set_dir_permissions_r(aStartPath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false)
168
+ cmd = []
169
+ if aGroup
170
+ cmd << (aUser ? "chown #{aUser}:#{aGroup}" : "chgrp #{aGroup}")
171
+ else
172
+ cmd << "chown #{aUser}" if aUser
173
+ end
174
+ cmd << "chmod #{aMode.to_s}" if aMode
175
+ cmd << "chmod g+s" if aSetGroupId
176
+ cmd.each do |c|
177
+ run_for_all(c,aStartPath,:dirs)
178
+ end
179
+ end
180
+
181
+ def set_permissions_cmd(aFilepath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false,aSudo=true)
182
+ cmd = []
183
+ if aGroup
184
+ cmd << (aUser ? "#{aSudo ? sudo : ''} chown #{aUser}:#{aGroup}" : "#{aSudo ? sudo : ''} chgrp #{aGroup}") + " #{aFilepath}"
185
+ else
186
+ cmd << "#{aSudo ? sudo : ''} chown #{aUser} #{aFilepath}" if aUser
187
+ end
188
+ cmd << "#{aSudo ? sudo : ''} chmod #{aMode.to_s} #{aFilepath}" if aMode
189
+ cmd << "#{aSudo ? sudo : ''} chmod g+s #{aFilepath}" if aSetGroupId
190
+ cmd.join(' && ')
191
+ end
192
+
193
+ def set_permissions(aFilepath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false,aSudo=true)
194
+ cmd = set_permissions_cmd(aFilepath,aUser,aGroup,aMode,aSetGroupId,aSudo)
195
+ run cmd
196
+ end
197
+
198
+ def mkdir_permissions(aStartPath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false,aSudo=true)
199
+ run "#{sudo} mkdir -p #{aStartPath}"
200
+ set_permissions(aStartPath,aUser,aGroup,aMode,aSetGroupId,aSudo)
201
+ end
202
+
203
+ # if aGroup is given, that will be the users only group
204
+ def adduser(aNewUser,aPassword,aGroup=nil)
205
+ run "#{sudo} adduser --gecos '' #{aGroup ? '--ingroup '+aGroup : ''} #{aNewUser}" do |ch, stream, out|
206
+ ch.send_data aPassword+"\n" if out =~ /UNIX password:/
207
+ end
208
+ end
209
+
210
+ def add_user_to_group(aUser,aGroup)
211
+ run "#{sudo} usermod -a -G #{aGroup} #{aUser}"
212
+ end
213
+
214
+ # returns 'buzzware-logikal' from 'git@git.assembla.com:buzzware/logikal.git'
215
+ def project_name_from_git_commit_url(aGitUrl)
216
+ parts = aGitUrl.split(/[@:\/]/) # eg ["git", "git.assembla.com", "buzzware", "logikal.git"]
217
+ return File.basename(parts[2..-1].join('-'),'.git')
218
+ end
219
+
220
+ # returns from git://github.com/buzzware/spree.git
221
+ def project_name_from_git_public_url(aGitUrl)
222
+ prot,url = aGitUrl.split(/\:\/\//)
223
+ url_parts = url.split('/')
224
+ host = url_parts.shift
225
+ File.basename(url_parts.join('-'),'.git')
226
+ end
227
+
228
+ def update_remote_git_cache(aGitUrl,aBranchOrTag=nil)
229
+ proj = project_name_from_git_public_url(aGitUrl)
230
+ cache_path = File.join(shared_path,'extra_cache')
231
+ run "mkdir -p #{cache_path}"
232
+ dest = File.join(cache_path,proj)
233
+ revision = ''
234
+ sub_mods = false
235
+
236
+ run "git clone #{aGitUrl} #{dest}" if !file_exists?(dest)
237
+ run "cd #{dest} && git checkout -f #{aBranchOrTag ? aBranchOrTag : ''} #{revision} && git reset --hard && git clean -dfqx"
238
+ if sub_mods
239
+ run "cd #{dest} && git submodule init && git submodule update"
240
+ end
241
+ return dest
242
+ end
243
+
244
+ def force_copy_mode_cmd(aFrom,aTo,aChmod=nil)
245
+ cmd = []
246
+ cmd << "rm -rf #{aTo}"
247
+ cmd << "cp -f #{aFrom} #{aTo}"
248
+ cmd << "chmod #{aChmod.to_s} #{aTo}" if aChmod
249
+ cmd.join(' && ')
250
+ end
251
+
252
+ def ensure_link_cmd(aTo,aFrom,aDir=nil,aUserGroup=nil,aSudo=nil)
253
+ aSudo ||= ''
254
+ cmd = []
255
+ cmd << "cd #{aDir}" if aDir
256
+ cmd << "#{aSudo} rm -rf #{aFrom}"
257
+ cmd << "#{aSudo} ln -sf #{aTo} #{aFrom}"
258
+ cmd << "#{aSudo} chown -h #{aUserGroup} #{aFrom}" if aUserGroup
259
+ cmd.join(' && ')
260
+ end
261
+
262
+ def ensure_folder(aPath,aOwner=nil,aGroup=nil,aMode=nil,aSudo=nil)
263
+ aSudo ||= ''
264
+ cmd = []
265
+ cmd << "#{aSudo} mkdir -p #{aPath}"
266
+ if aOwner || aGroup
267
+ cmd << "#{aSudo} chown #{aOwner} #{aPath}" if !aGroup
268
+ cmd << "#{aSudo} chgrp #{aGroup} #{aPath}" if !aOwner
269
+ cmd << "#{aSudo} chown #{aOwner}:#{aGroup} #{aPath}" if aOwner && aGroup
270
+ end
271
+ cmd << "chmod #{aMode} #{aPath}" if aMode
272
+ cmd.join(' && ')
273
+ end
274
+
275
+ # This means :
276
+ # * designers can ftp in to the server and upload/edit templates and partials
277
+ # * templates are Rails-style eg. erb but can be whatever you have Rails handlers for
278
+ # * designers can upload assets into a design folder that will be available publicly under /design
279
+ # * designers templates and assets are not affected by redeploys
280
+
281
+ def setup_designer_filesystem_cmd(aBrowserCmsRoot,aSharedDesignPath,aFtpPath,aUser,aApacheUser)
282
+
283
+ cmd = []
284
+
285
+ cmd << ensure_folder(aSharedDesignPath,aUser,aApacheUser,750)
286
+ cmd << ensure_folder(aSharedDesignPath+'/design',aUser,aApacheUser,750)
287
+ design_views = "#{aSharedDesignPath}/views"
288
+
289
+ cmd << ensure_folder(design_views,aUser,aApacheUser,750)
290
+ # copy files from database to shared/design
291
+ cmd << "cp -rf #{aBrowserCmsRoot}/tmp/views/* #{design_views}/"
292
+ cmd << ensure_folder(design_views+'/layouts/templates',aUser,aApacheUser,750)
293
+ cmd << ensure_folder(design_views+'/partials',aUser,aApacheUser,750)
294
+
295
+ #convert tmp views folder into a link to shared/design
296
+ cmd << ensure_link_cmd(design_views,'views',aBrowserCmsRoot+'/tmp',"#{aUser}:#{aApacheUser}")
297
+
298
+ # copy files from aBrowserCmsRoot to shared/design and make readonly
299
+ cmd << "cp -rf #{aBrowserCmsRoot}/app/views/* #{design_views}/"
300
+
301
+ # link design/public into public folder
302
+ cmd << ensure_link_cmd(aSharedDesignPath+'/design','design',aBrowserCmsRoot+'/public',"#{aUser}:#{aApacheUser}")
303
+
304
+ ## link shared/design/design into ftp folder
305
+ cmd << ensure_link_cmd(aSharedDesignPath+'/design','design',aFtpPath,"#{aUser}:#{aApacheUser}")
306
+ ## link templates into ftp folder
307
+ cmd << ensure_link_cmd(design_views,'views',aFtpPath,"#{aUser}:#{aApacheUser}")
308
+ #run "#{sudo} chgrp -h www-data #{deploy_to}/current" # this is to change owner of link, not target
309
+ cmd_s = cmd.join(" && ")
310
+ end
311
+
312
+ def install_script_from_string(aScriptString,aFilepath)
313
+ temp_path = File.join(deploy_to,File.basename(aFilepath))
314
+ put(aScriptString,temp_path)
315
+ run "#{sudo} mv #{temp_path} #{aFilepath}"
316
+ set_permissions(aFilepath,'root',user,750,false,true)
317
+ end
318
+
319
+ end
320
+
321
+ class CapUtilsClass
322
+ self.extend CapUtils
323
+ end
@@ -0,0 +1,188 @@
1
+ require 'net/ftp'
2
+
3
+ #this_path = File.dirname(__FILE__)
4
+ #require this_path+'/misc_utils'
5
+
6
+ String.class_eval do
7
+ def bite!(aValue=$/,aString=self)
8
+ if aString[0,aValue.length] == aValue
9
+ aString[0,aValue.length] = ''
10
+ return aString
11
+ else
12
+ return aString
13
+ end
14
+ end
15
+
16
+ def bite(aValue=$/)
17
+ bite!(aValue,self.clone)
18
+ end
19
+ end
20
+
21
+
22
+ module Net
23
+ class FTP
24
+ def FTP.with_connect(aHost,aUsername,aPassword,aDir=nil)
25
+ open(aHost,aUsername,aPassword) do |f|
26
+ f.passive = true
27
+ f.chdir(aDir) if aDir
28
+ yield f
29
+ end
30
+ end
31
+
32
+ def self.crack_file_line(aString)
33
+ values = aString.scan(/(.{10}).{28}(.{13})(.*)$/).flatten
34
+ {
35
+ :bits => values[0],
36
+ :date => values[1],
37
+ :name => values[2]
38
+ }
39
+ end
40
+
41
+ # BEGIN BUGFIXES
42
+
43
+ #
44
+ # Returns the size of the given (remote) filename.
45
+ #
46
+ def size(filename)
47
+ voidcmd("TYPE I")
48
+ resp = sendcmd("SIZE " + filename)
49
+ code = resp[0, 3]
50
+ if code != "213" && code != "220"
51
+ raise FTPReplyError, resp
52
+ end
53
+ return resp[3..-1].strip.to_i
54
+ end
55
+
56
+ # END BUGFIXES
57
+
58
+ def subdirs(aPath)
59
+ list.delete_if {|line| line[0,1]=='d'}
60
+ return list
61
+ end
62
+
63
+ def files(aPath)
64
+ list.delete_if {|line| line[0,1]!='d'}
65
+ return list
66
+ end
67
+
68
+ def expand_dir(aPath,aBase=nil)
69
+ return aPath if aPath=='/'
70
+ return MiscUtils::path_relative?(aPath) ? File.expand_path(aPath,aBase || pwd()) : File.expand_path(aPath)
71
+ end
72
+
73
+ def dir_exists?(aPath)
74
+ aPath = expand_dir(aPath)
75
+ return true if aPath=='/'
76
+ dirname = File.basename(aPath)
77
+ parent = MiscUtils.path_parent(aPath)
78
+ dirname!='' && nlst(parent).include?(dirname)
79
+ end
80
+
81
+ def file_exists?(aPath)
82
+ aPath = expand_dir(aPath)
83
+ filename = File.basename(aPath)
84
+ parent = File.dirname(aPath)
85
+ filename!='' && nlst(parent).include?(filename)
86
+ end
87
+
88
+ def filelist_recurse(aPath=nil,aResult=nil,&block)
89
+ #puts "filelist_recurse: #{aPath.to_s} #{aResult.inspect}"
90
+ orig_dir = !aResult ? pwd : nil # assigned if called at top with aResult=nil
91
+ aResult ||= []
92
+ aPath ||= ''
93
+ chdir(aPath)
94
+ list('*').each do |f|
95
+ is_dir = f[0,1]=='d'
96
+ details = FTP::crack_file_line(f)
97
+ full = File.join(aPath,details[:name])
98
+ if !block_given? || yield(full)
99
+ if is_dir
100
+ filelist_recurse(full,aResult)
101
+ else
102
+ aResult << full
103
+ end
104
+ end
105
+ end
106
+ chdir(orig_dir) if orig_dir
107
+ return aResult
108
+ end
109
+
110
+ def get_files(aRemoteDir,aLocalDir,aFiles,aOptions=nil)
111
+ aOptions = {:overwrite => true}.merge(aOptions || {})
112
+ aFiles.each do |r|
113
+ relative = r.bite(MiscUtils::append_slash(aRemoteDir))
114
+ d = File.join(aLocalDir,relative)
115
+ puts "getting #{relative}"
116
+ getbinaryfile(r, d) unless !aOptions[:overwrite] && File.exists?(d)
117
+ end
118
+ end
119
+
120
+ def get_dir(aRemoteDir,aLocalDir,aOptions=nil,&block)
121
+ remote_files = block_given? ? filelist_recurse(aRemoteDir,nil,&block) : filelist_recurse(aRemoteDir)
122
+ get_files(aRemoteDir,aLocalDir,remote_files,aOptions)
123
+ end
124
+
125
+ def highest_existing(aPath)
126
+ sep = MiscUtils::sniff_seperator(aPath)
127
+ path = MiscUtils::path_parts(File.expand_path(aPath)) if aPath.is_a?(String)
128
+ # now assume path is an Array
129
+ depth = path.length-1
130
+ depth.downto(0) do |i| # from full path up to root
131
+ curr = (path[0]=='' && i==0) ? '/' : path[0..i].join(sep)
132
+ return curr if dir_exists?(curr)
133
+ end
134
+ return sep # root
135
+ end
136
+
137
+ def ensure_dir(aPath,aThorough=false)
138
+ if !aThorough
139
+ mkdir(aPath) unless dir_exists?(aPath)
140
+ else
141
+ return if dir_exists?(aPath)
142
+ path = expand_dir(aPath)
143
+ hi_existing = highest_existing(path)
144
+ # path to create under hi_existing
145
+ to_create = MiscUtils::path_debase(path,hi_existing)
146
+ parts = MiscUtils::path_parts(to_create)
147
+ curr_path = hi_existing
148
+
149
+ parts.each do |part|
150
+ curr_path = File.join(curr_path,part)
151
+ mkdir(curr_path)
152
+ end
153
+ end
154
+ end
155
+
156
+ def put_files(aLocalDir,aRemoteDir,aFiles,aOptions=nil)
157
+ aOptions = {:overwrite => true}.merge(aOptions || {})
158
+
159
+ # convert all files to relative to aLocalDir
160
+ aFiles = aFiles.map { |f| f.bite(MiscUtils::append_slash(aLocalDir)) }.sort
161
+
162
+ filelist = nil
163
+ this_dir = last_dir = nil
164
+ aFiles.each do |r|
165
+ d = File.expand_path(r,aRemoteDir)
166
+ this_dir = File.dirname(d)
167
+ if this_dir!=last_dir
168
+ ensure_dir(this_dir,true)
169
+ filelist = files(this_dir) - ['.','..','.svn']
170
+ end
171
+ if aOptions[:overwrite] || !filelist.member?(File.basename(r))
172
+ puts "Putting #{r}"
173
+ putbinaryfile(File.expand_path(r,aLocalDir), d)
174
+ else
175
+ puts "Skipping #{relative}"
176
+ end
177
+ last_dir = this_dir
178
+ end
179
+ end
180
+
181
+ def put_dir(aLocalDir,aRemoteDir,&block)
182
+ local_files = block_given? ? MiscUtils::recursive_file_list(aLocalDir,true,&block) : MiscUtils::recursive_file_list(aLocalDir)
183
+ put_files(aLocalDir,aRemoteDir,local_files)
184
+ end
185
+
186
+ end
187
+ end
188
+
@@ -0,0 +1,16 @@
1
+ # can :
2
+ # require 'buzzville/recipes' or
3
+ # require 'buzzville/recipes/data'
4
+
5
+ require 'ruby-debug'; debugger
6
+
7
+ require 'capistrano'
8
+ require 'capistrano/cli'
9
+
10
+ @@cap_config = Capistrano::Configuration.respond_to?(:instance) ?
11
+ Capistrano::Configuration.instance(:must_exist) :
12
+ Capistrano.configuration(:must_exist)
13
+
14
+ #Dir.glob(File.join(File.dirname(__FILE__), '/recipes/*.rb')).each { |f| load f }
15
+ Dir.chdir(File.dirname(__FILE__)+'/..') { Dir['buzzville/recipes/*'] }.each {|f| load f }
16
+
@@ -0,0 +1,80 @@
1
+ require 'yore/yore_core'
2
+
3
+ require 'ruby-debug'; debugger
4
+
5
+ @@cap_config.load do
6
+ # cap stage -Dapp=spree yore:pull:p_to_d
7
+ # cap stage -Dapp=spree yore:push:d_to_p
8
+ # cap stage -Dapp=spree yore:save:p
9
+ # cap stage -Dapp=spree -Darchive=spree.tgz yore:load:p
10
+ #desc <<-DESC
11
+ # Save
12
+ #DESC
13
+
14
+ namespace :bv do
15
+ namespace :data do
16
+
17
+ def cap
18
+ @@cap_config
19
+ end
20
+
21
+ def pull_internal(aRemoteEnv,aLocalEnv)
22
+ remote_app_path = ''
23
+ local_app_path = ''
24
+ remote_file = 'blah'
25
+ local_file = 'something'
26
+ # assume yore installed remotely
27
+ cmd = "cd #{remote_app_path}; yore save"
28
+ cmd += " --kind=#{kind}" if kind
29
+ cmd += " --RAILS_ENV=#{aRemoteEnv} #{remote_file}"
30
+ run cmd
31
+ download(remote_file,local_file,:via => :scp)
32
+ local_yore = YoreCore::Yore.launch(nil,{:kind => kind,:RAILS_ENV => aLocalEnv,:basepath=>ENV['PWD']})
33
+ local_yore.load(local_file)
34
+ end
35
+
36
+ def push_internal(aLocalEnv,aRemoteEnv)
37
+ local_yore = YoreCore::Yore.launch(nil,{:kind => kind,:RAILS_ENV => aLocalEnv,:basepath=>ENV['PWD']})
38
+ remote_app_path = File.join(cap.deploy_to,'current')
39
+ local_app_path = local_yore.config[:basepath]
40
+ filename = cap.unique_app_name+"-"+Time.now.strftime('%Y%m%d-%H%M%S')
41
+ remote_file = File.join("/tmp",filename)
42
+ local_file = File.join("/tmp",filename)
43
+ local_yore.save(local_file)
44
+ upload(local_file,remote_file,:via => :scp)
45
+
46
+ run "echo $PATH"
47
+ # assume yore installed remotely
48
+ cmd = "cd #{remote_app_path}; yore load"
49
+ cmd += " --kind=#{kind}" if kind
50
+ cmd += " --RAILS_ENV=#{aRemoteEnv} #{remote_file}"
51
+ run cmd
52
+ end
53
+
54
+ namespace :pull do
55
+ task :p2d do
56
+ pull_internal('production','development')
57
+ end
58
+ task :p2p do
59
+ end
60
+ end
61
+ namespace :push do
62
+ task :d2p do
63
+ push_internal('development','production')
64
+ files.apply_permissions
65
+ deploy.restart
66
+ end
67
+ task :p2p do
68
+ end
69
+ end
70
+ #namespace :load do
71
+ # task :p do
72
+ # end
73
+ #end
74
+ #namespace :save do
75
+ # task :p do
76
+ # end
77
+ #end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,41 @@
1
+ require 'yore/yore_core'
2
+
3
+ @@cap_config.load do
4
+
5
+ namespace :bv do
6
+ namespace :files do
7
+
8
+ def cap
9
+ @@cap_config
10
+ end
11
+
12
+ def internal_permissions
13
+ case kind
14
+ when 'spree' then
15
+
16
+ #puts "set permissions for dirs and files"
17
+ #run_for_all("chmod 750",app_dir,:dirs)
18
+ #run_for_all("chmod 640",app_dir,:files)
19
+ #
20
+ #puts "set permissions for image dirs and files"
21
+ #run_for_all("chmod 770","#{public_dir}/images",:dirs)
22
+ #run_for_all("chmod 660","#{public_dir}/images",:files)
23
+
24
+ run "#{sudo} chgrp -h #{cap.apache_user} #{cap.current_path}" # this is to change owner of link, not target
25
+ run "#{sudo} chown -R #{cap.user}:#{cap.apache_user} #{cap.current_path}/" # the # is reqd to work for symlinks
26
+ run "#{sudo} chmod -R g+w #{cap.current_path}/" # unfortunately necessary as capistrano forgets to do this later with sudo
27
+ run "#{sudo} chown #{cap.apache_user}:#{cap.apache_user} #{cap.current_path}/config/environment.rb" # very important for passenger, which uses the owner of this file to run as
28
+ run "#{sudo} touch #{cap.current_path}/log/production.log"
29
+ run "#{sudo} chmod 666 #{cap.current_path}/log/production.log"
30
+ when 'rails' then
31
+ # dfdsf
32
+ end
33
+ end
34
+
35
+ task :apply_permissions do
36
+ internal_permissions
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,101 @@
1
+ @@cap_config.load do
2
+
3
+ namespace :bv do
4
+ namespace :ssl do
5
+ extend CapUtils
6
+
7
+ def cap
8
+ @@cap_config
9
+ end
10
+
11
+ # should set key_dir
12
+ task :new_key do
13
+ set :local_key_dir,File.expand_path('~/.ssh') unless (local_key_dir rescue false)
14
+ if !(key_name rescue false)
15
+ default_key_name = (new_user rescue nil) || 'new_key'
16
+ key_name_response = Capistrano::CLI.ui.ask("Enter a name for the key without extension (default: #{default_key_name}):").strip!
17
+ set :key_name, (key_name_response.nil? || key_name_response.empty?) ? default_key_name : key_name_response
18
+ end
19
+ pub = File.join(local_key_dir,key_name+'.pub')
20
+ ppk = File.join(local_key_dir,key_name+'.ppk')
21
+ raise StandardError.new("#{pub} or #{ppk} already exists") if File.exists?(pub) || File.exists?(ppk)
22
+ passphrase = Capistrano::CLI.password_prompt("Enter a passphrase (>= 5 characters):")
23
+ # create key - asks for name & passphrase and stores in ~/.ssh
24
+ shell "ssh-keygen -N #{passphrase} -f #{File.join(local_key_dir,key_name)}"
25
+ shell "#{sudo} mv #{File.join(local_key_dir,key_name)} #{ppk}"
26
+ shell "#{sudo} sed -i -e 's/== .*$/== #{key_name}.pub/' #{pub}"
27
+ shell "#{sudo} chown $USER #{pub}"
28
+ shell "#{sudo} chown $USER #{ppk}"
29
+ Capistrano::CLI.ui.say "created #{pub}"
30
+ Capistrano::CLI.ui.say "created #{ppk}"
31
+ Capistrano::CLI.ui.say "Recommended: ssh-add #{ppk}"
32
+ end
33
+
34
+ task :install_key do
35
+ set :new_user,Capistrano::CLI.ui.ask("Enter a username for installing the key :") unless (new_user rescue false)
36
+ set :key_name,Capistrano::CLI.ui.ask("Enter a name for the key eg. user name (without extension):") unless (key_name rescue false)
37
+ set :key_dir,"/home/#{new_user}/.ssh" unless (key_dir rescue false)
38
+ set :local_key_dir,File.expand_path("~/.ssh") unless (local_key_dir rescue false)
39
+
40
+ # prepare key dir for new_user
41
+ auth_keys = File.join(key_dir,'authorized_keys')
42
+ run "#{sudo} mkdir -p #{key_dir}"
43
+ run "#{sudo} touch #{auth_keys}"
44
+ run "#{sudo} chown #{new_user}:#{new_user} #{key_dir}"
45
+ run "#{sudo} chown #{new_user}:#{new_user} #{auth_keys}"
46
+ run "#{sudo} chmod 700 #{key_dir}"
47
+ run "#{sudo} chmod 600 #{auth_keys}"
48
+
49
+ # upload and install in authorized_keys
50
+ if capture("#{sudo} grep -q #{key_name}.pub #{auth_keys};echo $?")=='0'
51
+ puts "Key already installed. Not installing"
52
+ else
53
+ admin_dir = "/home/#{cap.user}"
54
+
55
+ run "#{sudo} rm -f #{File.join(admin_dir,key_name+'.pub')}"
56
+ upload(File.join(local_key_dir,key_name+'.pub'),File.join(admin_dir,key_name+'.pub'),:via => :scp,:mode => 600)
57
+ run "#{sudo} echo '' | #{sudo} tee -a #{auth_keys}" # new line
58
+ run "#{sudo} cat #{File.join(admin_dir,key_name+'.pub')} | #{sudo} tee -a #{auth_keys}"
59
+ run "#{sudo} rm #{File.join(admin_dir,key_name+'.pub')}"
60
+ run "#{sudo} sudo /etc/init.d/ssh restart"
61
+ end
62
+
63
+ # add to sshd_config AllowUsers if not already
64
+ allow_users = []
65
+ allow_str = capture("#{sudo} grep AllowUsers /etc/ssh/sshd_config")
66
+ allow_str.each_line do |line|
67
+ next unless line =~ /^AllowUsers /
68
+ allow_users += line.bite('AllowUsers').split(' ')
69
+ end
70
+ if !allow_users.include?(new_user)
71
+ run "#{sudo} sed -i -e 's/^AllowUsers /AllowUsers #{new_user} /' /etc/ssh/sshd_config"
72
+ end
73
+
74
+ s = <<EOS
75
+
76
+ You probably need to append :
77
+
78
+ Host #{host}
79
+ IdentityFile #{File.join(local_key_dir,key_name+'.ppk')}
80
+ User #{new_user}
81
+ Port #{sessions.values.first.transport.peer[:port]}
82
+
83
+ to your ~/.ssh/config file
84
+
85
+ and run locally :
86
+
87
+ ssh-add -K #{File.join(local_key_dir,key_name+'.ppk')}
88
+
89
+ and then you should be able to :
90
+
91
+ ssh #{new_user}@#{host}
92
+
93
+ without entering a password and the passphrase will be in your keychain.
94
+
95
+ EOS
96
+ Capistrano::CLI.ui.say(s)
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,46 @@
1
+ @@cap_config.load do
2
+
3
+ namespace :bv do
4
+ namespace :user do
5
+ extend CapUtils
6
+
7
+ def cap
8
+ @@cap_config
9
+ end
10
+
11
+ #sudo adduser ffff
12
+ #sudo passwd ffff
13
+ #sudo usermod -a -G www-data ffff
14
+ #cd /home/ffff/
15
+ #sudo ln -s /var/www/ffff/public public
16
+ #sudo chown -h ffff:www-data public
17
+ #sudo /etc/init.d/pure-ftpd restart
18
+
19
+ task :create do
20
+ set :new_user, Capistrano::CLI.ui.ask("Enter a name for the new user:") unless (self.new_user rescue false)
21
+ password = Capistrano::CLI.password_prompt("Enter a password for the new user:") unless (self.new_password rescue false)
22
+ set :user,admin_user
23
+
24
+ adduser(new_user,password)
25
+ add_user_to_group(new_user,apache_user)
26
+
27
+ Capistrano::CLI.ui.say "please run \"sudo sudoedit /etc/sudoers\" add the following line :"
28
+ Capistrano::CLI.ui.say "#{new_user} ALL=(ALL) ALL"
29
+ end
30
+
31
+ task :new_key do
32
+ set :new_user, Capistrano::CLI.ui.ask("Enter the user name:") unless (self.new_user rescue false)
33
+ set :user,admin_user
34
+ bv.ssl.new_key
35
+ bv.ssl.install_key
36
+ end
37
+
38
+ task :delete do
39
+ set :new_user, Capistrano::CLI.ui.ask("Enter the user name:") unless (self.new_user rescue false)
40
+ set :user,admin_user
41
+ run "#{sudo} userdel -rf #{new_user}"
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ # when you want to load the live version of buzzville, not the gem :
2
+ # require File.join(File.dirname(__FILE__),'../../../../../buzzville/lib/buzzville_dev.rb');
3
+ require_paths_first '.'
4
+ require 'buzzville'
5
+
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class BuzzvilleTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'buzzville'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: buzzville
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - buzzware
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-06 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: buzzcore
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.2.5
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: yore
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.5
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: cmdparse
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.0.2
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: thoughtbot-shoulda
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ description: Capistrano recipes and ruby code relating to deployment
56
+ email: contact@buzzware.com.au
57
+ executables: []
58
+
59
+ extensions: []
60
+
61
+ extra_rdoc_files:
62
+ - LICENSE
63
+ - README.rdoc
64
+ files:
65
+ - .document
66
+ - .gitignore
67
+ - LICENSE
68
+ - README.rdoc
69
+ - Rakefile
70
+ - VERSION
71
+ - buzzville.vpj
72
+ - buzzville.vpw
73
+ - lib/buzzville.rb
74
+ - lib/buzzville/cap_utils.rb
75
+ - lib/buzzville/ftp_extra.rb
76
+ - lib/buzzville/recipes.rb
77
+ - lib/buzzville/recipes/data.rb
78
+ - lib/buzzville/recipes/files.rb
79
+ - lib/buzzville/recipes/ssl.rb
80
+ - lib/buzzville/recipes/user.rb
81
+ - lib/buzzville_dev.rb
82
+ - test/buzzville_test.rb
83
+ - test/test_helper.rb
84
+ has_rdoc: true
85
+ homepage: http://github.com/buzzware/buzzville
86
+ licenses: []
87
+
88
+ post_install_message:
89
+ rdoc_options:
90
+ - --charset=UTF-8
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: "0"
98
+ version:
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: "0"
104
+ version:
105
+ requirements: []
106
+
107
+ rubyforge_project: buzzware
108
+ rubygems_version: 1.3.5
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: Capistrano recipes and ruby code relating to deployment
112
+ test_files:
113
+ - test/buzzville_test.rb
114
+ - test/test_helper.rb