buzzville 0.1.3 → 0.1.4

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/Rakefile CHANGED
@@ -11,10 +11,10 @@ begin
11
11
  gem.homepage = "http://github.com/buzzware/buzzville"
12
12
  gem.authors = ["buzzware"]
13
13
  gem.rubyforge_project = "buzzware"
14
- gem.add_dependency('buzzcore', '>= 0.2.5')
15
- gem.add_dependency('yore', '>= 0.0.5')
14
+ gem.add_dependency('buzzcore', '>= 0.3.3')
15
+ gem.add_dependency('yore', '>= 0.2.1')
16
16
  gem.add_dependency('cmdparse', '>= 2.0.2')
17
- gem.add_development_dependency "thoughtbot-shoulda"
17
+ gem.add_development_dependency "shoulda"
18
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
19
  end
20
20
  Jeweler::RubyforgeTasks.new do |rubyforge|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{buzzville}
8
+ s.version = "0.1.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["buzzware"]
12
+ s.date = %q{2010-01-28}
13
+ s.description = %q{Capistrano recipes and ruby code relating to deployment}
14
+ s.email = %q{contact@buzzware.com.au}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "buzzville.gemspec",
27
+ "buzzville.vpj",
28
+ "buzzville.vpw",
29
+ "lib/buzzville.rb",
30
+ "lib/buzzville/cap_utils.rb",
31
+ "lib/buzzville/ftp_extra.rb",
32
+ "lib/buzzville/recipes.rb",
33
+ "lib/buzzville/recipes/data.rb",
34
+ "lib/buzzville/recipes/files.rb",
35
+ "lib/buzzville/recipes/ssl.rb",
36
+ "lib/buzzville/recipes/user.rb",
37
+ "lib/buzzville_dev.rb",
38
+ "test/buzzville_test.rb",
39
+ "test/test_helper.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/buzzware/buzzville}
42
+ s.rdoc_options = ["--charset=UTF-8"]
43
+ s.require_paths = ["lib"]
44
+ s.rubyforge_project = %q{buzzware}
45
+ s.rubygems_version = %q{1.3.5}
46
+ s.summary = %q{Capistrano recipes and ruby code relating to deployment}
47
+ s.test_files = [
48
+ "test/buzzville_test.rb",
49
+ "test/test_helper.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ s.add_runtime_dependency(%q<buzzcore>, [">= 0.3.3"])
58
+ s.add_runtime_dependency(%q<yore>, [">= 0.2.1"])
59
+ s.add_runtime_dependency(%q<cmdparse>, [">= 2.0.2"])
60
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
61
+ else
62
+ s.add_dependency(%q<buzzcore>, [">= 0.3.3"])
63
+ s.add_dependency(%q<yore>, [">= 0.2.1"])
64
+ s.add_dependency(%q<cmdparse>, [">= 2.0.2"])
65
+ s.add_dependency(%q<shoulda>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<buzzcore>, [">= 0.3.3"])
69
+ s.add_dependency(%q<yore>, [">= 0.2.1"])
70
+ s.add_dependency(%q<cmdparse>, [">= 2.0.2"])
71
+ s.add_dependency(%q<shoulda>, [">= 0"])
72
+ end
73
+ end
@@ -8,6 +8,18 @@ require 'net/sftp'
8
8
 
9
9
  module CapUtils
10
10
 
11
+ # for debugging deploy :
12
+ #
13
+ # same as original, but without file removal on rollback
14
+ #task :update_code, :except => { :no_release => true } do
15
+ # on_rollback do
16
+ # require 'ruby-debug'; debugger
17
+ # end
18
+ # strategy.deploy!
19
+ # finalize_update
20
+ #end
21
+
22
+
11
23
  # upload the given local file to the remote server and set the given mode.
12
24
  # 0644 is the default mode
13
25
  #
@@ -101,7 +113,7 @@ module CapUtils
101
113
  def file_exists?(path)
102
114
  result = nil
103
115
  run "if [[ -e #{path} ]]; then echo 'true'; else echo 'false'; fi", :shell => false do |ch,stream,text|
104
- result = (text.strip! == 'true')
116
+ result = (text.strip == 'true')
105
117
  end
106
118
  result
107
119
  end
@@ -124,9 +136,9 @@ module CapUtils
124
136
  ensure_link("#{aSharedFolder}","#{aReleaseFolder}",nil,"#{user}:#{apache_user}")
125
137
  end
126
138
 
127
- def select_target_file(aFile)
128
- ext = MiscUtils.file_extension(aFile,false)
129
- no_ext = MiscUtils.file_no_extension(aFile,false)
139
+ def select_target_file(aFile,aExtendedExtension=false)
140
+ ext = MiscUtils.file_extension(aFile,aExtendedExtension)
141
+ no_ext = MiscUtils.file_no_extension(aFile,aExtendedExtension)
130
142
  dir = File.dirname(aFile)
131
143
  run "#{sudo} mv -f #{no_ext}.#{target}.#{ext} #{aFile}"
132
144
  run "#{sudo} rm -f #{no_ext}.*.#{ext}"
@@ -147,7 +159,7 @@ module CapUtils
147
159
  #sudo find . -type f -exec echo {} \;
148
160
  cmd = []
149
161
  cmd << "sudo" if aSudo
150
- cmd << "find #{aPath}"
162
+ cmd << "find #{MiscUtils.append_slash(aPath)}"
151
163
  cmd << "-wholename '#{aPattern}'" if aPattern
152
164
  cmd << "-prune -o" if aInvertPattern
153
165
  cmd << case aFilesOrDirs.to_s[0,1]
@@ -157,13 +169,42 @@ module CapUtils
157
169
  end
158
170
  cmd << "-exec"
159
171
  cmd << aCommand
160
- cmd << '{} \;'
172
+ cmd << "'{}' \\;"
161
173
  cmd = cmd.join(' ')
162
174
  run cmd
163
175
  end
164
176
 
165
- #run_for_all("chmod g+s #{File.expand_path(dir,public_dir)}",public_dir,:dirs)
177
+ # just quickly ensures user can deploy. Only for use before deploying, and should be followed by
178
+ # more secure settings
179
+ def permissions_for_deploy(aUser=nil,aGroup=nil,aPath=nil)
180
+ aUser ||= user
181
+ aGroup ||= apache_user
182
+ aPath ||= deploy_to
183
+ run "#{sudo} chown -R #{aUser}:#{aGroup} #{MiscUtils.append_slash(aPath)}"
184
+ run "#{sudo} chmod u+rw #{MiscUtils.append_slash(aPath)}"
185
+ run_for_all("chmod u+x",aPath,:dirs)
186
+ end
187
+
188
+ # set standard permissions for web sites - readonly for apache user
189
+ def permissions_for_web(aPath=nil,aUser=nil,aApacheUser=nil,aHideScm=nil)
190
+ aPath ||= deploy_to
191
+ aUser ||= user
192
+ aApacheUser ||= apache_user
193
+
194
+ run "#{sudo} chown -R #{aUser}:#{aApacheUser} #{MiscUtils.append_slash(aPath)}"
195
+ run "#{sudo} chmod -R 644 #{MiscUtils.append_slash(aPath)}"
196
+ run_for_all("chmod +x",aPath,:dirs)
197
+ run_for_all("chmod g+s",aPath,:dirs)
198
+ case aHideScm
199
+ when :svn then run_for_all("chown -R #{aUser}:#{aUser}",aPath,:dirs,"*/.svn")
200
+ end
201
+ end
166
202
 
203
+ # run this after permissions_for_web() on dirs that need to be writable by group (apache)
204
+ def permissions_for_web_writable(aPath)
205
+ run "#{sudo} chmod -R g+w #{MiscUtils.append_slash(aPath)}"
206
+ end
207
+
167
208
  def set_dir_permissions_r(aStartPath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false)
168
209
  cmd = []
169
210
  if aGroup
@@ -200,6 +241,12 @@ module CapUtils
200
241
  set_permissions(aStartPath,aUser,aGroup,aMode,aSetGroupId,aSudo)
201
242
  end
202
243
 
244
+ def make_public_cache_dir(aStartPath)
245
+ run "#{sudo} mkdir -p #{aStartPath}"
246
+ permissions_for_web(aStartPath)
247
+ permissions_for_web_writable(aStartPath)
248
+ end
249
+
203
250
  # if aGroup is given, that will be the users only group
204
251
  def adduser(aNewUser,aPassword,aGroup=nil)
205
252
  run "#{sudo} adduser --gecos '' #{aGroup ? '--ingroup '+aGroup : ''} #{aNewUser}" do |ch, stream, out|
@@ -288,7 +335,8 @@ module CapUtils
288
335
 
289
336
  cmd << ensure_folder(design_views,aUser,aApacheUser,750)
290
337
  # copy files from database to shared/design
291
- cmd << "cp -rf #{aBrowserCmsRoot}/tmp/views/* #{design_views}/"
338
+ # if [[ ! -L libtool ]]; then echo 'true'; fi !!! need NOT
339
+ cmd << "if [ ! -L #{aBrowserCmsRoot}/tmp/views ]; then cp -rf #{aBrowserCmsRoot}/tmp/views/* #{design_views}/ ; fi"
292
340
  cmd << ensure_folder(design_views+'/layouts/templates',aUser,aApacheUser,750)
293
341
  cmd << ensure_folder(design_views+'/partials',aUser,aApacheUser,750)
294
342
 
@@ -306,7 +354,7 @@ module CapUtils
306
354
  ## link templates into ftp folder
307
355
  cmd << ensure_link_cmd(design_views,'views',aFtpPath,"#{aUser}:#{aApacheUser}")
308
356
  #run "#{sudo} chgrp -h www-data #{deploy_to}/current" # this is to change owner of link, not target
309
- cmd_s = cmd.join(" && ")
357
+ cmd_s = cmd.join("\n")
310
358
  end
311
359
 
312
360
  def install_script_from_string(aScriptString,aFilepath)
@@ -316,6 +364,10 @@ module CapUtils
316
364
  set_permissions(aFilepath,'root',user,750,false,true)
317
365
  end
318
366
 
367
+ def svn_command(aCommand)
368
+ run "#{sudo} svn --trust-server-cert --non-interactive --username #{svn_user} --password #{svn_password} #{aCommand}"
369
+ end
370
+
319
371
  end
320
372
 
321
373
  class CapUtilsClass
@@ -2,8 +2,6 @@
2
2
  # require 'buzzville/recipes' or
3
3
  # require 'buzzville/recipes/data'
4
4
 
5
- require 'ruby-debug'; debugger
6
-
7
5
  require 'capistrano'
8
6
  require 'capistrano/cli'
9
7
 
@@ -1,7 +1,6 @@
1
+ require_paths_first File.join(File.dirname(__FILE__),'../../../../yore/lib');
1
2
  require 'yore/yore_core'
2
3
 
3
- require 'ruby-debug'; debugger
4
-
5
4
  @@cap_config.load do
6
5
  # cap stage -Dapp=spree yore:pull:p_to_d
7
6
  # cap stage -Dapp=spree yore:push:d_to_p
@@ -19,22 +18,24 @@ require 'ruby-debug'; debugger
19
18
  end
20
19
 
21
20
  def pull_internal(aRemoteEnv,aLocalEnv)
22
- remote_app_path = ''
23
- local_app_path = ''
24
- remote_file = 'blah'
25
- local_file = 'something'
21
+ local_yore = YoreCore::Yore.launch(nil,{:kind => kind,:RAILS_ENV => aLocalEnv},{:basepath=>ENV['PWD']})
22
+ remote_app_path = File.join(cap.deploy_to,'current')
23
+ local_app_path = local_yore.config[:basepath]
24
+ filename = cap.unique_app_name+"-"+Time.now.strftime('%Y%m%d-%H%M%S')
25
+ remote_file = File.join("/tmp",filename)
26
+ local_file = File.join("/tmp",filename)
27
+
26
28
  # assume yore installed remotely
27
29
  cmd = "cd #{remote_app_path}; yore save"
28
30
  cmd += " --kind=#{kind}" if kind
29
31
  cmd += " --RAILS_ENV=#{aRemoteEnv} #{remote_file}"
30
32
  run cmd
31
33
  download(remote_file,local_file,:via => :scp)
32
- local_yore = YoreCore::Yore.launch(nil,{:kind => kind,:RAILS_ENV => aLocalEnv,:basepath=>ENV['PWD']})
33
34
  local_yore.load(local_file)
34
35
  end
35
36
 
36
37
  def push_internal(aLocalEnv,aRemoteEnv)
37
- local_yore = YoreCore::Yore.launch(nil,{:kind => kind,:RAILS_ENV => aLocalEnv,:basepath=>ENV['PWD']})
38
+ local_yore = YoreCore::Yore.launch(nil,{:kind => kind,:RAILS_ENV => aLocalEnv},{:basepath=>ENV['PWD']})
38
39
  remote_app_path = File.join(cap.deploy_to,'current')
39
40
  local_app_path = local_yore.config[:basepath]
40
41
  filename = cap.unique_app_name+"-"+Time.now.strftime('%Y%m%d-%H%M%S')
@@ -42,7 +43,6 @@ require 'ruby-debug'; debugger
42
43
  local_file = File.join("/tmp",filename)
43
44
  local_yore.save(local_file)
44
45
  upload(local_file,remote_file,:via => :scp)
45
-
46
46
  run "echo $PATH"
47
47
  # assume yore installed remotely
48
48
  cmd = "cd #{remote_app_path}; yore load"
@@ -60,6 +60,8 @@ require 'ruby-debug'; debugger
60
60
  end
61
61
  namespace :push do
62
62
  task :d2p do
63
+ extend CapUtils
64
+ files.apply_deploy_permissions
63
65
  push_internal('development','production')
64
66
  files.apply_permissions
65
67
  deploy.restart
@@ -9,10 +9,33 @@ require 'yore/yore_core'
9
9
  @@cap_config
10
10
  end
11
11
 
12
- def internal_permissions
13
- case kind
12
+ def internal_apply_deploy_permissions(aKind)
13
+ cap.extend CapUtils
14
+ case aKind
15
+ when 'rails' then
16
+ permissions_for_deploy(cap.user,cap.apache_user,cap.current_path)
17
+ uploads = cap.shared_path+'/uploads'
18
+ if remote_file_exists?(uploads)
19
+ permissions_for_web(uploads,cap.user,cap.apache_user,true)
20
+ permissions_for_web_writable(uploads)
21
+ end
22
+ #uploads_path = File.expand_path('../shared/uploads',current_path)
23
+ #mkdir_permissions(uploads_path,user,apache_user,770,true)
14
24
  when 'spree' then
15
-
25
+ internal_apply_deploy_permissions('rails')
26
+ when 'browsercms' then
27
+ internal_apply_deploy_permissions('rails')
28
+ end
29
+ end
30
+
31
+ task :apply_deploy_permissions do
32
+ internal_apply_deploy_permissions(cap.kind)
33
+ end
34
+
35
+ def internal_permissions(aKind)
36
+ cap.extend CapUtils
37
+ case aKind
38
+ when 'rails' then
16
39
  #puts "set permissions for dirs and files"
17
40
  #run_for_all("chmod 750",app_dir,:dirs)
18
41
  #run_for_all("chmod 640",app_dir,:files)
@@ -21,19 +44,35 @@ require 'yore/yore_core'
21
44
  #run_for_all("chmod 770","#{public_dir}/images",:dirs)
22
45
  #run_for_all("chmod 660","#{public_dir}/images",:files)
23
46
 
47
+
24
48
  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
49
+
50
+ cap.permissions_for_web(cap.current_path,cap.user,cap.apache_user,true)
51
+
52
+ #run "#{sudo} chown -R #{cap.user}:#{cap.apache_user} #{cap.current_path}/" # the # is reqd to work for symlinks
53
+ #run "#{sudo} chmod -R g+w #{cap.current_path}/" # unfortunately necessary as capistrano forgets to do this later with sudo
54
+
55
+ uploads = cap.shared_path+'/uploads'
56
+ if remote_file_exists?(uploads)
57
+ permissions_for_web(uploads,cap.user,cap.apache_user,true)
58
+ permissions_for_web_writable(uploads)
59
+ end
60
+ #uploads_path = File.expand_path('../shared/uploads',current_path)
61
+ #mkdir_permissions(uploads_path,user,apache_user,770,true)
62
+
63
+ run "#{sudo} chown #{cap.user}:#{cap.user} #{cap.current_path}/config/environment.rb" # very important for passenger, which uses the owner of this file to run as
28
64
  run "#{sudo} touch #{cap.current_path}/log/production.log"
29
65
  run "#{sudo} chmod 666 #{cap.current_path}/log/production.log"
30
- when 'rails' then
31
- # dfdsf
66
+
67
+ when 'spree' then
68
+ internal_permissions('rails')
69
+ when 'browsercms' then
70
+ internal_permissions('rails')
32
71
  end
33
72
  end
34
73
 
35
74
  task :apply_permissions do
36
- internal_permissions
75
+ internal_permissions(cap.kind)
37
76
  end
38
77
 
39
78
  end
@@ -8,12 +8,16 @@
8
8
  @@cap_config
9
9
  end
10
10
 
11
+ #task :check_key do
12
+ # #sudo openssl rsa -check -noout -in ~/.ssh/iarts.ppk
13
+ #end
14
+
11
15
  # should set key_dir
12
16
  task :new_key do
13
17
  set :local_key_dir,File.expand_path('~/.ssh') unless (local_key_dir rescue false)
14
18
  if !(key_name rescue false)
15
19
  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!
20
+ key_name_response = Capistrano::CLI.ui.ask("Enter a name for the key without extension (default: #{default_key_name}):").strip
17
21
  set :key_name, (key_name_response.nil? || key_name_response.empty?) ? default_key_name : key_name_response
18
22
  end
19
23
  pub = File.join(local_key_dir,key_name+'.pub')
@@ -21,14 +25,14 @@
21
25
  raise StandardError.new("#{pub} or #{ppk} already exists") if File.exists?(pub) || File.exists?(ppk)
22
26
  passphrase = Capistrano::CLI.password_prompt("Enter a passphrase (>= 5 characters):")
23
27
  # create key - asks for name & passphrase and stores in ~/.ssh
24
- shell "ssh-keygen -N #{passphrase} -f #{File.join(local_key_dir,key_name)}"
28
+ shell "ssh-keygen #{passphrase.to_s.empty? ? '' : '-N '+passphrase} -f #{File.join(local_key_dir,key_name)}"
25
29
  shell "#{sudo} mv #{File.join(local_key_dir,key_name)} #{ppk}"
26
30
  shell "#{sudo} sed -i -e 's/== .*$/== #{key_name}.pub/' #{pub}"
27
31
  shell "#{sudo} chown $USER #{pub}"
28
32
  shell "#{sudo} chown $USER #{ppk}"
29
33
  Capistrano::CLI.ui.say "created #{pub}"
30
34
  Capistrano::CLI.ui.say "created #{ppk}"
31
- Capistrano::CLI.ui.say "Recommended: ssh-add #{ppk}"
35
+ Capistrano::CLI.ui.say "Recommended: ssh-add -k #{ppk}"
32
36
  end
33
37
 
34
38
  task :install_key do
@@ -57,7 +61,7 @@
57
61
  run "#{sudo} echo '' | #{sudo} tee -a #{auth_keys}" # new line
58
62
  run "#{sudo} cat #{File.join(admin_dir,key_name+'.pub')} | #{sudo} tee -a #{auth_keys}"
59
63
  run "#{sudo} rm #{File.join(admin_dir,key_name+'.pub')}"
60
- run "#{sudo} sudo /etc/init.d/ssh restart"
64
+ run "#{sudo} /etc/init.d/ssh restart"
61
65
  end
62
66
 
63
67
  # add to sshd_config AllowUsers if not already
@@ -75,11 +79,15 @@
75
79
 
76
80
  You probably need to append :
77
81
 
78
- Host #{host}
82
+ Host #{new_user}
79
83
  IdentityFile #{File.join(local_key_dir,key_name+'.ppk')}
80
84
  User #{new_user}
85
+ Hostname #{host}
81
86
  Port #{sessions.values.first.transport.peer[:port]}
82
-
87
+ TCPKeepAlive yes
88
+ IdentitiesOnly yes
89
+ PreferredAuthentications publickey
90
+
83
91
  to your ~/.ssh/config file
84
92
 
85
93
  and run locally :
@@ -88,7 +96,7 @@ and run locally :
88
96
 
89
97
  and then you should be able to :
90
98
 
91
- ssh #{new_user}@#{host}
99
+ ssh #{new_user}
92
100
 
93
101
  without entering a password and the passphrase will be in your keychain.
94
102
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buzzville
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - buzzware
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-06 00:00:00 +08:00
12
+ date: 2010-01-28 00:00:00 +08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.2.5
23
+ version: 0.3.3
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: yore
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.5
33
+ version: 0.2.1
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: cmdparse
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 2.0.2
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
- name: thoughtbot-shoulda
46
+ name: shoulda
47
47
  type: :development
48
48
  version_requirement:
49
49
  version_requirements: !ruby/object:Gem::Requirement
@@ -68,6 +68,7 @@ files:
68
68
  - README.rdoc
69
69
  - Rakefile
70
70
  - VERSION
71
+ - buzzville.gemspec
71
72
  - buzzville.vpj
72
73
  - buzzville.vpw
73
74
  - lib/buzzville.rb