capitate 0.1.7 → 0.1.8

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 (52) hide show
  1. data/Capfile +3 -11
  2. data/History.txt +8 -1
  3. data/Manifest.txt +4 -17
  4. data/bin/capitate +51 -19
  5. data/config/hoe.rb +3 -1
  6. data/lib/capitate/plugins/base.rb +81 -35
  7. data/lib/capitate/recipes.rb +1 -2
  8. data/lib/capitate/task_node.rb +157 -0
  9. data/lib/capitate/version.rb +1 -1
  10. data/lib/capitate.rb +2 -0
  11. data/lib/profiles/centos-sick.rb +18 -16
  12. data/lib/recipes/centos/imagemagick.rb +3 -2
  13. data/lib/recipes/centos/memcached.rb +18 -3
  14. data/lib/recipes/centos/mongrel_cluster.rb +15 -5
  15. data/lib/recipes/centos/monit.rb +14 -3
  16. data/lib/recipes/centos/mysql.rb +10 -3
  17. data/lib/recipes/centos/nginx.rb +29 -3
  18. data/lib/recipes/centos/ruby.rb +2 -2
  19. data/lib/recipes/centos/sphinx.rb +19 -6
  20. data/lib/recipes/docs.rb +17 -0
  21. data/lib/recipes/gems.rb +10 -1
  22. data/lib/recipes/memcached.rb +11 -1
  23. data/lib/recipes/mongrel_cluster.rb +13 -1
  24. data/lib/recipes/mysql.rb +41 -2
  25. data/lib/recipes/nginx.rb +25 -11
  26. data/lib/recipes/packages.rb +16 -1
  27. data/lib/recipes/rails.rb +16 -1
  28. data/lib/recipes/recipes.rb +30 -0
  29. data/tasks/website.rake +9 -0
  30. data/website/index.html +46 -44
  31. data/website/index.txt +24 -31
  32. data/website/stylesheets/screen.css +31 -12
  33. data/website/template.rhtml +19 -5
  34. data/website/template_recipe.rhtml +25 -0
  35. metadata +19 -24
  36. data/lib/capitate/config.rb +0 -106
  37. data/lib/doc/centos/memcached.yml +0 -18
  38. data/lib/doc/centos/mongrel_cluster.yml +0 -11
  39. data/lib/doc/centos/monit.yml +0 -12
  40. data/lib/doc/centos/mysql.yml +0 -6
  41. data/lib/doc/centos/nginx.yml +0 -25
  42. data/lib/doc/centos/sphinx.yml +0 -14
  43. data/lib/doc/gems.yml +0 -7
  44. data/lib/doc/install.yml +0 -11
  45. data/lib/doc/memcached.yml +0 -13
  46. data/lib/doc/mongrel_cluster.yml +0 -12
  47. data/lib/doc/mysql.yml +0 -46
  48. data/lib/doc/nginx.yml +0 -23
  49. data/lib/doc/packages.yml +0 -17
  50. data/lib/doc/rails.yml +0 -15
  51. data/lib/recipes/install.rb +0 -18
  52. data/tasks/capitate.rake +0 -10
@@ -1,8 +1,19 @@
1
- namespace :centos do
1
+ namespace :monit do
2
2
 
3
- namespace :monit do
3
+ namespace :centos do
4
4
 
5
- desc "Install monit"
5
+ desc <<-DESC
6
+ Install monit.
7
+
8
+ monit_port: Monit port. Defaults to 2812.
9
+
10
+ set :monit_port, 2812
11
+
12
+ monit_password: Monit password. Defaults to password prompt.
13
+
14
+ set :monit_password, Proc.new { Capistrano::CLI.ui.ask('Monit admin password (to set): ') })
15
+
16
+ DESC
6
17
  task :install do
7
18
 
8
19
  # Settings
@@ -1,8 +1,15 @@
1
- namespace :centos do
1
+ namespace :mysql do
2
2
 
3
- namespace :mysql do
3
+ namespace :centos do
4
4
 
5
- desc "Install mysql"
5
+ desc <<-DESC
6
+ Install mysql.
7
+
8
+ mysql_admin_password_set: Mysql admin password (to set). Defaults to password prompt.
9
+
10
+ set :mysql_admin_password_set, Proc.new { Capistrano::CLI.ui.ask('Mysql admin password (to set): ') }
11
+
12
+ DESC
6
13
  task :install do
7
14
 
8
15
  # Settings
@@ -1,8 +1,26 @@
1
- namespace :centos do
1
+ namespace :nginx do
2
2
 
3
- namespace :nginx do
3
+ namespace :centos do
4
4
 
5
- desc "Install nginx, conf, initscript, nginx user and service"
5
+ desc <<-DESC
6
+ Install nginx, conf, initscript, nginx user and service.
7
+ nginx_bin_path: Nginx sbin path. Defaults to /sbin/nginx
8
+
9
+ set :nginx_bin_path, "/sbin/nginx"
10
+
11
+ nginx_conf_path: Path to nginx conf. Defaults to /etc/nginx/nginx.conf
12
+
13
+ set :nginx_conf_path, "/etc/nginx/nginx.conf"
14
+
15
+ nginx_pid_path: Path to nginx pid file. Defaults to /var/run/nginx.pid
16
+
17
+ set :nginx_pid_path, "/var/run/nginx.pid"
18
+
19
+ nginx_prefix_path: Nginx install prefix. Defaults to /var/nginx
20
+
21
+ set :nginx_prefix_path, "/var/nginx"
22
+
23
+ DESC
6
24
  task :install do
7
25
 
8
26
  # Settings
@@ -40,6 +58,14 @@ namespace :centos do
40
58
  sudo "id nginx || /usr/sbin/adduser -r nginx"
41
59
  end
42
60
 
61
+ # Restart nginx
62
+ desc "Restart nginx (service)"
63
+ task :restart do
64
+ # TODO: Monit
65
+ sudo "/sbin/service nginx restart"
66
+ end
67
+
68
+
43
69
  end
44
70
 
45
71
  end
@@ -1,6 +1,6 @@
1
- namespace :centos do
1
+ namespace :ruby do
2
2
 
3
- namespace :ruby do
3
+ namespace :centos do
4
4
 
5
5
  desc "Install ruby and rubygems"
6
6
  task :install do
@@ -1,8 +1,15 @@
1
- namespace :centos do
1
+ namespace :sphinx do
2
2
 
3
- namespace :sphinx do
3
+ namespace :centos do
4
4
 
5
- desc "Install sphinx"
5
+ desc <<-DESC
6
+ Install sphinx.
7
+
8
+ sphinx_prefix: Sphinx install prefix. Defaults to "/usr/local/sphinx"
9
+
10
+ set :sphinx_prefix, "/usr/local/sphinx"
11
+
12
+ DESC
6
13
  task :install do
7
14
 
8
15
  # Settings
@@ -22,9 +29,15 @@ namespace :centos do
22
29
  script.make_install("sphinx", sphinx_options)
23
30
  end
24
31
 
25
- desc "Setup sphinx for application"
26
- after "centos:sphinx:setup", "sphinx:setup_monit"
27
- task :setup do
32
+ desc <<-DESC
33
+ Setup sphinx for application.
34
+
35
+ sphinx_prefix: Sphinx install prefix. Defaults to "/usr/local/sphinx"
36
+
37
+ set :sphinx_prefix, "/usr/local/sphinx"
38
+
39
+ DESC
40
+ task :setup do
28
41
 
29
42
  # Settings
30
43
  fetch_or_default(:sphinx_prefix, "/usr/local/sphinx")
@@ -0,0 +1,17 @@
1
+ namespace :docs do
2
+
3
+ desc "Generate documentation for all currently loaded recipes."
4
+ task :recipes do
5
+ top_node = capitate.task_tree
6
+
7
+ puts "Tree:\n#{}"
8
+
9
+ dir = "docs/recipes"
10
+ FileUtils.rm_rf(dir)
11
+ FileUtils.mkdir_p(dir)
12
+
13
+ top_node.write_doc(dir, "index", "Recipes")
14
+
15
+ end
16
+ end
17
+
data/lib/recipes/gems.rb CHANGED
@@ -1,6 +1,15 @@
1
1
  namespace :gems do
2
2
 
3
- desc "Install gems"
3
+ desc <<-DESC
4
+ Install gems.
5
+
6
+ set :gem_list, [
7
+ "rake",
8
+ "mysql -- --with-mysql-include=/usr/include/mysql --with-mysql-lib=/usr/lib/mysql --with-mysql-config",
9
+ "raspell"
10
+ ]
11
+
12
+ DESC
4
13
  task :install do
5
14
  # Settings
6
15
  fetch(:gem_list)
@@ -1,6 +1,16 @@
1
1
  namespace :memcached do
2
2
 
3
- desc "Install memcached monit hooks"
3
+ desc <<-DESC
4
+ Install memcached monit hooks.
5
+
6
+ memcached_pid_path: Path to memcached pid file. Defaults to /var/run/memcached.pid
7
+
8
+ set :memcached_pid_path, "/var/run/memcached.pid"
9
+
10
+ memcached_port: Memcached port. Defaults to 11211.
11
+
12
+ set :memcached_port, 11211
13
+ DESC
4
14
  task :install_monit do
5
15
 
6
16
  # Settings
@@ -1,7 +1,19 @@
1
1
  # Create init script
2
2
  namespace :mongrel_cluster do
3
3
 
4
- desc "Create monit configuration for mongrel cluster"
4
+ desc <<-DESC
5
+ Create monit configuration for mongrel cluster.
6
+
7
+ mongrel_size: Number of mongrels.
8
+
9
+ set :mongrel_size, 3
10
+
11
+ mongrel_port: Starting port for mongrels. If there are 3 mongrels with port 9000, then instances
12
+ will be at 9000, 9001, and 9002
13
+
14
+ set :mongrel_port, 9000
15
+
16
+ DESC
5
17
  task :setup_monit do
6
18
 
7
19
  # See http://www.igvita.com/2006/11/07/monit-makes-mongrel-play-nice/
data/lib/recipes/mysql.rb CHANGED
@@ -1,7 +1,18 @@
1
1
  # Mysql recipes
2
2
  namespace :mysql do
3
3
 
4
- desc "Install mysql monit hooks"
4
+ desc <<-DESC
5
+ Install mysql monit hooks.
6
+
7
+ db_port: Mysql port. Defaults to 3306.
8
+
9
+ set :db_port, 3306
10
+
11
+ mysql_pid_path: Path to mysql pid file. Defaults to /var/run/mysqld/mysqld.pid
12
+
13
+ set :mysql_pid_path, "/var/run/mysqld/mysqld.pid"
14
+
15
+ DESC
5
16
  task :install_monit do
6
17
 
7
18
  # Settings
@@ -12,7 +23,35 @@ namespace :mysql do
12
23
  sudo "install -o root /tmp/mysql.monitrc /etc/monit/mysql.monitrc"
13
24
  end
14
25
 
15
- desc "Create database user, and database with appropriate permissions"
26
+ desc <<-DESC
27
+ Create database user, and database with appropriate permissions.
28
+
29
+ db_name: Database name (application).
30
+
31
+ set :db_name, "app_db_name"
32
+
33
+ db_user: Database user (application).
34
+
35
+ set :db_user, "app_db_user"
36
+
37
+ db_pass: Database password (application).
38
+
39
+ set :db_pass, "the_password"
40
+
41
+ web_host: Web host to provide access privileges to (if recipe used in context of web app).
42
+ Defaults to nil. TODO: Support multiple web hosts
43
+
44
+ set :web_host, 10.0.6.100
45
+
46
+ db_host: Database host (to provide itself with access).
47
+
48
+ set :db_host, 10.0.6.101
49
+
50
+ mysql_admin_password: Mysql admin password (to use to connect). Defaults to password prompt.
51
+
52
+ set :mysql_admin_password, Proc.new { Capistrano::CLI.ui.ask('Mysql admin password: ') })
53
+
54
+ DESC
16
55
  task :setup do
17
56
 
18
57
  # Settings
data/lib/recipes/nginx.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  # Nginx recipes
2
2
  namespace :nginx do
3
3
 
4
- # Callbacks
5
- after "nginx:setup", "nginx:restart"
4
+ desc <<-DESC
5
+ Install nginx monit hooks.
6
+
7
+ nginx_pid_path: Path to nginx pid file. Defaults to /var/run/nginx.pid
8
+
9
+ set :nginx_pid_path, "/var/run/nginx.pid"
6
10
 
7
- desc "Install nginx monit hooks"
11
+ DESC
8
12
  task :install_monit do
9
13
 
10
14
  # Settings
@@ -14,7 +18,23 @@ namespace :nginx do
14
18
  sudo "install -o root /tmp/nginx.monitrc /etc/monit/nginx.monitrc"
15
19
  end
16
20
 
17
- desc "Create and update the nginx vhost include"
21
+ desc <<-DESC
22
+ Create and update the nginx vhost include.
23
+
24
+ mongrel_size: Number of mongrels.
25
+
26
+ set :mongrel_size, 3
27
+
28
+ mongrel_port: Starting port for mongrels.
29
+ If there are 3 mongrels with port 9000, then instances will be at 9000, 9001, and 9002
30
+
31
+ set :mongrel_port, 9000
32
+
33
+ domain_name: Domain name for nginx virtual host, (without www prefix).
34
+
35
+ set :domain_name, "foo.com"
36
+
37
+ DESC
18
38
  task :setup_mongrel do
19
39
 
20
40
  # Settings
@@ -30,11 +50,5 @@ namespace :nginx do
30
50
 
31
51
  sudo "install -o root /tmp/nginx_#{application}.conf /etc/nginx/vhosts/#{application}.conf"
32
52
  end
33
-
34
- # Restart nginx
35
- task :restart do
36
- # TODO: Monit
37
- sudo "/sbin/service nginx restart"
38
- end
39
-
53
+
40
54
  end
@@ -1,6 +1,21 @@
1
1
  namespace :packages do
2
2
 
3
- desc "Remove, update and install packages"
3
+ desc <<-DESC
4
+ Remove, update and install packages.
5
+
6
+ packages_type: Package manager type. Currently can only be :yum. \n\nTODO: Support more package managers.
7
+
8
+ set :packages_type, :yum
9
+
10
+ packages_remove: Packages to remove.
11
+
12
+ set :packages_remove, [ "openoffice.org-*", "ImageMagick" ]
13
+
14
+ packages_add: Packages to add.
15
+
16
+ set :packages_add, [ "gcc", "kernel-devel", "libevent-devel", "libxml2-devel" ]
17
+
18
+ DESC
4
19
  task :install do
5
20
 
6
21
  # Settings
data/lib/recipes/rails.rb CHANGED
@@ -1,7 +1,22 @@
1
1
  # Rails recipes
2
2
  namespace :rails do
3
3
 
4
- desc "Create database yaml in shared path"
4
+ desc <<-DESC
5
+ Create database yaml in shared path.
6
+
7
+ db_name: Database name (rails).
8
+
9
+ set :db_name, "app_db_name"
10
+
11
+ db_user: Database user (rails).
12
+
13
+ set :db_user, "app_db_user"
14
+
15
+ db_pass: Database password (rails).
16
+
17
+ set :db_pass, "the_password"
18
+
19
+ DESC
5
20
  task :setup do
6
21
 
7
22
  # Settings
@@ -0,0 +1,30 @@
1
+ namespace :recipes do
2
+
3
+ desc <<-DESC
4
+ Run recipes, as user.
5
+
6
+ *recipes_run*: Recipes to run.
7
+
8
+ set :recipes, [ "centos:setup_for_web", "packages:install", "ruby:centos:install" ]
9
+
10
+ *recipes_user*: The user to run as for these recipes. Defaults to root.
11
+
12
+ set :recipes_user, "root"
13
+
14
+ DESC
15
+ task :run do
16
+
17
+ # Settings
18
+ fetch(:recipes_run)
19
+ fetch_or_default(:recipes_user, "root")
20
+
21
+ # Change user to install user for this recipes run
22
+ set_user(recipes_user)
23
+
24
+ # These run after install task and install all the apps
25
+ recipes_run.each do |task_name|
26
+ after "recipes:run", task_name
27
+ end
28
+ end
29
+
30
+ end
data/tasks/website.rake CHANGED
@@ -3,6 +3,15 @@ task :website_generate => :ruby_env do
3
3
  (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
4
4
  sh %{ #{RUBY_APP} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
5
5
  end
6
+
7
+ # Clean and re-create
8
+ FileUtils.rm_rf("website/recipes")
9
+ FileUtils.mkdir_p("website/recipes")
10
+ sh "cap docs:recipes"
11
+ template = File.join(File.dirname(__FILE__), '/../website/template_recipe.rhtml')
12
+ Dir['docs/recipes/**/*.txt'].each do |txt|
13
+ sh %{ #{RUBY_APP} script/txt2html #{txt} #{template} > website/recipes/#{txt.split("/").last.gsub(/txt$/,'html')} }
14
+ end
6
15
  end
7
16
 
8
17
  desc 'Upload website files to rubyforge'
data/website/index.html CHANGED
@@ -5,7 +5,7 @@
5
5
  <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
6
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
7
  <title>
8
- Capistrano plugins, recipes and templates
8
+ &#x2192; &#8216;capitate&#8217;
9
9
  </title>
10
10
  <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
11
  <style>
@@ -21,24 +21,34 @@
21
21
  antiAlias: true,
22
22
  autoPad: true,
23
23
  validTags: ["div"]
24
- }
25
- var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
- versionBox.applyCornersToAll();
24
+ };
25
+
26
+ curvy_ids = [ "version", "recipes" ];
27
+ for(id in curvy_ids) {
28
+ var box = new curvyCorners(settings, document.getElementById(curvy_ids[id]));
29
+ box.applyCornersToAll();
30
+ }
27
31
  }
28
32
  </script>
29
33
  </head>
30
34
  <body>
31
- <div id="main">
35
+ <div id="main" class="landing">
32
36
 
33
- <h1>Capistrano plugins, recipes and templates</h1>
34
- <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/capitate"; return false'>
35
- <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/capitate" class="numbers">0.1.7</a>
37
- </div>
38
37
  <h1>&#x2192; &#8216;capitate&#8217;</h1>
39
38
 
39
+ <div id="version" class="clickable box" onclick='document.location = "http://rubyforge.org/projects/capitate"; return false'>
40
+ <p>Get Version</p>
41
+ <a href="http://rubyforge.org/projects/capitate" class="numbers">0.1.8</a>
42
+ </div>
43
+
44
+ <div id="recipes" class="box">
45
+ <a href="recipes/index.html">Recipes</a> &#x2192;
46
+ <a href="http://svn.ducktyper.com/capitate/trunk/lib/capitate/plugins/">Plugins</a> &#x2192;
47
+ <a href="http://svn.ducktyper.com/capitate/trunk/lib/templates/">Templates</a>
48
+ </div>
40
49
 
41
- <h2>What</h2>
50
+ <div style="clear:both">
51
+ <h2>What</h2>
42
52
 
43
53
 
44
54
  <p>Capistrano plugins, recipes and templates.</p>
@@ -47,22 +57,19 @@
47
57
  <h2>Installing</h2>
48
58
 
49
59
 
50
- <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">capitate</span></pre></p>
51
-
52
-
53
- <p>Create a Capfile (in your project):</p>
54
-
55
-
56
- <p><pre class='syntax'><span class="ident">capitate</span></pre></p>
60
+ <pre>sudo gem install capitate</pre>
57
61
 
62
+ <h2>Running</h2>
58
63
 
59
- <p>Create and set a profile in you Capfile:</p>
60
64
 
65
+ <p>Add capitate to your Capfile. Copy this somewhere near the top:</p>
61
66
 
62
- <p><pre class='syntax'><span class="comment"># load &quot;config/deployment/centos-sick.rb&quot;</span></pre></p>
63
67
 
64
-
65
- <p><em>See profiles section below for more info</em></p>
68
+ <p><pre class='syntax'>
69
+ <span class="ident">set</span> <span class="symbol">:project_root</span><span class="punct">,</span> <span class="constant">File</span><span class="punct">.</span><span class="ident">dirname</span><span class="punct">(</span><span class="constant">__FILE__</span><span class="punct">)</span>
70
+ <span class="ident">require</span> <span class="punct">'</span><span class="string">capitate</span><span class="punct">'</span>
71
+ <span class="ident">require</span> <span class="punct">'</span><span class="string">capitate/recipes</span><span class="punct">'</span>
72
+ </pre></p>
66
73
 
67
74
 
68
75
  <h2>The basics</h2>
@@ -79,49 +86,43 @@
79
86
  </ul>
80
87
 
81
88
 
82
- <h3>Profiles</h3>
83
-
84
-
85
- <p>Profiles are capfiles which store lists of recipes to run for cap install and deploy and settings for those recipes.</p>
86
-
89
+ <h3>Beefing up your deploy</h3>
87
90
 
88
- <p>For an example profile, see <a href="http://svn.ducktyper.com/capitate/trunk/lib/profiles/centos-sick.rb">centos-sick.rb</a></p>
89
91
 
92
+ <p>For an example deploy, see <a href="http://svn.ducktyper.com/capitate/trunk/lib/profiles/centos-sick.rb">centos-sick.rb</a></p>
90
93
 
91
- <p><span class="caps">TODO</span>: More on profiles&#8230;</p>
92
94
 
95
+ <p>You could copy this profile into config/deployment/ and add it to your Capfile:</p>
93
96
 
94
- <h3>Install recipes</h3>
95
97
 
98
+ <pre><code>load "config/deployment/centos-sick.rb"</code></pre>
96
99
 
97
- <p>To install a group of applications based on a profile (see Profiles section below):</p>
98
100
 
101
+ <h3>Use recipes</h3>
99
102
 
100
- <pre><code>cap install</code></pre>
101
103
 
104
+ <p><a href="recipes/index.html">View recipes documentation</a></p>
102
105
 
103
- <p><em>You may need to comment out &#8220;Defaults requiretty&#8221; in /etc/sudoders on the image before capistrano recipes will work.</em></p>
104
106
 
107
+ <p>For example, to script the install of a group of applications as root, use <a href="recipes/recipes.html">recipes:run</a>:</p>
105
108
 
106
- <h3>Deploying (application)</h3>
107
109
 
110
+ <p>Configure your Capfile to run it:</p>
108
111
 
109
- <p>If this is the first time you&#8217;ve deployed you&#8217;ll need to run:</p>
110
112
 
113
+ <p><pre class='syntax'>
114
+ <span class="ident">set</span> <span class="symbol">:recipes_run</span><span class="punct">,</span> <span class="punct">[</span> <span class="punct">&quot;</span><span class="string">ruby:centos:install</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">memcached:centos:install</span><span class="punct">&quot;</span> <span class="punct">]</span>
115
+ <span class="ident">set</span> <span class="symbol">:recipes_user</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">root</span><span class="punct">&quot;</span>
116
+ </pre></p>
111
117
 
112
- <pre><code>cap deploy:setup</code></pre>
113
118
 
119
+ <p>Then run:</p>
114
120
 
115
- <p>Otherwise, your standard deploy options:</p>
116
121
 
122
+ <pre><code>cap recipes:run</code></pre>
117
123
 
118
- <pre><code>cap deploy</code></pre>
119
124
 
120
-
121
- <pre><code>cap deploy:migrations (deploys and does migration)</code></pre>
122
-
123
-
124
- <pre><code>cap deploy:migrate (only does migration on existing deployment)</code></pre>
125
+ <p>This is just a basic example.</p>
125
126
 
126
127
 
127
128
  <h2>Forum</h2>
@@ -136,7 +137,7 @@
136
137
  <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
137
138
 
138
139
 
139
- <p>The trunk repository is <code>http://svn.ducktyper.com/var/svn/capitate/trunk</code> for anonymous access.</p>
140
+ <p>The trunk repository is <code>http://svn.ducktyper.com/capitate/trunk</code> for anonymous access.</p>
140
141
 
141
142
 
142
143
  <h2>License</h2>
@@ -149,6 +150,7 @@
149
150
 
150
151
 
151
152
  <p>Comments are welcome. Send an email to <a href="mailto:gabrielh@gmail.com">Gabriel Handford</a> via the <a href="http://groups.google.com/group/capitate">forum</a></p>
153
+ </div>
152
154
  <p class="coda">
153
155
  <a href="FIXME email">Gabriel Handford</a>, 21st February 2008<br>
154
156
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>