Patch #1393 » filesystem-adapter.patch
| app/helpers/repositories_helper.rb Tue Jun 03 17:32:01 2008 +0200 → app/helpers/repositories_helper.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 95 | 95 |
def bazaar_field_tags(form, repository) |
| 96 | 96 |
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?)))
|
| 97 | 97 |
end |
| 98 | ||
| 99 |
def filesystem_field_tags(form, repository) |
|
| 100 |
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
|
| 101 |
end |
|
| 102 | ||
| 98 | 103 |
end |
| /dev/null Thu Jan 01 00:00:00 1970 +0000 → app/models/repository/filesystem.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 1 |
# redMine - project management software |
|
| 2 |
# Copyright (C) 2006-2007 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/filesystem_adapter' |
|
| 22 | ||
| 23 |
class Repository::Filesystem < Repository |
|
| 24 |
attr_protected :root_url |
|
| 25 |
validates_presence_of :url |
|
| 26 | ||
| 27 |
def scm_adapter |
|
| 28 |
Redmine::Scm::Adapters::FilesystemAdapter |
|
| 29 |
end |
|
| 30 |
|
|
| 31 |
def self.scm_name |
|
| 32 |
'Filesystem' |
|
| 33 |
end |
|
| 34 |
|
|
| 35 |
def entries(path=nil, identifier=nil) |
|
| 36 |
scm.entries(path, identifier) |
|
| 37 |
end |
|
| 38 | ||
| 39 |
def fetch_changesets |
|
| 40 |
nil |
|
| 41 |
end |
|
| 42 |
|
|
| 43 |
end |
|
| doc/RUNNING_TESTS Tue Jun 03 17:32:01 2008 +0200 → doc/RUNNING_TESTS Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 24 | 24 |
--- |
| 25 | 25 |
gunzip < test/fixtures/repositories/git_repository.tar.gz | tar -xv -C tmp/test |
| 26 | 26 | |
| 27 |
FileSystem |
|
| 28 |
---------- |
|
| 29 |
gunzip < test/fixtures/repositories/filesystem_repository.tar.gz | tar -xv -C tmp/test |
|
| 30 | ||
| 27 | 31 | |
| 28 | 32 |
Running Tests |
| 29 | 33 |
============= |
| lib/redmine.rb Tue Jun 03 17:32:01 2008 +0200 → lib/redmine.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 11 | 11 |
# RMagick is not available |
| 12 | 12 |
end |
| 13 | 13 | |
| 14 |
REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git ) |
|
| 14 |
REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git Filesystem )
|
|
| 15 | 15 | |
| 16 | 16 |
# Permissions |
| 17 | 17 |
Redmine::AccessControl.map do |map| |
| lib/redmine/scm/adapters/abstract_adapter.rb Tue Jun 03 17:32:01 2008 +0200 → lib/redmine/scm/adapters/abstract_adapter.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 98 | 98 |
def with_trailling_slash(path) |
| 99 | 99 |
path ||= '' |
| 100 | 100 |
(path[-1,1] == "/") ? path : "#{path}/"
|
| 101 |
end |
|
| 102 | ||
| 103 |
def without_leading_slash(path) |
|
| 104 |
path ||= '' |
|
| 105 |
path.gsub(%r{^/+}, '')
|
|
| 106 |
end |
|
| 107 | ||
| 108 |
def without_trailling_slash(path) |
|
| 109 |
path ||= '' |
|
| 110 |
(path[-1,1] == "/") ? path[0..-2] : path |
|
| 101 | 111 |
end |
| 102 | 112 | |
| 103 | 113 |
def shell_quote(str) |
| /dev/null Thu Jan 01 00:00:00 1970 +0000 → lib/redmine/scm/adapters/filesystem_adapter.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 1 |
# redMine - project management software |
|
| 2 |
# Copyright (C) 2006-2007 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 | ||
| 30 |
def initialize(url, root_url=nil, login=nil, password=nil) |
|
| 31 |
@url = with_trailling_slash(url) |
|
| 32 |
end |
|
| 33 | ||
| 34 |
def format_path_ends(path, leading=true, trailling=true) |
|
| 35 |
path = leading ? with_leading_slash(path) : |
|
| 36 |
without_leading_slash(path) |
|
| 37 |
trailling ? with_trailling_slash(path) : |
|
| 38 |
without_trailling_slash(path) |
|
| 39 |
end |
|
| 40 | ||
| 41 |
def info |
|
| 42 |
info = Info.new({:root_url => target(),
|
|
| 43 |
:lastrev => nil |
|
| 44 |
}) |
|
| 45 |
info |
|
| 46 |
rescue CommandFailed |
|
| 47 |
return nil |
|
| 48 |
end |
|
| 49 |
|
|
| 50 |
def entries(path="", identifier=nil) |
|
| 51 |
entries = Entries.new |
|
| 52 |
Dir.new(target(path)).each do |e| |
|
| 53 |
relative_path = format_path_ends((format_path_ends(path, |
|
| 54 |
false, |
|
| 55 |
true) + e), |
|
| 56 |
false,false) |
|
| 57 |
target = target(relative_path) |
|
| 58 |
entries << |
|
| 59 |
Entry.new({ :name => File.basename(e),
|
|
| 60 |
# below : list unreadable files, but dont link them. |
|
| 61 |
:path => File.readable?(target) ? relative_path : "", |
|
| 62 |
:kind => (File.directory?(target) ? 'dir' : 'file'), |
|
| 63 |
:size => if (File.directory?(target)) |
|
| 64 |
nil else File.size(target) end, |
|
| 65 |
:lastrev => |
|
| 66 |
Revision.new({:time => (File.mtime(target)).localtime,
|
|
| 67 |
}) |
|
| 68 |
}) if File.exist?(target) and # paranoid test |
|
| 69 |
%w{file directory}.include?(File.ftype(target)) and # avoid special types
|
|
| 70 |
not File.basename(e).match(/^\.+$/) # avoid . and .. |
|
| 71 |
end |
|
| 72 |
entries.sort_by_name |
|
| 73 |
end |
|
| 74 |
|
|
| 75 |
def cat(path, identifier=nil) |
|
| 76 |
File.new(target(path)).read |
|
| 77 |
end |
|
| 78 | ||
| 79 |
private |
|
| 80 |
|
|
| 81 |
# AbstractAdapter::target is implicitly made to quote paths. |
|
| 82 |
# Here we do not shell-out, so we do not want quotes. |
|
| 83 |
def target(path=nil) |
|
| 84 |
#Prevent the use of .. |
|
| 85 |
if path and !path.match(/(^|\/)\.\.(\/|$)/) |
|
| 86 |
return "#{self.url}#{without_leading_slash(path)}"
|
|
| 87 |
end |
|
| 88 |
return self.url |
|
| 89 |
end |
|
| 90 |
|
|
| 91 |
end |
|
| 92 |
end |
|
| 93 |
end |
|
| 94 |
end |
|
| /dev/null Thu Jan 01 00:00:00 1970 +0000 → test/unit/filesystem_adapter_test.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 1 | ||
| 2 |
require File.dirname(__FILE__) + '/../test_helper' |
|
| 3 | ||
| 4 | ||
| 5 |
class FilesystemAdapterTest < Test::Unit::TestCase |
|
| 6 |
|
|
| 7 |
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/filesystem_repository'
|
|
| 8 |
|
|
| 9 |
if File.directory?(REPOSITORY_PATH) |
|
| 10 |
def setup |
|
| 11 |
@adapter = Redmine::Scm::Adapters::FilesystemAdapter.new(REPOSITORY_PATH) |
|
| 12 |
end |
|
| 13 |
|
|
| 14 |
def test_entries |
|
| 15 |
assert_equal 2, @adapter.entries.size |
|
| 16 |
assert_equal ["dir", "test"], @adapter.entries.collect(&:name) |
|
| 17 |
assert_equal ["dir", "test"], @adapter.entries(nil).collect(&:name) |
|
| 18 |
assert_equal ["dir", "test"], @adapter.entries("/").collect(&:name)
|
|
| 19 |
["dir", "/dir", "/dir/", "dir/"].each do |path| |
|
| 20 |
assert_equal ["subdir", "dirfile"], @adapter.entries(path).collect(&:name) |
|
| 21 |
end |
|
| 22 |
# If y try to use "..", the path is ignored |
|
| 23 |
["/../","dir/../", "..", "../", "/..", "dir/.."].each do |path| |
|
| 24 |
assert_equal ["dir", "test"], @adapter.entries(path).collect(&:name), ".. must be ignored in path argument" |
|
| 25 |
end |
|
| 26 |
end |
|
| 27 |
|
|
| 28 |
def test_cat |
|
| 29 |
assert_equal "TEST CAT\n", @adapter.cat("test")
|
|
| 30 |
assert_equal "TEST CAT\n", @adapter.cat("/test")
|
|
| 31 |
# Revision number is ignored |
|
| 32 |
assert_equal "TEST CAT\n", @adapter.cat("/test", 1)
|
|
| 33 |
end |
|
| 34 |
|
|
| 35 |
else |
|
| 36 |
puts "Filesystem test repository NOT FOUND. Skipping unit tests !!! See doc/RUNNING_TESTS." |
|
| 37 |
def test_fake; assert true end |
|
| 38 |
end |
|
| 39 |
|
|
| 40 |
end |
|
| 41 | ||
| 42 | ||
| /dev/null Thu Jan 01 00:00:00 1970 +0000 → test/unit/repository_filesystem_test.rb Fri Jun 06 11:20:28 2008 +0200 | ||
|---|---|---|
| 1 |
# redMine - project management software |
|
| 2 |
# Copyright (C) 2006-2007 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.dirname(__FILE__) + '/../test_helper' |
|
| 19 | ||
| 20 |
class RepositoryFilesystemTest < Test::Unit::TestCase |
|
| 21 |
fixtures :projects |
|
| 22 |
|
|
| 23 |
# No '..' in the repository path |
|
| 24 |
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/filesystem_repository'
|
|
| 25 |
|
|
| 26 |
def setup |
|
| 27 |
@project = Project.find(1) |
|
| 28 |
assert @repository = Repository::Filesystem.create(:project => @project, :url => REPOSITORY_PATH) |
|
| 29 |
end |
|
| 30 |
|
|
| 31 |
if File.directory?(REPOSITORY_PATH) |
|
| 32 |
def test_fetch_changesets |
|
| 33 |
@repository.fetch_changesets |
|
| 34 |
@repository.reload |
|
| 35 |
|
|
| 36 |
assert_equal 0, @repository.changesets.count |
|
| 37 |
assert_equal 0, @repository.changes.count |
|
| 38 |
end |
|
| 39 |
|
|
| 40 |
def test_entries |
|
| 41 |
assert_equal 2, @repository.entries("", 2).size
|
|
| 42 |
assert_equal 2, @repository.entries("dir", 3).size
|
|
| 43 |
end |
|
| 44 | ||
| 45 |
def test_cat |
|
| 46 |
assert_equal "TEST CAT\n", @repository.scm.cat("test")
|
|
| 47 |
end |
|
| 48 | ||
| 49 |
else |
|
| 50 |
puts "Filesystem test repository NOT FOUND. Skipping unit tests !!! See doc/RUNNING_TESTS." |
|
| 51 |
def test_fake; assert true end |
|
| 52 |
end |
|
| 53 |
end |
|