ktec-subtrac 0.1.15

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 (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
+