parent
96dacf3150
commit
dd9515d745
@ -1,179 +0,0 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# 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. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'redmine/scm/adapters/cvs_adapter' |
||||
require 'digest/sha1' |
||||
|
||||
class Repository::Cvs < Repository |
||||
validates_presence_of :url, :root_url, :log_encoding |
||||
|
||||
ATTRIBUTE_KEY_NAMES = { |
||||
"url" => "CVSROOT", |
||||
"root_url" => "Module", |
||||
"log_encoding" => "Commit messages encoding", |
||||
} |
||||
def self.human_attribute_name(attribute_key_name, options = {}) |
||||
ATTRIBUTE_KEY_NAMES[attribute_key_name] || super |
||||
end |
||||
|
||||
def self.scm_adapter_class |
||||
Redmine::Scm::Adapters::CvsAdapter |
||||
end |
||||
|
||||
def self.scm_name |
||||
'CVS' |
||||
end |
||||
|
||||
def entry(path=nil, identifier=nil) |
||||
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) |
||||
scm.entry(path, rev.nil? ? nil : rev.committed_on) |
||||
end |
||||
|
||||
def entries(path=nil, identifier=nil) |
||||
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) |
||||
entries = scm.entries(path, rev.nil? ? nil : rev.committed_on) |
||||
if entries |
||||
entries.each() do |entry| |
||||
if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? ) |
||||
change=changes.find_by_revision_and_path( |
||||
entry.lastrev.revision, |
||||
scm.with_leading_slash(entry.path) ) |
||||
if change |
||||
entry.lastrev.identifier = change.changeset.revision |
||||
entry.lastrev.revision = change.changeset.revision |
||||
entry.lastrev.author = change.changeset.committer |
||||
# entry.lastrev.branch = change.branch |
||||
end |
||||
end |
||||
end |
||||
end |
||||
entries |
||||
end |
||||
|
||||
def cat(path, identifier=nil) |
||||
rev = identifier.nil? ? nil : changesets.find_by_revision(identifier) |
||||
scm.cat(path, rev.nil? ? nil : rev.committed_on) |
||||
end |
||||
|
||||
def diff(path, rev, rev_to) |
||||
#convert rev to revision. CVS can't handle changesets here |
||||
diff=[] |
||||
changeset_from=changesets.find_by_revision(rev) |
||||
if rev_to.to_i > 0 |
||||
changeset_to=changesets.find_by_revision(rev_to) |
||||
end |
||||
changeset_from.changes.each() do |change_from| |
||||
|
||||
revision_from=nil |
||||
revision_to=nil |
||||
|
||||
revision_from=change_from.revision if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path)) |
||||
|
||||
if revision_from |
||||
if changeset_to |
||||
changeset_to.changes.each() do |change_to| |
||||
revision_to=change_to.revision if change_to.path==change_from.path |
||||
end |
||||
end |
||||
unless revision_to |
||||
revision_to=scm.get_previous_revision(revision_from) |
||||
end |
||||
file_diff = scm.diff(change_from.path, revision_from, revision_to) |
||||
diff = diff + file_diff unless file_diff.nil? |
||||
end |
||||
end |
||||
return diff |
||||
end |
||||
|
||||
def fetch_changesets |
||||
# 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. |
||||
# we now take a guess using the author, the commitlog and the commit-date. |
||||
|
||||
# last one is the next step to take. the commit-date is not equal for all |
||||
# commits in one changeset. cvs update the commit-date when the *,v file was touched. so |
||||
# we use a small delta here, to merge all changes belonging to _one_ changeset |
||||
time_delta=10.seconds |
||||
|
||||
fetch_since = latest_changeset ? latest_changeset.committed_on : nil |
||||
transaction do |
||||
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 |
||||
# is not exclusive at all. |
||||
tmp_time = revision.time.clone |
||||
unless changes.find_by_path_and_revision( |
||||
scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision]) |
||||
cmt = Changeset.normalize_comments(revision.message, repo_log_encoding) |
||||
cs = changesets.find(:first, :conditions=>{ |
||||
:committed_on=>tmp_time - time_delta .. tmp_time + time_delta, |
||||
:committer=>revision.author, |
||||
:comments=>cmt |
||||
}) |
||||
|
||||
# create a new changeset.... |
||||
unless cs |
||||
# we use a temporaray revision number here (just for inserting) |
||||
# later on, we calculate a continous positive number |
||||
tmp_time2 = tmp_time.clone.gmtime |
||||
branch = revision.paths[0][:branch] |
||||
scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S") |
||||
cs = Changeset.create(:repository => self, |
||||
:revision => "tmp#{tmp_rev_num}", |
||||
:scmid => scmid, |
||||
:committer => revision.author, |
||||
:committed_on => tmp_time, |
||||
:comments => revision.message) |
||||
tmp_rev_num += 1 |
||||
end |
||||
|
||||
#convert CVS-File-States to internal Action-abbrevations |
||||
#default action is (M)odified |
||||
action="M" |
||||
if revision.paths[0][:action]=="Exp" && revision.paths[0][:revision]=="1.1" |
||||
action="A" #add-action always at first revision (= 1.1) |
||||
elsif revision.paths[0][:action]=="dead" |
||||
action="D" #dead-state is similar to Delete |
||||
end |
||||
|
||||
Change.create(:changeset => cs, |
||||
:action => action, |
||||
:path => scm.with_leading_slash(revision.paths[0][:path]), |
||||
:revision => revision.paths[0][:revision], |
||||
:branch => revision.paths[0][:branch] |
||||
) |
||||
end |
||||
end |
||||
|
||||
# Renumber new changesets in chronological order |
||||
changesets.find( |
||||
:all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE 'tmp%'" |
||||
).each do |changeset| |
||||
changeset.update_attribute :revision, next_revision_number |
||||
end |
||||
end # transaction |
||||
@current_revision_number = nil |
||||
end |
||||
|
||||
private |
||||
|
||||
# Returns the next revision number to assign to a CVS changeset |
||||
def next_revision_number |
||||
# Need to retrieve existing revision numbers to sort them as integers |
||||
sql = "SELECT revision FROM #{Changeset.table_name} " |
||||
sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'" |
||||
@current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0) |
||||
@current_revision_number += 1 |
||||
end |
||||
end |
@ -1,436 +0,0 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# 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. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'redmine/scm/adapters/abstract_adapter' |
||||
|
||||
module Redmine |
||||
module Scm |
||||
module Adapters |
||||
class CvsAdapter < AbstractAdapter |
||||
|
||||
# CVS executable name |
||||
CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs" |
||||
|
||||
# raised if scm command exited with error, e.g. unknown revision. |
||||
class ScmCommandAborted < CommandFailed; end |
||||
|
||||
class << self |
||||
def client_command |
||||
@@bin ||= CVS_BIN |
||||
end |
||||
|
||||
def sq_bin |
||||
@@sq_bin ||= shell_quote(CVS_BIN) |
||||
end |
||||
|
||||
def client_version |
||||
@@client_version ||= (scm_command_version || []) |
||||
end |
||||
|
||||
def client_available |
||||
client_version_above?([1, 12]) |
||||
end |
||||
|
||||
def scm_command_version |
||||
scm_version = scm_version_from_command_line.dup |
||||
if scm_version.respond_to?(:force_encoding) |
||||
scm_version.force_encoding('ASCII-8BIT') |
||||
end |
||||
if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m) |
||||
m[2].scan(%r{\d+}).collect(&:to_i) |
||||
end |
||||
end |
||||
|
||||
def scm_version_from_command_line |
||||
shellout("#{sq_bin} --version") { |io| io.read }.to_s |
||||
end |
||||
end |
||||
|
||||
# Guidelines for the input: |
||||
# url -> the project-path, relative to the cvsroot (eg. module name) |
||||
# root_url -> the good old, sometimes damned, CVSROOT |
||||
# login -> unnecessary |
||||
# password -> unnecessary too |
||||
def initialize(url, root_url=nil, login=nil, password=nil, |
||||
path_encoding=nil) |
||||
@url = url |
||||
@login = login if login && !login.empty? |
||||
@password = (password || "") if @login |
||||
#TODO: better Exception here (IllegalArgumentException) |
||||
raise CommandFailed if root_url.blank? |
||||
@root_url = root_url |
||||
end |
||||
|
||||
def root_url |
||||
@root_url |
||||
end |
||||
|
||||
def url |
||||
@url |
||||
end |
||||
|
||||
def info |
||||
logger.debug "<cvs> info" |
||||
Info.new({:root_url => @root_url, :lastrev => nil}) |
||||
end |
||||
|
||||
def get_previous_revision(revision) |
||||
CvsRevisionHelper.new(revision).prevRev |
||||
end |
||||
|
||||
# Returns an Entries collection |
||||
# or nil if the given path doesn't exist in the repository |
||||
# this method is used by the repository-browser (aka LIST) |
||||
def entries(path=nil, identifier=nil) |
||||
logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'" |
||||
path_with_project="#{url}#{with_leading_slash(path)}" |
||||
entries = Entries.new |
||||
cmd_args = %w|rls -e| |
||||
cmd_args << "-D" << time_to_cvstime_rlog(identifier) if identifier |
||||
cmd_args << path_with_project |
||||
scm_cmd(*cmd_args) do |io| |
||||
io.each_line() do |line| |
||||
fields = line.chop.split('/',-1) |
||||
logger.debug(">>InspectLine #{fields.inspect}") |
||||
if fields[0]!="D" |
||||
time = nil |
||||
# Thu Dec 13 16:27:22 2007 |
||||
time_l = fields[-3].split(' ') |
||||
if time_l.size == 5 && time_l[4].length == 4 |
||||
begin |
||||
time = Time.parse( |
||||
"#{time_l[1]} #{time_l[2]} #{time_l[3]} GMT #{time_l[4]}") |
||||
rescue |
||||
end |
||||
end |
||||
entries << Entry.new( |
||||
{ |
||||
:name => fields[-5], |
||||
#:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]), |
||||
:path => "#{path}/#{fields[-5]}", |
||||
:kind => 'file', |
||||
:size => nil, |
||||
:lastrev => Revision.new( |
||||
{ |
||||
:revision => fields[-4], |
||||
:name => fields[-4], |
||||
:time => time, |
||||
:author => '' |
||||
}) |
||||
}) |
||||
else |
||||
entries << Entry.new( |
||||
{ |
||||
:name => fields[1], |
||||
:path => "#{path}/#{fields[1]}", |
||||
:kind => 'dir', |
||||
:size => nil, |
||||
:lastrev => nil |
||||
}) |
||||
end |
||||
end |
||||
end |
||||
entries.sort_by_name |
||||
rescue ScmCommandAborted |
||||
nil |
||||
end |
||||
|
||||
STARTLOG="----------------------------" |
||||
ENDLOG ="=============================================================================" |
||||
|
||||
# Returns all revisions found between identifier_from and identifier_to |
||||
# in the repository. both identifier have to be dates or nil. |
||||
# these method returns nothing but yield every result in block |
||||
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block) |
||||
logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" |
||||
|
||||
path_with_project="#{url}#{with_leading_slash(path)}" |
||||
cmd_args = %w|rlog| |
||||
cmd_args << "-d" << ">#{time_to_cvstime_rlog(identifier_from)}" if identifier_from |
||||
cmd_args << path_with_project |
||||
scm_cmd(*cmd_args) do |io| |
||||
state="entry_start" |
||||
|
||||
commit_log=String.new |
||||
revision=nil |
||||
date=nil |
||||
author=nil |
||||
entry_path=nil |
||||
entry_name=nil |
||||
file_state=nil |
||||
branch_map=nil |
||||
|
||||
io.each_line() do |line| |
||||
|
||||
if state!="revision" && /^#{ENDLOG}/ =~ line |
||||
commit_log=String.new |
||||
revision=nil |
||||
state="entry_start" |
||||
end |
||||
|
||||
if state=="entry_start" |
||||
branch_map=Hash.new |
||||
if /^RCS file: #{Regexp.escape(root_url_path)}\/#{Regexp.escape(path_with_project)}(.+),v$/ =~ line |
||||
entry_path = normalize_cvs_path($1) |
||||
entry_name = normalize_path(File.basename($1)) |
||||
logger.debug("Path #{entry_path} <=> Name #{entry_name}") |
||||
elsif /^head: (.+)$/ =~ line |
||||
entry_headRev = $1 #unless entry.nil? |
||||
elsif /^symbolic names:/ =~ line |
||||
state="symbolic" #unless entry.nil? |
||||
elsif /^#{STARTLOG}/ =~ line |
||||
commit_log=String.new |
||||
state="revision" |
||||
end |
||||
next |
||||
elsif state=="symbolic" |
||||
if /^(.*):\s(.*)/ =~ (line.strip) |
||||
branch_map[$1]=$2 |
||||
else |
||||
state="tags" |
||||
next |
||||
end |
||||
elsif state=="tags" |
||||
if /^#{STARTLOG}/ =~ line |
||||
commit_log = "" |
||||
state="revision" |
||||
elsif /^#{ENDLOG}/ =~ line |
||||
state="head" |
||||
end |
||||
next |
||||
elsif state=="revision" |
||||
if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line |
||||
if revision |
||||
|
||||
revHelper=CvsRevisionHelper.new(revision) |
||||
revBranch="HEAD" |
||||
|
||||
branch_map.each() do |branch_name,branch_point| |
||||
if revHelper.is_in_branch_with_symbol(branch_point) |
||||
revBranch=branch_name |
||||
end |
||||
end |
||||
|
||||
logger.debug("********** YIELD Revision #{revision}::#{revBranch}") |
||||
|
||||
yield Revision.new({ |
||||
:time => date, |
||||
:author => author, |
||||
:message=>commit_log.chomp, |
||||
:paths => [{ |
||||
:revision => revision, |
||||
:branch=> revBranch, |
||||
:path=>entry_path, |
||||
:name=>entry_name, |
||||
:kind=>'file', |
||||
:action=>file_state |
||||
}] |
||||
}) |
||||
end |
||||
|
||||
commit_log=String.new |
||||
revision=nil |
||||
|
||||
if /^#{ENDLOG}/ =~ line |
||||
state="entry_start" |
||||
end |
||||
next |
||||
end |
||||
|
||||
if /^branches: (.+)$/ =~ line |
||||
#TODO: version.branch = $1 |
||||
elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line |
||||
revision = $1 |
||||
elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line |
||||
date = Time.parse($1) |
||||
author = /author: ([^;]+)/.match(line)[1] |
||||
file_state = /state: ([^;]+)/.match(line)[1] |
||||
#TODO: linechanges only available in CVS.... maybe a feature our SVN implementation. i'm sure, they are |
||||
# useful for stats or something else |
||||
# linechanges =/lines: \+(\d+) -(\d+)/.match(line) |
||||
# unless linechanges.nil? |
||||
# version.line_plus = linechanges[1] |
||||
# version.line_minus = linechanges[2] |
||||
# else |
||||
# version.line_plus = 0 |
||||
# version.line_minus = 0 |
||||
# end |
||||
else |
||||
commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/ |
||||
end |
||||
end |
||||
end |
||||
end |
||||
rescue ScmCommandAborted |
||||
Revisions.new |
||||
end |
||||
|
||||
def diff(path, identifier_from, identifier_to=nil) |
||||
logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" |
||||
path_with_project="#{url}#{with_leading_slash(path)}" |
||||
cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}" |
||||
diff = [] |
||||
shellout(cmd) do |io| |
||||
io.each_line do |line| |
||||
diff << line |
||||
end |
||||
end |
||||
return nil if $? && $?.exitstatus != 0 |
||||
diff |
||||
end |
||||
|
||||
def cat(path, identifier=nil) |
||||
identifier = (identifier) ? identifier : "HEAD" |
||||
logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}" |
||||
path_with_project="#{url}#{with_leading_slash(path)}" |
||||
cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co" |
||||
cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier |
||||
cmd << " -p #{shell_quote path_with_project}" |
||||
cat = nil |
||||
shellout(cmd) do |io| |
||||
io.binmode |
||||
cat = io.read |
||||
end |
||||
return nil if $? && $?.exitstatus != 0 |
||||
cat |
||||
end |
||||
|
||||
def annotate(path, identifier=nil) |
||||
identifier = (identifier) ? identifier.to_i : "HEAD" |
||||
logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}" |
||||
path_with_project="#{url}#{with_leading_slash(path)}" |
||||
cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}" |
||||
blame = Annotate.new |
||||
shellout(cmd) do |io| |
||||
io.each_line do |line| |
||||
next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$} |
||||
blame.add_line($3.rstrip, Revision.new(:revision => $1, :author => $2.strip)) |
||||
end |
||||
end |
||||
return nil if $? && $?.exitstatus != 0 |
||||
blame |
||||
end |
||||
|
||||
private |
||||
|
||||
# Returns the root url without the connexion string |
||||
# :pserver:anonymous@foo.bar:/path => /path |
||||
# :ext:cvsservername:/path => /path |
||||
def root_url_path |
||||
root_url.to_s.gsub(/^:.+:\d*/, '') |
||||
end |
||||
|
||||
# convert a date/time into the CVS-format |
||||
def time_to_cvstime(time) |
||||
return nil if time.nil? |
||||
return Time.now if time == 'HEAD' |
||||
|
||||
unless time.kind_of? Time |
||||
time = Time.parse(time) |
||||
end |
||||
return time.strftime("%Y-%m-%d %H:%M:%S") |
||||
end |
||||
|
||||
def time_to_cvstime_rlog(time) |
||||
return nil if time.nil? |
||||
t1 = time.clone.localtime |
||||
return t1.strftime("%Y-%m-%d %H:%M:%S") |
||||
end |
||||
|
||||
def normalize_cvs_path(path) |
||||
normalize_path(path.gsub(/Attic\//,'')) |
||||
end |
||||
|
||||
def normalize_path(path) |
||||
path.sub(/^(\/)*(.*)/,'\2').sub(/(.*)(,v)+/,'\1') |
||||
end |
||||
|
||||
def scm_cmd(*args, &block) |
||||
full_args = [CVS_BIN, '-d', root_url] |
||||
full_args += args |
||||
ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block) |
||||
if $? && $?.exitstatus != 0 |
||||
raise ScmCommandAborted, "cvs exited with non-zero status: #{$?.exitstatus}" |
||||
end |
||||
ret |
||||
end |
||||
private :scm_cmd |
||||
end |
||||
|
||||
class CvsRevisionHelper |
||||
attr_accessor :complete_rev, :revision, :base, :branchid |
||||
|
||||
def initialize(complete_rev) |
||||
@complete_rev = complete_rev |
||||
parseRevision() |
||||
end |
||||
|
||||
def branchPoint |
||||
return @base |
||||
end |
||||
|
||||
def branchVersion |
||||
if isBranchRevision |
||||
return @base+"."+@branchid |
||||
end |
||||
return @base |
||||
end |
||||
|
||||
def isBranchRevision |
||||
!@branchid.nil? |
||||
end |
||||
|
||||
def prevRev |
||||
unless @revision==0 |
||||
return buildRevision(@revision-1) |
||||
end |
||||
return buildRevision(@revision) |
||||
end |
||||
|
||||
def is_in_branch_with_symbol(branch_symbol) |
||||
bpieces=branch_symbol.split(".") |
||||
branch_start="#{bpieces[0..-3].join(".")}.#{bpieces[-1]}" |
||||
return (branchVersion==branch_start) |
||||
end |
||||
|
||||
private |
||||
def buildRevision(rev) |
||||
if rev== 0 |
||||
if @branchid.nil? |
||||
@base+".0" |
||||
else |
||||
@base |
||||
end |
||||
elsif @branchid.nil? |
||||
@base+"."+rev.to_s |
||||
else |
||||
@base+"."+@branchid+"."+rev.to_s |
||||
end |
||||
end |
||||
|
||||
# Interpretiert die cvs revisionsnummern wie z.b. 1.14 oder 1.3.0.15 |
||||
def parseRevision() |
||||
pieces=@complete_rev.split(".") |
||||
@revision=pieces.last.to_i |
||||
baseSize=1 |
||||
baseSize+=(pieces.size/2) |
||||
@base=pieces[0..-baseSize].join(".") |
||||
if baseSize > 2 |
||||
@branchid=pieces[-2] |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
Binary file not shown.
@ -1,202 +0,0 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# 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. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
require File.expand_path('../../test_helper', __FILE__) |
||||
require 'repositories_controller' |
||||
|
||||
# Re-raise errors caught by the controller. |
||||
class RepositoriesController; def rescue_action(e) raise e end; end |
||||
|
||||
class RepositoriesCvsControllerTest < ActionController::TestCase |
||||
fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules |
||||
|
||||
# No '..' in the repository path |
||||
REPOSITORY_PATH = Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/cvs_repository' |
||||
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? |
||||
# CVS module |
||||
MODULE_NAME = 'test' |
||||
PRJ_ID = 3 |
||||
|
||||
def setup |
||||
@controller = RepositoriesController.new |
||||
@request = ActionController::TestRequest.new |
||||
@response = ActionController::TestResponse.new |
||||
Setting.default_language = 'en' |
||||
User.current = nil |
||||
|
||||
@project = Project.find(PRJ_ID) |
||||
@repository = Repository::Cvs.create(:project => Project.find(PRJ_ID), |
||||
:root_url => REPOSITORY_PATH, |
||||
:url => MODULE_NAME, |
||||
:log_encoding => 'UTF-8') |
||||
|
||||
# see repositories_subversion_controller_test.rb |
||||
def @repository.reload |
||||
ActiveRecord::Base.connection.clear_query_cache |
||||
self.class.find(self.id) |
||||
end |
||||
|
||||
assert @repository |
||||
end |
||||
|
||||
if File.directory?(REPOSITORY_PATH) |
||||
def test_browse_root |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :show, :id => PRJ_ID |
||||
assert_response :success |
||||
assert_template 'show' |
||||
assert_not_nil assigns(:entries) |
||||
assert_equal 3, assigns(:entries).size |
||||
|
||||
entry = assigns(:entries).detect {|e| e.name == 'images'} |
||||
assert_equal 'dir', entry.kind |
||||
|
||||
entry = assigns(:entries).detect {|e| e.name == 'README'} |
||||
assert_equal 'file', entry.kind |
||||
|
||||
assert_not_nil assigns(:changesets) |
||||
assigns(:changesets).size > 0 |
||||
end |
||||
|
||||
def test_browse_directory |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :show, :id => PRJ_ID, :path => ['images'] |
||||
assert_response :success |
||||
assert_template 'show' |
||||
assert_not_nil assigns(:entries) |
||||
assert_equal ['plus.png', 'delete.png', 'edit.png'], assigns(:entries).collect(&:name) |
||||
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_browse_at_given_revision |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :show, :id => PRJ_ID, :path => ['images'], :rev => 1 |
||||
assert_response :success |
||||
assert_template 'show' |
||||
assert_not_nil assigns(:entries) |
||||
assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name) |
||||
end |
||||
|
||||
def test_entry |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb'] |
||||
assert_response :success |
||||
assert_template 'entry' |
||||
assert_no_tag :tag => 'td', :attributes => { :class => /line-code/}, |
||||
:content => /before_filter/ |
||||
end |
||||
|
||||
def test_entry_at_given_revision |
||||
# changesets must be loaded |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb'], :rev => 2 |
||||
assert_response :success |
||||
assert_template 'entry' |
||||
# this line was removed in r3 |
||||
assert_tag :tag => 'td', :attributes => { :class => /line-code/}, |
||||
:content => /before_filter/ |
||||
end |
||||
|
||||
def test_entry_not_found |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :entry, :id => PRJ_ID, :path => ['sources', 'zzz.c'] |
||||
assert_tag :tag => 'p', :attributes => { :id => /errorExplanation/ }, |
||||
:content => /The entry or revision was not found in the repository/ |
||||
end |
||||
|
||||
def test_entry_download |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :entry, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb'], :format => 'raw' |
||||
assert_response :success |
||||
end |
||||
|
||||
def test_directory_entry |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :entry, :id => PRJ_ID, :path => ['sources'] |
||||
assert_response :success |
||||
assert_template 'show' |
||||
assert_not_nil assigns(:entry) |
||||
assert_equal 'sources', assigns(:entry).name |
||||
end |
||||
|
||||
def test_diff |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :diff, :id => PRJ_ID, :rev => 3, :type => 'inline' |
||||
assert_response :success |
||||
assert_template 'diff' |
||||
assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_out' }, |
||||
:content => /before_filter :require_login/ |
||||
assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_in' }, |
||||
:content => /with one change/ |
||||
end |
||||
|
||||
def test_diff_new_files |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :diff, :id => PRJ_ID, :rev => 1, :type => 'inline' |
||||
assert_response :success |
||||
assert_template 'diff' |
||||
assert_tag :tag => 'td', :attributes => { :class => 'line-code diff_in' }, |
||||
:content => /watched.remove_watcher/ |
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' }, |
||||
:content => /test\/README/ |
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' }, |
||||
:content => /test\/images\/delete.png / |
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' }, |
||||
:content => /test\/images\/edit.png/ |
||||
assert_tag :tag => 'th', :attributes => { :class => 'filename' }, |
||||
:content => /test\/sources\/watchers_controller.rb/ |
||||
end |
||||
|
||||
def test_annotate |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
get :annotate, :id => PRJ_ID, :path => ['sources', 'watchers_controller.rb'] |
||||
assert_response :success |
||||
assert_template 'annotate' |
||||
# 1.1 line |
||||
assert_tag :tag => 'th', :attributes => { :class => 'line-num' }, |
||||
:content => '18', |
||||
:sibling => { :tag => 'td', :attributes => { :class => 'revision' }, |
||||
:content => /1.1/, |
||||
:sibling => { :tag => 'td', :attributes => { :class => 'author' }, |
||||
:content => /LANG/ |
||||
} |
||||
} |
||||
# 1.2 line |
||||
assert_tag :tag => 'th', :attributes => { :class => 'line-num' }, |
||||
:content => '32', |
||||
:sibling => { :tag => 'td', :attributes => { :class => 'revision' }, |
||||
:content => /1.2/, |
||||
:sibling => { :tag => 'td', :attributes => { :class => 'author' }, |
||||
:content => /LANG/ |
||||
} |
||||
} |
||||
end |
||||
else |
||||
puts "CVS test repository NOT FOUND. Skipping functional tests !!!" |
||||
def test_fake; assert true end |
||||
end |
||||
end |
@ -1,81 +0,0 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# 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. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../../../test_helper', __FILE__) |
||||
begin |
||||
require 'mocha/setup' |
||||
|
||||
class CvsAdapterTest < ActiveSupport::TestCase |
||||
|
||||
REPOSITORY_PATH = Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/cvs_repository' |
||||
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? |
||||
MODULE_NAME = 'test' |
||||
|
||||
if File.directory?(REPOSITORY_PATH) |
||||
def setup |
||||
@adapter = Redmine::Scm::Adapters::CvsAdapter.new(MODULE_NAME, REPOSITORY_PATH) |
||||
end |
||||
|
||||
def test_scm_version |
||||
to_test = { "\nConcurrent Versions System (CVS) 1.12.13 (client/server)\n" => [1,12,13], |
||||
"\r\n1.12.12\r\n1.12.11" => [1,12,12], |
||||
"1.12.11\r\n1.12.10\r\n" => [1,12,11]} |
||||
to_test.each do |s, v| |
||||
test_scm_version_for(s, v) |
||||
end |
||||
end |
||||
|
||||
def test_revisions_all |
||||
cnt = 0 |
||||
@adapter.revisions('', nil, nil, :with_paths => true) do |revision| |
||||
cnt += 1 |
||||
end |
||||
assert_equal 14, cnt |
||||
end |
||||
|
||||
def test_revisions_from_rev3 |
||||
rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22) |
||||
cnt = 0 |
||||
@adapter.revisions('', rev3_committed_on, nil, :with_paths => true) do |revision| |
||||
cnt += 1 |
||||
end |
||||
assert_equal 2, cnt |
||||
end |
||||
|
||||
def test_entries_rev3 |
||||
rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22) |
||||
entries = @adapter.entries('sources', rev3_committed_on) |
||||
assert_equal 2, entries.size |
||||
assert_equal entries[0].name, "watchers_controller.rb" |
||||
assert_equal entries[0].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22) |
||||
end |
||||
|
||||
private |
||||
|
||||
def test_scm_version_for(scm_command_version, version) |
||||
@adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version) |
||||
assert_equal version, @adapter.class.scm_command_version |
||||
end |
||||
else |
||||
puts "Cvs test repository NOT FOUND. Skipping unit tests !!!" |
||||
def test_fake; assert true end |
||||
end |
||||
end |
||||
|
||||
rescue LoadError |
||||
class CvsMochaFake < ActiveSupport::TestCase |
||||
def test_fake; assert(false, "Requires mocha to run those tests") end |
||||
end |
||||
end |
||||
|
@ -1,104 +0,0 @@ |
||||
#-- encoding: UTF-8 |
||||
#-- copyright |
||||
# ChiliProject is a project management system. |
||||
# |
||||
# Copyright (C) 2010-2011 the ChiliProject Team |
||||
# |
||||
# 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. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
require File.expand_path('../../test_helper', __FILE__) |
||||
require 'pp' |
||||
class RepositoryCvsTest < ActiveSupport::TestCase |
||||
fixtures :projects |
||||
|
||||
# No '..' in the repository path |
||||
REPOSITORY_PATH = Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/cvs_repository' |
||||
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin? |
||||
# CVS module |
||||
MODULE_NAME = 'test' |
||||
|
||||
def setup |
||||
@project = Project.find(3) |
||||
@repository = Repository::Cvs.create(:project => @project, |
||||
:root_url => REPOSITORY_PATH, |
||||
:url => MODULE_NAME, |
||||
:log_encoding => 'UTF-8') |
||||
assert @repository |
||||
end |
||||
|
||||
if File.directory?(REPOSITORY_PATH) |
||||
def test_fetch_changesets_from_scratch |
||||
assert_equal 0, @repository.changesets.count |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
|
||||
assert_equal 5, @repository.changesets.count |
||||
assert_equal 14, @repository.changes.count |
||||
assert_not_nil @repository.changesets.find_by_comments('Two files changed') |
||||
|
||||
r2 = @repository.changesets.find_by_revision('2') |
||||
assert_equal 'v1-20071213-162510', r2.scmid |
||||
end |
||||
|
||||
def test_fetch_changesets_incremental |
||||
assert_equal 0, @repository.changesets.count |
||||
@repository.fetch_changesets |
||||
# Remove changesets with revision > 3 |
||||
@repository.changesets.find(:all).each {|c| c.destroy if c.revision.to_i > 3} |
||||
@repository.reload |
||||
assert_equal 3, @repository.changesets.count |
||||
assert_equal %w|3 2 1|, @repository.changesets.collect(&:revision) |
||||
|
||||
rev3_commit = @repository.changesets.reorder('committed_on DESC').first |
||||
assert_equal '3', rev3_commit.revision |
||||
# 2007-12-14 01:27:22 +0900 |
||||
rev3_committed_on = Time.gm(2007, 12, 13, 16, 27, 22) |
||||
assert_equal 'HEAD-20071213-162722', rev3_commit.scmid |
||||
assert_equal rev3_committed_on, rev3_commit.committed_on |
||||
latest_rev = @repository.latest_changeset |
||||
assert_equal rev3_committed_on, latest_rev.committed_on |
||||
|
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
assert_equal 5, @repository.changesets.count |
||||
|
||||
assert_equal %w|5 4 3 2 1|, @repository.changesets.collect(&:revision) |
||||
rev5_commit = @repository.changesets.find(:first, :order => 'committed_on DESC') |
||||
assert_equal 'HEAD-20071213-163001', rev5_commit.scmid |
||||
# 2007-12-14 01:30:01 +0900 |
||||
rev5_committed_on = Time.gm(2007, 12, 13, 16, 30, 1) |
||||
assert_equal rev5_committed_on, rev5_commit.committed_on |
||||
end |
||||
|
||||
def test_deleted_files_should_not_be_listed |
||||
assert_equal 0, @repository.changesets.count |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
assert_equal 5, @repository.changesets.count |
||||
|
||||
entries = @repository.entries('sources') |
||||
assert entries.detect {|e| e.name == 'watchers_controller.rb'} |
||||
assert_nil entries.detect {|e| e.name == 'welcome_controller.rb'} |
||||
end |
||||
|
||||
def test_entries_rev3 |
||||
@repository.fetch_changesets |
||||
@repository.reload |
||||
entries = @repository.entries('', '3') |
||||
assert_equal 3, entries.size |
||||
assert_equal entries[2].name, "README" |
||||
assert_equal entries[2].lastrev.time, Time.gm(2007, 12, 13, 16, 27, 22) |
||||
assert_equal entries[2].lastrev.identifier, '3' |
||||
assert_equal entries[2].lastrev.revision, '3' |
||||
assert_equal entries[2].lastrev.author, 'LANG' |
||||
end |
||||
else |
||||
puts "CVS test repository NOT FOUND. Skipping unit tests !!!" |
||||
def test_fake; assert true end |
||||
end |
||||
end |
Loading…
Reference in new issue