Revision 1298:4f746d8966dd .svn/pristine/39
| .svn/pristine/39/390e71b002ea8073c16b9d8e33ea8c3450b2266a.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2011 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
require File.expand_path('../../../../test_helper', __FILE__)
|
|
| 19 |
|
|
| 20 |
class Redmine::PluginTest < ActiveSupport::TestCase |
|
| 21 |
|
|
| 22 |
def setup |
|
| 23 |
@klass = Redmine::Plugin |
|
| 24 |
# In case some real plugins are installed |
|
| 25 |
@klass.clear |
|
| 26 |
end |
|
| 27 |
|
|
| 28 |
def teardown |
|
| 29 |
@klass.clear |
|
| 30 |
end |
|
| 31 |
|
|
| 32 |
def test_register |
|
| 33 |
@klass.register :foo do |
|
| 34 |
name 'Foo plugin' |
|
| 35 |
url 'http://example.net/plugins/foo' |
|
| 36 |
author 'John Smith' |
|
| 37 |
author_url 'http://example.net/jsmith' |
|
| 38 |
description 'This is a test plugin' |
|
| 39 |
version '0.0.1' |
|
| 40 |
settings :default => {'sample_setting' => 'value', 'foo'=>'bar'}, :partial => 'foo/settings'
|
|
| 41 |
end |
|
| 42 |
|
|
| 43 |
assert_equal 1, @klass.all.size |
|
| 44 |
|
|
| 45 |
plugin = @klass.find('foo')
|
|
| 46 |
assert plugin.is_a?(Redmine::Plugin) |
|
| 47 |
assert_equal :foo, plugin.id |
|
| 48 |
assert_equal 'Foo plugin', plugin.name |
|
| 49 |
assert_equal 'http://example.net/plugins/foo', plugin.url |
|
| 50 |
assert_equal 'John Smith', plugin.author |
|
| 51 |
assert_equal 'http://example.net/jsmith', plugin.author_url |
|
| 52 |
assert_equal 'This is a test plugin', plugin.description |
|
| 53 |
assert_equal '0.0.1', plugin.version |
|
| 54 |
end |
|
| 55 |
|
|
| 56 |
def test_requires_redmine |
|
| 57 |
test = self |
|
| 58 |
version = Redmine::VERSION.to_a.slice(0,3).join('.')
|
|
| 59 |
|
|
| 60 |
@klass.register :foo do |
|
| 61 |
test.assert requires_redmine(:version_or_higher => '0.1.0') |
|
| 62 |
test.assert requires_redmine(:version_or_higher => version) |
|
| 63 |
test.assert requires_redmine(version) |
|
| 64 |
test.assert_raise Redmine::PluginRequirementError do |
|
| 65 |
requires_redmine(:version_or_higher => '99.0.0') |
|
| 66 |
end |
|
| 67 |
|
|
| 68 |
test.assert requires_redmine(:version => version) |
|
| 69 |
test.assert requires_redmine(:version => [version, '99.0.0']) |
|
| 70 |
test.assert_raise Redmine::PluginRequirementError do |
|
| 71 |
requires_redmine(:version => '99.0.0') |
|
| 72 |
end |
|
| 73 |
test.assert_raise Redmine::PluginRequirementError do |
|
| 74 |
requires_redmine(:version => ['98.0.0', '99.0.0']) |
|
| 75 |
end |
|
| 76 |
end |
|
| 77 |
end |
|
| 78 |
|
|
| 79 |
def test_requires_redmine_plugin |
|
| 80 |
test = self |
|
| 81 |
other_version = '0.5.0' |
|
| 82 |
|
|
| 83 |
@klass.register :other do |
|
| 84 |
name 'Other' |
|
| 85 |
version other_version |
|
| 86 |
end |
|
| 87 |
|
|
| 88 |
@klass.register :foo do |
|
| 89 |
test.assert requires_redmine_plugin(:other, :version_or_higher => '0.1.0') |
|
| 90 |
test.assert requires_redmine_plugin(:other, :version_or_higher => other_version) |
|
| 91 |
test.assert requires_redmine_plugin(:other, other_version) |
|
| 92 |
test.assert_raise Redmine::PluginRequirementError do |
|
| 93 |
requires_redmine_plugin(:other, :version_or_higher => '99.0.0') |
|
| 94 |
end |
|
| 95 |
|
|
| 96 |
test.assert requires_redmine_plugin(:other, :version => other_version) |
|
| 97 |
test.assert requires_redmine_plugin(:other, :version => [other_version, '99.0.0']) |
|
| 98 |
test.assert_raise Redmine::PluginRequirementError do |
|
| 99 |
requires_redmine_plugin(:other, :version => '99.0.0') |
|
| 100 |
end |
|
| 101 |
test.assert_raise Redmine::PluginRequirementError do |
|
| 102 |
requires_redmine_plugin(:other, :version => ['98.0.0', '99.0.0']) |
|
| 103 |
end |
|
| 104 |
# Missing plugin |
|
| 105 |
test.assert_raise Redmine::PluginNotFound do |
|
| 106 |
requires_redmine_plugin(:missing, :version_or_higher => '0.1.0') |
|
| 107 |
end |
|
| 108 |
test.assert_raise Redmine::PluginNotFound do |
|
| 109 |
requires_redmine_plugin(:missing, '0.1.0') |
|
| 110 |
end |
|
| 111 |
test.assert_raise Redmine::PluginNotFound do |
|
| 112 |
requires_redmine_plugin(:missing, :version => '0.1.0') |
|
| 113 |
end |
|
| 114 |
|
|
| 115 |
end |
|
| 116 |
end |
|
| 117 |
end |
|
| .svn/pristine/39/391b1c790687d518fea17dcd03fc5883b7da327b.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
class IssuePriorityCustomField < CustomField |
|
| 19 |
def type_name |
|
| 20 |
:enumeration_issue_priorities |
|
| 21 |
end |
|
| 22 |
end |
|
| 23 |
|
|
| .svn/pristine/39/3989df463d71da05bed8c7a24a4bb085b8755d7f.svn-base | ||
|---|---|---|
| 1 |
Return-Path: <john.doe@somenet.foo> |
|
| 2 |
Received: from osiris ([127.0.0.1]) |
|
| 3 |
by OSIRIS |
|
| 4 |
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200 |
|
| 5 |
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris> |
|
| 6 |
To: <redmine@somenet.foo> |
|
| 7 |
Subject: Ticket by unknown user |
|
| 8 |
Date: Sun, 22 Jun 2008 12:28:07 +0200 |
|
| 9 |
MIME-Version: 1.0 |
|
| 10 |
Content-Type: text/plain; |
|
| 11 |
format=flowed; |
|
| 12 |
charset="iso-8859-1"; |
|
| 13 |
reply-type=original |
|
| 14 |
Content-Transfer-Encoding: 7bit |
|
| 15 |
|
|
| 16 |
This is a ticket submitted by an unknown user. |
|
| 17 |
|
|
| .svn/pristine/39/399f2a5d4375067a1c2f5abc78f9f28143ca9321.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
class ReportsController < ApplicationController |
|
| 19 |
menu_item :issues |
|
| 20 |
before_filter :find_project, :authorize, :find_issue_statuses |
|
| 21 |
|
|
| 22 |
def issue_report |
|
| 23 |
@trackers = @project.trackers |
|
| 24 |
@versions = @project.shared_versions.sort |
|
| 25 |
@priorities = IssuePriority.all.reverse |
|
| 26 |
@categories = @project.issue_categories |
|
| 27 |
@assignees = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort |
|
| 28 |
@authors = @project.users.sort |
|
| 29 |
@subprojects = @project.descendants.visible |
|
| 30 |
|
|
| 31 |
@issues_by_tracker = Issue.by_tracker(@project) |
|
| 32 |
@issues_by_version = Issue.by_version(@project) |
|
| 33 |
@issues_by_priority = Issue.by_priority(@project) |
|
| 34 |
@issues_by_category = Issue.by_category(@project) |
|
| 35 |
@issues_by_assigned_to = Issue.by_assigned_to(@project) |
|
| 36 |
@issues_by_author = Issue.by_author(@project) |
|
| 37 |
@issues_by_subproject = Issue.by_subproject(@project) || [] |
|
| 38 |
|
|
| 39 |
render :template => "reports/issue_report" |
|
| 40 |
end |
|
| 41 |
|
|
| 42 |
def issue_report_details |
|
| 43 |
case params[:detail] |
|
| 44 |
when "tracker" |
|
| 45 |
@field = "tracker_id" |
|
| 46 |
@rows = @project.trackers |
|
| 47 |
@data = Issue.by_tracker(@project) |
|
| 48 |
@report_title = l(:field_tracker) |
|
| 49 |
when "version" |
|
| 50 |
@field = "fixed_version_id" |
|
| 51 |
@rows = @project.shared_versions.sort |
|
| 52 |
@data = Issue.by_version(@project) |
|
| 53 |
@report_title = l(:field_version) |
|
| 54 |
when "priority" |
|
| 55 |
@field = "priority_id" |
|
| 56 |
@rows = IssuePriority.all.reverse |
|
| 57 |
@data = Issue.by_priority(@project) |
|
| 58 |
@report_title = l(:field_priority) |
|
| 59 |
when "category" |
|
| 60 |
@field = "category_id" |
|
| 61 |
@rows = @project.issue_categories |
|
| 62 |
@data = Issue.by_category(@project) |
|
| 63 |
@report_title = l(:field_category) |
|
| 64 |
when "assigned_to" |
|
| 65 |
@field = "assigned_to_id" |
|
| 66 |
@rows = (Setting.issue_group_assignment? ? @project.principals : @project.users).sort |
|
| 67 |
@data = Issue.by_assigned_to(@project) |
|
| 68 |
@report_title = l(:field_assigned_to) |
|
| 69 |
when "author" |
|
| 70 |
@field = "author_id" |
|
| 71 |
@rows = @project.users.sort |
|
| 72 |
@data = Issue.by_author(@project) |
|
| 73 |
@report_title = l(:field_author) |
|
| 74 |
when "subproject" |
|
| 75 |
@field = "project_id" |
|
| 76 |
@rows = @project.descendants.visible |
|
| 77 |
@data = Issue.by_subproject(@project) || [] |
|
| 78 |
@report_title = l(:field_subproject) |
|
| 79 |
end |
|
| 80 |
|
|
| 81 |
respond_to do |format| |
|
| 82 |
if @field |
|
| 83 |
format.html {}
|
|
| 84 |
else |
|
| 85 |
format.html { redirect_to :action => 'issue_report', :id => @project }
|
|
| 86 |
end |
|
| 87 |
end |
|
| 88 |
end |
|
| 89 |
|
|
| 90 |
private |
|
| 91 |
|
|
| 92 |
def find_issue_statuses |
|
| 93 |
@statuses = IssueStatus.sorted.all |
|
| 94 |
end |
|
| 95 |
end |
|
| .svn/pristine/39/39a608089a590c01af61f645951f37bfe827c689.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
require File.expand_path('../../test_helper', __FILE__)
|
|
| 19 |
|
|
| 20 |
class AdminTest < ActionController::IntegrationTest |
|
| 21 |
fixtures :projects, :trackers, :issue_statuses, :issues, |
|
| 22 |
:enumerations, :users, :issue_categories, |
|
| 23 |
:projects_trackers, |
|
| 24 |
:roles, |
|
| 25 |
:member_roles, |
|
| 26 |
:members, |
|
| 27 |
:enabled_modules |
|
| 28 |
|
|
| 29 |
def test_add_user |
|
| 30 |
log_user("admin", "admin")
|
|
| 31 |
get "/users/new" |
|
| 32 |
assert_response :success |
|
| 33 |
assert_template "users/new" |
|
| 34 |
post "/users", |
|
| 35 |
:user => { :login => "psmith", :firstname => "Paul",
|
|
| 36 |
:lastname => "Smith", :mail => "psmith@somenet.foo", |
|
| 37 |
:language => "en", :password => "psmith09", |
|
| 38 |
:password_confirmation => "psmith09" } |
|
| 39 |
|
|
| 40 |
user = User.find_by_login("psmith")
|
|
| 41 |
assert_kind_of User, user |
|
| 42 |
assert_redirected_to "/users/#{ user.id }/edit"
|
|
| 43 |
|
|
| 44 |
logged_user = User.try_to_login("psmith", "psmith09")
|
|
| 45 |
assert_kind_of User, logged_user |
|
| 46 |
assert_equal "Paul", logged_user.firstname |
|
| 47 |
|
|
| 48 |
put "users/#{user.id}", :id => user.id, :user => { :status => User::STATUS_LOCKED }
|
|
| 49 |
assert_redirected_to "/users/#{ user.id }/edit"
|
|
| 50 |
locked_user = User.try_to_login("psmith", "psmith09")
|
|
| 51 |
assert_equal nil, locked_user |
|
| 52 |
end |
|
| 53 |
|
|
| 54 |
test "Add a user as an anonymous user should fail" do |
|
| 55 |
post '/users', |
|
| 56 |
:user => { :login => 'psmith', :firstname => 'Paul'},
|
|
| 57 |
:password => "psmith09", :password_confirmation => "psmith09" |
|
| 58 |
assert_response :redirect |
|
| 59 |
assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fusers" |
|
| 60 |
end |
|
| 61 |
end |
|
| .svn/pristine/39/39e07ef2d5632f8e7ca245cda7735bd6e7674f6d.svn-base | ||
|---|---|---|
| 1 |
# Redmine - project management software |
|
| 2 |
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 |
|
|
| 18 |
require 'redmine/scm/adapters/abstract_adapter' |
|
| 19 |
|
|
| 20 |
module Redmine |
|
| 21 |
module Scm |
|
| 22 |
module Adapters |
|
| 23 |
class BazaarAdapter < AbstractAdapter |
|
| 24 |
|
|
| 25 |
# Bazaar executable name |
|
| 26 |
BZR_BIN = Redmine::Configuration['scm_bazaar_command'] || "bzr" |
|
| 27 |
|
|
| 28 |
class << self |
|
| 29 |
def client_command |
|
| 30 |
@@bin ||= BZR_BIN |
|
| 31 |
end |
|
| 32 |
|
|
| 33 |
def sq_bin |
|
| 34 |
@@sq_bin ||= shell_quote_command |
|
| 35 |
end |
|
| 36 |
|
|
| 37 |
def client_version |
|
| 38 |
@@client_version ||= (scm_command_version || []) |
|
| 39 |
end |
|
| 40 |
|
|
| 41 |
def client_available |
|
| 42 |
!client_version.empty? |
|
| 43 |
end |
|
| 44 |
|
|
| 45 |
def scm_command_version |
|
| 46 |
scm_version = scm_version_from_command_line.dup |
|
| 47 |
if scm_version.respond_to?(:force_encoding) |
|
| 48 |
scm_version.force_encoding('ASCII-8BIT')
|
|
| 49 |
end |
|
| 50 |
if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
|
|
| 51 |
m[2].scan(%r{\d+}).collect(&:to_i)
|
|
| 52 |
end |
|
| 53 |
end |
|
| 54 |
|
|
| 55 |
def scm_version_from_command_line |
|
| 56 |
shellout("#{sq_bin} --version") { |io| io.read }.to_s
|
|
| 57 |
end |
|
| 58 |
end |
|
| 59 |
|
|
| 60 |
def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil) |
|
| 61 |
@url = url |
|
| 62 |
@root_url = url |
|
| 63 |
@path_encoding = 'UTF-8' |
|
| 64 |
# do not call *super* for non ASCII repository path |
|
| 65 |
end |
|
| 66 |
|
|
| 67 |
def bzr_path_encodig=(encoding) |
|
| 68 |
@path_encoding = encoding |
|
| 69 |
end |
|
| 70 |
|
|
| 71 |
# Get info about the repository |
|
| 72 |
def info |
|
| 73 |
cmd_args = %w|revno| |
|
| 74 |
cmd_args << bzr_target('')
|
|
| 75 |
info = nil |
|
| 76 |
scm_cmd(*cmd_args) do |io| |
|
| 77 |
if io.read =~ %r{^(\d+)\r?$}
|
|
| 78 |
info = Info.new({:root_url => url,
|
|
| 79 |
:lastrev => Revision.new({
|
|
| 80 |
:identifier => $1 |
|
| 81 |
}) |
|
| 82 |
}) |
|
| 83 |
end |
|
| 84 |
end |
|
| 85 |
info |
|
| 86 |
rescue ScmCommandAborted |
|
| 87 |
return nil |
|
| 88 |
end |
|
| 89 |
|
|
| 90 |
# Returns an Entries collection |
|
| 91 |
# or nil if the given path doesn't exist in the repository |
|
| 92 |
def entries(path=nil, identifier=nil, options={})
|
|
| 93 |
path ||= '' |
|
| 94 |
entries = Entries.new |
|
| 95 |
identifier = -1 unless identifier && identifier.to_i > 0 |
|
| 96 |
cmd_args = %w|ls -v --show-ids| |
|
| 97 |
cmd_args << "-r#{identifier.to_i}"
|
|
| 98 |
cmd_args << bzr_target(path) |
|
| 99 |
scm_cmd(*cmd_args) do |io| |
|
| 100 |
prefix_utf8 = "#{url}/#{path}".gsub('\\', '/')
|
|
| 101 |
logger.debug "PREFIX: #{prefix_utf8}"
|
|
| 102 |
prefix = scm_iconv(@path_encoding, 'UTF-8', prefix_utf8) |
|
| 103 |
prefix.force_encoding('ASCII-8BIT') if prefix.respond_to?(:force_encoding)
|
|
| 104 |
re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
|
|
| 105 |
io.each_line do |line| |
|
| 106 |
next unless line =~ re |
|
| 107 |
name_locale, slash, revision = $3.strip, $4, $5.strip |
|
| 108 |
name = scm_iconv('UTF-8', @path_encoding, name_locale)
|
|
| 109 |
entries << Entry.new({:name => name,
|
|
| 110 |
:path => ((path.empty? ? "" : "#{path}/") + name),
|
|
| 111 |
:kind => (slash.blank? ? 'file' : 'dir'), |
|
| 112 |
:size => nil, |
|
| 113 |
:lastrev => Revision.new(:revision => revision) |
|
| 114 |
}) |
|
| 115 |
end |
|
| 116 |
end |
|
| 117 |
if logger && logger.debug? |
|
| 118 |
logger.debug("Found #{entries.size} entries in the repository for #{target(path)}")
|
|
| 119 |
end |
|
| 120 |
entries.sort_by_name |
|
| 121 |
rescue ScmCommandAborted |
|
| 122 |
return nil |
|
| 123 |
end |
|
| 124 |
|
|
| 125 |
def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
|
|
| 126 |
path ||= '' |
|
| 127 |
identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1' |
|
| 128 |
identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1 |
|
| 129 |
revisions = Revisions.new |
|
| 130 |
cmd_args = %w|log -v --show-ids| |
|
| 131 |
cmd_args << "-r#{identifier_to}..#{identifier_from}"
|
|
| 132 |
cmd_args << bzr_target(path) |
|
| 133 |
scm_cmd(*cmd_args) do |io| |
|
| 134 |
revision = nil |
|
| 135 |
parsing = nil |
|
| 136 |
io.each_line do |line| |
|
| 137 |
if line =~ /^----/ |
|
| 138 |
revisions << revision if revision |
|
| 139 |
revision = Revision.new(:paths => [], :message => '') |
|
| 140 |
parsing = nil |
|
| 141 |
else |
|
| 142 |
next unless revision |
|
| 143 |
if line =~ /^revno: (\d+)($|\s\[merge\]$)/ |
|
| 144 |
revision.identifier = $1.to_i |
|
| 145 |
elsif line =~ /^committer: (.+)$/ |
|
| 146 |
revision.author = $1.strip |
|
| 147 |
elsif line =~ /^revision-id:(.+)$/ |
|
| 148 |
revision.scmid = $1.strip |
|
| 149 |
elsif line =~ /^timestamp: (.+)$/ |
|
| 150 |
revision.time = Time.parse($1).localtime |
|
| 151 |
elsif line =~ /^ -----/ |
|
| 152 |
# partial revisions |
|
| 153 |
parsing = nil unless parsing == 'message' |
|
| 154 |
elsif line =~ /^(message|added|modified|removed|renamed):/ |
|
| 155 |
parsing = $1 |
|
| 156 |
elsif line =~ /^ (.*)$/ |
|
| 157 |
if parsing == 'message' |
|
| 158 |
revision.message << "#{$1}\n"
|
|
| 159 |
else |
|
| 160 |
if $1 =~ /^(.*)\s+(\S+)$/ |
|
| 161 |
path_locale = $1.strip |
|
| 162 |
path = scm_iconv('UTF-8', @path_encoding, path_locale)
|
|
| 163 |
revid = $2 |
|
| 164 |
case parsing |
|
| 165 |
when 'added' |
|
| 166 |
revision.paths << {:action => 'A', :path => "/#{path}", :revision => revid}
|
|
| 167 |
when 'modified' |
|
| 168 |
revision.paths << {:action => 'M', :path => "/#{path}", :revision => revid}
|
|
| 169 |
when 'removed' |
|
| 170 |
revision.paths << {:action => 'D', :path => "/#{path}", :revision => revid}
|
|
| 171 |
when 'renamed' |
|
| 172 |
new_path = path.split('=>').last
|
|
| 173 |
if new_path |
|
| 174 |
revision.paths << {:action => 'M', :path => "/#{new_path.strip}",
|
|
| 175 |
:revision => revid} |
|
| 176 |
end |
|
| 177 |
end |
|
| 178 |
end |
|
| 179 |
end |
|
| 180 |
else |
|
| 181 |
parsing = nil |
|
| 182 |
end |
|
| 183 |
end |
|
| 184 |
end |
|
| 185 |
revisions << revision if revision |
|
| 186 |
end |
|
| 187 |
revisions |
|
| 188 |
rescue ScmCommandAborted |
|
| 189 |
return nil |
|
| 190 |
end |
|
| 191 |
|
|
| 192 |
def diff(path, identifier_from, identifier_to=nil) |
|
| 193 |
path ||= '' |
|
| 194 |
if identifier_to |
|
| 195 |
identifier_to = identifier_to.to_i |
|
| 196 |
else |
|
| 197 |
identifier_to = identifier_from.to_i - 1 |
|
| 198 |
end |
|
| 199 |
if identifier_from |
|
| 200 |
identifier_from = identifier_from.to_i |
|
| 201 |
end |
|
| 202 |
diff = [] |
|
| 203 |
cmd_args = %w|diff| |
|
| 204 |
cmd_args << "-r#{identifier_to}..#{identifier_from}"
|
|
| 205 |
cmd_args << bzr_target(path) |
|
| 206 |
scm_cmd_no_raise(*cmd_args) do |io| |
|
| 207 |
io.each_line do |line| |
|
| 208 |
diff << line |
|
| 209 |
end |
|
| 210 |
end |
|
| 211 |
diff |
|
| 212 |
end |
|
| 213 |
|
|
| 214 |
def cat(path, identifier=nil) |
|
| 215 |
cat = nil |
|
| 216 |
cmd_args = %w|cat| |
|
| 217 |
cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
|
|
| 218 |
cmd_args << bzr_target(path) |
|
| 219 |
scm_cmd(*cmd_args) do |io| |
|
| 220 |
io.binmode |
|
| 221 |
cat = io.read |
|
| 222 |
end |
|
| 223 |
cat |
|
| 224 |
rescue ScmCommandAborted |
|
| 225 |
return nil |
|
| 226 |
end |
|
| 227 |
|
|
| 228 |
def annotate(path, identifier=nil) |
|
| 229 |
blame = Annotate.new |
|
| 230 |
cmd_args = %w|annotate -q --all| |
|
| 231 |
cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
|
|
| 232 |
cmd_args << bzr_target(path) |
|
| 233 |
scm_cmd(*cmd_args) do |io| |
|
| 234 |
author = nil |
|
| 235 |
identifier = nil |
|
| 236 |
io.each_line do |line| |
|
| 237 |
next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
|
|
| 238 |
rev = $1 |
|
| 239 |
blame.add_line($3.rstrip, |
|
| 240 |
Revision.new( |
|
| 241 |
:identifier => rev, |
|
| 242 |
:revision => rev, |
|
| 243 |
:author => $2.strip |
|
| 244 |
)) |
|
| 245 |
end |
|
| 246 |
end |
|
| 247 |
blame |
|
| 248 |
rescue ScmCommandAborted |
|
| 249 |
return nil |
|
| 250 |
end |
|
| 251 |
|
|
| 252 |
def self.branch_conf_path(path) |
|
| 253 |
bcp = nil |
|
| 254 |
m = path.match(%r{^(.*[/\\])\.bzr.*$})
|
|
| 255 |
if m |
|
| 256 |
bcp = m[1] |
|
| 257 |
else |
|
| 258 |
bcp = path |
|
| 259 |
end |
|
| 260 |
bcp.gsub!(%r{[\/\\]$}, "")
|
|
| 261 |
if bcp |
|
| 262 |
bcp = File.join(bcp, ".bzr", "branch", "branch.conf") |
|
| 263 |
end |
|
| 264 |
bcp |
|
| 265 |
end |
|
| 266 |
|
|
| 267 |
def append_revisions_only |
|
| 268 |
return @aro if ! @aro.nil? |
|
| 269 |
@aro = false |
|
| 270 |
bcp = self.class.branch_conf_path(url) |
|
| 271 |
if bcp && File.exist?(bcp) |
|
| 272 |
begin |
|
| 273 |
f = File::open(bcp, "r") |
|
| 274 |
cnt = 0 |
|
| 275 |
f.each_line do |line| |
|
| 276 |
l = line.chomp.to_s |
|
| 277 |
if l =~ /^\s*append_revisions_only\s*=\s*(\w+)\s*$/ |
|
| 278 |
str_aro = $1 |
|
| 279 |
if str_aro.upcase == "TRUE" |
|
| 280 |
@aro = true |
|
| 281 |
cnt += 1 |
|
| 282 |
elsif str_aro.upcase == "FALSE" |
|
| 283 |
@aro = false |
|
| 284 |
cnt += 1 |
|
| 285 |
end |
|
| 286 |
if cnt > 1 |
|
| 287 |
@aro = false |
|
| 288 |
break |
|
| 289 |
end |
|
| 290 |
end |
|
| 291 |
end |
|
| 292 |
ensure |
|
| 293 |
f.close |
|
| 294 |
end |
|
| 295 |
end |
|
| 296 |
@aro |
|
| 297 |
end |
|
| 298 |
|
|
| 299 |
def scm_cmd(*args, &block) |
|
| 300 |
full_args = [] |
|
| 301 |
full_args += args |
|
| 302 |
full_args_locale = [] |
|
| 303 |
full_args.map do |e| |
|
| 304 |
full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e) |
|
| 305 |
end |
|
| 306 |
ret = shellout( |
|
| 307 |
self.class.sq_bin + ' ' + |
|
| 308 |
full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 309 |
&block |
|
| 310 |
) |
|
| 311 |
if $? && $?.exitstatus != 0 |
|
| 312 |
raise ScmCommandAborted, "bzr exited with non-zero status: #{$?.exitstatus}"
|
|
| 313 |
end |
|
| 314 |
ret |
|
| 315 |
end |
|
| 316 |
private :scm_cmd |
|
| 317 |
|
|
| 318 |
def scm_cmd_no_raise(*args, &block) |
|
| 319 |
full_args = [] |
|
| 320 |
full_args += args |
|
| 321 |
full_args_locale = [] |
|
| 322 |
full_args.map do |e| |
|
| 323 |
full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e) |
|
| 324 |
end |
|
| 325 |
ret = shellout( |
|
| 326 |
self.class.sq_bin + ' ' + |
|
| 327 |
full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
|
|
| 328 |
&block |
|
| 329 |
) |
|
| 330 |
ret |
|
| 331 |
end |
|
| 332 |
private :scm_cmd_no_raise |
|
| 333 |
|
|
| 334 |
def bzr_target(path) |
|
| 335 |
target(path, false) |
|
| 336 |
end |
|
| 337 |
private :bzr_target |
|
| 338 |
end |
|
| 339 |
end |
|
| 340 |
end |
|
| 341 |
end |
|
| .svn/pristine/39/39e52a0654ea7d5e49b76b29ba4c1190481acad6.svn-base | ||
|---|---|---|
| 1 |
# RedMine - project management software |
|
| 2 |
# Copyright (C) 2006-2011 Jean-Philippe Lang |
|
| 3 |
# |
|
| 4 |
# FileSystem adapter |
|
| 5 |
# File written by Paul Rivier, at Demotera. |
|
| 6 |
# |
|
| 7 |
# This program is free software; you can redistribute it and/or |
|
| 8 |
# modify it under the terms of the GNU General Public License |
|
| 9 |
# as published by the Free Software Foundation; either version 2 |
|
| 10 |
# of the License, or (at your option) any later version. |
|
| 11 |
# |
|
| 12 |
# This program is distributed in the hope that it will be useful, |
|
| 13 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 14 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 15 |
# GNU General Public License for more details. |
|
| 16 |
# |
|
| 17 |
# You should have received a copy of the GNU General Public License |
|
| 18 |
# along with this program; if not, write to the Free Software |
|
| 19 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 20 |
|
|
| 21 |
require 'redmine/scm/adapters/abstract_adapter' |
|
| 22 |
require 'find' |
|
| 23 |
|
|
| 24 |
module Redmine |
|
| 25 |
module Scm |
|
| 26 |
module Adapters |
|
| 27 |
class FilesystemAdapter < AbstractAdapter |
|
| 28 |
|
|
| 29 |
class << self |
|
| 30 |
def client_available |
|
| 31 |
true |
|
| 32 |
end |
|
| 33 |
end |
|
| 34 |
|
|
| 35 |
def initialize(url, root_url=nil, login=nil, password=nil, |
|
| 36 |
path_encoding=nil) |
|
| 37 |
@url = with_trailling_slash(url) |
|
| 38 |
@path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding |
|
| 39 |
end |
|
| 40 |
|
|
| 41 |
def path_encoding |
|
| 42 |
@path_encoding |
|
| 43 |
end |
|
| 44 |
|
|
| 45 |
def format_path_ends(path, leading=true, trailling=true) |
|
| 46 |
path = leading ? with_leading_slash(path) : |
|
| 47 |
without_leading_slash(path) |
|
| 48 |
trailling ? with_trailling_slash(path) : |
|
| 49 |
without_trailling_slash(path) |
|
| 50 |
end |
|
| 51 |
|
|
| 52 |
def info |
|
| 53 |
info = Info.new({:root_url => target(),
|
|
| 54 |
:lastrev => nil |
|
| 55 |
}) |
|
| 56 |
info |
|
| 57 |
rescue CommandFailed |
|
| 58 |
return nil |
|
| 59 |
end |
|
| 60 |
|
|
| 61 |
def entries(path="", identifier=nil, options={})
|
|
| 62 |
entries = Entries.new |
|
| 63 |
trgt_utf8 = target(path) |
|
| 64 |
trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8) |
|
| 65 |
Dir.new(trgt).each do |e1| |
|
| 66 |
e_utf8 = scm_iconv('UTF-8', @path_encoding, e1)
|
|
| 67 |
next if e_utf8.blank? |
|
| 68 |
relative_path_utf8 = format_path_ends( |
|
| 69 |
(format_path_ends(path,false,true) + e_utf8),false,false) |
|
| 70 |
t1_utf8 = target(relative_path_utf8) |
|
| 71 |
t1 = scm_iconv(@path_encoding, 'UTF-8', t1_utf8) |
|
| 72 |
relative_path = scm_iconv(@path_encoding, 'UTF-8', relative_path_utf8) |
|
| 73 |
e1 = scm_iconv(@path_encoding, 'UTF-8', e_utf8) |
|
| 74 |
if File.exist?(t1) and # paranoid test |
|
| 75 |
%w{file directory}.include?(File.ftype(t1)) and # avoid special types
|
|
| 76 |
not File.basename(e1).match(/^\.+$/) # avoid . and .. |
|
| 77 |
p1 = File.readable?(t1) ? relative_path : "" |
|
| 78 |
utf_8_path = scm_iconv('UTF-8', @path_encoding, p1)
|
|
| 79 |
entries << |
|
| 80 |
Entry.new({ :name => scm_iconv('UTF-8', @path_encoding, File.basename(e1)),
|
|
| 81 |
# below : list unreadable files, but dont link them. |
|
| 82 |
:path => utf_8_path, |
|
| 83 |
:kind => (File.directory?(t1) ? 'dir' : 'file'), |
|
| 84 |
:size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first),
|
|
| 85 |
:lastrev => |
|
| 86 |
Revision.new({:time => (File.mtime(t1)) })
|
|
| 87 |
}) |
|
| 88 |
end |
|
| 89 |
end |
|
| 90 |
entries.sort_by_name |
|
| 91 |
rescue => err |
|
| 92 |
logger.error "scm: filesystem: error: #{err.message}"
|
|
| 93 |
raise CommandFailed.new(err.message) |
|
| 94 |
end |
|
| 95 |
|
|
| 96 |
def cat(path, identifier=nil) |
|
| 97 |
p = scm_iconv(@path_encoding, 'UTF-8', target(path)) |
|
| 98 |
File.new(p, "rb").read |
|
| 99 |
rescue => err |
|
| 100 |
logger.error "scm: filesystem: error: #{err.message}"
|
|
| 101 |
raise CommandFailed.new(err.message) |
|
| 102 |
end |
|
| 103 |
|
|
| 104 |
private |
|
| 105 |
|
|
| 106 |
# AbstractAdapter::target is implicitly made to quote paths. |
|
| 107 |
# Here we do not shell-out, so we do not want quotes. |
|
| 108 |
def target(path=nil) |
|
| 109 |
# Prevent the use of .. |
|
| 110 |
if path and !path.match(/(^|\/)\.\.(\/|$)/) |
|
| 111 |
return "#{self.url}#{without_leading_slash(path)}"
|
|
| 112 |
end |
|
| 113 |
return self.url |
|
| 114 |
end |
|
| 115 |
end |
|
| 116 |
end |
|
| 117 |
end |
|
| 118 |
end |
|
| .svn/pristine/39/39faeb0151b407d013fa291b6fe7a94c6860c63f.svn-base | ||
|---|---|---|
| 1 |
class AppAndPluginController < ApplicationController |
|
| 2 |
def an_action |
|
| 3 |
render_class_and_action 'from app' |
|
| 4 |
end |
|
| 5 |
end |
|
Also available in: Unified diff