Mercurial > hg > soundsoftware-site
comparison lib/redmine/scm/adapters/.svn/text-base/filesystem_adapter.rb.svn-base @ 511:107d36338b70 live
Merge from branch "cannam"
author | Chris Cannam |
---|---|
date | Thu, 14 Jul 2011 10:43:07 +0100 |
parents | cbce1fd3b1b7 |
children |
comparison
equal
deleted
inserted
replaced
451:a9f6345cb43d | 511:107d36338b70 |
---|---|
1 # redMine - project management software | 1 # RedMine - project management software |
2 # Copyright (C) 2006-2007 Jean-Philippe Lang | 2 # Copyright (C) 2006-2011 Jean-Philippe Lang |
3 # | 3 # |
4 # FileSystem adapter | 4 # FileSystem adapter |
5 # File written by Paul Rivier, at Demotera. | 5 # File written by Paul Rivier, at Demotera. |
6 # | 6 # |
7 # This program is free software; you can redistribute it and/or | 7 # This program is free software; you can redistribute it and/or |
8 # modify it under the terms of the GNU General Public License | 8 # modify it under the terms of the GNU General Public License |
9 # as published by the Free Software Foundation; either version 2 | 9 # as published by the Free Software Foundation; either version 2 |
10 # of the License, or (at your option) any later version. | 10 # of the License, or (at your option) any later version. |
11 # | 11 # |
12 # This program is distributed in the hope that it will be useful, | 12 # This program is distributed in the hope that it will be useful, |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 # GNU General Public License for more details. | 15 # GNU General Public License for more details. |
16 # | 16 # |
17 # You should have received a copy of the GNU General Public License | 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 | 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. | 19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | 20 |
21 require 'redmine/scm/adapters/abstract_adapter' | 21 require 'redmine/scm/adapters/abstract_adapter' |
22 require 'find' | 22 require 'find' |
23 | 23 |
24 module Redmine | 24 module Redmine |
25 module Scm | 25 module Scm |
26 module Adapters | 26 module Adapters |
27 class FilesystemAdapter < AbstractAdapter | 27 class FilesystemAdapter < AbstractAdapter |
28 | |
29 | 28 |
30 def initialize(url, root_url=nil, login=nil, password=nil) | 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) | |
31 @url = with_trailling_slash(url) | 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 | |
32 end | 43 end |
33 | 44 |
34 def format_path_ends(path, leading=true, trailling=true) | 45 def format_path_ends(path, leading=true, trailling=true) |
35 path = leading ? with_leading_slash(path) : | 46 path = leading ? with_leading_slash(path) : |
36 without_leading_slash(path) | 47 without_leading_slash(path) |
37 trailling ? with_trailling_slash(path) : | 48 trailling ? with_trailling_slash(path) : |
38 without_trailling_slash(path) | 49 without_trailling_slash(path) |
39 end | 50 end |
40 | 51 |
41 def info | 52 def info |
42 info = Info.new({:root_url => target(), | 53 info = Info.new({:root_url => target(), |
43 :lastrev => nil | 54 :lastrev => nil |
44 }) | 55 }) |
45 info | 56 info |
46 rescue CommandFailed | 57 rescue CommandFailed |
47 return nil | 58 return nil |
48 end | 59 end |
49 | 60 |
50 def entries(path="", identifier=nil) | 61 def entries(path="", identifier=nil, options={}) |
51 entries = Entries.new | 62 entries = Entries.new |
52 Dir.new(target(path)).each do |e| | 63 trgt_utf8 = target(path) |
53 relative_path = format_path_ends((format_path_ends(path, | 64 trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8) |
54 false, | 65 Dir.new(trgt).each do |e1| |
55 true) + e), | 66 e_utf8 = scm_iconv('UTF-8', @path_encoding, e1) |
56 false,false) | 67 next if e_utf8.blank? |
57 target = target(relative_path) | 68 relative_path_utf8 = format_path_ends( |
58 entries << | 69 (format_path_ends(path,false,true) + e_utf8),false,false) |
59 Entry.new({ :name => File.basename(e), | 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)), | |
60 # below : list unreadable files, but dont link them. | 81 # below : list unreadable files, but dont link them. |
61 :path => File.readable?(target) ? relative_path : "", | 82 :path => utf_8_path, |
62 :kind => (File.directory?(target) ? 'dir' : 'file'), | 83 :kind => (File.directory?(t1) ? 'dir' : 'file'), |
63 :size => (File.directory?(target) ? nil : [File.size(target)].pack('l').unpack('L').first), | 84 :size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first), |
64 :lastrev => | 85 :lastrev => |
65 Revision.new({:time => (File.mtime(target)).localtime, | 86 Revision.new({:time => (File.mtime(t1)) }) |
66 }) | 87 }) |
67 }) if File.exist?(target) and # paranoid test | 88 end |
68 %w{file directory}.include?(File.ftype(target)) and # avoid special types | |
69 not File.basename(e).match(/^\.+$/) # avoid . and .. | |
70 end | 89 end |
71 entries.sort_by_name | 90 entries.sort_by_name |
91 rescue => err | |
92 logger.error "scm: filesystem: error: #{err.message}" | |
93 raise CommandFailed.new(err.message) | |
72 end | 94 end |
73 | 95 |
74 def cat(path, identifier=nil) | 96 def cat(path, identifier=nil) |
75 File.new(target(path), "rb").read | 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) | |
76 end | 102 end |
77 | 103 |
78 private | 104 private |
79 | 105 |
80 # AbstractAdapter::target is implicitly made to quote paths. | 106 # AbstractAdapter::target is implicitly made to quote paths. |
81 # Here we do not shell-out, so we do not want quotes. | 107 # Here we do not shell-out, so we do not want quotes. |
82 def target(path=nil) | 108 def target(path=nil) |
83 #Prevent the use of .. | 109 # Prevent the use of .. |
84 if path and !path.match(/(^|\/)\.\.(\/|$)/) | 110 if path and !path.match(/(^|\/)\.\.(\/|$)/) |
85 return "#{self.url}#{without_leading_slash(path)}" | 111 return "#{self.url}#{without_leading_slash(path)}" |
86 end | 112 end |
87 return self.url | 113 return self.url |
88 end | 114 end |
89 | |
90 end | 115 end |
91 end | 116 end |
92 end | 117 end |
93 end | 118 end |