ktec-subtrac 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +188 -0
  3. data/Rakefile +56 -0
  4. data/VERSION.yml +4 -0
  5. data/bin/subtrac +43 -0
  6. data/lib/subtrac.rb +450 -0
  7. data/lib/subtrac/commands.rb +6 -0
  8. data/lib/subtrac/commands/create.rb +13 -0
  9. data/lib/subtrac/commands/install.rb +10 -0
  10. data/lib/subtrac/common/favicon.ico +0 -0
  11. data/lib/subtrac/common/images/trac/banner_bg.jpg +0 -0
  12. data/lib/subtrac/common/images/trac/bar_bg.gif +0 -0
  13. data/lib/subtrac/common/images/trac/footer_back.png +0 -0
  14. data/lib/subtrac/common/images/trac/main_bg.gif +0 -0
  15. data/lib/subtrac/common/images/trac/saint_logo_small.png +0 -0
  16. data/lib/subtrac/common/static/404.html +14 -0
  17. data/lib/subtrac/common/styles/trac.css +222 -0
  18. data/lib/subtrac/config/config.yml +58 -0
  19. data/lib/subtrac/shared/trac.ini +163 -0
  20. data/lib/subtrac/templates/location.erb +16 -0
  21. data/lib/subtrac/templates/projects/blank/svn/branches/README +0 -0
  22. data/lib/subtrac/templates/projects/blank/svn/tags/README +0 -0
  23. data/lib/subtrac/templates/projects/blank/svn/trunk/README +0 -0
  24. data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +57 -0
  25. data/lib/subtrac/templates/projects/new/svn/trunk/trac/wiki/WikiStart +46 -0
  26. data/lib/subtrac/templates/projects/new/trac/wiki/WikiStart +23 -0
  27. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/index/index.html +21 -0
  28. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/layout.html +56 -0
  29. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/site.html +27 -0
  30. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/theme.html +86 -0
  31. data/lib/subtrac/templates/projects/trac_theme/trac/wiki/WikiStart +4 -0
  32. data/lib/subtrac/templates/trac.ini.erb +48 -0
  33. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/__init__.py +0 -0
  34. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/bg.gif +0 -0
  35. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/bg_page.gif +0 -0
  36. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/bg_page_in.jpg +0 -0
  37. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/btn_more.gif +0 -0
  38. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/col_bg.gif +0 -0
  39. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/col_title_bg.gif +0 -0
  40. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/col_top.gif +0 -0
  41. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/content_article_bg.jpg +0 -0
  42. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/content_title_bg.gif +0 -0
  43. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/footer.jpg +0 -0
  44. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/header.jpg +0 -0
  45. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_archive.gif +0 -0
  46. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_archive2.gif +0 -0
  47. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_cat.gif +0 -0
  48. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_comments.gif +0 -0
  49. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_date.gif +0 -0
  50. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_links.gif +0 -0
  51. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_list.gif +0 -0
  52. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_rss.gif +0 -0
  53. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_top.gif +0 -0
  54. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/ico_user.gif +0 -0
  55. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/search_input.gif +0 -0
  56. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/search_submit.gif +0 -0
  57. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_active_l.gif +0 -0
  58. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_active_r.gif +0 -0
  59. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_hover.gif +0 -0
  60. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_hover_l.gif +0 -0
  61. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_hover_r.gif +0 -0
  62. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_link.gif +0 -0
  63. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_link_l.gif +0 -0
  64. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tab_link_r.gif +0 -0
  65. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/img/tmp_photo.gif +0 -0
  66. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/saint.css +168 -0
  67. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/htdocs/screenshot.png +0 -0
  68. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/templates/saint_theme.html +143 -0
  69. data/lib/subtrac/templates/trac/themes/sainttheme/crystalxtheme/theme.py +12 -0
  70. data/lib/subtrac/templates/trac/themes/sainttheme/setup.py +29 -0
  71. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/css/subtrac.css +1805 -0
  72. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/archive-li-first.png +0 -0
  73. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/archive-li-hover.png +0 -0
  74. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/archive-li-last.png +0 -0
  75. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/archive-li.png +0 -0
  76. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/archive.png +0 -0
  77. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/body-home.png +0 -0
  78. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/body.png +0 -0
  79. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/content-product.png +0 -0
  80. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/content.png +0 -0
  81. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/header.png +0 -0
  82. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/master.css +1805 -0
  83. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/masthead.png +0 -0
  84. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/more.png +0 -0
  85. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/products-li-large.png +0 -0
  86. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/products-li.png +0 -0
  87. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/rss-span.png +0 -0
  88. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/rss.png +0 -0
  89. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/search.png +0 -0
  90. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/sec-navigation-li.png +0 -0
  91. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/sec-navigation.png +0 -0
  92. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/slogan.png +0 -0
  93. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/wrapper-home.png +0 -0
  94. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/img/wrapper.png +0 -0
  95. data/lib/subtrac/templates/trac/themes/subtractheme/prototype/subtractheme.html +351 -0
  96. data/lib/subtrac/templates/trac/themes/subtractheme/setup.py +29 -0
  97. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/__init__.py +0 -0
  98. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/archive-li-first.png +0 -0
  99. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/archive-li-hover.png +0 -0
  100. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/archive-li-last.png +0 -0
  101. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/archive-li.png +0 -0
  102. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/archive.png +0 -0
  103. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/body-home.png +0 -0
  104. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/body.png +0 -0
  105. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/content-product.png +0 -0
  106. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/content.png +0 -0
  107. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/header.png +0 -0
  108. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/master.css +1805 -0
  109. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/masthead.png +0 -0
  110. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/more.png +0 -0
  111. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/products-li-large.png +0 -0
  112. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/products-li.png +0 -0
  113. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/rss-span.png +0 -0
  114. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/rss.png +0 -0
  115. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/search.png +0 -0
  116. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/sec-navigation-li.png +0 -0
  117. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/sec-navigation.png +0 -0
  118. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/slogan.png +0 -0
  119. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/wrapper-home.png +0 -0
  120. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/img/wrapper.png +0 -0
  121. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/htdocs/subtrac.css +1805 -0
  122. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/templates/subtrac_theme.html +143 -0
  123. data/lib/subtrac/templates/trac/themes/subtractheme/subtractheme/theme.py +12 -0
  124. data/lib/subtrac/templates/vhost.conf.erb +38 -0
  125. data/lib/subtrac/version.rb +4 -0
  126. metadata +187 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 =
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.
data/README.markdown ADDED
@@ -0,0 +1,188 @@
1
+ # subtrac
2
+
3
+ Simple and opinionated helper for creating and managing subversion and trac projects.
4
+
5
+ ## Installation on a fresh jeos (ubuntu) slice
6
+
7
+ # install some basic requirements
8
+ sudo apt-get install openssh-server apache2 sqlite wget ruby1.8-dev ruby1.8 rubygems
9
+ # add github to package list
10
+ gem sources -a http://gems.github.com
11
+ # install the subtrac package and dependencies
12
+ sudo gem install --include-dependencies ktec-subtrac
13
+
14
+ Note: since gems and ubuntu don't entirely play nicely, its necessary to add the gem path to .bashrc file.
15
+ For all users, you can add it here:
16
+ sudo vi /etc/bash.bashrc
17
+
18
+ ...
19
+ export PATH=$PATH:/var/lib/gems/1.8/bin
20
+
21
+
22
+ # Installing on VirtualBox 2.2
23
+
24
+ Start with a Fresh VM Image
25
+ Install jeos (hardy)
26
+
27
+ ## install the guest additions
28
+ # mount guest additions (select Devices>Install Guest Additions from menu)
29
+ sudo mount /media/cdrom0/ -o unhide
30
+ # install gcc and make
31
+ sudo aptitude install build-essential linux-headers-`uname -r`
32
+ sudo /cdrom/VBoxLinuxAdditions-x86.run all
33
+
34
+ ## install openssh-server?
35
+ sudo apt-get install openssh-server
36
+
37
+ ## some other pre-requisites
38
+ sudo aptitude install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 sqlite3
39
+
40
+ ## install apache2, python and some modules
41
+ sudo apt-get install apache2 libapache2-mod-python libapache2-mod-python-doc \
42
+ libapache2-svn python-setuptools subversion python-subversion \
43
+ libapache2-dav graphviz htmldoc enscript
44
+ # enable mod_rewrite
45
+ sudo a2enmod rewrite
46
+
47
+ ## install Trac
48
+ sudo easy_install -U setuptools
49
+ sudo easy_install Trac
50
+
51
+ ## some cool plugins
52
+ sudo easy_install http://svn.edgewall.org/repos/genshi/trunk/ http://trac-hacks.org/svn/accountmanagerplugin/trunk http://trac-hacks.org/svn/customfieldadminplugin/0.11 http://trac-hacks.org/svn/eclipsetracplugin/tracrpcext/0.10 http://trac-hacks.org/svn/iniadminplugin/0.11 http://trac-hacks.org/svn/masterticketsplugin/0.11 http://trac-hacks.org/svn/pagetopdfplugin/0.10 http://trac-hacks.org/svn/progressmetermacro/0.11 http://trac-hacks.org/svn/ticketdeleteplugin/0.11 http://trac-hacks.org/svn/tracwysiwygplugin/0.11 http://wikinotification.ufsoft.org/svn/trunk http://trac-hacks.org/svn/advancedticketworkflowplugin/0.11 http://trac-hacks.org/svn/clientsplugin/0.11 http://trac-hacks.org/svn/emailtotracscript/trunk http://trac-hacks.org/svn/finegrainedpageauthzeditorplugin/0.11 \
53
+ http://trac-hacks.org/svn/gnomebrtheme/0.11
54
+ http://trac-hacks.org/svn/irresistibletheme/0.11
55
+ http://trac-hacks.org/svn/themeengineplugin/0.11 http://trac-hacks.org/svn/crystalxtheme/0.11
56
+
57
+
58
+ ## install gems and update
59
+ sudo apt-get install rubygems
60
+ sudo gem update --system
61
+
62
+ Which introduced this error:
63
+ /usr/bin/gem:23: uninitialized constant Gem::GemRunner(NameError)
64
+ Simply add the line to the file /usr/bin/gem (may be different on a mac)
65
+ require 'rubygems/gem_runner'
66
+ after
67
+ require 'rubygems'
68
+ OR
69
+
70
+ sudo mv /usr/bin/gem /usr/bin/gem.old; sudo ln -s /usr/bin/gem1.8 /usr/bin/gem
71
+
72
+ # edit bash.bashrc so all users can run the gem binaries
73
+ sudo vi /etc/bash.bashrc ? not sure we need this any more...
74
+ # add github to the gem sources list
75
+ sudo gem sources -a http://gems.github.com
76
+ # install subtrac gem package
77
+ sudo gem install keithsalisbury-subtrac
78
+
79
+ ## install subtrac server
80
+ sudo subtrac install [--clean]
81
+
82
+
83
+ # Other things to setup
84
+
85
+ ## Mount a shared host folder from the VM Guest
86
+ sudo mkdir /mnt/subtrac
87
+ sudo mount.vboxsf pkg /mnt/subtrac/
88
+
89
+ ## Setting up VM to use an internal loop back interface
90
+
91
+ ### Configure the interface
92
+
93
+ sudo ifconfig vboxnet0 192.168.56.1 up
94
+
95
+ ### Configure the VM
96
+
97
+ VBoxManage modifyvm dev.subtrac.com -hostifdev2 'vboxnet0: ethernet'
98
+
99
+ Boot it, and give it a static address on the same subnet, mine looks like this:
100
+
101
+ ### Assign a static ip to interface2
102
+
103
+ sudo vi /etc/networking/interfaces
104
+
105
+ # The primary network interface
106
+ auto eth0
107
+ iface eth0 inet dhcp
108
+
109
+ # The secondary network interface
110
+ auto eth1
111
+ iface eth1 inet static
112
+ address 192.168.56.2
113
+ netmask 255.255.255.0
114
+
115
+ For linux users there's an even cooler way to set this up...
116
+ http://muffinresearch.co.uk/archives/2009/04/08/virtualbox-access-guests-via-a-virtual-interface/
117
+
118
+ ### OSX Map your new domain to the ip
119
+
120
+ sudo mate /private/etc/hosts
121
+
122
+ 192.168.56.2 dev.subtrac.com
123
+
124
+ ### OSX Auto start the VM on bootup
125
+
126
+ sudo mate /Library/LaunchDaemons/com.subtrac.dev.plist
127
+
128
+ And make it look something like this:
129
+
130
+ <?xml version="1.0" encoding="UTF-8"?>
131
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
132
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
133
+ <plist version="1.0">
134
+ <dict>
135
+ <key>Label</key>
136
+ <string>Bring up interface</string>
137
+ <key>ProgramArguments</key>
138
+ <array>
139
+ <string>ifconfig</string>
140
+ <string>vboxnet0</string>
141
+ <string>192.168.56.1</string>
142
+ <string>up</string>
143
+ </array>
144
+ <key>RunAtLoad</key>
145
+ <true/>
146
+ <key>UserName</key>
147
+ <string>root</string>
148
+ </dict>
149
+ <dict>
150
+ <key>Label</key>
151
+ <string>Subtrac Development Server</string>
152
+ <key>ServiceDescription</key>
153
+ <string>VirtualBox</string>
154
+ <key>ProgramArguments</key>
155
+ <array>
156
+ <string>/usr/bin/VBoxHeadless</string>
157
+ <string>-startvm</string>
158
+ <string>dev.subtrac.com</string>
159
+ </array>
160
+ <key>RunAtLoad</key>
161
+ <true/>
162
+ <key>HopefullyExitsFirst</key>
163
+ <true/>
164
+ <!-- use if you want it to bounce automatically...
165
+ <key>KeepAlive</key>
166
+ <true/>
167
+ -->
168
+ <key>UserName</key>
169
+ <string>root</string>
170
+ </dict>
171
+ </plist>
172
+
173
+ ### Login with out a prompt
174
+
175
+ # generate a new keypair
176
+ sh-keygen -t rsa
177
+
178
+ # push the pub key up to the server
179
+ cat ~/.ssh/id_rsa.pub | ssh keith@dev.subtrac.com "cat - >> ~/.ssh/authorized_keys"
180
+
181
+ # chmod the file **on the server**:
182
+ sudo chmod 600 ~/.ssh/authorized_keys
183
+
184
+
185
+
186
+ ## Copyright
187
+
188
+ Copyright (c) 2009 Keith Salisbury. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "subtrac"
8
+ gem.summary = %Q{Simple and opinionated helper for creating and managing subversion and trac projects.}
9
+ gem.email = "keithsalisbury@gmail.com"
10
+ gem.homepage = "http://ktec.subtrac.com/subtrac"
11
+ gem.authors = ["Keith Salisbury"]
12
+ gem.add_dependency('visionmedia-commander', '>= 3.2.5')
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.subtrac.com"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ if File.exist?('VERSION.yml')
45
+ config = YAML.load(File.read('VERSION.yml'))
46
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
47
+ else
48
+ version = ""
49
+ end
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "subtrac #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
56
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 15
data/bin/subtrac ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander'
5
+
6
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
7
+ require 'subtrac'
8
+
9
+ program :name, 'subtrac'
10
+ program :version, Subtrac::VERSION
11
+ program :description, 'subtrac will install and manage a collection of subversion respositories and associated trac sites'
12
+
13
+ command :install do |c|
14
+ c.syntax = 'subtrac install [options]'
15
+ c.summary = ''
16
+ c.description = 'Installation of default files required to host multipe development projects.'
17
+ c.example 'description', 'installs the default trac and svn setup'
18
+ c.option '-c','--clean', 'Performs a clean install'
19
+ c.option '-d','--defaults', 'Accept all defaults'
20
+ c.when_called Subtrac::Commands::Install
21
+ end
22
+
23
+ command :create do |c|
24
+ c.syntax = 'subtrac create [options]'
25
+ c.summary = ''
26
+ c.description = ''
27
+ c.example 'description', 'creates a new project'
28
+ c.option '-p','--project PROJECT', 'Name of project to create'
29
+ c.option '-c','--client CLIENT', 'Name of client to create the project for'
30
+ c.when_called Subtrac::Commands::Create
31
+ end
32
+
33
+ =begin
34
+ command :delete do |c|
35
+ c.syntax = 'subtrac delete [options]'
36
+ c.summary = ''
37
+ c.description = ''
38
+ c.example 'description', 'deletes an existing project'
39
+ c.option '--project', 'Name of project to delete'
40
+ c.option '--client', 'Name of client the project was for'
41
+ c.when_called Devserver::Commands::Create
42
+ end
43
+ =end
data/lib/subtrac.rb ADDED
@@ -0,0 +1,450 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2009, Keith Salisbury (www.globalkeith.com)
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # Neither the name of the original author nor the names of contributors
16
+ # may be used to endorse or promote products derived from this software
17
+ # without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ #
30
+ # You may need these...
31
+ #
32
+ # sudo apt-get install ruby rubygems
33
+ # sudo gem sources -a http://gems.github.com
34
+ # sudo gem install visionmedia-commander
35
+ # sudo gem install yaml erb fileutils
36
+ #
37
+
38
+ require 'yaml'
39
+ require 'erb'
40
+ require 'fileutils'
41
+ require 'subtrac/version'
42
+ require 'subtrac/commands'
43
+
44
+
45
+ module Subtrac
46
+
47
+ SUBTRAC_ROOT = "#{File.dirname(__FILE__)}/" unless defined?(SUBTRAC_ROOT)
48
+ SUBTRAC_ENV = (ENV['SUBTRAC_ENV'] || 'development').dup unless defined?(SUBTRAC_ENV)
49
+ USER_CONFIG = 'config/user.yml'
50
+
51
+ class << self
52
+
53
+ # The Configuration instance used to configure the Subtrac environment
54
+ def configuration
55
+ @@configuration
56
+ end
57
+
58
+ def configuration=(configuration)
59
+ @@configuration = configuration
60
+ end
61
+
62
+ def initialized?
63
+ @initialized || false
64
+ end
65
+
66
+ def initialized=(initialized)
67
+ @initialized ||= initialized
68
+ end
69
+
70
+ def root
71
+ Pathname.new(SUBTRAC_ROOT) if defined?(SUBTRAC_ROOT)
72
+ end
73
+
74
+ def public_path
75
+ @@public_path ||= self.root ? File.join(self.root, "public") : "public"
76
+ end
77
+
78
+ def subtrac_path
79
+ @@subtrac_path ||= self.root ? File.join(self.root, "subtrac") : "subtrac"
80
+ end
81
+
82
+ def public_path=(path)
83
+ @@public_path = path
84
+ end
85
+
86
+ def docs_dir
87
+ @@docs_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:docs])
88
+ end
89
+
90
+ def docs_dir=(dir)
91
+ @@docs_dir = dir
92
+ end
93
+
94
+ def svn_dir
95
+ @@svn_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:svn])
96
+ end
97
+
98
+ def svn_dir=(dir)
99
+ @@svn_dir = dir
100
+ end
101
+
102
+ def trac_dir
103
+ @@trac_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:trac])
104
+ end
105
+
106
+ def trac_dir=(dir)
107
+ @@trac_dir = dir
108
+ end
109
+
110
+ def temp_dir
111
+ @@temp_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:temp])
112
+ end
113
+
114
+ def temp_dir=(dir)
115
+ @@temp_dir = dir
116
+ end
117
+
118
+ def log_dir
119
+ @@log_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:log])
120
+ end
121
+
122
+ def log_dir=(dir)
123
+ @@log_dir = dir
124
+ end
125
+
126
+ def locations_dir
127
+ @@locations_dir ||= File.join(@install_dir,@APP_CONFIG[:dirs][:locations])
128
+ end
129
+
130
+ def locations_dir=(dir)
131
+ @@locations_dir = dir
132
+ end
133
+
134
+ end
135
+
136
+ # Loads the configuration YML file
137
+ def self.load_config
138
+ # TODO: We need to refactor this code so it will load the default configuration only if one has not been created
139
+ puts "\n==== Loading configuration file ===="
140
+ # load configuration file
141
+ file_path = File.join(subtrac_path, USER_CONFIG)
142
+ file_path = File.join(subtrac_path,"/config/config.yml") if not File.exists?(file_path)
143
+ puts "Attempting to read config file: #{file_path}"
144
+ begin
145
+ raw_config = File.read(file_path)
146
+ yamlFile = YAML.load(raw_config)
147
+ rescue Exception => e
148
+ raise StandardError, "Config #{file_path} could not be loaded."
149
+ end
150
+ if yamlFile
151
+ if yamlFile[SUBTRAC_ENV]
152
+ @APP_CONFIG = yamlFile[SUBTRAC_ENV]
153
+ else
154
+ raise StandardError, "config/config.yml exists, but doesn't have a configuration for #{SUBTRAC_ENV}."
155
+ end
156
+ else
157
+ raise StandardError, "config/config.yml does not exist."
158
+ end
159
+ puts "\n==== Installation options ===="
160
+
161
+ say("Setting up default configuration...")
162
+ @server_name = @APP_CONFIG[:server_name]
163
+ @server_hostname = @APP_CONFIG[:server_hostname]
164
+ @server_ip = @APP_CONFIG[:server_ip]
165
+
166
+ @default_client = @APP_CONFIG[:default_client]
167
+ @default_project = @APP_CONFIG[:default_project]
168
+
169
+ @install_dir = File.expand_path(@APP_CONFIG[:installation_dir])
170
+ @conf_dir = @APP_CONFIG[:apache2_conf]
171
+
172
+ @ldap_enable = @APP_CONFIG[:ldap][:enable]
173
+ if (@ldap_enable) then
174
+ @ldap_bind_dn = @APP_CONFIG[:ldap][:bind_dn]
175
+ @ldap_bind_password = @APP_CONFIG[:ldap][:bind_password]
176
+ @ldap_url = @APP_CONFIG[:ldap][:host]
177
+ end
178
+
179
+ end
180
+
181
+
182
+ # Install
183
+ def self.install(args,options)
184
+ puts "\n==== Installing development server files ===="
185
+
186
+ if options.defaults then
187
+ create_environment_directories(options.clean)
188
+ install_common_files()
189
+ install_default_theme()
190
+ configure_admin_user()
191
+ create_virtual_host()
192
+ # create default project and client
193
+ create_project(@default_project,@default_client)
194
+ save_config()
195
+ else
196
+ # check where we are installing
197
+ change_install_dir = agree("The default installation directory is \"#{@install_dir}\". Would you like to change this? [Y/n]") if
198
+ @install_dir = ask("Where would you like to install this server?") if change_install_dir
199
+
200
+ unless !File.directory?(@install_dir)
201
+ # Ask if the user agrees (yes or no)
202
+ confirm_clean = agree("Err, it seems there's some stuff in there. You sure you want me to overwrite? [Y/n]") if options.clean
203
+ confirm_clean = agree("Doubly sure? I can't undo this....[Y/n]") if confirm_clean
204
+ end
205
+
206
+ # right lets install
207
+ change_server_name = agree("The default server name is \"#{@server_name}\". Would you like to change this? [Y/n]")
208
+ @server_name = ask("What would you like to call your new development server? ") if change_server_name
209
+
210
+ create_environment_directories(confirm_clean)
211
+ install_common_files()
212
+ install_default_theme()
213
+ configure_admin_user()
214
+ # TODO: Need to check for default client/project before creating virtual host
215
+ # otherwise we need remove the rewrite rule
216
+ create_virtual_host()
217
+ confirm_default_client = agree("Do you want to create a default client project? [Y/n]")
218
+ # create default project and client
219
+ if confirm_default_client
220
+ change_client = agree("The default client name is \"#{@default_client}\". Would you like to change this? [Y/n]")
221
+ @default_client = ask("What client name would you like to use? ") if change_client
222
+ change_project = agree("The default project name is \"#{@default_project}\". Would you like to change this? [Y/n]")
223
+ @default_project = ask("What would you like to call your new project? ") if change_project
224
+ create_project(@default_project,@default_client)
225
+ end
226
+ save_config()
227
+ end
228
+
229
+ end
230
+
231
+ private
232
+
233
+ # Write the changes configuration to disk
234
+ def self.save_config
235
+ # save the things that might have changed
236
+ @APP_CONFIG[:server_name] = @server_name
237
+ @APP_CONFIG[:server_hostname] = @server_hostname
238
+ @APP_CONFIG[:server_ip] = @server_ip
239
+
240
+ @APP_CONFIG[:default_client] = @default_client
241
+ @APP_CONFIG[:default_project] = @default_project
242
+
243
+ @APP_CONFIG[:installation_dir] = @install_dir
244
+ @APP_CONFIG[:apache2_conf] = @conf_dir
245
+
246
+ @APP_CONFIG[:ldap][:bind_dn] = @ldap_bind_dn
247
+ @APP_CONFIG[:ldap][:bind_password] = @ldap_bind_password
248
+ @APP_CONFIG[:ldap][:host] = @ldap_url
249
+
250
+ file_path = File.join(subtrac_path, USER_CONFIG)
251
+ open(file_path, 'w') {|f| YAML.dump({SUBTRAC_ENV => @APP_CONFIG}, f)}
252
+ end
253
+
254
+ # creates a directory if it does not exist
255
+ def self.create_if_missing(*names)
256
+ names.each do |name|
257
+ unless File.directory?(name)
258
+ puts "Creating directory called #{names}..."
259
+ FileUtils.mkdir_p(name)
260
+ end
261
+ end
262
+ end
263
+
264
+ # publishes an erb template
265
+ def self.parse_template(infile,outfile,binding)
266
+ file = File.open(outfile, 'w+')
267
+ if file
268
+ template = ERB.new(IO.read(infile))
269
+ if template
270
+ file.syswrite(template.result(binding))
271
+ else
272
+ raise "Could not read template. file #{infile}"
273
+ end
274
+ else
275
+ raise "Unable to open file for writing. file #{outfile}"
276
+ end
277
+ end
278
+
279
+ # creates a new virtual host and reloads apache and enables the new virtual host
280
+ def self.create_virtual_host
281
+ # TODO: Need to check for default client/project before creating virtual host
282
+ # otherwise we need remove the rewrite rule
283
+ puts "\n==== Creating new virtual host ===="
284
+ vhost_template = File.join(subtrac_path, @APP_CONFIG[:templates][:virtual_host])
285
+ puts "group apache tempalte: #{vhost_template}"
286
+ new_vhost = File.join(@conf_dir,@server_hostname)
287
+ puts "group apache file: #{new_vhost}"
288
+ parse_template(vhost_template,new_vhost,binding) if SUBTRAC_ENV != 'test'
289
+ # reload apache configuration
290
+ `/etc/init.d/apache2 force-reload` if SUBTRAC_ENV != 'test'
291
+ `a2ensite #{@server_hostname}` if SUBTRAC_ENV != 'test'
292
+ end
293
+
294
+ def self.install_common_files
295
+ puts "\n==== Installing common files ===="
296
+ # TODO: implement a mask for .svn folders
297
+ # TODO: refactor /common to the app config
298
+ FileUtils.cp_r(Dir.glob(File.join(subtrac_path, "common/.")),docs_dir)
299
+ FileUtils.cp_r(Dir.glob(File.join(subtrac_path, "shared/.")),create_if_missing(File.join(trac_dir, ".shared")))
300
+ # this need to be replaced with a question/answer session
301
+ #FileUtils.cp(,@install_dir)
302
+ end
303
+
304
+ def self.configure_admin_user
305
+ puts "\n==== Configure admin user ===="
306
+ # create admin user
307
+ passwd_file = File.join(@install_dir, ".passwd")
308
+ admin_user = ask("New admin user: ") { |q| q.echo = true }
309
+ admin_pass = ask("New password: ") { |q| q.echo = "*" }
310
+ admin_pass_confirm = ask("Re-type new password: ") { |q| q.echo = "*" }
311
+ if (admin_pass == admin_pass_confirm) then
312
+ `htpasswd -c -b #{passwd_file} #{admin_user} #{admin_pass}`
313
+ @APP_CONFIG[:admin_user] = admin_user
314
+ @APP_CONFIG[:admin_pass] = admin_pass
315
+ # ensure this guy is added to trac admin group
316
+ @APP_CONFIG[:trac][:permissions][admin_user] = "admins"
317
+ else
318
+ # call the password chooser again
319
+ end
320
+ end
321
+
322
+ def self.create_environment_directories(overwrite=false)
323
+ puts "\n==== Creating new environment directories ===="
324
+ FileUtils.rm_rf @install_dir if overwrite
325
+ create_if_missing @install_dir
326
+ # create the environment directories
327
+ @APP_CONFIG[:dirs].each do |key, value|
328
+ dir = File.join(@install_dir,value)
329
+ create_if_missing dir
330
+ end
331
+ end
332
+
333
+ def self.create_client(name)
334
+ puts "\n==== Create a new client called #{name} ===="
335
+ client_name = name.downcase
336
+ # create apache configuration
337
+ puts "subtrac_path: #{subtrac_path}"
338
+ puts "templates_location: #{@APP_CONFIG[:templates][:location]}"
339
+ location_template = File.join(subtrac_path, @APP_CONFIG[:templates][:location])
340
+ puts "location_template: #{location_template}"
341
+ location_conf = File.join(locations_dir,"#{client_name}.conf")
342
+ puts "location_conf: #{location_conf}"
343
+ parse_template(location_template,location_conf,binding)
344
+ `/etc/init.d/apache2 force-reload` if SUBTRAC_ENV != 'test'
345
+
346
+ # create svn+trac directory
347
+ create_if_missing File.join(svn_dir,client_name)
348
+ create_if_missing File.join(trac_dir,client_name)
349
+
350
+ end
351
+
352
+ def self.install_default_theme
353
+ puts "\n==== Create a new client called #{name} ===="
354
+ # create a project for this clients trac theme
355
+ #create_project("trac_theme", client_name,@APP_CONFIG[:default_theme_template])
356
+
357
+ # check the theme project out
358
+ #client_theme_dir = File.join(trac_dir,client_name,".theme")
359
+ #create_if_missing(client_theme_dir)
360
+ #FileUtils.chown_R('www-data', 'www-data', client_theme_dir, :verbose => true) if SUBTRAC_ENV != 'test'
361
+ #puts "Attempting checkout of theme project..."
362
+
363
+ #`sudo svn co --username #{@APP_CONFIG[:admin_user]} --password #{@APP_CONFIG[:admin_pass]} \
364
+ # file://#{svn_dir}/#{client_name}/trac_theme/trunk #{client_theme_dir}` if SUBTRAC_ENV != 'test'
365
+ template_dir = File.join(subtrac_path, "templates","trac","themes","subtractheme")
366
+ `sudo easy_install #{template_dir}`
367
+ end
368
+
369
+ def self.create_project(project, client, project_type=@APP_CONFIG[:default_project_template])
370
+ puts "\n==== Create a new project called #{project} for #{client} ===="
371
+
372
+ client_name = client.downcase
373
+ project_name = project.downcase
374
+
375
+ # create client directory if needed
376
+ create_client(client_name) if (!File.directory? File.join(svn_dir,client_name))
377
+
378
+ project_svn_dir = File.join(svn_dir,client_name,project_name)
379
+ project_trac_dir = File.join(trac_dir,client_name,project_name)
380
+
381
+ # TODO: Need to change this to use a 'groups' yml file
382
+ if (File.directory? project_svn_dir) then
383
+ raise StandardError, "A project called #{project} already exists in the #{client} repository. Would you like to replace it?"
384
+ end
385
+
386
+ # create new project directories
387
+ say("Create project directories...")
388
+ create_if_missing project_svn_dir
389
+ create_if_missing project_trac_dir
390
+
391
+ project_template = File.join(subtrac_path, @APP_CONFIG[:templates][:projects],project_type)
392
+
393
+ # copy template svn project to a temp folder, then svn import it into the repo
394
+ say("Create temporary project directory and copy template files...")
395
+ svn_template_dir = File.join(project_template,"svn")
396
+ project_temp_dir = File.join(temp_dir,project_name)
397
+ FileUtils.cp_r(svn_template_dir,project_temp_dir)
398
+
399
+ # create a new subversion repository
400
+ say("Creating a new subversion repository...")
401
+ `svnadmin create #{project_svn_dir}` if SUBTRAC_ENV != 'test'
402
+
403
+ # import into svn
404
+ say("Importing temporary project into the new subversion repository...")
405
+ `svn import #{project_temp_dir} file:///#{project_svn_dir} --message "initial import"` if SUBTRAC_ENV != 'test'
406
+ # delete the temporary directory
407
+ FileUtils.rm_r(project_temp_dir, :force => true)
408
+
409
+ # create a new trac site
410
+ say("Creating a new trac site...")
411
+ result = `trac-admin #{project_trac_dir} initenv #{project_name} sqlite:#{project_trac_dir}/db/trac.db svn #{project_svn_dir}` if SUBTRAC_ENV != 'test'
412
+ FileUtils.chown_R('www-data', 'www-data', project_trac_dir, :verbose => true) if SUBTRAC_ENV != 'test'
413
+ FileUtils.mkdir_p("#{project_trac_dir}/conf") if SUBTRAC_ENV == 'test' # fake the folder for tests
414
+
415
+ say("Installing trac configuration...")
416
+ # install shared trac.ini
417
+ trac_ini_template = File.join(subtrac_path, @APP_CONFIG[:templates][:trac])
418
+ parse_template(trac_ini_template,File.join(project_trac_dir,"/conf/trac.ini"),binding)
419
+
420
+ # remove custom templates directory so trac uses the shared location (while we wait for trac patch)
421
+ #FileUtils.rm_rf("#{project_trac_dir}/templates")
422
+
423
+ say("Setting up default trac permissions...")
424
+ # set up trac permissions
425
+ @APP_CONFIG[:trac][:permissions].each do |key, value|
426
+ `sudo trac-admin #{project_trac_dir} permission add #{key} #{value}` if SUBTRAC_ENV != 'test'
427
+ end
428
+
429
+ say("Adding default trac wiki pages...")
430
+ # loop through the directory and import all pages
431
+ Dir.foreach("#{project_template}/trac/wiki/.") do |file|
432
+ # do something with the file here
433
+ unless ['.', '..','.svn'].include? file
434
+ temp_file = File.join(temp_dir,file)
435
+ puts = binding
436
+ parse_template(File.join(project_template,"trac/wiki",file), temp_file, binding)
437
+ `trac-admin #{project_trac_dir} wiki import #{file} #{temp_file}` if SUBTRAC_ENV != 'test'
438
+ FileUtils.rm(temp_file)
439
+ end
440
+ end
441
+
442
+ # run trac upgrade
443
+ say("Upgrading the trac installation...")
444
+ `trac-admin #{project_trac_dir} upgrade` if SUBTRAC_ENV != 'test'
445
+
446
+ end
447
+ end
448
+
449
+
450
+