Merge remote-tracking branch 'origin/release/8.3' into dev

pull/7052/head
Jens Ulferts 6 years ago
commit 72594b7765
No known key found for this signature in database
GPG Key ID: 3CAA4B1182CF5308
  1. 6
      app/assets/stylesheets/content/work_packages/_table_content.sass
  2. 75
      app/controllers/work_packages/bulk_controller.rb
  3. 13
      app/models/repository/subversion.rb
  4. 7
      app/services/service_result.rb
  5. 93
      app/services/work_packages/bulk/update_service.rb
  6. 29
      app/views/work_packages/bulk/edit.html.erb
  7. 4
      config/locales/en.yml
  8. 19
      lib/open_project/scm/adapters/subversion.rb
  9. 66
      lib/tasks/testing.rake
  10. 4
      script/ci/setup.sh
  11. 2
      spec/controllers/work_packages/bulk_controller_spec.rb
  12. 124
      spec/features/work_packages/bulk/update_work_package_spec.rb
  13. 164
      spec_legacy/functional/repositories_controller_spec.rb
  14. 255
      spec_legacy/functional/repositories_git_controller_spec.rb
  15. 302
      spec_legacy/functional/repositories_subversion_controller_spec.rb
  16. 254
      spec_legacy/unit/lib/redmine/scm/adapters/git_adapter_spec.rb
  17. 64
      spec_legacy/unit/lib/redmine/scm/adapters/subversion_adapter_spec.rb
  18. 338
      spec_legacy/unit/repository_git_spec.rb
  19. 212
      spec_legacy/unit/repository_subversion_spec.rb

@ -66,8 +66,10 @@
color: $nm-color-error-icon
// Remove padding from grouping rows (exceeds allowed width of 41px)
.wp-table--group-header td
padding: 0 !important
.wp-table--group-header
height: $table-timeline--row-height
td
padding: 0 !important
// Shrink column of details / inline-create icons
.wp-table--configuration-modal--trigger

@ -38,39 +38,22 @@ class WorkPackages::BulkController < ApplicationController
include IssuesHelper
def edit
@available_statuses = @projects.map { |p| Workflow.available_statuses(p) }.inject { |memo, w| memo & w }
@custom_fields = @projects.map(&:all_work_package_custom_fields).inject { |memo, c| memo & c }
@assignables = @projects.map(&:possible_assignees).inject { |memo, a| memo & a }
@responsibles = @projects.map(&:possible_responsibles).inject { |memo, a| memo & a }
@types = @projects.map(&:types).inject { |memo, t| memo & t }
setup_edit
end
def update
unsaved_work_package_ids = []
saved_work_packages = []
@work_packages.each do |work_package|
work_package.reload
work_package.add_journal(User.current, params[:notes])
# filter parameters by whitelist and add defaults
attributes = parse_params_for_bulk_work_package_attributes params, work_package.project
@call = ::WorkPackages::Bulk::UpdateService
.new(user: current_user, work_packages: @work_packages)
.call(params: params)
call_hook(:controller_work_packages_bulk_edit_before_save, params: params, work_package: work_package)
service_call = WorkPackages::UpdateService
.new(user: user, work_package: work_package)
.call(attributes: attributes, send_notifications: params[:send_notification] == '1')
if service_call.success?
saved_work_packages << service_call.result
else
unsaved_work_package_ids << work_package.id
end
if @call.success?
flash[:notice] = t(:notice_successful_update)
redirect_back_or_default(controller: '/work_packages', action: :index, project_id: @project)
else
@bulk_errors = @call.errors
setup_edit
render action: :edit
end
set_flash_from_bulk_save(@work_packages, unsaved_work_package_ids)
redirect_back_or_default(controller: '/work_packages', action: :index, project_id: @project)
end
def destroy
@ -103,6 +86,14 @@ class WorkPackages::BulkController < ApplicationController
private
def setup_edit
@available_statuses = @projects.map { |p| Workflow.available_statuses(p) }.inject { |memo, w| memo & w }
@custom_fields = @projects.map(&:all_work_package_custom_fields).inject { |memo, c| memo & c }
@assignables = @projects.map(&:possible_assignees).inject { |memo, a| memo & a }
@responsibles = @projects.map(&:possible_responsibles).inject { |memo, a| memo & a }
@types = @projects.map(&:types).inject { |memo, t| memo & t }
end
def destroy_work_packages(work_packages)
work_packages.each do |work_package|
begin
@ -116,34 +107,6 @@ class WorkPackages::BulkController < ApplicationController
end
end
def parse_params_for_bulk_work_package_attributes(params, project)
return {} unless params.has_key? :work_package
safe_params = permitted_params.update_work_package project: project
attributes = safe_params.reject { |_k, v| v.blank? }
attributes.keys.each do |k|
attributes[k] = '' if attributes[k] == 'none'
end
attributes[:custom_field_values].reject! { |_k, v| v.blank? } if attributes[:custom_field_values]
attributes.delete :custom_field_values if not attributes.has_key?(:custom_field_values) or attributes[:custom_field_values].empty?
attributes
end
# Sets the `flash` notice or error based the number of work packages that did not save
#
# @param [Array, WorkPackage] work_packages all of the saved and unsaved WorkPackages
# @param [Array, Integer] unsaved_work_package_ids the WorkPackage ids that were not saved
def set_flash_from_bulk_save(work_packages, unsaved_work_package_ids)
if unsaved_work_package_ids.empty?
flash[:notice] = l(:notice_successful_update) unless work_packages.empty?
else
flash[:error] = l(:notice_failed_to_save_work_packages,
count: unsaved_work_package_ids.size,
total: work_packages.size,
ids: '#' + unsaved_work_package_ids.join(', #'))
end
end
def user
current_user
end

@ -94,13 +94,16 @@ class Repository::Subversion < Repository
def fetch_changesets
scm_info = scm.info
if scm_info
# latest revision found in database
db_revision = latest_changeset ? latest_changeset.revision.to_i : 0
# latest revision found in database, may be nil
db_revision = latest_changeset&.revision&.to_i
# first revision to fetch
identifier_from = db_revision ? db_revision + 1 : scm.start_revision
# latest revision in the repository
scm_revision = scm_info.lastrev.identifier.to_i
if db_revision < scm_revision
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
identifier_from = db_revision + 1
if db_revision.nil? || db_revision < scm_revision
Rails.logger.debug { "Fetching changesets for repository #{url}" }
while (identifier_from <= scm_revision)
# loads changesets by batches of 200
identifier_to = [identifier_from + 199, scm_revision].min

@ -38,6 +38,7 @@ class ServiceResult
def initialize(success: false,
errors: nil,
context: {},
dependent_results: [],
result: nil)
self.success = success
self.result = result
@ -50,7 +51,7 @@ class ServiceResult
ActiveModel::Errors.new(self)
end
self.dependent_results = []
self.dependent_results = dependent_results
end
alias success? :success
@ -65,7 +66,9 @@ class ServiceResult
end
def all_results
[result] + dependent_results.map(&:result)
dependent_results.map(&:result).tap do |results|
results.unshift result unless result.nil?
end
end
def all_errors

@ -0,0 +1,93 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module WorkPackages
module Bulk
class UpdateService
include ::Shared::ServiceContext
include ::HookHelper
attr_accessor :user, :work_packages, :permitted_params
def initialize(user:, work_packages:)
self.user = user
self.work_packages = work_packages
end
def call(params:)
self.permitted_params = PermittedParams.new(params, user)
in_context(true) do
bulk_update(params)
end
end
private
def bulk_update(params)
saved = []
errors = {}
work_packages.each do |work_package|
work_package.add_journal(user, params[:notes])
# filter parameters by whitelist and add defaults
attributes = parse_params_for_bulk_work_package_attributes params, work_package.project
call_hook(:controller_work_packages_bulk_edit_before_save, params: params, work_package: work_package)
service_call = WorkPackages::UpdateService
.new(user: user, work_package: work_package)
.call(attributes: attributes, send_notifications: params[:send_notification] == '1')
if service_call.success?
saved << work_package.id
else
errors[work_package.id] = service_call.errors.full_messages
end
end
ServiceResult.new success: errors.empty?, result: saved, errors: errors
end
def parse_params_for_bulk_work_package_attributes(params, project)
return {} unless params.has_key? :work_package
safe_params = permitted_params.update_work_package project: project
attributes = safe_params.reject { |_k, v| v.blank? }
attributes.keys.each do |k|
attributes[k] = '' if attributes[k] == 'none'
end
attributes[:custom_field_values].reject! { |_k, v| v.blank? } if attributes[:custom_field_values]
attributes.delete :custom_field_values if not attributes.has_key?(:custom_field_values) or attributes[:custom_field_values].empty?
attributes
end
end
end
end

@ -28,8 +28,35 @@ See docs/COPYRIGHT.rdoc for more details.
++#%>
<% html_title l(:label_bulk_edit_selected_work_packages) %>
<% if @bulk_errors.present? %>
<div class="notification-box -error">
<a title="close" class="notification-box--close icon-context icon-close"></a>
<div class="notification-box--content">
<p><strong><%= t('work_packages.bulk.could_not_be_saved') %></strong></p>
<ul>
<% @bulk_errors.each do |wpid, messages| %>
<li>
<%= link_to "##{wpid}", work_package_path(wpid) %>:
<%= safe_join messages, ', ' %>
</li>
<% end %>
</ul>
</div>
</div>
<% end %>
<h2><%= l(:label_bulk_edit_selected_work_packages) %></h2>
<ul><%= @work_packages.collect {|i| content_tag('li', link_to(h("#{i.type} ##{i.id}"), work_package_path(i)) + h(": #{i.subject}")) }.join("\n").html_safe %></ul>
<ul>
<% @work_packages.each do |wp| %>
<li>
<%= link_to(h("#{wp.type} ##{wp.id}"), work_package_path(wp)) %>:
<%= wp.subject %>
</li>
<% end %>
</ul>
<%= styled_form_tag(url_for(controller: '/work_packages/bulk', action: :update),
method: :put, class: '-wide-labels') do %>
<%= @work_packages.collect {|i| hidden_field_tag('ids[]', i.id)}.join.html_safe %>

@ -255,6 +255,10 @@ en:
one: 'One descendant work package'
other: '%{count} work package descendants'
bulk:
could_not_be_saved: "The following work packages could not be saved:"
move:
no_common_statuses_exists: "There is no status available for all selected work packages. Their status cannot be changed."
unsupported_for_multiple_projects: 'Bulk move/copy is not supported for work packages from multiple projects'

@ -177,6 +177,25 @@ module OpenProject
revisions
end
##
# For repositories that are actually checked-out sub directories of
# other repositories Repository#fetch_changesets will fail trying to
# go through revisions 1:200 because the lowest available revision
# can be greater than 200.
#
# To fix this we find out the earliest available revision here
# and start from there.
def start_revision
cmd = %w(log -r1:HEAD --limit 1) + [target('')]
rev = capture_svn(cmd).lines.map(&:strip)
.select { |line| line =~ /\Ar\d+ \|/ }
.map { |line| line.split(" ").first.sub(/\Ar/, "") }
.first
rev ? rev.to_i : 0
end
def diff(path, identifier_from, identifier_to = nil, _type = 'inline')
path ||= ''

@ -28,72 +28,6 @@
#++
namespace :test do
desc 'Run unit and functional scm tests'
task :scm do
errors = %w(test:scm:units test:scm:functionals).collect { |task|
begin
Rake::Task[task].invoke
nil
rescue => e
task
end
}.compact
abort "Errors running #{errors.to_sentence(locale: :en)}!" if errors.any?
end
namespace :scm do
namespace :setup do
desc 'Creates directory for test repositories'
task :create_dir do
FileUtils.mkdir_p Rails.root + '/tmp/test'
end
supported_scms = [:subversion, :git]
desc 'Creates a test subversion repository'
supported_scms.each do |scm|
desc "Creates a test #{scm} repository"
task scm => :create_dir do
repo_path = File.join(Rails.root, "tmp/test/#{scm}_repository")
FileUtils.mkdir_p repo_path
# system "gunzip < spec/fixtures/repositories/#{scm}_repository.tar.gz | tar -xv -C tmp/test"
system "tar -xvz -C #{repo_path} -f spec/fixtures/repositories/#{scm}_repository.tar.gz"
end
end
desc 'Creates all test repositories'
task all: supported_scms
end
desc 'Updates installed test repositories'
task :update do
require 'fileutils'
Dir.glob('tmp/test/*_repository').each do |dir|
next unless File.basename(dir) =~ %r{\A(.+)_repository\z} && File.directory?(dir)
scm = $1
next unless fixture = Dir.glob("spec/fixtures/repositories/#{scm}_repository.*").first
next if File.stat(dir).ctime > File.stat(fixture).mtime
FileUtils.rm_rf dir
Rake::Task["test:scm:setup:#{scm}"].execute
end
end
Rake::TestTask.new(units: 'db:test:prepare') do |t|
t.libs << 'test'
t.verbose = true
t.test_files = FileList['test/unit/repository*_test.rb'] + FileList['test/unit/lib/redmine/scm/**/*_test.rb']
end
Rake::Task['test:scm:units'].comment = 'Run the scm unit tests'
Rake::TestTask.new(functionals: 'db:test:prepare') do |t|
t.libs << 'test'
t.verbose = true
t.test_files = FileList['test/functional/repositories*_test.rb']
end
Rake::Task['test:scm:functionals'].comment = 'Run the scm functional tests'
end
desc 'runs all tests'
namespace :suite do
task run: [:cucumber, :spec, 'spec:legacy']

@ -68,8 +68,4 @@ if [ $1 = 'units' ]; then
run "sudo apt-get install -qq pandoc"
fi
if [ $1 = 'spec_legacy' ]; then
run "bundle exec rake test:scm:setup:all"
fi
run "cp -rp public/assets/frontend_assets.manifest.json config/frontend_assets.manifest.json"

@ -399,7 +399,7 @@ describe WorkPackages::BulkController, type: :controller do
include_context 'update_request'
it 'does not succeed' do
expect(flash[:error]).to include(work_package_ids.join(', #'))
expect(assigns[:bulk_errors].keys).to match_array(work_package_ids)
expect(subject).to match_array [user.id]
end
end

@ -0,0 +1,124 @@
require 'spec_helper'
require 'features/page_objects/notification'
describe 'Bulk update work packages through Rails view', js: true do
let(:dev_role) do
FactoryBot.create :role,
permissions: %i[view_work_packages]
end
let(:mover_role) do
FactoryBot.create :role,
permissions: %i[view_work_packages copy_work_packages move_work_packages manage_subtasks add_work_packages]
end
let(:dev) do
FactoryBot.create :user,
firstname: 'Dev',
lastname: 'Guy',
member_in_project: project,
member_through_role: dev_role
end
let(:mover) do
FactoryBot.create :admin,
firstname: 'Manager',
lastname: 'Guy',
member_in_project: project,
member_through_role: mover_role
end
let(:type) { FactoryBot.create :type, name: 'Bug' }
let!(:project) { FactoryBot.create(:project, name: 'Source', types: [type]) }
let!(:status) { FactoryBot.create :status }
let!(:work_package) {
FactoryBot.create(:work_package,
author: dev,
status: status,
project: project,
type: type)
}
let!(:work_package2) {
FactoryBot.create(:work_package,
author: dev,
status: status,
project: project,
type: type)
}
let!(:status2) { FactoryBot.create :default_status }
let!(:workflow) do
FactoryBot.create :workflow,
type_id: type.id,
old_status: work_package.status,
new_status: status2,
role: mover_role
end
let(:wp_table) { ::Pages::WorkPackagesTable.new(project) }
let(:context_menu) { Components::WorkPackages::ContextMenu.new }
before do
login_as current_user
wp_table.visit!
expect_angular_frontend_initialized
wp_table.expect_work_package_listed work_package, work_package2
# Select all work packages
find('body').send_keys [:control, 'a']
end
describe 'copying work packages' do
context 'with permission' do
let(:current_user) { mover }
before do
context_menu.open_for work_package
context_menu.choose 'Bulk edit'
# On work packages edit page
expect(page).to have_selector('#work_package_status_id')
select status2.name, from: 'work_package_status_id'
end
it 'sets two statuses' do
click_on 'Submit'
expect_angular_frontend_initialized
wp_table.expect_work_package_count 2
# Should update the status
work_package2.reload
work_package.reload
expect(work_package.status_id).to eq(status2.id)
expect(work_package2.status_id).to eq(status2.id)
end
context 'when making an error in the form' do
it 'does not update the work packages' do
fill_in 'work_package_start_date', with: '123'
click_on 'Submit'
expect(page).to have_selector('.notification-box', text: I18n.t('work_packages.bulk.could_not_be_saved'))
expect(page).to have_selector('.notification-box', text: work_package.id)
expect(page).to have_selector('.notification-box', text: work_package2.id)
# Should not update the status
work_package2.reload
work_package.reload
expect(work_package.status_id).to eq(status.id)
expect(work_package2.status_id).to eq(status.id)
end
end
end
context 'without permission' do
let(:current_user) { dev }
it 'does not allow to copy' do
context_menu.open_for work_package
context_menu.expect_no_options 'Bulk edit'
end
end
end
end

@ -1,164 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require_relative '../legacy_spec_helper'
require 'repositories_controller'
describe RepositoriesController, type: :controller do
render_views
# We load legacy fixtures and repository
# but now have to override them with the temporary subversion
# repository, as the filesystem repository has been stripped.
fixtures :all
before do
unless repository_configured?('subversion')
skip 'Subversion test repository NOT FOUND. Skipping functional tests !!!'
end
end
let(:project) { Project.find(1) }
before do
User.current = nil
end
it 'should revisions' do
get :revisions, params: { project_id: 1 }
assert_response :success
assert_template 'revisions'
refute_nil assigns(:changesets)
end
it 'should revision' do
get :revision, params: { project_id: 1, rev: 1 }
assert_response :success
refute_nil assigns(:changeset)
assert_equal '1', assigns(:changeset).revision
end
it 'should revision with before nil and after normal' do
get :revision, params: { project_id: 1, rev: 1 }
assert_response :success
assert_template 'revision'
assert_select('ul',
{
attributes: { class: 'toolbar-items' },
descendant: {
tag: 'a',
attributes: {
href: @controller.url_for(
only_path: true,
controller: 'repositories',
action: 'revision',
project_id: 'ecookbook',
rev: '0'
)
}
}
}, false)
assert_select 'ul',
attributes: { class: 'toolbar-items' },
descendant: {
tag: 'a',
attributes: {
href: @controller.url_for(
only_path: true,
controller: 'repositories',
action: 'revision',
project_id: 'ecookbook',
rev: '2'
)
}
}
end
it 'should graph commits per month' do
get :graph, params: { project_id: 1, graph: 'commits_per_month' }
assert_response :success
assert_equal 'image/svg+xml', response.content_type
end
it 'should committers' do
session[:user_id] = 2
# add a commit with an unknown user
Changeset.create!(
repository: Project.find(1).repository,
committer: 'foo',
committed_on: Time.now,
revision: 100,
comments: 'Committed by foo.'
)
get :committers, params: { project_id: 1 }
assert_response :success
assert_template 'committers'
assert_select 'td',
content: 'foo',
sibling: {
tag: 'td',
child: {
tag: 'select',
attributes: { name: %r{^committers\[\d+\]\[\]$} }
}
}
assert_select('td',
{
content: 'foo',
sibling: {
tag: 'td',
descendant: { tag: 'option', attributes: { selected: 'selected' } }
}
}, false)
end
it 'should map committers' do
session[:user_id] = 2
# add a commit with an unknown user
c = Changeset.create!(
repository: Project.find(1).repository,
committer: 'foo',
committed_on: Time.now,
revision: 100,
comments: 'Committed by foo.'
)
assert_no_difference "Changeset.where('user_id = 3').count" do
post :committers,
params: {
project_id: 1,
committers: { '0' => ['foo', '2'],
'1' => ['dlopper', '3'] }
}
assert_redirected_to '/projects/ecookbook/repository/committers'
assert_equal User.find(2), c.reload.user
end
end
end

@ -1,255 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require_relative '../legacy_spec_helper'
require 'repositories_controller'
describe RepositoriesController, 'Git', type: :controller do
render_views
fixtures :all
# No '..' in the repository path
let(:git_repository_path) {
path = Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository'
path.gsub!(/\//, '\\') if Redmine::Platform.mswin?
path
}
before do
skip 'Git test repository NOT FOUND. Skipping functional tests !!!' unless File.directory?(git_repository_path)
User.current = nil
@repository = Repository::Git.create(
project: Project.find(3),
scm_type: 'local',
url: git_repository_path,
path_encoding: 'ISO-8859-1'
)
assert @repository
end
it 'should browse root' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: 3 }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assert_equal 10, assigns(:entries).size
assert assigns(:entries).detect { |e| e.name == 'images' && e.kind == 'dir' }
assert assigns(:entries).detect { |e| e.name == 'this_is_a_really_long_and_verbose_directory_name' && 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' }
assert assigns(:entries).detect { |e| e.name == 'copied_README' && e.kind == 'file' }
assert assigns(:entries).detect { |e| e.name == 'new_file.txt' && e.kind == 'file' }
assert assigns(:entries).detect { |e| e.name == 'renamed_test.txt' && e.kind == 'file' }
assert assigns(:entries).detect { |e| e.name == 'filemane with spaces.txt' && e.kind == 'file' }
assert assigns(:entries).detect { |e| e.name == ' filename with a leading space.txt ' && e.kind == 'file' }
refute_nil assigns(:changesets)
assigns(:changesets).size > 0
end
it 'should browse branch' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: 3, rev: 'test_branch' }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assert_equal 4, 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' }
assert assigns(:entries).detect { |e| e.name == 'test.txt' && e.kind == 'file' }
refute_nil assigns(:changesets)
assigns(:changesets).size > 0
end
it 'should browse tag' do
@repository.fetch_changesets
@repository.reload
[
'tag00.lightweight',
'tag01.annotated',
].each do |t1|
get :show, params: { project_id: 3, rev: t1 }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assigns(:entries).size > 0
refute_nil assigns(:changesets)
assigns(:changesets).size > 0
end
end
it 'should browse directory' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: 3, repo_path: 'images' }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assert_equal ['edit.png'], assigns(:entries).map(&:name)
entry = assigns(:entries).detect { |e| e.name == 'edit.png' }
refute_nil entry
assert_equal 'file', entry.kind
assert_equal 'images/edit.png', entry.path
refute_nil assigns(:changesets)
assigns(:changesets).size > 0
end
it 'should browse at given revision' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: 3, repo_path: 'images', rev: '7234cb2750b63f47bff735edc50a1c0a433c2518' }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assert_equal ['delete.png'], assigns(:entries).map(&:name)
refute_nil assigns(:changesets)
assigns(:changesets).size > 0
end
it 'should changes' do
get :changes, params: { project_id: 3, repo_path: 'images/edit.png' }
assert_response :success
assert_template 'changes'
assert_select 'div',
attributes: { class: 'repository-breadcrumbs' },
content: 'edit.png'
end
it 'should entry show' do
get :entry, params: { project_id: 3, repo_path: 'sources/watchers_controller.rb' }
assert_response :success
assert_template 'entry'
# Line 19
assert_select 'th',
content: /11/,
attributes: { class: /line-num/ },
sibling: { tag: 'td', content: /WITHOUT ANY WARRANTY/ }
end
it 'should entry download' do
get :entry, params: { project_id: 3, repo_path: 'sources/watchers_controller.rb', format: 'raw' }
assert_response :success
# File content
assert response.body.include?('WITHOUT ANY WARRANTY')
end
it 'should directory entry' do
get :entry, params: { project_id: 3, repo_path: 'sources' }
assert_response :success
assert_template 'show'
refute_nil assigns(:entry)
assert_equal 'sources', assigns(:entry).name
end
it 'should diff' do
@repository.fetch_changesets
@repository.reload
# Full diff of changeset 2f9c0091
get :diff, params: { project_id: 3, rev: '2f9c0091c754a91af7a9c478e36556b4bde8dcf7' }
assert_response :success
assert_template 'diff'
# Line 22 removed
assert_select 'th',
content: /22/,
sibling: { tag: 'td',
attributes: { class: /diff_out/ },
content: /def remove/ }
assert_select 'h2', content: /2f9c0091/
end
it 'should diff two revs' do
@repository.fetch_changesets
@repository.reload
get :diff, params: { project_id: 3, rev: '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
rev_to: '2f9c0091c754a91af7a9c478e36556b4bde8dcf7' }
assert_response :success
assert_template 'diff'
diff = assigns(:diff)
refute_nil diff
assert_select 'h2', content: /2f9c0091:61b685fb/
end
it 'should annotate' do
get :annotate, params: { project_id: 3, repo_path: 'sources/watchers_controller.rb' }
assert_response :success
assert_template 'annotate'
# Line 23, changeset 2f9c0091
assert_select 'th', content: /24/,
sibling: { tag: 'td', child: { tag: 'a', content: /2f9c0091/ } },
sibling: { tag: 'td', content: /jsmith/ },
sibling: { tag: 'td', content: /watcher =/ }
end
it 'should annotate at given revision' do
@repository.fetch_changesets
@repository.reload
get :annotate, params: { project_id: 3, rev: 'deff7', repo_path: 'sources/watchers_controller.rb' }
assert_response :success
assert_template 'annotate'
assert_select 'div',
attributes: { class: 'repository-breadcrumbs' },
content: /at deff712f/
end
it 'should annotate binary file' do
get :annotate, params: { project_id: 3, repo_path: 'images/edit.png' }
assert_response 200
assert_select 'p', attributes: { class: /nodata/ },
content: I18n.t('repositories.warnings.cannot_annotate')
end
it 'should revision' do
@repository.fetch_changesets
@repository.reload
['61b685fbe55ab05b5ac68402d5720c1a6ac973d1', '61b685f'].each do |r|
get :revision, params: { project_id: 3, rev: r }
assert_response :success
assert_template 'revision'
end
end
it 'should empty revision' do
@repository.fetch_changesets
@repository.reload
['', ' ', nil].each do |r|
get :revision, params: { project_id: 3, rev: r }
assert_response 404
assert_error_tag content: /was not found/
end
end
end

@ -1,302 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require_relative '../legacy_spec_helper'
require 'repositories_controller'
describe RepositoriesController, 'Subversion', type: :controller do
render_views
fixtures :all
PRJ_ID = 3
before do
skip 'Subversion test repository NOT FOUND. Skipping functional tests !!!' unless repository_configured?('subversion')
Setting.default_language = 'en'
User.current = nil
@project = Project.find(PRJ_ID)
@repository = Repository::Subversion.create(project: @project,
scm_type: 'local',
url: self.class.subversion_repository_url)
assert @repository
end
it 'should show' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: PRJ_ID }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
refute_nil assigns(:changesets)
end
it 'should browse root' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: PRJ_ID }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
entry = assigns(:entries).detect { |e| e.name == 'subversion_test' }
assert_equal 'dir', entry.kind
end
it 'should browse directory' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: PRJ_ID, repo_path: 'subversion_test' }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assert_equal ['[folder_with_brackets]', 'folder', '.project', 'helloworld.c', 'textfile.txt'], assigns(:entries).map(&:name)
entry = assigns(:entries).detect { |e| e.name == 'helloworld.c' }
assert_equal 'file', entry.kind
assert_equal 'subversion_test/helloworld.c', entry.path
assert_select 'a', content: 'helloworld.c', attributes: { class: /text\-x\-c/ }
end
it 'should browse at given revision' do
@repository.fetch_changesets
@repository.reload
get :show, params: { project_id: PRJ_ID, repo_path: 'subversion_test', rev: 4 }
assert_response :success
assert_template 'show'
refute_nil assigns(:entries)
assert_equal ['folder', '.project', 'helloworld.c', 'helloworld.rb', 'textfile.txt'], assigns(:entries).map(&:name)
end
it 'should file changes' do
@repository.fetch_changesets
@repository.reload
get :changes, params: { project_id: PRJ_ID, repo_path: 'subversion_test/folder/helloworld.rb' }
assert_response :success
assert_template 'changes'
changesets = assigns(:changesets)
refute_nil changesets
assert_equal %w(6 3 2), changesets.map(&:revision)
# svn properties displayed with svn >= 1.5 only
if @repository.scm.client_version_above?([1, 5, 0])
refute_nil assigns(:properties)
assert_equal 'native', assigns(:properties)['svn:eol-style']
assert_select 'ul',
child: { tag: 'li',
child: { tag: 'b', content: 'svn:eol-style' },
child: { tag: 'span', content: 'native' } }
end
end
it 'should directory changes' do
@repository.fetch_changesets
@repository.reload
get :changes, params: { project_id: PRJ_ID, repo_path: 'subversion_test/folder' }
assert_response :success
assert_template 'changes'
changesets = assigns(:changesets)
refute_nil changesets
assert_equal %w(10 9 7 6 5 2), changesets.map(&:revision)
end
it 'should entry' do
@repository.fetch_changesets
@repository.reload
get :entry, params: { project_id: PRJ_ID, repo_path: 'subversion_test/helloworld.c' }
assert_response :success
assert_template 'entry'
end
context 'small file upload size',
with_settings: { file_max_size_displayed: 0 } do
it 'should entry should send if too big' do
@repository.fetch_changesets
@repository.reload
get :entry, params: { project_id: PRJ_ID, repo_path: 'subversion_test/helloworld.c' }
assert_response :success
assert_template nil
assert_equal 'attachment; filename="helloworld.c"', response.headers['Content-Disposition']
end
end
it 'should entry at given revision' do
@repository.fetch_changesets
@repository.reload
get :entry, params: { project_id: PRJ_ID, repo_path: 'subversion_test/helloworld.rb', rev: 2 }
assert_response :success
assert_template 'entry'
# this line was removed in r3 and file was moved in r6
assert_select 'td', attributes: { class: /line-code/ },
content: /Here's the code/
end
it 'should entry not found' do
@repository.fetch_changesets
@repository.reload
get :entry, params: { project_id: PRJ_ID, repo_path: 'subversion_test/zzz.c' }
assert_select 'div', attributes: { id: /errorExplanation/ },
content: /The entry or revision was not found in the repository/
end
it 'should entry download' do
@repository.fetch_changesets
@repository.reload
get :entry, params: { project_id: PRJ_ID, repo_path: 'subversion_test/helloworld.c', format: 'raw' }
assert_response :success
assert_template nil
assert_equal 'attachment; filename="helloworld.c"', response.headers['Content-Disposition']
end
it 'should directory entry' do
@repository.fetch_changesets
@repository.reload
get :entry, params: { project_id: PRJ_ID, repo_path: 'subversion_test/folder' }
assert_response :success
assert_template 'show'
refute_nil assigns(:entry)
assert_equal 'folder', assigns(:entry).name
end
# TODO: this test needs fixtures.
it 'should revision' do
@repository.fetch_changesets
@repository.reload
get :revision, params: { project_id: 1, rev: 2 }
assert_response :success
assert_template 'revision'
assert_select 'ul',
child: { tag: 'li',
# link to the entry at rev 2
child: { tag: 'a',
attributes: { href: '/projects/ecookbook/repository/revisions/2/entry/test/some/path/in/the/repo' },
content: 'repo',
# link to partial diff
sibling: { tag: 'a',
attributes: { href: '/projects/ecookbook/repository/revisions/2/diff/test/some/path/in/the/repo' }
}
}
}
end
it 'should invalid revision' do
@repository.fetch_changesets
@repository.reload
get :revision, params: { project_id: PRJ_ID, rev: 'something_weird' }
assert_response 404
assert_error_tag content: /was not found/
end
it 'should invalid revision diff' do
get :diff, params: { project_id: PRJ_ID, rev: '1', rev_to: 'something_weird' }
assert_response 404
assert_error_tag content: /was not found/
end
it 'should empty revision' do
@repository.fetch_changesets
@repository.reload
['', ' ', nil].each do |r|
get :revision, params: { project_id: PRJ_ID, rev: r }
assert_response 404
assert_error_tag content: /was not found/
end
end
# TODO: this test needs fixtures.
it 'should revision with repository pointing to a subdirectory' do
r = Project.find(1).repository
# Changes repository url to a subdirectory
r.update_attribute :url, (r.url + '/subversion_test/folder/')
get :revision, params: { project_id: 1, rev: 2 }
assert_response :success
assert_template 'revision'
assert_select 'ul',
child: { tag: 'li',
# link to the entry at rev 2
child: { tag: 'a',
attributes: { href: '/projects/ecookbook/repository/revisions/2/entry/test/some/path/in/the/repo' },
content: 'repo',
# link to partial diff
sibling: { tag: 'a',
attributes: { href: '/projects/ecookbook/repository/revisions/2/diff/test/some/path/in/the/repo' }
}
}
}
end
it 'should revision diff' do
@repository.fetch_changesets
@repository.reload
get :diff, params: { project_id: PRJ_ID, rev: 3 }
assert_response :success
assert_template 'diff'
assert_select 'h2', content: /3/
end
it 'should directory diff' do
@repository.fetch_changesets
@repository.reload
get :diff, params: { project_id: PRJ_ID, rev: 6, rev_to: 2, repo_path: 'subversion_test/folder' }
assert_response :success
assert_template 'diff'
diff = assigns(:diff)
refute_nil diff
# 2 files modified
assert_equal 2, Redmine::UnifiedDiff.new(diff).size
assert_select 'h2', content: /2:6/
end
it 'should annotate' do
@repository.fetch_changesets
@repository.reload
get :annotate, params: { project_id: PRJ_ID, repo_path: 'subversion_test/helloworld.c' }
assert_response :success
assert_template 'annotate'
end
it 'should annotate at given revision' do
@repository.fetch_changesets
@repository.reload
get :annotate, params: { project_id: PRJ_ID, rev: 8, repo_path: 'subversion_test/helloworld.c' }
assert_response :success
assert_template 'annotate'
assert_select 'div',
attributes: { class: 'repository-breadcrumbs' },
content: /at 8/
end
end

@ -1,254 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
# This file includes UTF-8 "Felix Schäfer".
# We need to consider Ruby 1.9 compatibility.
require 'legacy_spec_helper'
describe OpenProject::Scm::Adapters::Git, type: :model do
let(:git_repository_path) { Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository' }
FELIX_UTF8 = 'Felix Schäfer'
FELIX_HEX = "Felix Sch\xC3\xA4fer"
CHAR_1_HEX = "\xc3\x9c"
## Ruby uses ANSI api to fork a process on Windows.
## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
## and these are incompatible with ASCII.
# WINDOWS_PASS1 = Redmine::Platform.mswin?
WINDOWS_PASS1 = false
before do
skip 'Git test repository NOT FOUND. Skipping unit tests !!!' unless File.directory?(git_repository_path)
@adapter = OpenProject::Scm::Adapters::Git.new(
git_repository_path,
nil,
nil,
nil,
'ISO-8859-1'
)
assert @adapter
@char_1 = CHAR_1_HEX.dup
if @char_1.respond_to?(:force_encoding)
@char_1.force_encoding('UTF-8')
end
end
it 'should scm version' do
to_test = { "git version 1.7.3.4\n" => [1, 7, 3, 4],
"1.6.1\n1.7\n1.8" => [1, 6, 1],
"1.6.2\r\n1.8.1\r\n1.9.1" => [1, 6, 2] }
to_test.each do |s, v|
test_scm_version_for(s, v)
end
end
it 'should branches' do
assert_equal [
'latin-1-path-encoding',
'master',
'test-latin-1',
'test_branch',
], @adapter.branches
end
it 'should tags' do
assert_equal [
'tag00.lightweight',
'tag01.annotated',
], @adapter.tags
end
it 'should getting all revisions' do
assert_equal 22, @adapter.revisions('', nil, nil, all: true).length
end
it 'should getting certain revisions' do
assert_equal 1, @adapter.revisions('', '899a15d^', '899a15d').length
end
it 'should revisions reverse' do
revs1 = @adapter.revisions('', nil, nil, all: true, reverse: true)
assert_equal 22, revs1.length
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[0].identifier
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[20].identifier
since2 = Time.gm(2010, 9, 30, 0, 0, 0)
revs2 = @adapter.revisions('', nil, nil, all: true, since: since2, reverse: true)
assert_equal 7, revs2.length
assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', revs2[0].identifier
assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[5].identifier
assert_equal '71e5c1d3dca6304805b143b9d0e6695fb3895ea4', revs2[6].identifier
end
it 'should getting revisions with spaces in filename' do
assert_equal 1, @adapter.revisions('filemane with spaces.txt',
nil, nil, all: true).length
end
it 'should getting revisions with leading and trailing spaces in filename' do
assert_equal ' filename with a leading space.txt ',
@adapter.revisions(' filename with a leading space.txt ',
nil, nil, all: true)[0].paths[0][:path]
end
it 'should getting entries with leading and trailing spaces in filename' do
assert_equal ' filename with a leading space.txt ',
@adapter.entries('',
'83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
end
it 'should annotate' do
annotate = @adapter.annotate('sources/watchers_controller.rb')
assert_kind_of OpenProject::Scm::Adapters::Annotate, annotate
assert_equal 41, annotate.lines.size
assert_equal '# This program is free software; you can redistribute it and/or',
annotate.lines[4].strip
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518',
annotate.revisions[4].identifier
assert_equal 'jsmith', annotate.revisions[4].author
end
it 'should annotate moved file' do
annotate = @adapter.annotate('renamed_test.txt')
assert_kind_of OpenProject::Scm::Adapters::Annotate, annotate
assert_equal 2, annotate.lines.size
end
it 'should last rev' do
last_rev = @adapter.lastrev('README',
'4f26664364207fa8b1af9f8722647ab2d4ac5d43')
assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', last_rev.scmid
assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', last_rev.identifier
assert_equal 'Adam Soltys <asoltys@gmail.com>', last_rev.author
assert_equal '2009-06-24 05:27:38 +0000'.to_time, last_rev.time
end
it 'should last rev with spaces in filename' do
last_rev = @adapter.lastrev('filemane with spaces.txt',
'ed5bb786bbda2dee66a2d50faf51429dbc043a7b')
str_felix_utf8 = FELIX_UTF8.dup
str_felix_hex = FELIX_HEX.dup
last_rev_author = last_rev.author
if last_rev_author.respond_to?(:force_encoding)
last_rev_author.force_encoding('UTF-8')
end
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', last_rev.scmid
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', last_rev.identifier
assert_equal "#{str_felix_utf8} <felix@fachschaften.org>",
last_rev.author
assert_equal "#{str_felix_hex} <felix@fachschaften.org>",
last_rev.author
assert_equal '2010-09-18 19:59:46 +0000'.to_time, last_rev.time
end
it 'test latin 1 path' do
if WINDOWS_PASS1
#
else
p2 = "latin-1-dir/test-#{@char_1}-2.txt"
['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
assert @adapter.diff(p2, r1)
assert @adapter.cat(p2, r1)
annotation = @adapter.annotate(p2, r1)
assert annotation.present?, 'No annotation returned'
assert_equal 1, annotation.lines.length
['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
assert @adapter.diff(p2, r1, r2)
end
end
end
end
it 'should entries tag' do
entries1 = @adapter.entries(nil, 'tag01.annotated')
assert entries1
assert_equal 3, entries1.size
assert_equal 'sources', entries1[1].name
assert_equal 'sources', entries1[1].path
assert_equal 'dir', entries1[1].kind
readme = entries1[2]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 27, readme.size
assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
end
it 'should entries branch' do
entries1 = @adapter.entries(nil, 'test_branch')
assert entries1
assert_equal 4, entries1.size
assert_equal 'sources', entries1[1].name
assert_equal 'sources', entries1[1].path
assert_equal 'dir', entries1[1].kind
readme = entries1[2]
assert_equal 'README', readme.name
assert_equal 'README', readme.path
assert_equal 'file', readme.kind
assert_equal 159, readme.size
assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
end
it 'should entries latin 1 files' do
entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
assert entries1
assert_equal 3, entries1.size
f1 = entries1[1]
assert_equal "test-#{@char_1}-2.txt", f1.name
assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
assert_equal 'file', f1.kind
end
it 'should entries latin 1 dir' do
if WINDOWS_PASS1
#
else
entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
'1ca7f5ed')
assert entries1
assert_equal 3, entries1.size
f1 = entries1[1]
assert_equal "test-#{@char_1}-2.txt", f1.name
assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
assert_equal 'file', f1.kind
end
end
private
def test_scm_version_for(scm_command_version, version)
expect(@adapter).to receive(:scm_version_from_command_line).and_return(scm_command_version)
assert_equal version, @adapter.git_binary_version
end
end

@ -1,64 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'legacy_spec_helper'
describe OpenProject::Scm::Adapters::Subversion, type: :model do
if repository_configured?('subversion')
before do
@adapter = OpenProject::Scm::Adapters::Subversion.new(self.class.subversion_repository_url)
end
it 'should client version' do
v = @adapter.client_version
assert v.is_a?(Array)
end
it 'should scm version' do
to_test = { "svn, version 1.6.13 (r1002816)\n" => [1, 6, 13],
"svn, versione 1.6.13 (r1002816)\n" => [1, 6, 13],
"1.6.1\n1.7\n1.8" => [1, 6, 1],
"1.6.2\r\n1.8.1\r\n1.9.1" => [1, 6, 2] }
to_test.each do |s, v|
test_scm_version_for(s, v)
end
end
private
def test_scm_version_for(scm_version, version)
expect(@adapter).to receive(:scm_version_from_command_line).and_return(scm_version)
assert_equal version, @adapter.svn_binary_version
end
else
puts 'Subversion test repository NOT FOUND. Skipping unit tests !!!'
it 'should fake' do; assert true end
end
end

@ -1,338 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'legacy_spec_helper'
describe Repository::Git, type: :model do
fixtures :all
# No '..' in the repository path
let(:git_repository_path) {
path = Rails.root.to_s.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository'
path.gsub!(/\//, '\\') if Redmine::Platform.mswin?
path
}
FELIX_HEX2 = "Felix Sch\xC3\xA4fer"
CHAR_1_HEX2 = "\xc3\x9c"
## Ruby uses ANSI api to fork a process on Windows.
## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
## and these are incompatible with ASCII.
# WINDOWS_PASS = Redmine::Platform.mswin?
WINDOWS_PASS = false
before do
skip 'Git test repository NOT FOUND. Skipping unit tests !!!' unless File.directory?(git_repository_path)
@project = Project.find(3)
@repository = Repository::Git.create(
project: @project,
scm_type: 'local',
url: git_repository_path,
path_encoding: 'ISO-8859-1'
)
assert @repository
@char_1 = CHAR_1_HEX2.dup
if @char_1.respond_to?(:force_encoding)
@char_1.force_encoding('UTF-8')
end
end
it 'should fetch changesets from scratch' do
@repository.fetch_changesets
@repository.reload
assert_equal 22, @repository.changesets.count
file_count = @repository.file_changes.count
assert([33,34].include? file_count) # Mac OS X reports one file less changed
commit = @repository.changesets.reorder(Arel.sql('committed_on ASC')).first
assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments
assert_equal 'jsmith <jsmith@foo.bar>', commit.committer
assert_equal User.find_by_login('jsmith'), commit.user
# TODO: add a commit with commit time <> author time to the test repository
assert_equal '2007-12-14 09:22:52 +0000'.to_time, commit.committed_on
assert_equal '2007-12-14'.to_date, commit.commit_date
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', commit.revision
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', commit.scmid
assert_equal 3, commit.file_changes.count
change = commit.file_changes.sort_by(&:path).first
assert_equal 'README', change.path
assert_equal 'A', change.action
end
it 'should fetch changesets incremental' do
@repository.fetch_changesets
# Remove the 3 latest changesets
@repository.changesets.order(Arel.sql('committed_on DESC')).limit(8).each(&:destroy)
@repository.reload
cs1 = @repository.changesets
assert_equal 14, cs1.count
rev_a_commit = @repository.changesets.order(Arel.sql('committed_on DESC')).first
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', rev_a_commit.revision
# Mon Jul 5 22:34:26 2010 +0200
rev_a_committed_on = Time.gm(2010, 9, 18, 19, 59, 46)
assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', rev_a_commit.scmid
assert_equal rev_a_committed_on, rev_a_commit.committed_on
latest_rev = @repository.latest_changeset
assert_equal rev_a_committed_on, latest_rev.committed_on
@repository.fetch_changesets
assert_equal 22, @repository.changesets.count
end
it 'should latest changesets' do
@repository.fetch_changesets
@repository.reload
# with limit
changesets = @repository.latest_changesets('', nil, 2)
assert_equal 2, changesets.size
# with path
changesets = @repository.latest_changesets('images', nil)
assert_equal [
'deff712f05a90d96edbd70facc47d944be5897e3',
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', nil)
assert_equal [
'32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf',
'4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8',
'713f4944648826f558cf548222f813dabe7cbb04',
'61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
# with path, revision and limit
changesets = @repository.latest_changesets('images', '899a15dba')
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('images', '899a15dba', 1)
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', '899a15dba')
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', '899a15dba', 1)
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
], changesets.map(&:revision)
# with path, tag and limit
changesets = @repository.latest_changesets('images', 'tag01.annotated')
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('images', 'tag01.annotated', 1)
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', 'tag01.annotated')
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', 'tag01.annotated', 1)
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
], changesets.map(&:revision)
# with path, branch and limit
changesets = @repository.latest_changesets('images', 'test_branch')
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('images', 'test_branch', 1)
assert_equal [
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', 'test_branch')
assert_equal [
'713f4944648826f558cf548222f813dabe7cbb04',
'61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
'899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
'7234cb2750b63f47bff735edc50a1c0a433c2518',
], changesets.map(&:revision)
changesets = @repository.latest_changesets('README', 'test_branch', 2)
assert_equal [
'713f4944648826f558cf548222f813dabe7cbb04',
'61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
], changesets.map(&:revision)
# latin-1 encoding path
changesets = @repository.latest_changesets(
"latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89')
assert_equal [
'64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
'4fc55c43bf3d3dc2efb66145365ddc17639ce81e',
], changesets.map(&:revision)
changesets = @repository.latest_changesets(
"latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89', 1)
assert_equal [
'64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
], changesets.map(&:revision)
end
it 'should latest changesets latin 1 dir' do
if WINDOWS_PASS
#
else
@repository.fetch_changesets
@repository.reload
changesets = @repository.latest_changesets(
"latin-1-dir/test-#{@char_1}-subdir", '1ca7f5ed')
assert_equal [
'1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127',
], changesets.map(&:revision)
end
end
it 'should find changeset by name' do
@repository.fetch_changesets
@repository.reload
['7234cb2750b63f47bff735edc50a1c0a433c2518', '7234cb2750b'].each do |r|
assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518',
@repository.find_changeset_by_name(r).revision
end
end
it 'should find changeset by empty name' do
@repository.fetch_changesets
@repository.reload
['', ' ', nil].each do |r|
assert_nil @repository.find_changeset_by_name(r)
end
end
it 'should identifier' do
@repository.fetch_changesets
@repository.reload
c = @repository.changesets.find_by(revision: '7234cb2750b63f47bff735edc50a1c0a433c2518')
assert_equal c.scmid, c.identifier
end
it 'should format identifier' do
@repository.fetch_changesets
@repository.reload
c = @repository.changesets.find_by(revision: '7234cb2750b63f47bff735edc50a1c0a433c2518')
assert_equal '7234cb27', c.format_identifier
end
it 'should activities' do
c = Changeset.create(repository: @repository,
committed_on: Time.now,
revision: 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
scmid: 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
comments: 'test')
event = find_events(User.find(2)).first # manager
assert event.event_title.include?('abc7234c:')
assert event.event_path =~ /\?rev=abc7234cb2750b63f47bff735edc50a1c0a433c2$/
end
it 'should log utf8' do
@repository.fetch_changesets
@repository.reload
str_felix_hex = FELIX_HEX2.dup
if str_felix_hex.respond_to?(:force_encoding)
str_felix_hex.force_encoding('UTF-8')
end
c = @repository.changesets.find_by(revision: 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b')
assert_equal "#{str_felix_hex} <felix@fachschaften.org>", c.committer
end
it 'should previous' do
@repository.fetch_changesets
@repository.reload
%w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
changeset = @repository.find_changeset_by_name(r1)
%w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
assert_equal @repository.find_changeset_by_name(r2), changeset.previous
end
end
end
it 'should previous nil' do
@repository.fetch_changesets
@repository.reload
%w|7234cb2750b63f47bff735edc50a1c0a433c2518 7234cb2|.each do |r1|
changeset = @repository.find_changeset_by_name(r1)
assert_nil changeset.previous
end
end
it 'should next' do
@repository.fetch_changesets
@repository.reload
%w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
changeset = @repository.find_changeset_by_name(r2)
%w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
assert_equal @repository.find_changeset_by_name(r1), changeset.next
end
end
end
it 'should next nil' do
@repository.fetch_changesets
@repository.reload
%w|71e5c1d3dca6304805b143b9d0e6695fb3895ea4 71e5c1d3|.each do |r1|
changeset = @repository.find_changeset_by_name(r1)
assert_nil changeset.next
end
end
private
def find_events(user, options = {})
fetcher = Redmine::Activity::Fetcher.new(user, options)
fetcher.scope = ['changesets']
fetcher.events(Date.today - 30, Date.today + 1)
end
end

@ -1,212 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 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.
#
# 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.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'legacy_spec_helper'
describe Repository::Subversion, type: :model do
fixtures :all
before do
skip 'Subversion test repository NOT FOUND. Skipping unit tests !!!' unless repository_configured?('subversion')
@project = Project.find(3)
@repository = Repository::Subversion.create(project: @project,
scm_type: 'existing',
url: self.class.subversion_repository_url)
assert @repository
end
it 'should fetch changesets from scratch' do
@repository.fetch_changesets
@repository.reload
assert_equal 14, @repository.changesets.count
assert_equal 34, @repository.file_changes.count
assert_equal 'Initial import.', @repository.changesets.find_by(revision: '1').comments
end
it 'should fetch changesets incremental' do
@repository.fetch_changesets
# Remove changesets with revision > 5
@repository.changesets.each do |c| c.destroy if c.revision.to_i > 5 end
@repository.reload
assert_equal 5, @repository.changesets.count
@repository.fetch_changesets
assert_equal 14, @repository.changesets.count
end
it 'should latest changesets' do
@repository.fetch_changesets
# with limit
changesets = @repository.latest_changesets('', nil, 2)
assert_equal 2, changesets.size
assert_equal @repository.latest_changesets('', nil).take(2), changesets
# with path
changesets = @repository.latest_changesets('subversion_test/folder', nil)
assert_equal ['10', '9', '7', '6', '5', '2'], changesets.map(&:revision)
# with path and revision
changesets = @repository.latest_changesets('subversion_test/folder', 8)
assert_equal ['7', '6', '5', '2'], changesets.map(&:revision)
end
it 'should directory listing with square brackets in path' do
@repository.fetch_changesets
@repository.reload
entries = @repository.entries('subversion_test/[folder_with_brackets]')
refute_nil entries, 'Expect to find entries in folder_with_brackets'
assert_equal 1, entries.size, 'Expect one entry in folder_with_brackets'
assert_equal 'README.txt', entries.first.name
end
it 'should directory listing with square brackets in base' do
@project = Project.find(3)
@repository = Repository::Subversion.create(
project: @project,
scm_type: 'local',
url: "file:///#{self.class.repository_path('subversion')}/subversion_test/[folder_with_brackets]")
@repository.fetch_changesets
@repository.reload
assert_equal 1, @repository.changesets.count, 'Expected to see 1 revision'
assert_equal 2, @repository.file_changes.count, 'Expected to see 2 changes, dir add and file add'
entries = @repository.entries('')
refute_nil entries, 'Expect to find entries'
assert_equal 1, entries.size, 'Expect a single entry'
assert_equal 'README.txt', entries.first.name
end
it 'should identifier' do
@repository.fetch_changesets
@repository.reload
c = @repository.changesets.find_by(revision: '1')
assert_equal c.revision, c.identifier
end
it 'should find changeset by empty name' do
@repository.fetch_changesets
@repository.reload
['', ' ', nil].each do |r|
assert_nil @repository.find_changeset_by_name(r)
end
end
it 'should identifier nine digit' do
c = Changeset.new(repository: @repository, committed_on: Time.now,
revision: '123456789', comments: 'test')
assert_equal c.identifier, c.revision
end
it 'should format identifier' do
@repository.fetch_changesets
@repository.reload
c = @repository.changesets.find_by(revision: '1')
assert_equal c.format_identifier, c.revision
end
it 'should format identifier nine digit' do
c = Changeset.new(repository: @repository, committed_on: Time.now,
revision: '123456789', comments: 'test')
assert_equal c.format_identifier, c.revision
end
it 'should activities' do
c = Changeset.create(repository: @repository, committed_on: Time.now,
revision: '1', comments: 'test')
event = find_events(User.find(2)).first # manager
assert event.event_title.include?('1:')
assert event.event_path =~ /\?rev=1$/
end
it 'should activities nine digit' do
c = Changeset.create(repository: @repository, committed_on: Time.now,
revision: '123456789', comments: 'test')
event = find_events(User.find(2)).first # manager
assert event.event_title.include?('123456789:')
assert event.event_path =~ /\?rev=123456789$/
end
it 'should log encoding ignore setting' do
Setting.commit_logs_encoding = 'windows-1252'
s1 = "\xC2\x80"
s2 = "\xc3\x82\xc2\x80"
if s1.respond_to?(:force_encoding)
s1.force_encoding('ISO-8859-1')
s2.force_encoding('UTF-8')
assert_equal s1.encode('UTF-8'), s2
end
c = Changeset.new(repository: @repository,
comments: s2,
revision: '123',
committed_on: Time.now)
assert c.save
assert_equal s2, c.comments
end
it 'should previous' do
@repository.fetch_changesets
@repository.reload
changeset = @repository.find_changeset_by_name('3')
assert_equal @repository.find_changeset_by_name('2'), changeset.previous
end
it 'should previous nil' do
@repository.fetch_changesets
@repository.reload
changeset = @repository.find_changeset_by_name('1')
assert_nil changeset.previous
end
it 'should next' do
@repository.fetch_changesets
@repository.reload
changeset = @repository.find_changeset_by_name('2')
assert_equal @repository.find_changeset_by_name('3'), changeset.next
end
it 'should next nil' do
@repository.fetch_changesets
@repository.reload
changeset = @repository.find_changeset_by_name('14')
assert_nil changeset.next
end
private
def find_events(user, options = {})
fetcher = Redmine::Activity::Fetcher.new(user, options)
fetcher.scope = ['changesets']
fetcher.events(Date.today - 30, Date.today + 1)
end
end
Loading…
Cancel
Save