@@ -23,7 +23,7 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 |
|
28 | |||
29 | class << self |
|
29 | class << self | |
@@ -34,6 +34,7 module Redmine | |||||
34 |
|
34 | |||
35 | def initialize(url, root_url=nil, login=nil, password=nil) |
|
35 | def initialize(url, root_url=nil, login=nil, password=nil) | |
36 | @url = with_trailling_slash(url) |
|
36 | @url = with_trailling_slash(url) | |
|
37 | @path_encoding = 'UTF-8' | |||
37 | end |
|
38 | end | |
38 |
|
39 | |||
39 | def format_path_ends(path, leading=true, trailling=true) |
|
40 | def format_path_ends(path, leading=true, trailling=true) | |
@@ -51,47 +52,59 module Redmine | |||||
51 | rescue CommandFailed |
|
52 | rescue CommandFailed | |
52 | return nil |
|
53 | return nil | |
53 | end |
|
54 | end | |
54 |
|
55 | |||
55 | def entries(path="", identifier=nil) |
|
56 | def entries(path="", identifier=nil) | |
56 | entries = Entries.new |
|
57 | entries = Entries.new | |
57 | Dir.new(target(path)).each do |e| |
|
58 | trgt_utf8 = target(path) | |
58 | relative_path = format_path_ends((format_path_ends(path, |
|
59 | trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8) | |
59 | false, |
|
60 | Dir.new(trgt).each do |e1| | |
60 | true) + e), |
|
61 | e_utf8 = scm_iconv('UTF-8', @path_encoding, e1) | |
61 | false,false) |
|
62 | relative_path_utf8 = format_path_ends((format_path_ends(path,false,true) + e_utf8),false,false) | |
62 |
t |
|
63 | t1_utf8 = target(relative_path_utf8) | |
63 | entries << |
|
64 | t1 = scm_iconv(@path_encoding, 'UTF-8', t1_utf8) | |
64 | Entry.new({ :name => File.basename(e), |
|
65 | relative_path = scm_iconv(@path_encoding, 'UTF-8', relative_path_utf8) | |
|
66 | e1 = scm_iconv(@path_encoding, 'UTF-8', e_utf8) | |||
|
67 | if File.exist?(t1) and # paranoid test | |||
|
68 | %w{file directory}.include?(File.ftype(t1)) and # avoid special types | |||
|
69 | not File.basename(e1).match(/^\.+$/) # avoid . and .. | |||
|
70 | p1 = File.readable?(t1) ? relative_path : "" | |||
|
71 | utf_8_path = scm_iconv('UTF-8', @path_encoding, p1) | |||
|
72 | entries << | |||
|
73 | Entry.new({ :name => scm_iconv('UTF-8', @path_encoding, File.basename(e1)), | |||
65 | # below : list unreadable files, but dont link them. |
|
74 | # below : list unreadable files, but dont link them. | |
66 |
:path => |
|
75 | :path => utf_8_path, | |
67 |
:kind => (File.directory?(t |
|
76 | :kind => (File.directory?(t1) ? 'dir' : 'file'), | |
68 |
:size => (File.directory?(t |
|
77 | :size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first), | |
69 | :lastrev => |
|
78 | :lastrev => | |
70 |
Revision.new({:time => (File.mtime(t |
|
79 | Revision.new({:time => (File.mtime(t1)) }) | |
71 |
|
|
80 | }) | |
72 | }) if File.exist?(target) and # paranoid test |
|
81 | end | |
73 | %w{file directory}.include?(File.ftype(target)) and # avoid special types |
|
|||
74 | not File.basename(e).match(/^\.+$/) # avoid . and .. |
|
|||
75 | end |
|
82 | end | |
76 | entries.sort_by_name |
|
83 | entries.sort_by_name | |
|
84 | rescue => err | |||
|
85 | logger.error "scm: filesystem: error: #{err.message}" | |||
|
86 | raise CommandFailed.new(err.message) | |||
77 | end |
|
87 | end | |
78 |
|
88 | |||
79 | def cat(path, identifier=nil) |
|
89 | def cat(path, identifier=nil) | |
80 | File.new(target(path), "rb").read |
|
90 | p = scm_iconv(@path_encoding, 'UTF-8', target(path)) | |
|
91 | File.new(p, "rb").read | |||
|
92 | rescue => err | |||
|
93 | logger.error "scm: filesystem: error: #{err.message}" | |||
|
94 | raise CommandFailed.new(err.message) | |||
81 | end |
|
95 | end | |
82 |
|
96 | |||
83 | private |
|
97 | private | |
84 |
|
98 | |||
85 | # AbstractAdapter::target is implicitly made to quote paths. |
|
99 | # AbstractAdapter::target is implicitly made to quote paths. | |
86 | # Here we do not shell-out, so we do not want quotes. |
|
100 | # Here we do not shell-out, so we do not want quotes. | |
87 | def target(path=nil) |
|
101 | def target(path=nil) | |
88 | #Prevent the use of .. |
|
102 | # Prevent the use of .. | |
89 | if path and !path.match(/(^|\/)\.\.(\/|$)/) |
|
103 | if path and !path.match(/(^|\/)\.\.(\/|$)/) | |
90 | return "#{self.url}#{without_leading_slash(path)}" |
|
104 | return "#{self.url}#{without_leading_slash(path)}" | |
91 | end |
|
105 | end | |
92 | return self.url |
|
106 | return self.url | |
93 | end |
|
107 | end | |
94 |
|
||||
95 | end |
|
108 | end | |
96 | end |
|
109 | end | |
97 | end |
|
110 | end |
General Comments 0
You need to be logged in to leave comments.
Login now