Merged Git support branch (r1200 to r1226).
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1236 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
6fcc512cb7
commit
3a9b0988c7
|
@ -134,7 +134,7 @@ class RepositoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def diff
|
def diff
|
||||||
@rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
|
@rev_to = params[:rev_to]
|
||||||
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
|
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
|
||||||
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
|
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ private
|
||||||
render_404 and return false unless @repository
|
render_404 and return false unless @repository
|
||||||
@path = params[:path].join('/') unless params[:path].nil?
|
@path = params[:path].join('/') unless params[:path].nil?
|
||||||
@path ||= ''
|
@path ||= ''
|
||||||
@rev = params[:rev].to_i if params[:rev]
|
@rev = params[:rev]
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
|
|
|
@ -270,6 +270,7 @@ module ApplicationHelper
|
||||||
# #52 -> Link to issue #52
|
# #52 -> Link to issue #52
|
||||||
# Changesets:
|
# Changesets:
|
||||||
# r52 -> Link to revision 52
|
# r52 -> Link to revision 52
|
||||||
|
# commit:a85130f -> Link to scmid starting with a85130f
|
||||||
# Documents:
|
# Documents:
|
||||||
# document#17 -> Link to document with id 17
|
# document#17 -> Link to document with id 17
|
||||||
# document:Greetings -> Link to the document with title "Greetings"
|
# document:Greetings -> Link to the document with title "Greetings"
|
||||||
|
@ -280,7 +281,7 @@ module ApplicationHelper
|
||||||
# version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
|
# version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
|
||||||
# Attachments:
|
# Attachments:
|
||||||
# attachment:file.zip -> Link to the attachment of the current object named file.zip
|
# attachment:file.zip -> Link to the attachment of the current object named file.zip
|
||||||
text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version)?((#|r)(\d+)|(:)([^"][^\s<>]+|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
|
text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version|commit)?((#|r)(\d+)|(:)([^"][^\s<>]+|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
|
||||||
leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
|
leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
|
||||||
link = nil
|
link = nil
|
||||||
if esc.nil?
|
if esc.nil?
|
||||||
|
@ -325,6 +326,10 @@ module ApplicationHelper
|
||||||
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
|
||||||
:class => 'version'
|
:class => 'version'
|
||||||
end
|
end
|
||||||
|
when 'commit'
|
||||||
|
if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
|
||||||
|
link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project.id, :rev => changeset.revision}, :class => 'changeset', :title => truncate(changeset.comments, 100)
|
||||||
|
end
|
||||||
when 'attachment'
|
when 'attachment'
|
||||||
if attachments && attachment = attachments.detect {|a| a.filename == name }
|
if attachments && attachment = attachments.detect {|a| a.filename == name }
|
||||||
link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
|
link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
|
||||||
|
|
|
@ -25,6 +25,10 @@ module RepositoriesHelper
|
||||||
type ? CodeRay.scan(content, type).html : h(content)
|
type ? CodeRay.scan(content, type).html : h(content)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_revision(txt)
|
||||||
|
txt.to_s[0,8]
|
||||||
|
end
|
||||||
|
|
||||||
def to_utf8(str)
|
def to_utf8(str)
|
||||||
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
||||||
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
|
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
|
||||||
|
@ -76,6 +80,10 @@ module RepositoriesHelper
|
||||||
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def git_field_tags(form, repository)
|
||||||
|
content_tag('p', form.text_field(:url, :label => 'Path to .git directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
||||||
|
end
|
||||||
|
|
||||||
def cvs_field_tags(form, repository)
|
def cvs_field_tags(form, repository)
|
||||||
content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) +
|
content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) +
|
||||||
content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?))
|
content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?))
|
||||||
|
|
|
@ -32,7 +32,6 @@ class Changeset < ActiveRecord::Base
|
||||||
:date_column => 'committed_on'
|
:date_column => 'committed_on'
|
||||||
|
|
||||||
validates_presence_of :repository_id, :revision, :committed_on, :commit_date
|
validates_presence_of :repository_id, :revision, :committed_on, :commit_date
|
||||||
validates_numericality_of :revision, :only_integer => true
|
|
||||||
validates_uniqueness_of :revision, :scope => :repository_id
|
validates_uniqueness_of :revision, :scope => :repository_id
|
||||||
validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
|
validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
|
||||||
|
|
||||||
|
@ -89,7 +88,11 @@ class Changeset < ActiveRecord::Base
|
||||||
# don't change the status is the issue is closed
|
# don't change the status is the issue is closed
|
||||||
next if issue.status.is_closed?
|
next if issue.status.is_closed?
|
||||||
user = committer_user || User.anonymous
|
user = committer_user || User.anonymous
|
||||||
journal = issue.init_journal(user, l(:text_status_changed_by_changeset, "r#{self.revision}"))
|
csettext = "r#{self.revision}"
|
||||||
|
if self.scmid && (! (csettext =~ /^r[0-9]+$/))
|
||||||
|
csettext = "commit:\"#{self.scmid}\""
|
||||||
|
end
|
||||||
|
journal = issue.init_journal(user, l(:text_status_changed_by_changeset, csettext))
|
||||||
issue.status = fix_status
|
issue.status = fix_status
|
||||||
issue.done_ratio = done_ratio if done_ratio
|
issue.done_ratio = done_ratio if done_ratio
|
||||||
issue.save
|
issue.save
|
||||||
|
@ -114,11 +117,11 @@ class Changeset < ActiveRecord::Base
|
||||||
|
|
||||||
# Returns the previous changeset
|
# Returns the previous changeset
|
||||||
def previous
|
def previous
|
||||||
@previous ||= Changeset.find(:first, :conditions => ['revision < ? AND repository_id = ?', self.revision, self.repository_id], :order => 'revision DESC')
|
@previous ||= Changeset.find(:first, :conditions => ['id < ? AND repository_id = ?', self.id, self.repository_id], :order => 'id DESC')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the next changeset
|
# Returns the next changeset
|
||||||
def next
|
def next
|
||||||
@next ||= Changeset.find(:first, :conditions => ['revision > ? AND repository_id = ?', self.revision, self.repository_id], :order => 'revision ASC')
|
@next ||= Changeset.find(:first, :conditions => ['id > ? AND repository_id = ?', self.id, self.repository_id], :order => 'id ASC')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
class Repository < ActiveRecord::Base
|
class Repository < ActiveRecord::Base
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
has_many :changesets, :dependent => :destroy, :order => "#{Changeset.table_name}.revision DESC"
|
has_many :changesets, :dependent => :destroy, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
|
||||||
has_many :changes, :through => :changesets
|
has_many :changes, :through => :changesets
|
||||||
|
|
||||||
def scm
|
def scm
|
||||||
|
@ -51,7 +51,7 @@ class Repository < ActiveRecord::Base
|
||||||
path = "/#{path}" unless path.starts_with?('/')
|
path = "/#{path}" unless path.starts_with?('/')
|
||||||
Change.find(:all, :include => :changeset,
|
Change.find(:all, :include => :changeset,
|
||||||
:conditions => ["repository_id = ? AND path = ?", id, path],
|
:conditions => ["repository_id = ? AND path = ?", id, path],
|
||||||
:order => "committed_on DESC, #{Changeset.table_name}.revision DESC").collect(&:changeset)
|
:order => "committed_on DESC, #{Changeset.table_name}.id DESC").collect(&:changeset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def latest_changeset
|
def latest_changeset
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Repository::Bazaar < Repository
|
||||||
scm_info = scm.info
|
scm_info = scm.info
|
||||||
if scm_info
|
if scm_info
|
||||||
# latest revision found in database
|
# latest revision found in database
|
||||||
db_revision = latest_changeset ? latest_changeset.revision : 0
|
db_revision = latest_changeset ? latest_changeset.revision.to_i : 0
|
||||||
# latest revision in the repository
|
# latest revision in the repository
|
||||||
scm_revision = scm_info.lastrev.identifier.to_i
|
scm_revision = scm_info.lastrev.identifier.to_i
|
||||||
if db_revision < scm_revision
|
if db_revision < scm_revision
|
||||||
|
|
|
@ -82,9 +82,6 @@ class Repository::Cvs < Repository
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_changesets
|
def fetch_changesets
|
||||||
#not the preferred way with CVS. maybe we should introduce always a cron-job for this
|
|
||||||
last_commit = changesets.maximum(:committed_on)
|
|
||||||
|
|
||||||
# some nifty bits to introduce a commit-id with cvs
|
# some nifty bits to introduce a commit-id with cvs
|
||||||
# natively cvs doesn't provide any kind of changesets, there is only a revision per file.
|
# natively cvs doesn't provide any kind of changesets, there is only a revision per file.
|
||||||
# we now take a guess using the author, the commitlog and the commit-date.
|
# we now take a guess using the author, the commitlog and the commit-date.
|
||||||
|
@ -94,8 +91,10 @@ class Repository::Cvs < Repository
|
||||||
# we use a small delta here, to merge all changes belonging to _one_ changeset
|
# we use a small delta here, to merge all changes belonging to _one_ changeset
|
||||||
time_delta=10.seconds
|
time_delta=10.seconds
|
||||||
|
|
||||||
|
fetch_since = latest_changeset ? latest_changeset.committed_on : nil
|
||||||
transaction do
|
transaction do
|
||||||
scm.revisions('', last_commit, nil, :with_paths => true) do |revision|
|
tmp_rev_num = 1
|
||||||
|
scm.revisions('', fetch_since, nil, :with_paths => true) do |revision|
|
||||||
# only add the change to the database, if it doen't exists. the cvs log
|
# only add the change to the database, if it doen't exists. the cvs log
|
||||||
# is not exclusive at all.
|
# is not exclusive at all.
|
||||||
unless changes.find_by_path_and_revision(scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
|
unless changes.find_by_path_and_revision(scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
|
||||||
|
@ -108,17 +107,15 @@ class Repository::Cvs < Repository
|
||||||
|
|
||||||
# create a new changeset....
|
# create a new changeset....
|
||||||
unless cs
|
unless cs
|
||||||
# we use a negative changeset-number here (just for inserting)
|
# we use a temporaray revision number here (just for inserting)
|
||||||
# later on, we calculate a continous positive number
|
# later on, we calculate a continous positive number
|
||||||
next_rev = changesets.minimum(:revision)
|
latest = changesets.find(:first, :order => 'id DESC')
|
||||||
next_rev = 0 if next_rev.nil? or next_rev > 0
|
|
||||||
next_rev = next_rev - 1
|
|
||||||
|
|
||||||
cs = Changeset.create(:repository => self,
|
cs = Changeset.create(:repository => self,
|
||||||
:revision => next_rev,
|
:revision => "_#{tmp_rev_num}",
|
||||||
:committer => revision.author,
|
:committer => revision.author,
|
||||||
:committed_on => revision.time,
|
:committed_on => revision.time,
|
||||||
:comments => revision.message)
|
:comments => revision.message)
|
||||||
|
tmp_rev_num += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
#convert CVS-File-States to internal Action-abbrevations
|
#convert CVS-File-States to internal Action-abbrevations
|
||||||
|
@ -139,12 +136,13 @@ class Repository::Cvs < Repository
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
next_rev = [changesets.maximum(:revision) || 0, 0].max
|
# Renumber new changesets in chronological order
|
||||||
changesets.find(:all, :conditions=>["revision < 0"], :order=>"committed_on ASC").each() do |changeset|
|
c = changesets.find(:first, :order => 'committed_on DESC, id DESC', :conditions => "revision NOT LIKE '_%'")
|
||||||
next_rev = next_rev + 1
|
next_rev = c.nil? ? 1 : (c.revision.to_i + 1)
|
||||||
changeset.revision = next_rev
|
changesets.find(:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE '_%'").each do |changeset|
|
||||||
changeset.save!
|
changeset.update_attribute :revision, next_rev
|
||||||
end
|
next_rev += 1
|
||||||
end
|
end
|
||||||
|
end # transaction
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,18 +47,19 @@ class Repository::Darcs < Repository
|
||||||
|
|
||||||
def diff(path, rev, rev_to, type)
|
def diff(path, rev, rev_to, type)
|
||||||
patch_from = changesets.find_by_revision(rev)
|
patch_from = changesets.find_by_revision(rev)
|
||||||
|
return nil if patch_from.nil?
|
||||||
patch_to = changesets.find_by_revision(rev_to) if rev_to
|
patch_to = changesets.find_by_revision(rev_to) if rev_to
|
||||||
if path.blank?
|
if path.blank?
|
||||||
path = patch_from.changes.collect{|change| change.path}.join(' ')
|
path = patch_from.changes.collect{|change| change.path}.join(' ')
|
||||||
end
|
end
|
||||||
scm.diff(path, patch_from.scmid, patch_to.scmid, type)
|
patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil, type) : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_changesets
|
def fetch_changesets
|
||||||
scm_info = scm.info
|
scm_info = scm.info
|
||||||
if scm_info
|
if scm_info
|
||||||
db_last_id = latest_changeset ? latest_changeset.scmid : nil
|
db_last_id = latest_changeset ? latest_changeset.scmid : nil
|
||||||
next_rev = latest_changeset ? latest_changeset.revision + 1 : 1
|
next_rev = latest_changeset ? latest_changeset.revision.to_i + 1 : 1
|
||||||
# latest revision in the repository
|
# latest revision in the repository
|
||||||
scm_revision = scm_info.lastrev.scmid
|
scm_revision = scm_info.lastrev.scmid
|
||||||
unless changesets.find_by_scmid(scm_revision)
|
unless changesets.find_by_scmid(scm_revision)
|
||||||
|
@ -72,8 +73,6 @@ class Repository::Darcs < Repository
|
||||||
:committed_on => revision.time,
|
:committed_on => revision.time,
|
||||||
:comments => revision.message)
|
:comments => revision.message)
|
||||||
|
|
||||||
next if changeset.new_record?
|
|
||||||
|
|
||||||
revision.paths.each do |change|
|
revision.paths.each do |change|
|
||||||
Change.create(:changeset => changeset,
|
Change.create(:changeset => changeset,
|
||||||
:action => change[:action],
|
:action => change[:action],
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||||
|
# Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require 'redmine/scm/adapters/git_adapter'
|
||||||
|
|
||||||
|
class Repository::Git < Repository
|
||||||
|
attr_protected :root_url
|
||||||
|
validates_presence_of :url
|
||||||
|
|
||||||
|
def scm_adapter
|
||||||
|
Redmine::Scm::Adapters::GitAdapter
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.scm_name
|
||||||
|
'Git'
|
||||||
|
end
|
||||||
|
|
||||||
|
def changesets_for_path(path)
|
||||||
|
Change.find(:all, :include => :changeset,
|
||||||
|
:conditions => ["repository_id = ? AND path = ?", id, path],
|
||||||
|
:order => "committed_on DESC, #{Changeset.table_name}.revision DESC").collect(&:changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_changesets
|
||||||
|
scm_info = scm.info
|
||||||
|
if scm_info
|
||||||
|
# latest revision found in database
|
||||||
|
db_revision = latest_changeset ? latest_changeset.revision : nil
|
||||||
|
# latest revision in the repository
|
||||||
|
scm_revision = scm_info.lastrev.scmid
|
||||||
|
|
||||||
|
unless changesets.find_by_scmid(scm_revision)
|
||||||
|
|
||||||
|
revisions = scm.revisions('', db_revision, nil)
|
||||||
|
transaction do
|
||||||
|
revisions.reverse_each do |revision|
|
||||||
|
changeset = Changeset.create(:repository => self,
|
||||||
|
:revision => revision.identifier,
|
||||||
|
:scmid => revision.scmid,
|
||||||
|
:committer => revision.author,
|
||||||
|
:committed_on => revision.time,
|
||||||
|
:comments => revision.message)
|
||||||
|
|
||||||
|
revision.paths.each do |change|
|
||||||
|
Change.create(:changeset => changeset,
|
||||||
|
:action => change[:action],
|
||||||
|
:path => change[:path],
|
||||||
|
:from_path => change[:from_path],
|
||||||
|
:from_revision => change[:from_revision])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -39,7 +39,7 @@ class Repository::Subversion < Repository
|
||||||
scm_info = scm.info
|
scm_info = scm.info
|
||||||
if scm_info
|
if scm_info
|
||||||
# latest revision found in database
|
# latest revision found in database
|
||||||
db_revision = latest_changeset ? latest_changeset.revision : 0
|
db_revision = latest_changeset ? latest_changeset.revision.to_i : 0
|
||||||
# latest revision in the repository
|
# latest revision in the repository
|
||||||
scm_revision = scm_info.lastrev.identifier.to_i
|
scm_revision = scm_info.lastrev.identifier.to_i
|
||||||
if db_revision < scm_revision
|
if db_revision < scm_revision
|
||||||
|
|
|
@ -23,7 +23,7 @@ else
|
||||||
end %>
|
end %>
|
||||||
</td>
|
</td>
|
||||||
<td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td>
|
<td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td>
|
||||||
<td class="revision"><%= link_to(entry.lastrev.name, :action => 'revision', :id => @project, :rev => entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %></td>
|
<td class="revision"><%= link_to(format_revision(entry.lastrev.name), :action => 'revision', :id => @project, :rev => entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %></td>
|
||||||
<td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td>
|
<td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td>
|
||||||
<td class="author"><%=h(entry.lastrev.author.to_s.split('<').first) if entry.lastrev %></td>
|
<td class="author"><%=h(entry.lastrev.author.to_s.split('<').first) if entry.lastrev %></td>
|
||||||
<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev %>
|
<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev %>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<% line_num = 1 %>
|
<% line_num = 1 %>
|
||||||
<% revisions.each do |changeset| %>
|
<% revisions.each do |changeset| %>
|
||||||
<tr class="changeset <%= cycle 'odd', 'even' %>">
|
<tr class="changeset <%= cycle 'odd', 'even' %>">
|
||||||
<td class="id"><%= link_to changeset.revision, :action => 'revision', :id => project, :rev => changeset.revision %></td>
|
<td class="id"><%= link_to format_revision(changeset.revision), :action => 'revision', :id => project, :rev => changeset.revision %></td>
|
||||||
<td class="checkbox"><%= radio_button_tag('rev', changeset.revision, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td>
|
<td class="checkbox"><%= radio_button_tag('rev', changeset.revision, (line_num==1), :id => "cb-#{line_num}", :onclick => "$('cbto-#{line_num+1}').checked=true;") if show_diff && (line_num < revisions.size) %></td>
|
||||||
<td class="checkbox"><%= radio_button_tag('rev_to', changeset.revision, (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>
|
<td class="checkbox"><%= radio_button_tag('rev_to', changeset.revision, (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>
|
||||||
<td class="committed_on"><%= format_time(changeset.committed_on) %></td>
|
<td class="committed_on"><%= format_time(changeset.committed_on) %></td>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
|
<tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
|
||||||
<th class="line-num"><%= line_num %></th>
|
<th class="line-num"><%= line_num %></th>
|
||||||
<td class="revision">
|
<td class="revision">
|
||||||
<%= (revision.identifier ? link_to(revision.identifier, :action => 'revision', :id => @project, :rev => revision.identifier) : revision.revision) if revision %></td>
|
<%= (revision.identifier ? link_to(format_revision(revision.identifier), :action => 'revision', :id => @project, :rev => revision.identifier) : format_revision(revision.revision)) if revision %></td>
|
||||||
<td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td>
|
<td class="author"><%= h(revision.author.to_s.split('<').first) if revision %></td>
|
||||||
<td class="line-code"><pre><%= line %></pre></td>
|
<td class="line-code"><pre><%= line %></pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<h2><%= l(:label_revision) %> <%= @rev %>: <%= @path.gsub(/^.*\//, '') %></h2>
|
<h2><%= l(:label_revision) %> <%= format_revision(@rev) %> <%= @path.gsub(/^.*\//, '') %></h2>
|
||||||
|
|
||||||
<!-- Choose view type -->
|
<!-- Choose view type -->
|
||||||
<% form_tag({ :controller => 'repositories', :action => 'diff'}, :method => 'get') do %>
|
<% form_tag({ :controller => 'repositories', :action => 'diff'}, :method => 'get') do %>
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">@<%= @rev %></th>
|
<th colspan="2">@<%= format_revision @rev %></th>
|
||||||
<th colspan="2">@<%= @rev_to %></th>
|
<th colspan="2">@<%= format_revision @rev_to %></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -56,8 +56,8 @@
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>@<%= @rev %></th>
|
<th>@<%= format_revision @rev %></th>
|
||||||
<th>@<%= @rev_to %></th>
|
<th>@<%= format_revision @rev_to %></th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2><%= l(:label_revision) %> <%= @changeset.revision %></h2>
|
<h2><%= l(:label_revision) %> <%= format_revision(@changeset.revision) %></h2>
|
||||||
|
|
||||||
<p><% if @changeset.scmid %>ID: <%= @changeset.scmid %><br /><% end %>
|
<p><% if @changeset.scmid %>ID: <%= @changeset.scmid %><br /><% end %>
|
||||||
<em><%= @changeset.committer.to_s.split('<').first %>, <%= format_time(@changeset.committed_on) %></em></p>
|
<em><%= @changeset.committer.to_s.split('<').first %>, <%= format_time(@changeset.committed_on) %></em></p>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class ChangeChangesetsRevisionToString < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
change_column :changesets, :revision, :string, :null => false
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
change_column :changesets, :revision, :integer, :null => false
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
class ChangeChangesFromRevisionToString < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
change_column :changes, :from_revision, :string
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
change_column :changes, :from_revision, :integer
|
||||||
|
end
|
||||||
|
end
|
|
@ -19,3 +19,19 @@ gunzip < test/fixtures/repositories/bazaar_repository.tar.gz | tar -xv -C tmp/te
|
||||||
Mercurial
|
Mercurial
|
||||||
---------
|
---------
|
||||||
gunzip < test/fixtures/repositories/mercurial_repository.tar.gz | tar -xv -C tmp/test
|
gunzip < test/fixtures/repositories/mercurial_repository.tar.gz | tar -xv -C tmp/test
|
||||||
|
|
||||||
|
Git
|
||||||
|
---
|
||||||
|
gunzip < test/fixtures/repositories/git_repository.tar.gz | tar -xv -C tmp/test
|
||||||
|
|
||||||
|
|
||||||
|
Running Tests
|
||||||
|
=============
|
||||||
|
|
||||||
|
Run
|
||||||
|
|
||||||
|
rake --tasks | grep test
|
||||||
|
|
||||||
|
to see available tests.
|
||||||
|
|
||||||
|
RAILS_ENV=test rake test will run tests.
|
||||||
|
|
|
@ -10,7 +10,7 @@ rescue LoadError
|
||||||
# RMagick is not available
|
# RMagick is not available
|
||||||
end
|
end
|
||||||
|
|
||||||
REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar )
|
REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git )
|
||||||
|
|
||||||
# Permissions
|
# Permissions
|
||||||
Redmine::AccessControl.map do |map|
|
Redmine::AccessControl.map do |map|
|
||||||
|
|
|
@ -102,8 +102,12 @@ module Redmine
|
||||||
def diff(path, identifier_from, identifier_to=nil, type="inline")
|
def diff(path, identifier_from, identifier_to=nil, type="inline")
|
||||||
path = '*' if path.blank?
|
path = '*' if path.blank?
|
||||||
cmd = "#{DARCS_BIN} diff --repodir #{@url}"
|
cmd = "#{DARCS_BIN} diff --repodir #{@url}"
|
||||||
|
if identifier_to.nil?
|
||||||
|
cmd << " --match \"hash #{identifier_from}\""
|
||||||
|
else
|
||||||
cmd << " --to-match \"hash #{identifier_from}\""
|
cmd << " --to-match \"hash #{identifier_from}\""
|
||||||
cmd << " --from-match \"hash #{identifier_to}\"" if identifier_to
|
cmd << " --from-match \"hash #{identifier_to}\""
|
||||||
|
end
|
||||||
cmd << " -u #{path}"
|
cmd << " -u #{path}"
|
||||||
diff = []
|
diff = []
|
||||||
shellout(cmd) do |io|
|
shellout(cmd) do |io|
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require 'redmine/scm/adapters/abstract_adapter'
|
||||||
|
|
||||||
|
module Redmine
|
||||||
|
module Scm
|
||||||
|
module Adapters
|
||||||
|
class GitAdapter < AbstractAdapter
|
||||||
|
|
||||||
|
# Git executable name
|
||||||
|
GIT_BIN = "git"
|
||||||
|
|
||||||
|
# Get the revision of a particuliar file
|
||||||
|
def get_rev (rev,path)
|
||||||
|
cmd="git --git-dir #{target('')} show #{shell_quote rev} -- #{shell_quote path}" if rev!='latest' and (! rev.nil?)
|
||||||
|
cmd="git --git-dir #{target('')} log -1 master -- #{shell_quote path}" if
|
||||||
|
rev=='latest' or rev.nil?
|
||||||
|
rev=[]
|
||||||
|
i=0
|
||||||
|
shellout(cmd) do |io|
|
||||||
|
files=[]
|
||||||
|
changeset = {}
|
||||||
|
parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
|
||||||
|
|
||||||
|
io.each_line do |line|
|
||||||
|
if line =~ /^commit ([0-9a-f]{40})$/
|
||||||
|
key = "commit"
|
||||||
|
value = $1
|
||||||
|
if (parsing_descr == 1 || parsing_descr == 2)
|
||||||
|
parsing_descr = 0
|
||||||
|
rev = Revision.new({:identifier => changeset[:commit],
|
||||||
|
:scmid => changeset[:commit],
|
||||||
|
:author => changeset[:author],
|
||||||
|
:time => Time.parse(changeset[:date]),
|
||||||
|
:message => changeset[:description],
|
||||||
|
:paths => files
|
||||||
|
})
|
||||||
|
changeset = {}
|
||||||
|
files = []
|
||||||
|
end
|
||||||
|
changeset[:commit] = $1
|
||||||
|
elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
|
||||||
|
key = $1
|
||||||
|
value = $2
|
||||||
|
if key == "Author"
|
||||||
|
changeset[:author] = value
|
||||||
|
elsif key == "Date"
|
||||||
|
changeset[:date] = value
|
||||||
|
end
|
||||||
|
elsif (parsing_descr == 0) && line.chomp.to_s == ""
|
||||||
|
parsing_descr = 1
|
||||||
|
changeset[:description] = ""
|
||||||
|
elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/
|
||||||
|
parsing_descr = 2
|
||||||
|
fileaction = $1
|
||||||
|
filepath = $2
|
||||||
|
files << {:action => fileaction, :path => filepath}
|
||||||
|
elsif (parsing_descr == 1) && line.chomp.to_s == ""
|
||||||
|
parsing_descr = 2
|
||||||
|
elsif (parsing_descr == 1)
|
||||||
|
changeset[:description] << line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rev = Revision.new({:identifier => changeset[:commit],
|
||||||
|
:scmid => changeset[:commit],
|
||||||
|
:author => changeset[:author],
|
||||||
|
:time => Time.parse(changeset[:date]),
|
||||||
|
:message => changeset[:description],
|
||||||
|
:paths => files
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
get_rev('latest',path) if rev == []
|
||||||
|
|
||||||
|
return nil if $? && $?.exitstatus != 0
|
||||||
|
return rev
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def info
|
||||||
|
root_url = target('')
|
||||||
|
info = Info.new({:root_url => target(''),
|
||||||
|
:lastrev => revisions(root_url,nil,nil,{:limit => 1}).first
|
||||||
|
})
|
||||||
|
info
|
||||||
|
rescue Errno::ENOENT => e
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def entries(path=nil, identifier=nil)
|
||||||
|
path ||= ''
|
||||||
|
entries = Entries.new
|
||||||
|
cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l "
|
||||||
|
cmd << shell_quote("HEAD:" + path) if identifier.nil?
|
||||||
|
cmd << shell_quote(identifier + ":" + path) if identifier
|
||||||
|
shellout(cmd) do |io|
|
||||||
|
io.each_line do |line|
|
||||||
|
e = line.chomp.to_s
|
||||||
|
if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\s+(.+)$/
|
||||||
|
type = $1
|
||||||
|
sha = $2
|
||||||
|
size = $3
|
||||||
|
name = $4
|
||||||
|
entries << Entry.new({:name => name,
|
||||||
|
:path => (path.empty? ? name : "#{path}/#{name}"),
|
||||||
|
:kind => ((type == "tree") ? 'dir' : 'file'),
|
||||||
|
:size => ((type == "tree") ? nil : size),
|
||||||
|
:lastrev => get_rev(identifier,(path.empty? ? name : "#{path}/#{name}"))
|
||||||
|
|
||||||
|
}) unless entries.detect{|entry| entry.name == name}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil if $? && $?.exitstatus != 0
|
||||||
|
entries.sort_by_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def entry(path=nil, identifier=nil)
|
||||||
|
path ||= ''
|
||||||
|
search_path = path.split('/')[0..-2].join('/')
|
||||||
|
entry_name = path.split('/').last
|
||||||
|
e = entries(search_path, identifier)
|
||||||
|
e ? e.detect{|entry| entry.name == entry_name} : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def revisions(path, identifier_from, identifier_to, options={})
|
||||||
|
revisions = Revisions.new
|
||||||
|
cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw "
|
||||||
|
cmd << " -n #{options[:limit].to_i} " if (!options.nil?) && options[:limit]
|
||||||
|
cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from
|
||||||
|
cmd << " #{shell_quote identifier_to} " if identifier_to
|
||||||
|
#cmd << " HEAD " if !identifier_to
|
||||||
|
shellout(cmd) do |io|
|
||||||
|
files=[]
|
||||||
|
changeset = {}
|
||||||
|
parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
|
||||||
|
revno = 1
|
||||||
|
|
||||||
|
io.each_line do |line|
|
||||||
|
if line =~ /^commit ([0-9a-f]{40})$/
|
||||||
|
key = "commit"
|
||||||
|
value = $1
|
||||||
|
if (parsing_descr == 1 || parsing_descr == 2)
|
||||||
|
parsing_descr = 0
|
||||||
|
revisions << Revision.new({:identifier => changeset[:commit],
|
||||||
|
:scmid => changeset[:commit],
|
||||||
|
:author => changeset[:author],
|
||||||
|
:time => Time.parse(changeset[:date]),
|
||||||
|
:message => changeset[:description],
|
||||||
|
:paths => files
|
||||||
|
})
|
||||||
|
changeset = {}
|
||||||
|
files = []
|
||||||
|
revno = revno + 1
|
||||||
|
end
|
||||||
|
changeset[:commit] = $1
|
||||||
|
elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
|
||||||
|
key = $1
|
||||||
|
value = $2
|
||||||
|
if key == "Author"
|
||||||
|
changeset[:author] = value
|
||||||
|
elsif key == "Date"
|
||||||
|
changeset[:date] = value
|
||||||
|
end
|
||||||
|
elsif (parsing_descr == 0) && line.chomp.to_s == ""
|
||||||
|
parsing_descr = 1
|
||||||
|
changeset[:description] = ""
|
||||||
|
elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/
|
||||||
|
parsing_descr = 2
|
||||||
|
fileaction = $1
|
||||||
|
filepath = $2
|
||||||
|
files << {:action => fileaction, :path => filepath}
|
||||||
|
elsif (parsing_descr == 1) && line.chomp.to_s == ""
|
||||||
|
parsing_descr = 2
|
||||||
|
elsif (parsing_descr == 1)
|
||||||
|
changeset[:description] << line[4..-1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
revisions << Revision.new({:identifier => changeset[:commit],
|
||||||
|
:scmid => changeset[:commit],
|
||||||
|
:author => changeset[:author],
|
||||||
|
:time => Time.parse(changeset[:date]),
|
||||||
|
:message => changeset[:description],
|
||||||
|
:paths => files
|
||||||
|
}) if changeset[:commit]
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil if $? && $?.exitstatus != 0
|
||||||
|
revisions
|
||||||
|
end
|
||||||
|
|
||||||
|
def diff(path, identifier_from, identifier_to=nil, type="inline")
|
||||||
|
path ||= ''
|
||||||
|
if !identifier_to
|
||||||
|
identifier_to = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd = "#{GIT_BIN} --git-dir #{target('')} show #{shell_quote identifier_from}" if identifier_to.nil?
|
||||||
|
cmd = "#{GIT_BIN} --git-dir #{target('')} diff #{shell_quote identifier_to} #{shell_quote identifier_from}" if !identifier_to.nil?
|
||||||
|
cmd << " -- #{shell_quote path}" unless path.empty?
|
||||||
|
diff = []
|
||||||
|
shellout(cmd) do |io|
|
||||||
|
io.each_line do |line|
|
||||||
|
diff << line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil if $? && $?.exitstatus != 0
|
||||||
|
DiffTableList.new diff, type
|
||||||
|
end
|
||||||
|
|
||||||
|
def annotate(path, identifier=nil)
|
||||||
|
identifier = 'HEAD' if identifier.blank?
|
||||||
|
cmd = "#{GIT_BIN} --git-dir #{target('')} blame -l #{shell_quote identifier} -- #{shell_quote path}"
|
||||||
|
blame = Annotate.new
|
||||||
|
shellout(cmd) do |io|
|
||||||
|
io.each_line do |line|
|
||||||
|
next unless line =~ /([0-9a-f]{39,40})\s\((\w*)[^\)]*\)(.*)$/
|
||||||
|
blame.add_line($3.rstrip, Revision.new(:identifier => $1, :author => $2.strip))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil if $? && $?.exitstatus != 0
|
||||||
|
blame
|
||||||
|
end
|
||||||
|
|
||||||
|
def cat(path, identifier=nil)
|
||||||
|
if identifier.nil?
|
||||||
|
identifier = 'HEAD'
|
||||||
|
end
|
||||||
|
cmd = "#{GIT_BIN} --git-dir #{target('')} show #{shell_quote(identifier + ':' + path)}"
|
||||||
|
cat = nil
|
||||||
|
shellout(cmd) do |io|
|
||||||
|
io.binmode
|
||||||
|
cat = io.read
|
||||||
|
end
|
||||||
|
return nil if $? && $?.exitstatus != 0
|
||||||
|
cat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,94 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
require 'repositories_controller'
|
||||||
|
|
||||||
|
# Re-raise errors caught by the controller.
|
||||||
|
class RepositoriesController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
|
class RepositoriesDarcsControllerTest < Test::Unit::TestCase
|
||||||
|
fixtures :projects, :users, :roles, :members, :repositories, :enabled_modules
|
||||||
|
|
||||||
|
# No '..' in the repository path
|
||||||
|
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/darcs_repository'
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@controller = RepositoriesController.new
|
||||||
|
@request = ActionController::TestRequest.new
|
||||||
|
@response = ActionController::TestResponse.new
|
||||||
|
User.current = nil
|
||||||
|
Repository::Darcs.create(:project => Project.find(3), :url => REPOSITORY_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.directory?(REPOSITORY_PATH)
|
||||||
|
def test_show
|
||||||
|
get :show, :id => 3
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'show'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_not_nil assigns(:changesets)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_browse_root
|
||||||
|
get :browse, :id => 3
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'browse'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_equal 3, assigns(:entries).size
|
||||||
|
assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
|
||||||
|
assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
|
||||||
|
assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_browse_directory
|
||||||
|
get :browse, :id => 3, :path => ['images']
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'browse'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_equal 2, assigns(:entries).size
|
||||||
|
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||||
|
assert_not_nil entry
|
||||||
|
assert_equal 'file', entry.kind
|
||||||
|
assert_equal 'images/edit.png', entry.path
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_changes
|
||||||
|
get :changes, :id => 3, :path => ['images', 'edit.png']
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'changes'
|
||||||
|
assert_tag :tag => 'h2', :content => 'edit.png'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_diff
|
||||||
|
Project.find(3).repository.fetch_changesets
|
||||||
|
# Full diff of changeset 5
|
||||||
|
get :diff, :id => 3, :rev => 5
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'diff'
|
||||||
|
# Line 22 removed
|
||||||
|
assert_tag :tag => 'th',
|
||||||
|
:content => /22/,
|
||||||
|
:sibling => { :tag => 'td',
|
||||||
|
:attributes => { :class => /diff_out/ },
|
||||||
|
:content => /def remove/ }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Darcs test repository NOT FOUND. Skipping functional tests !!!"
|
||||||
|
def test_fake; assert true end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,123 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
require 'repositories_controller'
|
||||||
|
|
||||||
|
# Re-raise errors caught by the controller.
|
||||||
|
class RepositoriesController; def rescue_action(e) raise e end; end
|
||||||
|
|
||||||
|
class RepositoriesGitControllerTest < Test::Unit::TestCase
|
||||||
|
fixtures :projects, :users, :roles, :members, :repositories, :enabled_modules
|
||||||
|
|
||||||
|
# No '..' in the repository path
|
||||||
|
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository'
|
||||||
|
REPOSITORY_PATH.gsub!(/\//, "\\") if RUBY_PLATFORM =~ /mswin/
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@controller = RepositoriesController.new
|
||||||
|
@request = ActionController::TestRequest.new
|
||||||
|
@response = ActionController::TestResponse.new
|
||||||
|
User.current = nil
|
||||||
|
Repository::Git.create(:project => Project.find(3), :url => REPOSITORY_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.directory?(REPOSITORY_PATH)
|
||||||
|
def test_show
|
||||||
|
get :show, :id => 3
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'show'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_not_nil assigns(:changesets)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_browse_root
|
||||||
|
get :browse, :id => 3
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'browse'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_equal 3, assigns(:entries).size
|
||||||
|
assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
|
||||||
|
assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
|
||||||
|
assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_browse_directory
|
||||||
|
get :browse, :id => 3, :path => ['images']
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'browse'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_equal 2, assigns(:entries).size
|
||||||
|
entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
|
||||||
|
assert_not_nil entry
|
||||||
|
assert_equal 'file', entry.kind
|
||||||
|
assert_equal 'images/edit.png', entry.path
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_changes
|
||||||
|
get :changes, :id => 3, :path => ['images', 'edit.png']
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'changes'
|
||||||
|
assert_tag :tag => 'h2', :content => 'edit.png'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entry_show
|
||||||
|
get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb']
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'entry'
|
||||||
|
# Line 19
|
||||||
|
assert_tag :tag => 'th',
|
||||||
|
:content => /10/,
|
||||||
|
:attributes => { :class => /line-num/ },
|
||||||
|
:sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_entry_download
|
||||||
|
get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb'], :format => 'raw'
|
||||||
|
assert_response :success
|
||||||
|
# File content
|
||||||
|
assert @response.body.include?('WITHOUT ANY WARRANTY')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_diff
|
||||||
|
# Full diff of changeset 2f9c0091
|
||||||
|
get :diff, :id => 3, :rev => '2f9c0091c754a91af7a9c478e36556b4bde8dcf7'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'diff'
|
||||||
|
# Line 22 removed
|
||||||
|
assert_tag :tag => 'th',
|
||||||
|
:content => /22/,
|
||||||
|
:sibling => { :tag => 'td',
|
||||||
|
:attributes => { :class => /diff_out/ },
|
||||||
|
:content => /def remove/ }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_annotate
|
||||||
|
get :annotate, :id => 3, :path => ['sources', 'watchers_controller.rb']
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'annotate'
|
||||||
|
# Line 23, changeset 2f9c0091
|
||||||
|
assert_tag :tag => 'th', :content => /23/,
|
||||||
|
:sibling => { :tag => 'td', :child => { :tag => 'a', :content => /2f9c0091/ } },
|
||||||
|
:sibling => { :tag => 'td', :content => /jsmith/ },
|
||||||
|
:sibling => { :tag => 'td', :content => /watcher =/ }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Git test repository NOT FOUND. Skipping functional tests !!!"
|
||||||
|
def test_fake; assert true end
|
||||||
|
end
|
||||||
|
end
|
|
@ -40,13 +40,13 @@ class RepositoryCvsTest < Test::Unit::TestCase
|
||||||
|
|
||||||
assert_equal 5, @repository.changesets.count
|
assert_equal 5, @repository.changesets.count
|
||||||
assert_equal 14, @repository.changes.count
|
assert_equal 14, @repository.changes.count
|
||||||
assert_equal 'Two files changed', @repository.changesets.find_by_revision(3).comments
|
assert_not_nil @repository.changesets.find_by_comments('Two files changed')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fetch_changesets_incremental
|
def test_fetch_changesets_incremental
|
||||||
@repository.fetch_changesets
|
@repository.fetch_changesets
|
||||||
# Remove changesets with revision > 2
|
# Remove the 3 latest changesets
|
||||||
@repository.changesets.find(:all, :conditions => 'revision > 2').each(&:destroy)
|
@repository.changesets.find(:all, :order => 'committed_on DESC', :limit => 3).each(&:destroy)
|
||||||
@repository.reload
|
@repository.reload
|
||||||
assert_equal 2, @repository.changesets.count
|
assert_equal 2, @repository.changesets.count
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2008 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
|
||||||
|
class RepositoryDarcsTest < Test::Unit::TestCase
|
||||||
|
fixtures :projects
|
||||||
|
|
||||||
|
# No '..' in the repository path
|
||||||
|
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/darcs_repository'
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@project = Project.find(1)
|
||||||
|
assert @repository = Repository::Darcs.create(:project => @project, :url => REPOSITORY_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.directory?(REPOSITORY_PATH)
|
||||||
|
def test_fetch_changesets_from_scratch
|
||||||
|
@repository.fetch_changesets
|
||||||
|
@repository.reload
|
||||||
|
|
||||||
|
assert_equal 6, @repository.changesets.count
|
||||||
|
assert_equal 13, @repository.changes.count
|
||||||
|
assert_equal "Initial commit.", @repository.changesets.find_by_revision(1).comments
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fetch_changesets_incremental
|
||||||
|
@repository.fetch_changesets
|
||||||
|
# Remove changesets with revision > 3
|
||||||
|
@repository.changesets.find(:all, :conditions => 'revision > 3').each(&:destroy)
|
||||||
|
@repository.reload
|
||||||
|
assert_equal 3, @repository.changesets.count
|
||||||
|
|
||||||
|
@repository.fetch_changesets
|
||||||
|
assert_equal 6, @repository.changesets.count
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Darcs test repository NOT FOUND. Skipping unit tests !!!"
|
||||||
|
def test_fake; assert true end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,56 @@
|
||||||
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
|
|
||||||
|
class RepositoryGitTest < Test::Unit::TestCase
|
||||||
|
fixtures :projects
|
||||||
|
|
||||||
|
# No '..' in the repository path
|
||||||
|
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository'
|
||||||
|
REPOSITORY_PATH.gsub!(/\//, "\\") if RUBY_PLATFORM =~ /mswin/
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@project = Project.find(1)
|
||||||
|
assert @repository = Repository::Git.create(:project => @project, :url => REPOSITORY_PATH)
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.directory?(REPOSITORY_PATH)
|
||||||
|
def test_fetch_changesets_from_scratch
|
||||||
|
@repository.fetch_changesets
|
||||||
|
@repository.reload
|
||||||
|
|
||||||
|
assert_equal 6, @repository.changesets.count
|
||||||
|
assert_equal 11, @repository.changes.count
|
||||||
|
assert_equal "Initial import.\nThe repository contains 3 files.", @repository.changesets.find(:first, :order => 'id ASC').comments
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fetch_changesets_incremental
|
||||||
|
@repository.fetch_changesets
|
||||||
|
# Remove the 3 latest changesets
|
||||||
|
@repository.changesets.find(:all, :order => 'id DESC', :limit => 3).each(&:destroy)
|
||||||
|
@repository.reload
|
||||||
|
assert_equal 3, @repository.changesets.count
|
||||||
|
|
||||||
|
@repository.fetch_changesets
|
||||||
|
assert_equal 6, @repository.changesets.count
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Git test repository NOT FOUND. Skipping unit tests !!!"
|
||||||
|
def test_fake; assert true end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue