##// END OF EJS Templates
Adds support for multiple repositories per project (#779)....
Jean-Philippe Lang -
r8530:1bd5e58c8478
parent child
Show More
@@ -0,0 +1,9
1 class AddRepositoriesIdentifier < ActiveRecord::Migration
2 def self.up
3 add_column :repositories, :identifier, :string
4 end
5
6 def self.down
7 remove_column :repositories, :identifier
8 end
9 end
@@ -0,0 +1,9
1 class AddRepositoriesIsDefault < ActiveRecord::Migration
2 def self.up
3 add_column :repositories, :is_default, :boolean, :default => false
4 end
5
6 def self.down
7 remove_column :repositories, :is_default
8 end
9 end
@@ -0,0 +1,14
1 class SetDefaultRepositories < ActiveRecord::Migration
2 def self.up
3 Repository.update_all(["is_default = ?", false])
4 # Sets the last repository as default in case multiple repositories exist for the same project
5 Repository.connection.select_values("SELECT r.id FROM #{Repository.table_name} r" +
6 " WHERE r.id = (SELECT max(r1.id) FROM #{Repository.table_name} r1 WHERE r1.project_id = r.project_id)").each do |i|
7 Repository.update_all(["is_default = ?", true], ["id = ?", i])
8 end
9 end
10
11 def self.down
12 Repository.update_all(["is_default = ?", false])
13 end
14 end
@@ -28,7 +28,6 class RepositoriesController < ApplicationController
28 default_search_scope :changesets
28 default_search_scope :changesets
29
29
30 before_filter :find_project_by_project_id, :only => [:new, :create]
30 before_filter :find_project_by_project_id, :only => [:new, :create]
31 before_filter :check_repository_uniqueness, :only => [:new, :create]
32 before_filter :find_repository, :only => [:edit, :update, :destroy, :committers]
31 before_filter :find_repository, :only => [:edit, :update, :destroy, :committers]
33 before_filter :find_project_repository, :except => [:new, :create, :edit, :update, :destroy, :committers]
32 before_filter :find_project_repository, :except => [:new, :create, :edit, :update, :destroy, :committers]
34 before_filter :authorize
33 before_filter :authorize
@@ -39,6 +38,7 class RepositoriesController < ApplicationController
39 def new
38 def new
40 scm = params[:repository_scm] || Redmine::Scm::Base.all.first
39 scm = params[:repository_scm] || Redmine::Scm::Base.all.first
41 @repository = Repository.factory(scm)
40 @repository = Repository.factory(scm)
41 @repository.is_default = @project.repository.nil?
42 @repository.project = @project
42 @repository.project = @project
43 render :layout => !request.xhr?
43 render :layout => !request.xhr?
44 end
44 end
@@ -97,6 +97,7 class RepositoriesController < ApplicationController
97 (show_error_not_found; return) unless @entries
97 (show_error_not_found; return) unless @entries
98 @changesets = @repository.latest_changesets(@path, @rev)
98 @changesets = @repository.latest_changesets(@path, @rev)
99 @properties = @repository.properties(@path, @rev)
99 @properties = @repository.properties(@path, @rev)
100 @repositories = @project.repositories
100 render :action => 'show'
101 render :action => 'show'
101 end
102 end
102 end
103 end
@@ -255,18 +256,15 class RepositoriesController < ApplicationController
255 render_404
256 render_404
256 end
257 end
257
258
258 # TODO: remove it when multiple SCM support is added
259 def check_repository_uniqueness
260 if @project.repository
261 redirect_to settings_project_path(@project, :tab => 'repositories')
262 end
263 end
264
265 REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
259 REV_PARAM_RE = %r{\A[a-f0-9]*\Z}i
266
260
267 def find_project_repository
261 def find_project_repository
268 @project = Project.find(params[:id])
262 @project = Project.find(params[:id])
263 if params[:repository_id].present?
264 @repository = @project.repositories.find_by_identifier_param(params[:repository_id])
265 else
269 @repository = @project.repository
266 @repository = @project.repository
267 end
270 (render_404; return false) unless @repository
268 (render_404; return false) unless @repository
271 @path = params[:path].join('/') unless params[:path].nil?
269 @path = params[:path].join('/') unless params[:path].nil?
272 @path ||= ''
270 @path ||= ''
@@ -19,7 +19,7 class SysController < ActionController::Base
19 before_filter :check_enabled
19 before_filter :check_enabled
20
20
21 def projects
21 def projects
22 p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier')
22 p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => "#{Project.table_name}.identifier")
23 # extra_info attribute from repository breaks activeresource client
23 # extra_info attribute from repository breaks activeresource client
24 render :xml => p.to_xml(:only => [:id, :identifier, :name, :is_public, :status], :include => {:repository => {:only => [:id, :url]}})
24 render :xml => p.to_xml(:only => [:id, :identifier, :name, :is_public, :status], :include => {:repository => {:only => [:id, :url]}})
25 end
25 end
@@ -44,11 +44,11 class SysController < ActionController::Base
44 if params[:id]
44 if params[:id]
45 projects << Project.active.has_module(:repository).find(params[:id])
45 projects << Project.active.has_module(:repository).find(params[:id])
46 else
46 else
47 projects = Project.active.has_module(:repository).find(:all, :include => :repository)
47 projects = Project.active.has_module(:repository).all
48 end
48 end
49 projects.each do |project|
49 projects.each do |project|
50 if project.repository
50 project.repositories.each do |repository|
51 project.repository.fetch_changesets
51 repository.fetch_changesets
52 end
52 end
53 end
53 end
54 render :nothing => true, :status => 200
54 render :nothing => true, :status => 200
@@ -106,12 +106,15 module ApplicationHelper
106 # Generates a link to a SCM revision
106 # Generates a link to a SCM revision
107 # Options:
107 # Options:
108 # * :text - Link text (default to the formatted revision)
108 # * :text - Link text (default to the formatted revision)
109 def link_to_revision(revision, project, options={})
109 def link_to_revision(revision, repository, options={})
110 if repository.is_a?(Project)
111 repository = repository.repository
112 end
110 text = options.delete(:text) || format_revision(revision)
113 text = options.delete(:text) || format_revision(revision)
111 rev = revision.respond_to?(:identifier) ? revision.identifier : revision
114 rev = revision.respond_to?(:identifier) ? revision.identifier : revision
112 link_to(
115 link_to(
113 h(text),
116 h(text),
114 {:controller => 'repositories', :action => 'revision', :id => project, :rev => rev},
117 {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
115 :title => l(:label_revision_id, format_revision(revision))
118 :title => l(:label_revision_id, format_revision(revision))
116 )
119 )
117 end
120 end
@@ -92,6 +92,7 module RepositoriesHelper
92 text = link_to(h(text), :controller => 'repositories',
92 text = link_to(h(text), :controller => 'repositories',
93 :action => 'show',
93 :action => 'show',
94 :id => @project,
94 :id => @project,
95 :repository_id => @repository.identifier_param,
95 :path => path_param,
96 :path => path_param,
96 :rev => @changeset.identifier)
97 :rev => @changeset.identifier)
97 output << "<li class='#{style}'>#{text}"
98 output << "<li class='#{style}'>#{text}"
@@ -103,12 +104,14 module RepositoriesHelper
103 text = link_to(h(text), :controller => 'repositories',
104 text = link_to(h(text), :controller => 'repositories',
104 :action => 'entry',
105 :action => 'entry',
105 :id => @project,
106 :id => @project,
107 :repository_id => @repository.identifier_param,
106 :path => path_param,
108 :path => path_param,
107 :rev => @changeset.identifier) unless c.action == 'D'
109 :rev => @changeset.identifier) unless c.action == 'D'
108 text << " - #{h(c.revision)}" unless c.revision.blank?
110 text << " - #{h(c.revision)}" unless c.revision.blank?
109 text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories',
111 text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories',
110 :action => 'diff',
112 :action => 'diff',
111 :id => @project,
113 :id => @project,
114 :repository_id => @repository.identifier_param,
112 :path => path_param,
115 :path => path_param,
113 :rev => @changeset.identifier) + ') '.html_safe if c.action == 'M'
116 :rev => @changeset.identifier) + ') '.html_safe if c.action == 'M'
114 text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank?
117 text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank?
@@ -46,7 +46,8 class Project < ActiveRecord::Base
46 has_many :news, :dependent => :destroy, :include => :author
46 has_many :news, :dependent => :destroy, :include => :author
47 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
47 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
48 has_many :boards, :dependent => :destroy, :order => "position ASC"
48 has_many :boards, :dependent => :destroy, :order => "position ASC"
49 has_one :repository, :dependent => :destroy
49 has_one :repository, :conditions => ["is_default = ?", true]
50 has_many :repositories, :dependent => :destroy
50 has_many :changesets, :through => :repository
51 has_many :changesets, :through => :repository
51 has_one :wiki, :dependent => :destroy
52 has_one :wiki, :dependent => :destroy
52 # Custom field for the project issues
53 # Custom field for the project issues
@@ -26,11 +26,19 class Repository < ActiveRecord::Base
26
26
27 serialize :extra_info
27 serialize :extra_info
28
28
29 before_save :check_default
30
29 # Raw SQL to delete changesets and changes in the database
31 # Raw SQL to delete changesets and changes in the database
30 # has_many :changesets, :dependent => :destroy is too slow for big repositories
32 # has_many :changesets, :dependent => :destroy is too slow for big repositories
31 before_destroy :clear_changesets
33 before_destroy :clear_changesets
32
34
33 validates_length_of :password, :maximum => 255, :allow_nil => true
35 validates_length_of :password, :maximum => 255, :allow_nil => true
36 validates_length_of :identifier, :maximum => 255, :allow_blank => true
37 validates_presence_of :identifier, :unless => Proc.new { |r| r.is_default? || r.set_as_default? }
38 validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true
39 validates_exclusion_of :identifier, :in => %w(show entry raw changes annotate diff show stats graph)
40 # donwcase letters, digits, dashes but not digits only
41 validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-]*$/, :allow_blank => true
34 # Checks if the SCM is enabled when creating a repository
42 # Checks if the SCM is enabled when creating a repository
35 validate :repo_create_validation, :on => :create
43 validate :repo_create_validation, :on => :create
36
44
@@ -65,8 +73,10 class Repository < ActiveRecord::Base
65 end
73 end
66
74
67 send :attributes_without_extra_info=, p, guard_protected_attributes
75 send :attributes_without_extra_info=, p, guard_protected_attributes
76 if p_extra.keys.any?
68 merge_extra_info(p_extra)
77 merge_extra_info(p_extra)
69 end
78 end
79 end
70
80
71 # Removes leading and trailing whitespace
81 # Removes leading and trailing whitespace
72 def url=(arg)
82 def url=(arg)
@@ -101,6 +111,44 class Repository < ActiveRecord::Base
101 self.class.scm_name
111 self.class.scm_name
102 end
112 end
103
113
114 def name
115 if is_default?
116 l(:field_repository_is_default)
117 elsif identifier.present?
118 identifier
119 else
120 scm_name
121 end
122 end
123
124 def identifier_param
125 if is_default?
126 nil
127 elsif identifier.present?
128 identifier
129 else
130 id.to_s
131 end
132 end
133
134 def <=>(repository)
135 if is_default?
136 -1
137 elsif repository.is_default?
138 1
139 else
140 identifier <=> repository.identifier
141 end
142 end
143
144 def self.find_by_identifier_param(param)
145 if param.to_s =~ /^\d+$/
146 find_by_id(param)
147 else
148 find_by_identifier(param)
149 end
150 end
151
104 def merge_extra_info(arg)
152 def merge_extra_info(arg)
105 h = extra_info || {}
153 h = extra_info || {}
106 return h if arg.nil?
154 return h if arg.nil?
@@ -269,10 +317,10 class Repository < ActiveRecord::Base
269 # Can be called periodically by an external script
317 # Can be called periodically by an external script
270 # eg. ruby script/runner "Repository.fetch_changesets"
318 # eg. ruby script/runner "Repository.fetch_changesets"
271 def self.fetch_changesets
319 def self.fetch_changesets
272 Project.active.has_module(:repository).find(:all, :include => :repository).each do |project|
320 Project.active.has_module(:repository).all.each do |project|
273 if project.repository
321 project.repositories.each do |repository|
274 begin
322 begin
275 project.repository.fetch_changesets
323 repository.fetch_changesets
276 rescue Redmine::Scm::Adapters::CommandFailed => e
324 rescue Redmine::Scm::Adapters::CommandFailed => e
277 logger.error "scm: error during fetching changesets: #{e.message}"
325 logger.error "scm: error during fetching changesets: #{e.message}"
278 end
326 end
@@ -334,6 +382,21 class Repository < ActiveRecord::Base
334 ret
382 ret
335 end
383 end
336
384
385 def set_as_default?
386 new_record? && project && !Repository.first(:conditions => {:project_id => project.id})
387 end
388
389 protected
390
391 def check_default
392 if !is_default? && set_as_default?
393 self.is_default = true
394 end
395 if is_default? && is_default_changed?
396 Repository.update_all(["is_default = ?", false], ["project_id = ?", project_id])
397 end
398 end
399
337 private
400 private
338
401
339 def clear_changesets
402 def clear_changesets
@@ -1,6 +1,6
1 <% changesets.each do |changeset| %>
1 <% changesets.each do |changeset| %>
2 <div class="changeset <%= cycle('odd', 'even') %>">
2 <div class="changeset <%= cycle('odd', 'even') %>">
3 <p><%= link_to_revision(changeset, changeset.project,
3 <p><%= link_to_revision(changeset, changeset.repository,
4 :text => "#{l(:label_revision)} #{changeset.format_identifier}") %><br />
4 :text => "#{l(:label_revision)} #{changeset.format_identifier}") %><br />
5 <span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
5 <span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
6 <div class="wiki">
6 <div class="wiki">
@@ -1,16 +1,20
1 <% if @project.repository %>
1 <% if @project.repositories.any? %>
2 <table class="list">
2 <table class="list">
3 <thead>
3 <thead>
4 <tr>
4 <tr>
5 <th><%= l(:label_scm) %></th>
5 <th><%= l(:label_scm) %></th>
6 <th><%= l(:field_identifier) %></th>
7 <th><%= l(:field_repository_is_default) %></th>
6 <th><%= l(:label_repository) %></th>
8 <th><%= l(:label_repository) %></th>
7 <th></th>
9 <th></th>
8 </tr>
10 </tr>
9 </thead>
11 </thead>
10 <tbody>
12 <tbody>
11 <% repository = @project.repository %>
13 <% @project.repositories.each do |repository| %>
12 <tr class="<%= cycle 'odd', 'even' %>">
14 <tr class="<%= cycle 'odd', 'even' %>">
13 <td><%=h repository.scm_name %></td>
15 <td><%=h repository.scm_name %></td>
16 <td><%=h repository.identifier %></td>
17 <td align="center"><%= checked_image repository.is_default? %></td>
14 <td><%=h repository.url %></td>
18 <td><%=h repository.url %></td>
15 <td class="buttons">
19 <td class="buttons">
16 <% if User.current.allowed_to?(:manage_repository, @project) %>
20 <% if User.current.allowed_to?(:manage_repository, @project) %>
@@ -25,12 +29,13
25 <% end %>
29 <% end %>
26 </td>
30 </td>
27 </tr>
31 </tr>
32 <% end %>
28 </tbody>
33 </tbody>
29 </table>
34 </table>
30 <% else %>
35 <% else %>
31 <p class="nodata"><%= l(:label_no_data) %></p>
36 <p class="nodata"><%= l(:label_no_data) %></p>
32 <% end %>
37 <% end %>
33
38
34 <% if @project.repository.nil? && User.current.allowed_to?(:manage_repository, @project) %>
39 <% if User.current.allowed_to?(:manage_repository, @project) %>
35 <p><%= link_to l(:label_repository_new), new_project_repository_path(@project), :class => 'icon icon-add' %></p>
40 <p><%= link_to l(:label_repository_new), new_project_repository_path(@project), :class => 'icon icon-add' %></p>
36 <% end %>
41 <% end %>
@@ -1,4 +1,4
1 <%= link_to 'root', :action => 'show', :id => @project, :path => '', :rev => @rev %>
1 <%= link_to 'root', :action => 'show', :id => @project, :repository_id => @repository.identifier_param, :path => '', :rev => @rev %>
2 <%
2 <%
3 dirs = path.split('/')
3 dirs = path.split('/')
4 if 'file' == kind
4 if 'file' == kind
@@ -10,12 +10,12 dirs.each do |dir|
10 link_path << '/' unless link_path.empty?
10 link_path << '/' unless link_path.empty?
11 link_path << "#{dir}"
11 link_path << "#{dir}"
12 %>
12 %>
13 / <%= link_to h(dir), :action => 'show', :id => @project,
13 / <%= link_to h(dir), :action => 'show', :id => @project, :repository_id => @repository.identifier_param,
14 :path => to_path_param(link_path), :rev => @rev %>
14 :path => to_path_param(link_path), :rev => @rev %>
15 <% end %>
15 <% end %>
16 <% if filename %>
16 <% if filename %>
17 / <%= link_to h(filename),
17 / <%= link_to h(filename),
18 :action => 'changes', :id => @project,
18 :action => 'changes', :id => @project, :repository_id => @repository.identifier_param,
19 :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
19 :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
20 <% end %>
20 <% end %>
21 <%
21 <%
@@ -11,6 +11,7
11 :url => {
11 :url => {
12 :action => 'show',
12 :action => 'show',
13 :id => @project,
13 :id => @project,
14 :repository_id => @repository.identifier_param,
14 :path => to_path_param(ent_path),
15 :path => to_path_param(ent_path),
15 :rev => @rev,
16 :rev => @rev,
16 :depth => (depth + 1),
17 :depth => (depth + 1),
@@ -24,13 +25,13
24 ) %>">&nbsp</span>
25 ) %>">&nbsp</span>
25 <% end %>
26 <% end %>
26 <%= link_to h(ent_name),
27 <%= link_to h(ent_name),
27 {:action => (entry.is_dir? ? 'show' : 'changes'), :id => @project, :path => to_path_param(ent_path), :rev => @rev},
28 {:action => (entry.is_dir? ? 'show' : 'changes'), :id => @project, :repository_id => @repository.identifier_param, :path => to_path_param(ent_path), :rev => @rev},
28 :class => (entry.is_dir? ? 'icon icon-folder' : "icon icon-file #{Redmine::MimeType.css_class_of(ent_name)}")%>
29 :class => (entry.is_dir? ? 'icon icon-folder' : "icon icon-file #{Redmine::MimeType.css_class_of(ent_name)}")%>
29 </td>
30 </td>
30 <td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td>
31 <td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td>
31 <% changeset = @project.repository.find_changeset_by_name(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %>
32 <% changeset = @project.repository.find_changeset_by_name(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %>
32 <% if @repository.report_last_commit %>
33 <% if @repository.report_last_commit %>
33 <td class="revision"><%= link_to_revision(changeset, @project) if changeset %></td>
34 <td class="revision"><%= link_to_revision(changeset, @repository) if changeset %></td>
34 <td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td>
35 <td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td>
35 <td class="author"><%= changeset.nil? ? h(Redmine::CodesetUtil.replace_invalid_utf8(entry.lastrev.author.to_s.split('<').first)) : h(changeset.author) if entry.lastrev %></td>
36 <td class="author"><%= changeset.nil? ? h(Redmine::CodesetUtil.replace_invalid_utf8(entry.lastrev.author.to_s.split('<').first)) : h(changeset.author) if entry.lastrev %></td>
36 <td class="comments"><%=h truncate(changeset.comments, :length => 50) unless changeset.nil? %></td>
37 <td class="comments"><%=h truncate(changeset.comments, :length => 50) unless changeset.nil? %></td>
@@ -9,6 +9,9
9 <% end %>
9 <% end %>
10 </p>
10 </p>
11
11
12 <p><%= f.text_field :identifier %></p>
13 <p><%= f.check_box :is_default, :label => :field_repository_is_default %></p>
14
12 <% button_disabled = true %>
15 <% button_disabled = true %>
13 <% if @repository %>
16 <% if @repository %>
14 <% button_disabled = ! @repository.class.scm_available %>
17 <% button_disabled = ! @repository.class.scm_available %>
@@ -3,11 +3,12
3 <% end %>
3 <% end %>
4
4
5 <%= link_to l(:label_statistics),
5 <%= link_to l(:label_statistics),
6 {:action => 'stats', :id => @project},
6 {:action => 'stats', :id => @project, :repository_id => @repository.identifier_param},
7 :class => 'icon icon-stats' %>
7 :class => 'icon icon-stats' %>
8
8
9 <% form_tag({:action => controller.action_name,
9 <% form_tag({:action => controller.action_name,
10 :id => @project,
10 :id => @project,
11 :repository_id => @repository.identifier_param,
11 :path => to_path_param(@path),
12 :path => to_path_param(@path),
12 :rev => ''},
13 :rev => ''},
13 {:method => :get, :id => 'revision_selector'}) do -%>
14 {:method => :get, :id => 'revision_selector'}) do -%>
@@ -1,5 +1,5
1 <% show_revision_graph = ( @repository.supports_revision_graph? && path.blank? ) %>
1 <% show_revision_graph = ( @repository.supports_revision_graph? && path.blank? ) %>
2 <% form_tag({:controller => 'repositories', :action => 'diff', :id => @project, :path => to_path_param(path)}, :method => :get) do %>
2 <% form_tag({:controller => 'repositories', :action => 'diff', :id => @project, :repository_id => @repository.identifier_param, :path => to_path_param(path)}, :method => :get) do %>
3 <table class="list changesets">
3 <table class="list changesets">
4 <thead><tr>
4 <thead><tr>
5 <% if show_revision_graph %>
5 <% if show_revision_graph %>
@@ -23,6 +23,7
23 <% href_base = Proc.new {|x| url_for(:controller => 'repositories',
23 <% href_base = Proc.new {|x| url_for(:controller => 'repositories',
24 :action => 'revision',
24 :action => 'revision',
25 :id => project,
25 :id => project,
26 :repository_id => @repository.identifier_param,
26 :rev => x) } %>
27 :rev => x) } %>
27 <%= render :partial => 'revision_graph',
28 <%= render :partial => 'revision_graph',
28 :locals => {
29 :locals => {
@@ -35,7 +36,7
35 </td>
36 </td>
36 <% end %>
37 <% end %>
37 <% end %>
38 <% end %>
38 <td class="id"><%= link_to_revision(changeset, project) %></td>
39 <td class="id"><%= link_to_revision(changeset, @repository) %></td>
39 <td class="checkbox"><%= radio_button_tag('rev', changeset.identifier, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td>
40 <td class="checkbox"><%= radio_button_tag('rev', changeset.identifier, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td>
40 <td class="checkbox"><%= radio_button_tag('rev_to', changeset.identifier, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td>
41 <td class="checkbox"><%= radio_button_tag('rev_to', changeset.identifier, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td>
41 <td class="committed_on"><%= format_time(changeset.committed_on) %></td>
42 <td class="committed_on"><%= format_time(changeset.committed_on) %></td>
@@ -19,7 +19,7
19 <tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
19 <tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
20 <th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th>
20 <th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th>
21 <td class="revision">
21 <td class="revision">
22 <%= (revision.identifier ? link_to_revision(revision, @project) : format_revision(revision)) if revision %></td>
22 <%= (revision.identifier ? link_to_revision(revision, @repository) : format_revision(revision)) if revision %></td>
23 <td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td>
23 <td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td>
24 <td class="line-code"><pre><%= line %></pre></td>
24 <td class="line-code"><pre><%= line %></pre></td>
25 </tr>
25 </tr>
@@ -1,13 +1,13
1 <div class="contextual">
1 <div class="contextual">
2 &#171;
2 &#171;
3 <% unless @changeset.previous.nil? -%>
3 <% unless @changeset.previous.nil? -%>
4 <%= link_to_revision(@changeset.previous, @project, :text => l(:label_previous)) %>
4 <%= link_to_revision(@changeset.previous, @repository, :text => l(:label_previous)) %>
5 <% else -%>
5 <% else -%>
6 <%= l(:label_previous) %>
6 <%= l(:label_previous) %>
7 <% end -%>
7 <% end -%>
8 |
8 |
9 <% unless @changeset.next.nil? -%>
9 <% unless @changeset.next.nil? -%>
10 <%= link_to_revision(@changeset.next, @project, :text => l(:label_next)) %>
10 <%= link_to_revision(@changeset.next, @repository, :text => l(:label_next)) %>
11 <% else -%>
11 <% else -%>
12 <%= l(:label_next) %>
12 <%= l(:label_next) %>
13 <% end -%>
13 <% end -%>
@@ -16,6 +16,7
16 <% form_tag({:controller => 'repositories',
16 <% form_tag({:controller => 'repositories',
17 :action => 'revision',
17 :action => 'revision',
18 :id => @project,
18 :id => @project,
19 :repository_id => @repository.identifier_param,
19 :rev => nil},
20 :rev => nil},
20 :method => :get) do %>
21 :method => :get) do %>
21 <%= text_field_tag 'rev', @rev, :size => 8 %>
22 <%= text_field_tag 'rev', @rev, :size => 8 %>
@@ -37,7 +38,7
37 <td><%= l(:label_parent_revision) %></td>
38 <td><%= l(:label_parent_revision) %></td>
38 <td>
39 <td>
39 <%= @changeset.parents.collect{
40 <%= @changeset.parents.collect{
40 |p| link_to_revision(p, @project, :text => format_revision(p))
41 |p| link_to_revision(p, @repository, :text => format_revision(p))
41 }.join(", ").html_safe %>
42 }.join(", ").html_safe %>
42 </td>
43 </td>
43 </tr>
44 </tr>
@@ -47,7 +48,7
47 <td><%= l(:label_child_revision) %></td>
48 <td><%= l(:label_child_revision) %></td>
48 <td>
49 <td>
49 <%= @changeset.children.collect{
50 <%= @changeset.children.collect{
50 |p| link_to_revision(p, @project, :text => format_revision(p))
51 |p| link_to_revision(p, @repository, :text => format_revision(p))
51 }.join(", ").html_safe %>
52 }.join(", ").html_safe %>
52 </td>
53 </td>
53 </tr>
54 </tr>
@@ -85,6 +86,7
85 <p><%= link_to(l(:label_view_diff),
86 <p><%= link_to(l(:label_view_diff),
86 :action => 'diff',
87 :action => 'diff',
87 :id => @project,
88 :id => @project,
89 :repository_id => @repository.identifier_param,
88 :path => "",
90 :path => "",
89 :rev => @changeset.identifier) if @changeset.changes.any? %></p>
91 :rev => @changeset.identifier) if @changeset.changes.any? %></p>
90
92
@@ -1,5 +1,5
1 <div class="contextual">
1 <div class="contextual">
2 <% form_tag({:action => 'revision', :id => @project}) do %>
2 <% form_tag({:action => 'revision', :id => @project, :repository_id => @repository.identifier_param}) do %>
3 <%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %>
3 <%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %>
4 <%= submit_tag 'OK' %>
4 <%= submit_tag 'OK' %>
5 <% end %>
5 <% end %>
@@ -25,7 +25,7
25 sep = ''
25 sep = ''
26 %>
26 %>
27 <% if @repository.supports_all_revisions? && @path.blank? %>
27 <% if @repository.supports_all_revisions? && @path.blank? %>
28 <%= link_to l(:label_view_all_revisions), :action => 'revisions', :id => @project %>
28 <%= link_to l(:label_view_all_revisions), :action => 'revisions', :id => @project, :repository_id => @repository.identifier_param %>
29 <% sep = '|' %>
29 <% sep = '|' %>
30 <% end %>
30 <% end %>
31 <%
31 <%
@@ -38,6 +38,7
38 :action => 'changes',
38 :action => 'changes',
39 :path => to_path_param(@path),
39 :path => to_path_param(@path),
40 :id => @project,
40 :id => @project,
41 :repository_id => @repository.identifier_param,
41 :rev => @rev
42 :rev => @rev
42 %>
43 %>
43 <% end %>
44 <% end %>
@@ -52,11 +53,22
52 <% end %>
53 <% end %>
53
54
54 <% other_formats_links do |f| %>
55 <% other_formats_links do |f| %>
55 <%= f.link_to 'Atom', :url => {:action => 'revisions', :id => @project, :key => User.current.rss_key} %>
56 <%= f.link_to 'Atom', :url => {:action => 'revisions', :id => @project, :repository_id => @repository.identifier_param, :key => User.current.rss_key} %>
56 <% end %>
57 <% end %>
57 <% end %>
58 <% end %>
58 <% end %>
59 <% end %>
59
60
61 <% if @repositories.size > 1 %>
62 <% content_for :sidebar do %>
63 <h3><%= l(:label_repository_plural) %></h3>
64 <%= @repositories.sort.collect {|repo|
65 link_to h(repo.name),
66 {:controller => 'repositories', :action => 'show', :id => @project, :repository_id => repo.identifier_param, :rev => nil, :path => nil},
67 :class => 'repository' + (repo == @repository ? ' selected' : '')
68 }.join('<br />').html_safe %></p>
69 <% end %>
70 <% end %>
71
60 <% content_for :header_tags do %>
72 <% content_for :header_tags do %>
61 <%= stylesheet_link_tag "scm" %>
73 <%= stylesheet_link_tag "scm" %>
62 <% end %>
74 <% end %>
@@ -1,10 +1,10
1 <h2><%= l(:label_statistics) %></h2>
1 <h2><%= l(:label_statistics) %></h2>
2
2
3 <p>
3 <p>
4 <%= tag("embed", :width => 800, :height => 300, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :graph => "commits_per_month")) %>
4 <%= tag("embed", :width => 800, :height => 300, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "commits_per_month")) %>
5 </p>
5 </p>
6 <p>
6 <p>
7 <%= tag("embed", :width => 800, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :graph => "commits_per_author")) %>
7 <%= tag("embed", :width => 800, :height => 400, :type => "image/svg+xml", :src => url_for(:controller => 'repositories', :action => 'graph', :id => @project, :repository_id => @repository.identifier_param, :graph => "commits_per_author")) %>
8 </p>
8 </p>
9
9
10 <p><%= link_to l(:button_back), :action => 'show', :id => @project %></p>
10 <p><%= link_to l(:button_back), :action => 'show', :id => @project %></p>
@@ -318,6 +318,7 en:
318 field_root_directory: Root directory
318 field_root_directory: Root directory
319 field_cvsroot: CVSROOT
319 field_cvsroot: CVSROOT
320 field_cvs_module: Module
320 field_cvs_module: Module
321 field_repository_is_default: Main repository
321
322
322 setting_app_title: Application title
323 setting_app_title: Application title
323 setting_app_subtitle: Application subtitle
324 setting_app_subtitle: Application subtitle
@@ -317,6 +317,7 fr:
317 field_issues_visibility: Visibilité des demandes
317 field_issues_visibility: Visibilité des demandes
318 field_is_private: Privée
318 field_is_private: Privée
319 field_commit_logs_encoding: Encodage des messages de commit
319 field_commit_logs_encoding: Encodage des messages de commit
320 field_repository_is_default: Dépôt principal
320
321
321 setting_app_title: Titre de l'application
322 setting_app_title: Titre de l'application
322 setting_app_subtitle: Sous-titre de l'application
323 setting_app_subtitle: Sous-titre de l'application
@@ -235,7 +235,8 ActionController::Routing::Routes.draw do |map|
235 :action => 'show'
235 :action => 'show'
236 repository_views.connect 'projects/:id/repository/statistics',
236 repository_views.connect 'projects/:id/repository/statistics',
237 :action => 'stats'
237 :action => 'stats'
238
238 repository_views.connect 'projects/:id/repository/graph',
239 :action => 'graph'
239 repository_views.connect 'projects/:id/repository/revisions',
240 repository_views.connect 'projects/:id/repository/revisions',
240 :action => 'revisions'
241 :action => 'revisions'
241 repository_views.connect 'projects/:id/repository/revisions.:format',
242 repository_views.connect 'projects/:id/repository/revisions.:format',
@@ -247,28 +248,39 ActionController::Routing::Routes.draw do |map|
247 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format',
248 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format',
248 :action => 'diff'
249 :action => 'diff'
249 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path',
250 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path',
250 :action => 'entry',
251 :action => 'entry', :format => 'raw'
251 :format => 'raw',
252 :requirements => { :rev => /[a-z0-9\.\-_]+/ }
253 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path',
252 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path',
254 :requirements => { :rev => /[a-z0-9\.\-_]+/ }
253 :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
255
256 repository_views.connect 'projects/:id/repository/raw/*path',
254 repository_views.connect 'projects/:id/repository/raw/*path',
257 :action => 'entry', :format => 'raw'
255 :action => 'entry', :format => 'raw'
258 repository_views.connect 'projects/:id/repository/browse/*path',
256 repository_views.connect 'projects/:id/repository/:action/*path',
259 :action => 'browse'
257 :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
260 repository_views.connect 'projects/:id/repository/entry/*path',
258
261 :action => 'entry'
259 # Same routes with a repository_id
262 repository_views.connect 'projects/:id/repository/changes/*path',
260 repository_views.connect 'projects/:id/repository/:repository_id/statistics',
263 :action => 'changes'
261 :action => 'stats'
264 repository_views.connect 'projects/:id/repository/annotate/*path',
262 repository_views.connect 'projects/:id/repository/:repository_id/graph',
265 :action => 'annotate'
263 :action => 'graph'
266 repository_views.connect 'projects/:id/repository/diff/*path',
264 repository_views.connect 'projects/:id/repository/:repository_id/revisions',
265 :action => 'revisions'
266 repository_views.connect 'projects/:id/repository/:repository_id/revisions.:format',
267 :action => 'revisions'
268 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev',
269 :action => 'revision'
270 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/diff',
271 :action => 'diff'
272 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/diff.:format',
267 :action => 'diff'
273 :action => 'diff'
268 repository_views.connect 'projects/:id/repository/show/*path',
274 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/raw/*path',
275 :action => 'entry', :format => 'raw'
276 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/:action/*path',
277 :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
278 repository_views.connect 'projects/:id/repository/:repository_id/raw/*path',
279 :action => 'entry', :format => 'raw'
280 repository_views.connect 'projects/:id/repository/:repository_id/:action/*path',
281 :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
282 repository_views.connect 'projects/:id/repository/:repository_id',
269 :action => 'show'
283 :action => 'show'
270 repository_views.connect 'projects/:id/repository/graph',
271 :action => 'graph'
272 end
284 end
273
285
274 repositories.connect 'projects/:id/repository/revision',
286 repositories.connect 'projects/:id/repository/revision',
@@ -108,6 +108,7 a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
108 a img{ border: 0; }
108 a img{ border: 0; }
109
109
110 a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; }
110 a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; }
111 a.repository.selected {font-weight:bold;}
111
112
112 /***** Tables *****/
113 /***** Tables *****/
113 table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
114 table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
@@ -1,5 +1,5
1 class Repository < ActiveRecord::Base
1 class Repository < ActiveRecord::Base
2 generator_for :type => 'Subversion'
2 generator_for :type => 'Subversion'
3 generator_for :url, :start => 'file:///test/svn'
3 generator_for :url, :start => 'file:///test/svn'
4
4 generator_for :identifier, :start => 'repo1'
5 end
5 end
@@ -7,6 +7,7 repositories_001:
7 password: ""
7 password: ""
8 login: ""
8 login: ""
9 type: Subversion
9 type: Subversion
10 is_default: true
10 repositories_002:
11 repositories_002:
11 project_id: 2
12 project_id: 2
12 url: svn://localhost/test
13 url: svn://localhost/test
@@ -15,3 +16,4 repositories_002:
15 password: ""
16 password: ""
16 login: ""
17 login: ""
17 type: Subversion
18 type: Subversion
19 is_default: true
@@ -43,19 +43,12 class RepositoriesControllerTest < ActionController::TestCase
43 assert_tag 'input', :attributes => {:name => 'repository[url]'}
43 assert_tag 'input', :attributes => {:name => 'repository[url]'}
44 end
44 end
45
45
46 # TODO: remove it when multiple SCM support is added
47 def test_new_with_existing_repository
48 @request.session[:user_id] = 1
49 get :new, :project_id => 'ecookbook'
50 assert_response 302
51 end
52
53 def test_create
46 def test_create
54 @request.session[:user_id] = 1
47 @request.session[:user_id] = 1
55 assert_difference 'Repository.count' do
48 assert_difference 'Repository.count' do
56 post :create, :project_id => 'subproject1',
49 post :create, :project_id => 'subproject1',
57 :repository_scm => 'Subversion',
50 :repository_scm => 'Subversion',
58 :repository => {:url => 'file:///test'}
51 :repository => {:url => 'file:///test', :is_default => '1', :identifier => ''}
59 end
52 end
60 assert_response 302
53 assert_response 302
61 repository = Repository.first(:order => 'id DESC')
54 repository = Repository.first(:order => 'id DESC')
@@ -113,9 +106,25 class RepositoriesControllerTest < ActionController::TestCase
113 get :revisions, :id => 1
106 get :revisions, :id => 1
114 assert_response :success
107 assert_response :success
115 assert_template 'revisions'
108 assert_template 'revisions'
109 assert_equal Repository.find(10), assigns(:repository)
110 assert_not_nil assigns(:changesets)
111 end
112
113 def test_revisions_for_other_repository
114 repository = Repository::Subversion.create!(:project_id => 1, :identifier => 'foo', :url => 'file:///foo')
115
116 get :revisions, :id => 1, :repository_id => 'foo'
117 assert_response :success
118 assert_template 'revisions'
119 assert_equal repository, assigns(:repository)
116 assert_not_nil assigns(:changesets)
120 assert_not_nil assigns(:changesets)
117 end
121 end
118
122
123 def test_revisions_for_invalid_repository
124 get :revisions, :id => 1, :repository_id => 'foo'
125 assert_response 404
126 end
127
119 def test_revision
128 def test_revision
120 get :revision, :id => 1, :rev => 1
129 get :revision, :id => 1, :rev => 1
121 assert_response :success
130 assert_response :success
@@ -70,6 +70,29 class RoutingRepositoriesTest < ActionController::IntegrationTest
70 :path => "/projects/redmine/repository/statistics" },
70 :path => "/projects/redmine/repository/statistics" },
71 { :controller => 'repositories', :action => 'stats', :id => 'redmine' }
71 { :controller => 'repositories', :action => 'stats', :id => 'redmine' }
72 )
72 )
73 assert_routing(
74 { :method => 'get',
75 :path => "/projects/redmine/repository/graph" },
76 { :controller => 'repositories', :action => 'graph', :id => 'redmine' }
77 )
78 end
79
80 def test_repositories_with_repository_id
81 assert_routing(
82 { :method => 'get',
83 :path => "/projects/redmine/repository/foo" },
84 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo' }
85 )
86 assert_routing(
87 { :method => 'get',
88 :path => "/projects/redmine/repository/foo/statistics" },
89 { :controller => 'repositories', :action => 'stats', :id => 'redmine', :repository_id => 'foo' }
90 )
91 assert_routing(
92 { :method => 'get',
93 :path => "/projects/redmine/repository/foo/graph" },
94 { :controller => 'repositories', :action => 'graph', :id => 'redmine', :repository_id => 'foo' }
95 )
73 end
96 end
74
97
75 def test_repositories_revisions
98 def test_repositories_revisions
@@ -153,6 +176,87 class RoutingRepositoriesTest < ActionController::IntegrationTest
153 )
176 )
154 end
177 end
155
178
179 def test_repositories_revisions_with_repository_id
180 empty_path_param = []
181 assert_routing(
182 { :method => 'get',
183 :path => "/projects/redmine/repository/foo/revisions" },
184 { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo' }
185 )
186 assert_routing(
187 { :method => 'get',
188 :path => "/projects/redmine/repository/foo/revisions.atom" },
189 { :controller => 'repositories', :action => 'revisions', :id => 'redmine', :repository_id => 'foo',
190 :format => 'atom' }
191 )
192 assert_routing(
193 { :method => 'get',
194 :path => "/projects/redmine/repository/foo/revisions/2457" },
195 { :controller => 'repositories', :action => 'revision', :id => 'redmine', :repository_id => 'foo',
196 :rev => '2457' }
197 )
198 assert_routing(
199 { :method => 'get',
200 :path => "/projects/redmine/repository/foo/revisions/2457/show" },
201 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
202 :path => empty_path_param, :rev => '2457' }
203 )
204 assert_routing(
205 { :method => 'get',
206 :path => "/projects/redmine/repository/foo/revisions/2457/show/#{@path_hash[:path]}" },
207 { :controller => 'repositories', :action => 'show', :id => 'redmine', :repository_id => 'foo',
208 :path => @path_hash[:param] , :rev => '2457'}
209 )
210 assert_routing(
211 { :method => 'get',
212 :path => "/projects/redmine/repository/foo/revisions/2457/changes" },
213 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
214 :path => empty_path_param, :rev => '2457' }
215 )
216 assert_routing(
217 { :method => 'get',
218 :path => "/projects/redmine/repository/foo/revisions/2457/changes/#{@path_hash[:path]}" },
219 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
220 :path => @path_hash[:param] , :rev => '2457'}
221 )
222 assert_routing(
223 { :method => 'get',
224 :path => "/projects/redmine/repository/foo/revisions/2457/diff" },
225 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
226 :rev => '2457' }
227 )
228 assert_routing(
229 { :method => 'get',
230 :path => "/projects/redmine/repository/foo/revisions/2457/diff.diff" },
231 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
232 :rev => '2457', :format => 'diff' }
233 )
234 assert_routing(
235 { :method => 'get',
236 :path => "/projects/redmine/repository/foo/revisions/2/diff/#{@path_hash[:path]}" },
237 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
238 :path => @path_hash[:param], :rev => '2' }
239 )
240 assert_routing(
241 { :method => 'get',
242 :path => "/projects/redmine/repository/foo/revisions/2/entry/#{@path_hash[:path]}" },
243 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
244 :path => @path_hash[:param], :rev => '2' }
245 )
246 assert_routing(
247 { :method => 'get',
248 :path => "/projects/redmine/repository/foo/revisions/2/raw/#{@path_hash[:path]}" },
249 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
250 :path => @path_hash[:param], :rev => '2', :format => 'raw' }
251 )
252 assert_routing(
253 { :method => 'get',
254 :path => "/projects/redmine/repository/foo/revisions/2/annotate/#{@path_hash[:path]}" },
255 { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
256 :path => @path_hash[:param], :rev => '2' }
257 )
258 end
259
156 def test_repositories_non_revisions_path
260 def test_repositories_non_revisions_path
157 assert_routing(
261 assert_routing(
158 { :method => 'get',
262 { :method => 'get',
@@ -192,6 +296,45 class RoutingRepositoriesTest < ActionController::IntegrationTest
192 )
296 )
193 end
297 end
194
298
299 def test_repositories_non_revisions_path_with_repository_id
300 assert_routing(
301 { :method => 'get',
302 :path => "/projects/redmine/repository/foo/diff/#{@path_hash[:path]}" },
303 { :controller => 'repositories', :action => 'diff', :id => 'redmine', :repository_id => 'foo',
304 :path => @path_hash[:param] }
305 )
306 assert_routing(
307 { :method => 'get',
308 :path => "/projects/redmine/repository/foo/browse/#{@path_hash[:path]}" },
309 { :controller => 'repositories', :action => 'browse', :id => 'redmine', :repository_id => 'foo',
310 :path => @path_hash[:param] }
311 )
312 assert_routing(
313 { :method => 'get',
314 :path => "/projects/redmine/repository/foo/entry/#{@path_hash[:path]}" },
315 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
316 :path => @path_hash[:param] }
317 )
318 assert_routing(
319 { :method => 'get',
320 :path => "/projects/redmine/repository/foo/raw/#{@path_hash[:path]}" },
321 { :controller => 'repositories', :action => 'entry', :id => 'redmine', :repository_id => 'foo',
322 :path => @path_hash[:param], :format => 'raw' }
323 )
324 assert_routing(
325 { :method => 'get',
326 :path => "/projects/redmine/repository/foo/annotate/#{@path_hash[:path]}" },
327 { :controller => 'repositories', :action => 'annotate', :id => 'redmine', :repository_id => 'foo',
328 :path => @path_hash[:param] }
329 )
330 assert_routing(
331 { :method => 'get',
332 :path => "/projects/redmine/repository/foo/changes/#{@path_hash[:path]}" },
333 { :controller => 'repositories', :action => 'changes', :id => 'redmine', :repository_id => 'foo',
334 :path => @path_hash[:param] }
335 )
336 end
337
195 private
338 private
196
339
197 def repository_path_hash(arr)
340 def repository_path_hash(arr)
@@ -50,6 +50,19 class RepositoryTest < ActiveSupport::TestCase
50 assert_equal repository, project.repository
50 assert_equal repository, project.repository
51 end
51 end
52
52
53 def test_first_repository_should_be_set_as_default
54 repository1 = Repository::Subversion.new(:project => Project.find(3), :identifier => 'svn1', :url => 'file:///svn1')
55 assert repository1.save
56 assert repository1.is_default?
57
58 repository2 = Repository::Subversion.new(:project => Project.find(3), :identifier => 'svn2', :url => 'file:///svn2')
59 assert repository2.save
60 assert !repository2.is_default?
61
62 assert_equal repository1, Project.find(3).repository
63 assert_equal [repository1, repository2], Project.find(3).repositories.sort
64 end
65
53 def test_destroy
66 def test_destroy
54 changesets = Changeset.count(:all, :conditions => "repository_id = 10")
67 changesets = Changeset.count(:all, :conditions => "repository_id = 10")
55 changes = Change.count(:all, :conditions => "repository_id = 10",
68 changes = Change.count(:all, :conditions => "repository_id = 10",
@@ -316,9 +316,8 class UserTest < ActiveSupport::TestCase
316
316
317 def test_destroy_should_nullify_changesets
317 def test_destroy_should_nullify_changesets
318 changeset = Changeset.create!(
318 changeset = Changeset.create!(
319 :repository => Repository::Subversion.create!(
319 :repository => Repository::Subversion.generate!(
320 :project_id => 1,
320 :project_id => 1
321 :url => 'file:///var/svn'
322 ),
321 ),
323 :revision => '12',
322 :revision => '12',
324 :committed_on => Time.now,
323 :committed_on => Time.now,
General Comments 0
You need to be logged in to leave comments. Login now