damagecontrol 0.5.0

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 (155) hide show
  1. data/README +75 -0
  2. data/README.license +5 -0
  3. data/Rakefile +111 -0
  4. data/app/controllers/admin_controller.rb +10 -0
  5. data/app/controllers/application.rb +163 -0
  6. data/app/controllers/files_controller.rb +19 -0
  7. data/app/controllers/project_controller.rb +284 -0
  8. data/app/controllers/scm_controller.rb +49 -0
  9. data/app/helpers/admin_helper.rb +2 -0
  10. data/app/helpers/application_helper.rb +3 -0
  11. data/app/helpers/project_helper.rb +2 -0
  12. data/app/views/dhtml_sites.txt +6 -0
  13. data/app/views/files/list.rhtml +4 -0
  14. data/app/views/layouts/rscm.rhtml +79 -0
  15. data/app/views/project/_bugzilla.rhtml +13 -0
  16. data/app/views/project/_changesets_list.rhtml +52 -0
  17. data/app/views/project/_cvs.rhtml +171 -0
  18. data/app/views/project/_jira.rhtml +19 -0
  19. data/app/views/project/_mooky.rhtml +23 -0
  20. data/app/views/project/_null.rhtml +0 -0
  21. data/app/views/project/_project.rhtml +36 -0
  22. data/app/views/project/_rubyforge.rhtml +19 -0
  23. data/app/views/project/_scarab.rhtml +19 -0
  24. data/app/views/project/_scms.rhtml +15 -0
  25. data/app/views/project/_sourceforge.rhtml +19 -0
  26. data/app/views/project/_starteam.rhtml +43 -0
  27. data/app/views/project/_svn.rhtml +22 -0
  28. data/app/views/project/_trac.rhtml +13 -0
  29. data/app/views/project/_trackers.rhtml +18 -0
  30. data/app/views/project/changesets.rhtml +31 -0
  31. data/app/views/project/index.rhtml +23 -0
  32. data/app/views/project/view.rhtml +70 -0
  33. data/app/views/scm/checkout_status.rhtml +44 -0
  34. data/app/views/scm/diff.rhtml +1 -0
  35. data/app/views/scm/scroll.html +27 -0
  36. data/bin/damagecontrol +7 -0
  37. data/bin/damagecontrol-webrick +2 -0
  38. data/config/database.yml +20 -0
  39. data/config/environment.rb +60 -0
  40. data/config/environments/development.rb +3 -0
  41. data/config/environments/production.rb +2 -0
  42. data/config/environments/test.rb +3 -0
  43. data/lib/damagecontrol/app.rb +74 -0
  44. data/lib/damagecontrol/build.rb +104 -0
  45. data/lib/damagecontrol/diff_htmlizer.rb +82 -0
  46. data/lib/damagecontrol/diff_parser.rb +153 -0
  47. data/lib/damagecontrol/directories.rb +126 -0
  48. data/lib/damagecontrol/poller.rb +72 -0
  49. data/lib/damagecontrol/project.rb +213 -0
  50. data/lib/damagecontrol/project_dependencies.rb +8 -0
  51. data/lib/damagecontrol/scm_web.rb +50 -0
  52. data/lib/damagecontrol/standard_persister.rb +49 -0
  53. data/lib/damagecontrol/tracker.rb +164 -0
  54. data/lib/damagecontrol/visitor/build_executor.rb +32 -0
  55. data/lib/damagecontrol/visitor/diff_persister.rb +41 -0
  56. data/lib/damagecontrol/visitor/rss_writer.rb +43 -0
  57. data/lib/damagecontrol/visitor/yaml_persister.rb +71 -0
  58. data/public/404.html +6 -0
  59. data/public/500.html +6 -0
  60. data/public/dispatch.cgi +10 -0
  61. data/public/dispatch.fcgi +7 -0
  62. data/public/dispatch.rb +10 -0
  63. data/public/images/16x16/about.png +0 -0
  64. data/public/images/16x16/bug_green.png +0 -0
  65. data/public/images/16x16/bug_red.png +0 -0
  66. data/public/images/16x16/bug_yellow.png +0 -0
  67. data/public/images/16x16/component.png +0 -0
  68. data/public/images/16x16/console.png +0 -0
  69. data/public/images/16x16/console_error.png +0 -0
  70. data/public/images/16x16/document_add.png +0 -0
  71. data/public/images/16x16/document_delete.png +0 -0
  72. data/public/images/16x16/document_edit.png +0 -0
  73. data/public/images/16x16/document_exchange.png +0 -0
  74. data/public/images/16x16/document_new.png +0 -0
  75. data/public/images/16x16/document_warning.png +0 -0
  76. data/public/images/16x16/safe.png +0 -0
  77. data/public/images/16x16/scroll_information.png +0 -0
  78. data/public/images/16x16/wrench.png +0 -0
  79. data/public/images/24x24/box_delete.png +0 -0
  80. data/public/images/24x24/box_into.png +0 -0
  81. data/public/images/24x24/box_new.png +0 -0
  82. data/public/images/24x24/console_network.png +0 -0
  83. data/public/images/24x24/document_edit.png +0 -0
  84. data/public/images/24x24/find.png +0 -0
  85. data/public/images/24x24/folders.png +0 -0
  86. data/public/images/24x24/garbage.png +0 -0
  87. data/public/images/24x24/gear_connection.png +0 -0
  88. data/public/images/24x24/gear_delete.png +0 -0
  89. data/public/images/24x24/gears_run.png +0 -0
  90. data/public/images/24x24/home.png +0 -0
  91. data/public/images/24x24/navigate_left.png +0 -0
  92. data/public/images/24x24/navigate_right.png +0 -0
  93. data/public/images/24x24/package_new.png +0 -0
  94. data/public/images/24x24/safe.png +0 -0
  95. data/public/images/24x24/safe_new.png +0 -0
  96. data/public/images/24x24/safe_out.png +0 -0
  97. data/public/images/24x24/scroll_information.png +0 -0
  98. data/public/images/24x24/stop.png +0 -0
  99. data/public/images/24x24/wrench.png +0 -0
  100. data/public/images/README.license +2 -0
  101. data/public/images/blue-16.gif +0 -0
  102. data/public/images/blue-32.gif +0 -0
  103. data/public/images/bugzilla.png +0 -0
  104. data/public/images/cvs.png +0 -0
  105. data/public/images/footer.gif +0 -0
  106. data/public/images/green-128.gif +0 -0
  107. data/public/images/green-16.gif +0 -0
  108. data/public/images/green-32.gif +0 -0
  109. data/public/images/grey-16.gif +0 -0
  110. data/public/images/grey-32.gif +0 -0
  111. data/public/images/jira.gif +0 -0
  112. data/public/images/red-16.gif +0 -0
  113. data/public/images/red-32.gif +0 -0
  114. data/public/images/red-pulse-32.gif +0 -0
  115. data/public/images/rss.gif +0 -0
  116. data/public/images/rubyforge.png +0 -0
  117. data/public/images/scarab.gif +0 -0
  118. data/public/images/sourceforge.gif +0 -0
  119. data/public/images/starteam.png +0 -0
  120. data/public/images/svnlogo64.png +0 -0
  121. data/public/images/trac.png +0 -0
  122. data/public/index.html +1 -0
  123. data/public/javascripts/dw_event.js +34 -0
  124. data/public/javascripts/dw_tooltip.js +86 -0
  125. data/public/javascripts/dw_viewport.js +55 -0
  126. data/public/javascripts/pngfix.js +29 -0
  127. data/public/javascripts/toggle_diff.js +25 -0
  128. data/public/licenses/DAMAGECONTROL.license +28 -0
  129. data/public/licenses/INCORS.license +32 -0
  130. data/public/stylesheets/diff.css +23 -0
  131. data/public/stylesheets/style.css +307 -0
  132. data/script/breakpointer +5 -0
  133. data/script/console +30 -0
  134. data/script/generate +70 -0
  135. data/script/server +61 -0
  136. data/test/damagecontrol/a_program.rb +3 -0
  137. data/test/damagecontrol/a_slow_program.rb +3 -0
  138. data/test/damagecontrol/build_test.rb +59 -0
  139. data/test/damagecontrol/diff_htmlizer_test.rb +31 -0
  140. data/test/damagecontrol/diff_parser_test.rb +61 -0
  141. data/test/damagecontrol/file_ext.rb +12 -0
  142. data/test/damagecontrol/poller_test.rb +56 -0
  143. data/test/damagecontrol/project_test.rb +144 -0
  144. data/test/damagecontrol/scm_web_test.rb +22 -0
  145. data/test/damagecontrol/test.diff +38 -0
  146. data/test/damagecontrol/test.html +40 -0
  147. data/test/damagecontrol/tracker_test.rb +48 -0
  148. data/test/damagecontrol/visitor/changesets.rss +34 -0
  149. data/test/damagecontrol/visitor/diff_persister_test.rb +49 -0
  150. data/test/damagecontrol/visitor/rss_writer_test.rb +40 -0
  151. data/test/damagecontrol/visitor/yaml_persister_test.rb +40 -0
  152. data/test/functional/admin_controller_test.rb +17 -0
  153. data/test/functional/project_controller_test.rb +17 -0
  154. data/test/test_helper.rb +14 -0
  155. metadata +245 -0
data/README ADDED
@@ -0,0 +1,75 @@
1
+ = DamageControl - a cross platform continuous integration server.
2
+
3
+ = Feature overview
4
+
5
+ * Supports all SCMs supported by RSCM.
6
+ * Web interface based on RoR (http://www.rubyonrails.org/)
7
+ * Colourised HTML diffs.
8
+ * RSS feeds for changesets and builds.
9
+ * Generation of URL links to diffs for several popular SCM web front-ends.
10
+ * Generation of URL links to bugs/issues for several popular bug/issue trackers.
11
+ * Uses UTC times according to the SCM server's clock, not the machine running RSCM. No NTP needed!
12
+
13
+ == DamageControl Server
14
+
15
+ DamageControl ships with a web app based on Ruby On Rails (which you currently have to install separately). To launch:
16
+
17
+ ruby script/server
18
+
19
+ You also need to launch (in a separate console) the DamageControl daemon process:
20
+
21
+ ruby -Ilib lib/damagecontrol/server.rb
22
+
23
+ The daemon process is the core of DamageContriol that performs SCM access and executes builds. The web app communicates with this process over Drb to display results.
24
+
25
+ The reason why two processes are needed is due to the fact that Dir.chdir may happen in various threads,
26
+ which would confuse the webapp if they ran in the same Ruby process. We tried with forking, but this is not
27
+ supported on Windows. We may support a fork-based one-process alternative for Linux/Cygwin in the future.
28
+
29
+ Once the two servers are started, you can access the web app on:
30
+
31
+ http://localhost:4712/
32
+
33
+ == Colourised HTML diffs
34
+
35
+ The web interface will present changesets as colourised diffs. Even for SCMs you never thought would support
36
+ that kind of feature. (As long as there is an RSCM plugin for it).
37
+
38
+ == RSS Support
39
+
40
+ The DamageControl daemon can generate RSS feeds for all supported SCMs. The RSS feeds will have one item per changeset.
41
+ Each RSS item's description contains the changeset's commit message, optionally with HTML links to
42
+ issue/bug tracker issues (if detected in the changeset's commit message). The item's description
43
+ will also contain a list of all the modified files, optionally with HTML links to a diff page
44
+ in an SCM web front-end.
45
+
46
+ == Supported Issue trackers
47
+
48
+ DamageControl can recognise bug/issue numbers (in commit messages) for a number of popular issue
49
+ tracking systems. It converts the SCM commit message to HTML with links to the issues mentioned in the commit message.
50
+
51
+ * Bugzilla - http://www.bugzilla.org/
52
+ * JIRA - http://www.atlassian.com/software/jira/
53
+ * RubyForge - http://rubyforge.org/
54
+ * Scarab - http://scarab.tigris.org/
55
+ * SourceForge - http://sourceforge.net/
56
+ * Trac - http://www.edgewall.com/trac/
57
+
58
+ Planned:
59
+
60
+ * RT - http://fsck.com/projects/rt/
61
+
62
+ == SCM web front-ends - diffs
63
+
64
+ DamageControl's web interface features colourised diffs for all changes in a changeset.
65
+ It can also generate links to individual diff pages in other SCM web frontends:
66
+
67
+ * RSCM Built-in HTML diffs.
68
+ * Fisheye - http://www.cenqua.com/fisheye/
69
+ * ViewCVS - http://viewcvs.sourceforge.net/
70
+
71
+ Planned:
72
+
73
+ * Trac - http://www.edgewall.com/trac/
74
+ * Chora - http://horde.org/chora/
75
+
data/README.license ADDED
@@ -0,0 +1,5 @@
1
+ This software consists of parts that are covered by different licenses.
2
+ See the following locations for details:
3
+
4
+ * public/licenses directories.
5
+ * public/images/README.license
data/Rakefile ADDED
@@ -0,0 +1,111 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+
9
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
10
+ PKG_NAME = 'damagecontrol'
11
+ PKG_VERSION = '0.5.0' + PKG_BUILD
12
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
13
+
14
+ desc "Default Task"
15
+ task :default => [ :all ]
16
+
17
+ # Run the unit tests
18
+ # To run a specific test: rake test TEST=path/to/test
19
+ fl = FileList.new('test/**/*_test.rb')
20
+ # TODO: figure out how to add all the stuff in app.
21
+ Rake::TestTask.new { |t|
22
+ # We need some of the test utils from rscm
23
+ t.libs << "test" << File.expand_path(File.dirname(__FILE__) + "/../rscm/test") << File.expand_path(File.dirname(__FILE__) + "/../rscm/lib")
24
+ t.test_files = fl
25
+ t.verbose = true
26
+ }
27
+
28
+ rd = Rake::RDocTask.new { |rdoc|
29
+ rdoc.rdoc_dir = 'doc'
30
+ rdoc.title = 'DamageControl - Cross platform Continuous Integration server'
31
+ rdoc.options << '--line-numbers' << '--inline-source'
32
+ rdoc.rdoc_files.include('README')
33
+ rdoc.rdoc_files.include('lib/**/*.rb')
34
+ rdoc.rdoc_files.include('docs/**/*.rd')
35
+ }
36
+
37
+ task :all => [:gem]
38
+
39
+ PKG_FILES = FileList[
40
+ '[A-Z]*',
41
+ 'doc/**/*',
42
+ 'bin/**/*',
43
+ 'app/**/*',
44
+ 'config/**/*',
45
+ 'docs/**/*',
46
+ 'lib/**/*',
47
+ 'public/**/*',
48
+ 'script/**/*',
49
+ 'test/**/*'
50
+ ]
51
+
52
+ if ! defined?(Gem)
53
+ puts "Package Target requires RubyGEMs"
54
+ else
55
+ spec = Gem::Specification.new do |s|
56
+
57
+ #### Basic information.
58
+
59
+ s.name = 'damagecontrol'
60
+ s.version = PKG_VERSION
61
+ s.summary = "DamageControl"
62
+ s.description = <<-EOF
63
+ DamageControl.
64
+ EOF
65
+
66
+ #### Dependencies and requirements.
67
+
68
+ s.add_dependency('log4r', '> 1.0.4')
69
+ s.add_dependency('rscm')
70
+ s.add_dependency('needle')
71
+ # s.add_dependency('rgl')
72
+ #s.requirements << ""
73
+
74
+ #### Which files are to be included in this gem? Everything! (Except CVS directories.)
75
+
76
+ s.files = PKG_FILES.to_a
77
+
78
+ #### C code extensions.
79
+
80
+ #s.extensions << "ext/rmagic/extconf.rb"
81
+
82
+ #### Load-time details: library and application (you will need one or both).
83
+
84
+ s.require_path = 'lib' # Use these for libraries.
85
+ s.autorequire = 'damagecontrol/app'
86
+
87
+ s.bindir = "bin" # Use these for applications.
88
+ s.executables = ["damagecontrol", "damagecontrol-webrick"]
89
+ s.default_executable = "damagecontrol"
90
+
91
+ #### Documentation and testing.
92
+
93
+ s.has_rdoc = true
94
+ s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
95
+ rd.options.each do |op|
96
+ s.rdoc_options << op
97
+ end
98
+
99
+ #### Author and project details.
100
+
101
+ s.author = "Aslak Hellesoy"
102
+ s.email = "dev@damagecontrol.codehaus.org"
103
+ s.homepage = "http://damagecontrol.codehaus.org/"
104
+ # s.rubyforge_project = "rscm"
105
+ end
106
+
107
+ Rake::GemPackageTask.new(spec) do |pkg|
108
+ pkg.need_zip = true
109
+ pkg.need_tar = true
110
+ end
111
+ end
@@ -0,0 +1,10 @@
1
+ #require 'rscm'
2
+ #require 'rscm/tracker'
3
+
4
+ class AdminController < ApplicationController
5
+
6
+ def new_project
7
+ redirect_to(:controller => "project", :action => "view")
8
+ end
9
+
10
+ end
@@ -0,0 +1,163 @@
1
+ # The filters added to this controller will be run for all controllers in the application.
2
+ # Likewise will all the methods added be available for all controllers.
3
+
4
+ require 'rubygems'
5
+ require_gem 'rscm'
6
+ require 'damagecontrol/project'
7
+ require 'damagecontrol/build'
8
+ require 'damagecontrol/tracker'
9
+ require 'damagecontrol/scm_web'
10
+
11
+ # Start Drb - this is how we communicate with the daemon.
12
+ DRb.start_service()
13
+ Rscm = DRbObject.new(nil, 'druby://localhost:9000')
14
+
15
+ class ApplicationController < ActionController::Base
16
+
17
+ layout 'rscm'
18
+
19
+ def initialize
20
+ @sidebar_links = [
21
+ {
22
+ :controller => "project",
23
+ :action => "new",
24
+ :image => "/images/24x24/box_new.png",
25
+ :name => "New project"
26
+ }
27
+ ]
28
+ @controller = self
29
+ end
30
+
31
+ # Loads the project specified by the +id+ parameter and places it into the @project variable
32
+ def load_project
33
+ project_name = @params["id"]
34
+ @project = DamageControl::Project.load(project_name)
35
+ end
36
+
37
+ def breadcrumbs
38
+ subpaths = @request.path.split(/\//)
39
+ # subpaths.collect { |p| link_to_unless_current(p) }.links.join(" ")
40
+ end
41
+
42
+ protected
43
+
44
+ # Sets the links to display in the sidebar. Override this method in other controllers
45
+ # To change what to display.
46
+ def set_sidebar_links
47
+
48
+ end
49
+
50
+ end
51
+
52
+ module ActionView
53
+ module Helpers
54
+ module UrlHelper
55
+ # Modify the original behaviour of +link_to+ so that the link
56
+ # includes the client's timezone as URL param +timezone+ in the request.
57
+ # Can be used by server to adjust formatting of UTC dates so they match the client's time zone.
58
+ def convert_confirm_option_to_javascript!(html_options)
59
+ # We're adding this JS call to add the timezone info as a URL param.
60
+ html_options["onclick"] = "intercept(this);"
61
+ if html_options.include?(:confirm)
62
+ html_options["onclick"] += "return confirm('#{html_options[:confirm]}');"
63
+ html_options.delete(:confirm)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ class Base
70
+ def text_or_input(input, options)
71
+ if(input)
72
+ options[:class] = "setting-input" unless options[:class]
73
+ tag("input", options)
74
+ elsif(options[:value] =~ /^http?:\/\//)
75
+ content_tag("a", options[:value], "href" => options[:value])
76
+ else
77
+ options[:value]
78
+ end
79
+ end
80
+
81
+ def text_or_select(input, options)
82
+ values = options.delete(:values)
83
+ if(input)
84
+ options[:class] = "setting-input" unless options[:class]
85
+
86
+ option_tags = ""
87
+ values.each do |value|
88
+ option_attrs = {:value => value.class.name}
89
+ option_attrs[:selected] = "true" if value.selected?
90
+ option_tag = content_tag("option", value.name, option_attrs)
91
+ option_tags << option_tag
92
+ end
93
+ content_tag("select", option_tags, options)
94
+ else
95
+ values.find {|v| v.selected?}.name
96
+ end
97
+ end
98
+
99
+ # Creates an image with a tooltip that will show on mouseover.
100
+ #
101
+ # Options:
102
+ # * <tt>:txt</tt> - The text to put in the tooltip. Can be HTML.
103
+ # * <tt>:img</tt> - The image to display on the page. Defaults to '/images/16x16/about.png'
104
+ def tip(options)
105
+ tip = options.delete(:txt)
106
+ options[:src] = options.delete(:img) || "/images/16x16/about.png"
107
+ options[:onmouseover] = "Tooltip.show(event,#{tip})"
108
+ options[:onmouseout] = "Tooltip.hide()"
109
+
110
+ tag("img", options)
111
+ end
112
+ end
113
+ end
114
+
115
+ module DamageControl
116
+
117
+ # Add some generic web capabilities to the RSCM classes
118
+ module Web
119
+ module Configuration
120
+
121
+ def selected?
122
+ false
123
+ end
124
+
125
+ # Returns the short lowercase name. Used for javascript and render_partial.
126
+ def short
127
+ $1.downcase if self.class.name =~ /.*::(.*)/
128
+ end
129
+
130
+ end
131
+ end
132
+ end
133
+
134
+ class RSCM::AbstractSCM
135
+ include DamageControl::Web::Configuration
136
+ end
137
+
138
+ class DamageControl::Tracker::Base
139
+ include DamageControl::Web::Configuration
140
+ end
141
+
142
+ class DamageControl::Project
143
+ include DamageControl::Web::Configuration
144
+ end
145
+
146
+ class DamageControl::Build
147
+ def small_image
148
+ exit_code == 0 ? "/images/green-16.gif" : "/images/red-16.gif"
149
+ end
150
+ end
151
+
152
+ class RSCM::Change
153
+ ICONS = {
154
+ MODIFIED => "/images/16x16/document_edit.png",
155
+ DELETED => "/images/16x16/document_delete.png",
156
+ ADDED => "/images/16x16/document_add.png",
157
+ MOVED => "/images/16x16/document_exchange.png",
158
+ }
159
+
160
+ def icon
161
+ ICONS[@status] || "/images/16x16/document_warning.png"
162
+ end
163
+ end
@@ -0,0 +1,19 @@
1
+ require 'rscm/directories'
2
+
3
+ class FilesController < ApplicationController
4
+
5
+ def list
6
+ load_project
7
+
8
+ root = @project.checkout_dir
9
+ relative_path = @params['path']
10
+ absolute_path = relative_path ? "#{root}/#{relative_path}" : root
11
+ if(File.file?(absolute_path))
12
+ # TODO: use http://rubyforge.org/projects/syntax/
13
+ # TODO: the file contents should be rendered within the regular layout
14
+ render_text(File.open(absolute_path).read)
15
+ else
16
+ @relative_paths = Dir["#{absolute_path}/*"].collect {|f| f[root.length+1..-1]}
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,284 @@
1
+ require 'rscm'
2
+ require 'damagecontrol/project'
3
+ require 'damagecontrol/directories'
4
+ require 'damagecontrol/diff_parser'
5
+ require 'damagecontrol/diff_htmlizer'
6
+
7
+ class ProjectController < ApplicationController
8
+
9
+ # TODO: check if the various SCMs are installed and disable them with a warning if not.
10
+ # Each SCM class should have an available? method
11
+
12
+ SCMS = [
13
+ # Uncomment this to see Mooky in action in the web interface!
14
+ # RSCM::Mooky,
15
+ RSCM::CVS,
16
+ RSCM::SVN,
17
+ RSCM::StarTeam
18
+ ]
19
+
20
+ TRACKERS = [
21
+ DamageControl::Tracker::Null,
22
+ DamageControl::Tracker::Bugzilla,
23
+ DamageControl::Tracker::JIRA,
24
+ DamageControl::Tracker::RubyForge,
25
+ DamageControl::Tracker::SourceForge,
26
+ DamageControl::Tracker::Scarab,
27
+ DamageControl::Tracker::Trac
28
+ ]
29
+
30
+ SCM_WEBS = [
31
+ # SCMWeb::Null.new,
32
+ # SCMWeb::ViewCVS.new,
33
+ # SCMWeb::Fisheye.new
34
+ ]
35
+
36
+ def initialize
37
+ super
38
+ @navigation_name = "changesets_list"
39
+ end
40
+
41
+ def index
42
+ @projects = DamageControl::Project.find_all
43
+ @navigation_name = "null"
44
+ end
45
+
46
+ def new
47
+ @project = DamageControl::Project.new
48
+ @scms = SCMS.collect {|o| o.new}
49
+ first_scm = @scms[0]
50
+ def first_scm.selected?
51
+ true
52
+ end
53
+ @trackers = TRACKERS.collect {|o| o.new}
54
+ first_tracker = @trackers[0]
55
+ def first_tracker.selected?
56
+ true
57
+ end
58
+ @edit = true
59
+ @new_project = true
60
+ render_action("view")
61
+ end
62
+
63
+ def view
64
+ return render_text("No project specified") unless @params["id"]
65
+ @edit = false
66
+ load
67
+ end
68
+
69
+ def edit
70
+ @edit = true
71
+ load
72
+ render_action("view")
73
+ end
74
+
75
+ def changesets_rss
76
+ load
77
+ send_file(@project.changesets_rss_file)
78
+ end
79
+
80
+ def delete
81
+ load_project
82
+ begin
83
+ Rscm.delete_project(project)
84
+ rescue => e
85
+ return render_text("Couldn't connect to RSCM server. Please make sure it's running.<br>" + e.message)
86
+ end
87
+ index
88
+ end
89
+
90
+ def save
91
+ project = instantiate_from_params("project")
92
+ project.scm = instantiate_from_params("scm")
93
+ project.tracker = instantiate_from_params("tracker")
94
+
95
+ begin
96
+ Rscm.save_project(project)
97
+ rescue => e
98
+ $stderr.puts(e.backtrace.join("\n"))
99
+ return render_text("Couldn't connect to RSCM server. Please make sure it's running.<br>" + e.message)
100
+ end
101
+
102
+ redirect_to(:action => "view", :id => project.name)
103
+ end
104
+
105
+ def changesets
106
+ load
107
+ last_changeset_identifier = @params["changeset"]
108
+ @changesets = @project.changesets(last_changeset_identifier.to_identifier, 1)
109
+ @changesets.accept(HtmlDiffVisitor.new(@project))
110
+ end
111
+
112
+ protected
113
+
114
+ # Visitor that adds a method called +html_diff+ to each change
115
+ class HtmlDiffVisitor
116
+ def initialize(project)
117
+ @project = project
118
+ end
119
+
120
+ def visit_changesets(changesets)
121
+ end
122
+
123
+ def visit_changeset(changeset)
124
+ @changeset = changeset
125
+ end
126
+
127
+ def visit_change(change)
128
+ def change.html_diff=(html)
129
+ @html = html
130
+ end
131
+
132
+ def change.html_diff
133
+ @html
134
+ end
135
+
136
+ html = ""
137
+ dp = DamageControl::DiffParser.new
138
+ diff_file = DamageControl::Directories.diff_file(@project.name, @changeset, change)
139
+ if(File.exist?(diff_file))
140
+ File.open(diff_file) do |diffs_io|
141
+ diffs = dp.parse_diffs(diffs_io)
142
+ dh = DamageControl::DiffHtmlizer.new(html)
143
+ diffs.accept(dh)
144
+ if(html == "")
145
+ html = "Diff was calculated, but was empty. (This may be a bug - new, moved and binary files and are not supported yet)."
146
+ end
147
+ end
148
+ else
149
+ html = "Diff not calculated yet."
150
+ end
151
+ change.html_diff = html
152
+ end
153
+ end
154
+
155
+ def set_sidebar_links
156
+ if(@project.exists?)
157
+ @sidebar_links << {
158
+ :controller => "project",
159
+ :action => "edit",
160
+ :id => @project.name,
161
+ :image => "/images/24x24/wrench.png",
162
+ :name => "Edit #{@project.name} settings"
163
+ }
164
+ end
165
+
166
+ # if(@project.exists?)
167
+ # @sidebar_links << {
168
+ # :controller => "project",
169
+ # :action => "delete",
170
+ # :id => @project.name,
171
+ # :image => "/images/24x24/box_delete.png",
172
+ # :name => "Delete #{@project.name} project"
173
+ # }
174
+ # end
175
+
176
+ if(@project.exists? && @project.scm && !@project.scm.exists? && @project.scm.can_create?)
177
+ @sidebar_links << {
178
+ :controller => "scm",
179
+ :action => "create",
180
+ :id => @project.name,
181
+ :image => "/images/24x24/safe_new.png",
182
+ :name => "Create #{@project.scm.name} repository"
183
+ }
184
+ end
185
+
186
+ # if(@project.exists? && !@project.checked_out?)
187
+ # @sidebar_links << {
188
+ # :controller => "scm",
189
+ # :action => "checkout",
190
+ # :id => @project.name,
191
+ # :image => "/images/24x24/safe_out.png",
192
+ # :name => "Check out from #{@project.scm.name}"
193
+ # }
194
+ # end
195
+
196
+ if(@project.exists? && @project.checked_out?)
197
+ @sidebar_links << {
198
+ :controller => "files",
199
+ :action => "list",
200
+ :id => @project.name,
201
+ :image => "/images/24x24/folders.png",
202
+ :name => "Browse working copy"
203
+ }
204
+ end
205
+
206
+ if(@project.exists? && @project.checked_out?)
207
+ @sidebar_links << {
208
+ :controller => "scm",
209
+ :action => "delete_working_copy",
210
+ :id => @project.name,
211
+ :image => "/images/24x24/garbage.png",
212
+ :name => "Delete working copy"
213
+ }
214
+ end
215
+
216
+ if(@project.exists?)
217
+ @sidebar_links << {
218
+ :href => @project.tracker.url,
219
+ :image => "/images/24x24/scroll_information.png",
220
+ :name => @project.tracker.name
221
+ }
222
+ end
223
+
224
+ if(@project.exists? && @project.home_page && @project.home_page != "")
225
+ @sidebar_links << {
226
+ :href => @project.home_page,
227
+ :image => "/images/24x24/home.png",
228
+ :name => "#{@project.name} home page"
229
+ }
230
+ end
231
+
232
+ if(@project.changesets_rss_exists?)
233
+ @sidebar_links << {
234
+ :controller => "project",
235
+ :action => "changesets_rss",
236
+ :id => @project.name,
237
+ :image => "/images/rss.gif",
238
+ :name => "Changesets RSS"
239
+ }
240
+ end
241
+
242
+ end
243
+
244
+ private
245
+
246
+ def load
247
+ load_project
248
+
249
+ scm = @project.scm
250
+ def scm.selected?
251
+ true
252
+ end
253
+
254
+ tracker = @project.tracker
255
+ def tracker.selected?
256
+ true
257
+ end
258
+
259
+ # Make a dupe of the scm/tracker lists and substitute with project's value
260
+ @scms = SCMS.collect {|o| o.new}
261
+ @scms.each_index {|i| @scms[i] = @project.scm if @scms[i].class == @project.scm.class}
262
+
263
+ @trackers = TRACKERS.collect {|o| o.new}
264
+ @trackers.each_index {|i| @trackers[i] = @project.tracker if @trackers[i].class == @project.tracker.class}
265
+
266
+ @linkable_changesets = @project.changesets(@project.latest_changeset_identifier, 10)
267
+ @select_changeset_identifiers = @project.changeset_identifiers[0..-(@linkable_changesets.length+1)]
268
+
269
+ set_sidebar_links
270
+ end
271
+
272
+ # Instantiates an object from parameters
273
+ def instantiate_from_params(param)
274
+ class_name = @params[param]
275
+ clazz = eval(class_name)
276
+ ob = clazz.new
277
+ attribs = @params[class_name] || {}
278
+ attribs.each do |k,v|
279
+ ob.send("#{k}=", v)
280
+ end
281
+ ob
282
+ end
283
+
284
+ end