Revision 441:cbce1fd3b1b7 lib/redmine/scm/adapters/.svn

View differences:

lib/redmine/scm/adapters/.svn/all-wcprops
1 1
K 25
2 2
svn:wc:ra_dav:version-url
3
V 49
4
/svn/!svn/ver/4993/trunk/lib/redmine/scm/adapters
3
V 63
4
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters
5 5
END
6 6
subversion_adapter.rb
7 7
K 25
8 8
svn:wc:ra_dav:version-url
9
V 71
10
/svn/!svn/ver/4993/trunk/lib/redmine/scm/adapters/subversion_adapter.rb
9
V 85
10
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/subversion_adapter.rb
11 11
END
12 12
bazaar_adapter.rb
13 13
K 25
14 14
svn:wc:ra_dav:version-url
15
V 67
16
/svn/!svn/ver/4992/trunk/lib/redmine/scm/adapters/bazaar_adapter.rb
15
V 81
16
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/bazaar_adapter.rb
17 17
END
18 18
abstract_adapter.rb
19 19
K 25
20 20
svn:wc:ra_dav:version-url
21
V 69
22
/svn/!svn/ver/4959/trunk/lib/redmine/scm/adapters/abstract_adapter.rb
21
V 83
22
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/abstract_adapter.rb
23 23
END
24 24
git_adapter.rb
25 25
K 25
26 26
svn:wc:ra_dav:version-url
27
V 64
28
/svn/!svn/ver/4992/trunk/lib/redmine/scm/adapters/git_adapter.rb
27
V 78
28
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/git_adapter.rb
29 29
END
30 30
mercurial_adapter.rb
31 31
K 25
32 32
svn:wc:ra_dav:version-url
33
V 70
34
/svn/!svn/ver/4993/trunk/lib/redmine/scm/adapters/mercurial_adapter.rb
33
V 84
34
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/mercurial_adapter.rb
35 35
END
36 36
filesystem_adapter.rb
37 37
K 25
38 38
svn:wc:ra_dav:version-url
39
V 71
40
/svn/!svn/ver/4941/trunk/lib/redmine/scm/adapters/filesystem_adapter.rb
39
V 85
40
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/filesystem_adapter.rb
41 41
END
42 42
cvs_adapter.rb
43 43
K 25
44 44
svn:wc:ra_dav:version-url
45
V 64
46
/svn/!svn/ver/4992/trunk/lib/redmine/scm/adapters/cvs_adapter.rb
45
V 78
46
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/cvs_adapter.rb
47 47
END
48 48
darcs_adapter.rb
49 49
K 25
50 50
svn:wc:ra_dav:version-url
51
V 66
52
/svn/!svn/ver/4992/trunk/lib/redmine/scm/adapters/darcs_adapter.rb
51
V 80
52
/svn/!svn/ver/5878/branches/1.2-stable/lib/redmine/scm/adapters/darcs_adapter.rb
53 53
END
lib/redmine/scm/adapters/.svn/entries
1 1
10
2 2

  
3 3
dir
4
4993
5
http://redmine.rubyforge.org/svn/trunk/lib/redmine/scm/adapters
4
6000
5
http://redmine.rubyforge.org/svn/branches/1.2-stable/lib/redmine/scm/adapters
6 6
http://redmine.rubyforge.org/svn
7 7

  
8 8

  
9 9

  
10
2011-03-03T05:51:46.224821Z
11
4993
10
2011-05-21T02:39:42.521746Z
11
5870
12 12
tmaruyama
13 13

  
14 14

  
......
32 32

  
33 33

  
34 34

  
35
2011-03-03T11:40:18.000000Z
36
7e0b7e8a12996f271854b48e2d7611e4
37
2011-03-03T05:51:46.224821Z
38
4993
35
2011-06-06T13:20:53.000000Z
36
bf7d7b180f55d2100736e363ce125552
37
2011-05-10T17:52:56.415969Z
38
5731
39 39
tmaruyama
40
has-props
40 41

  
41 42

  
42 43

  
......
57 58

  
58 59

  
59 60

  
60

  
61
11535
61
11495
62 62

63 63
bazaar_adapter.rb
64 64
file
......
66 66

  
67 67

  
68 68

  
69
2011-03-03T11:40:18.000000Z
70
2614557fb37905301939071ec226fe16
71
2011-03-03T05:32:33.802461Z
72
4992
69
2011-06-06T13:20:53.000000Z
70
8bcb2a65cfdf8d27dc53f10469887018
71
2011-05-06T12:57:32.851840Z
72
5668
73 73
tmaruyama
74 74
has-props
75 75

  
......
92 92

  
93 93

  
94 94

  
95
8274
95
8398
96 96

97 97
mercurial
98 98
dir
......
103 103

  
104 104

  
105 105

  
106
2011-03-03T11:40:18.000000Z
107
5cc0323dd42df9a3377099b0fdf9e95f
108
2011-02-28T04:46:42.639929Z
109
4959
106
2011-06-06T13:20:53.000000Z
107
b5e95cdfce320e25a25588b5bf01d39a
108
2011-05-21T02:16:51.624699Z
109
5863
110 110
tmaruyama
111 111
has-props
112 112

  
......
129 129

  
130 130

  
131 131

  
132
9832
132
9625
133 133

134 134
git_adapter.rb
135 135
file
......
137 137

  
138 138

  
139 139

  
140
2011-03-03T11:40:18.000000Z
141
ba10ae64fed2363f2533aa558752be37
142
2011-03-03T05:32:33.802461Z
143
4992
140
2011-06-06T13:20:53.000000Z
141
8b7b85fc7884f18402dfd33412bb1632
142
2011-05-21T02:39:42.521746Z
143
5870
144 144
tmaruyama
145 145
has-props
146 146

  
......
163 163

  
164 164

  
165 165

  
166
11905
166
13537
167 167

168 168
mercurial_adapter.rb
169 169
file
......
171 171

  
172 172

  
173 173

  
174
2011-03-03T11:40:18.000000Z
175
fe99380d7b29fe936554e10293751813
176
2011-03-03T05:51:46.224821Z
177
4993
174
2011-06-06T13:20:53.000000Z
175
ef24fdf73dd59d164e60121c21aa5b93
176
2011-05-21T02:38:04.545904Z
177
5868
178 178
tmaruyama
179 179
has-props
180 180

  
......
197 197

  
198 198

  
199 199

  
200
11159
200
11824
201 201

202 202
filesystem_adapter.rb
203 203
file
......
205 205

  
206 206

  
207 207

  
208
2011-03-03T11:40:18.000000Z
209
4acd04cfa5dac0e54a35b8ef4a565217
210
2011-02-24T05:58:59.661399Z
211
4941
208
2011-06-06T13:20:53.000000Z
209
23ac49fabb89c7578c173ef09c7f280f
210
2011-05-21T02:17:34.152882Z
211
5864
212 212
tmaruyama
213 213
has-props
214 214

  
......
231 231

  
232 232

  
233 233

  
234
4266
234
4409
235 235

236 236
cvs_adapter.rb
237 237
file
......
239 239

  
240 240

  
241 241

  
242
2011-03-03T11:40:18.000000Z
243
a3914eff33df4b5a05a108945137360b
244
2011-03-03T05:32:33.802461Z
245
4992
242
2011-06-06T13:20:53.000000Z
243
0c56303ba5340dfff7860be537a1ccc1
244
2011-05-21T02:18:53.346845Z
245
5866
246 246
tmaruyama
247 247
has-props
248 248

  
......
265 265

  
266 266

  
267 267

  
268
14573
268
16766
269 269

270 270
darcs_adapter.rb
271 271
file
......
273 273

  
274 274

  
275 275

  
276
2011-03-03T11:40:18.000000Z
277
23725596dd2797f4dcdd5336e715c59a
278
2011-03-03T05:32:33.802461Z
279
4992
276
2011-06-06T13:20:53.000000Z
277
f039e19c659f52d26c9be8a566b90539
278
2011-05-06T12:57:54.181968Z
279
5669
280 280
tmaruyama
281 281
has-props
282 282

  
......
299 299

  
300 300

  
301 301

  
302
8925
302
8935
303 303

lib/redmine/scm/adapters/.svn/text-base/abstract_adapter.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
90 90
        def url
91 91
          @url
92 92
        end
93
      
93

  
94
        def path_encoding
95
          nil
96
        end
97

  
94 98
        # get info about the svn repository
95 99
        def info
96 100
          return nil
97 101
        end
98
        
102

  
99 103
        # Returns the entry identified by path and revision identifier
100 104
        # or nil if entry doesn't exist in the repository
101 105
        def entry(path=nil, identifier=nil)
......
111 115
            es ? es.detect {|e| e.name == search_name} : nil
112 116
          end
113 117
        end
114
        
118

  
115 119
        # Returns an Entries collection
116 120
        # or nil if the given path doesn't exist in the repository
117
        def entries(path=nil, identifier=nil)
121
        def entries(path=nil, identifier=nil, options={})
118 122
          return nil
119 123
        end
120 124

  
......
122 126
          return nil
123 127
        end
124 128

  
125
        def tags 
129
        def tags
126 130
          return nil
127 131
        end
128 132

  
129 133
        def default_branch
130 134
          return nil
131 135
        end
132
        
136

  
133 137
        def properties(path, identifier=nil)
134 138
          return nil
135 139
        end
136
    
140

  
137 141
        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
138 142
          return nil
139 143
        end
140
        
144

  
141 145
        def diff(path, identifier_from, identifier_to=nil)
142 146
          return nil
143 147
        end
144
        
148

  
145 149
        def cat(path, identifier=nil)
146 150
          return nil
147 151
        end
148
        
152

  
149 153
        def with_leading_slash(path)
150 154
          path ||= ''
151 155
          (path[0,1]!="/") ? "/#{path}" : path
......
175 179
          info = self.info
176 180
          info ? info.root_url : nil
177 181
        end
178
        
182

  
179 183
        def target(path)
180 184
          path ||= ''
181 185
          base = path.match(/^\//) ? root_url : url
......
223 227
          q = (Redmine::Platform.mswin? ? '"' : "'")
224 228
          cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
225 229
        end
226
        
230

  
227 231
        def strip_credential(cmd)
228 232
          self.class.strip_credential(cmd)
229 233
        end
......
242 246

  
243 247
      class Entries < Array
244 248
        def sort_by_name
245
          sort {|x,y| 
249
          sort {|x,y|
246 250
            if x.kind == y.kind
247 251
              x.name.to_s <=> y.name.to_s
248 252
            else
......
250 254
            end
251 255
          }
252 256
        end
253
        
257

  
254 258
        def revisions
255 259
          revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
256 260
        end
257 261
      end
258
      
262

  
259 263
      class Info
260 264
        attr_accessor :root_url, :lastrev
261 265
        def initialize(attributes={})
......
263 267
          self.lastrev = attributes[:lastrev]
264 268
        end
265 269
      end
266
      
270

  
267 271
      class Entry
268 272
        attr_accessor :name, :path, :kind, :size, :lastrev
269 273
        def initialize(attributes={})
......
273 277
          self.size = attributes[:size].to_i if attributes[:size]
274 278
          self.lastrev = attributes[:lastrev]
275 279
        end
276
        
280

  
277 281
        def is_file?
278 282
          'file' == self.kind
279 283
        end
280
        
284

  
281 285
        def is_dir?
282 286
          'dir' == self.kind
283 287
        end
284
        
288

  
285 289
        def is_text?
286 290
          Redmine::MimeType.is_type?('text', name)
287 291
        end
288 292
      end
289
      
293

  
290 294
      class Revisions < Array
291 295
        def latest
292 296
          sort {|x,y|
......
296 300
              0
297 301
            end
298 302
          }.last
299
        end 
303
        end
300 304
      end
301
      
305

  
302 306
      class Revision
303
        attr_accessor :scmid, :name, :author, :time, :message, :paths, :revision, :branch
304
        attr_writer :identifier
307
        attr_accessor :scmid, :name, :author, :time, :message,
308
                      :paths, :revision, :branch, :identifier
305 309

  
306 310
        def initialize(attributes={})
307 311
          self.identifier = attributes[:identifier]
308
          self.scmid = attributes[:scmid]
309
          self.name = attributes[:name] || self.identifier
310
          self.author = attributes[:author]
311
          self.time = attributes[:time]
312
          self.message = attributes[:message] || ""
313
          self.paths = attributes[:paths]
314
          self.revision = attributes[:revision]
315
          self.branch = attributes[:branch]
316
        end
317

  
318
        # Returns the identifier of this revision; see also Changeset model
319
        def identifier
320
          (@identifier || revision).to_s
312
          self.scmid      = attributes[:scmid]
313
          self.name       = attributes[:name] || self.identifier
314
          self.author     = attributes[:author]
315
          self.time       = attributes[:time]
316
          self.message    = attributes[:message] || ""
317
          self.paths      = attributes[:paths]
318
          self.revision   = attributes[:revision]
319
          self.branch     = attributes[:branch]
321 320
        end
322 321

  
323 322
        # Returns the readable identifier.
324 323
        def format_identifier
325
          identifier
324
          self.identifier.to_s
326 325
        end
327 326
      end
328 327

  
329 328
      class Annotate
330 329
        attr_reader :lines, :revisions
331
        
330

  
332 331
        def initialize
333 332
          @lines = []
334 333
          @revisions = []
335 334
        end
336
        
335

  
337 336
        def add_line(line, revision)
338 337
          @lines << line
339 338
          @revisions << revision
340 339
        end
341
        
340

  
342 341
        def content
343 342
          content = lines.join("\n")
344 343
        end
345
        
344

  
346 345
        def empty?
347 346
          lines.empty?
348 347
        end
lib/redmine/scm/adapters/.svn/text-base/bazaar_adapter.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
78 78

  
79 79
        # Returns an Entries collection
80 80
        # or nil if the given path doesn't exist in the repository
81
        def entries(path=nil, identifier=nil)
81
        def entries(path=nil, identifier=nil, options={})
82 82
          path ||= ''
83 83
          entries = Entries.new
84 84
          cmd = "#{self.class.sq_bin} ls -v --show-ids"
85
          identifier = -1 unless identifier && identifier.to_i > 0 
86
          cmd << " -r#{identifier.to_i}" 
85
          identifier = -1 unless identifier && identifier.to_i > 0
86
          cmd << " -r#{identifier.to_i}"
87 87
          cmd << " #{target(path)}"
88 88
          shellout(cmd) do |io|
89 89
            prefix = "#{url}/#{path}".gsub('\\', '/')
......
120 120
                parsing = nil
121 121
              else
122 122
                next unless revision
123
                
124 123
                if line =~ /^revno: (\d+)($|\s\[merge\]$)/
125 124
                  revision.identifier = $1.to_i
126 125
                elsif line =~ /^committer: (.+)$/
......
168 167
        def diff(path, identifier_from, identifier_to=nil)
169 168
          path ||= ''
170 169
          if identifier_to
171
            identifier_to = identifier_to.to_i 
170
            identifier_to = identifier_to.to_i
172 171
          else
173 172
            identifier_to = identifier_from.to_i - 1
174 173
          end
......
209 208
            identifier = nil
210 209
            io.each_line do |line|
211 210
              next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
212
              blame.add_line($3.rstrip, Revision.new(:identifier => $1.to_i, :author => $2.strip))
211
              rev = $1
212
              blame.add_line($3.rstrip,
213
                 Revision.new(
214
                  :identifier => rev,
215
                  :revision   => rev,
216
                  :author     => $2.strip
217
                  ))
213 218
            end
214 219
          end
215 220
          return nil if $? && $?.exitstatus != 0
lib/redmine/scm/adapters/.svn/text-base/cvs_adapter.rb.svn-base
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
25 25
        # CVS executable name
26 26
        CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs"
27 27

  
28
        # raised if scm command exited with error, e.g. unknown revision.
29
        class ScmCommandAborted < CommandFailed; end
30

  
28 31
        class << self
29 32
          def client_command
30 33
            @@bin    ||= CVS_BIN
......
58 61
        end
59 62

  
60 63
        # Guidelines for the input:
61
        #  url -> the project-path, relative to the cvsroot (eg. module name)
64
        #  url      -> the project-path, relative to the cvsroot (eg. module name)
62 65
        #  root_url -> the good old, sometimes damned, CVSROOT
63
        #  login -> unnecessary
66
        #  login    -> unnecessary
64 67
        #  password -> unnecessary too
65 68
        def initialize(url, root_url=nil, login=nil, password=nil,
66 69
                       path_encoding=nil)
67
          @url = url
68
          @login = login if login && !login.empty?
70
          @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
71
          @url      = url
72
          # TODO: better Exception here (IllegalArgumentException)
73
          raise CommandFailed if root_url.blank?
74
          @root_url  = root_url
75

  
76
          # These are unused.
77
          @login    = login if login && !login.empty?
69 78
          @password = (password || "") if @login
70
          #TODO: better Exception here (IllegalArgumentException)
71
          raise CommandFailed if root_url.blank?
72
          @root_url = root_url
73 79
        end
74 80

  
75
        def root_url
76
          @root_url
77
        end
78

  
79
        def url
80
          @url
81
        def path_encoding
82
          @path_encoding
81 83
        end
82 84

  
83 85
        def info
......
92 94
        # Returns an Entries collection
93 95
        # or nil if the given path doesn't exist in the repository
94 96
        # this method is used by the repository-browser (aka LIST)
95
        def entries(path=nil, identifier=nil)
97
        def entries(path=nil, identifier=nil, options={})
96 98
          logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
97
          path_with_project="#{url}#{with_leading_slash(path)}"
99
          path_locale = scm_iconv(@path_encoding, 'UTF-8', path)
100
          path_locale.force_encoding("ASCII-8BIT") if path_locale.respond_to?(:force_encoding)
98 101
          entries = Entries.new
99
          cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rls -e"
100
          cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
101
          cmd << " #{shell_quote path_with_project}"
102
          shellout(cmd) do |io|
103
            io.each_line(){|line|
104
              fields=line.chop.split('/',-1)
102
          cmd_args = %w|-q rls -e|
103
          cmd_args << "-D" << time_to_cvstime_rlog(identifier) if identifier
104
          cmd_args << path_with_proj(path)
105
          scm_cmd(*cmd_args) do |io|
106
            io.each_line() do |line|
107
              fields = line.chop.split('/',-1)
105 108
              logger.debug(">>InspectLine #{fields.inspect}")
106

  
107 109
              if fields[0]!="D"
108
                entries << Entry.new({:name => fields[-5],
110
                time = nil
111
                # Thu Dec 13 16:27:22 2007
112
                time_l = fields[-3].split(' ')
113
                if time_l.size == 5 && time_l[4].length == 4
114
                  begin
115
                    time = Time.parse(
116
                             "#{time_l[1]} #{time_l[2]} #{time_l[3]} GMT #{time_l[4]}")
117
                  rescue
118
                  end
119
                end
120
                entries << Entry.new(
121
                 {
122
                  :name => scm_iconv('UTF-8', @path_encoding, fields[-5]),
109 123
                  #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]),
110
                  :path => "#{path}/#{fields[-5]}",
124
                  :path => scm_iconv('UTF-8', @path_encoding, "#{path_locale}/#{fields[-5]}"),
111 125
                  :kind => 'file',
112 126
                  :size => nil,
113
                  :lastrev => Revision.new({
114
                    :revision => fields[-4],
115
                    :name => fields[-4],
116
                    :time => Time.parse(fields[-3]),
117
                    :author => ''
127
                  :lastrev => Revision.new(
128
                      {
129
                        :revision => fields[-4],
130
                        :name     => scm_iconv('UTF-8', @path_encoding, fields[-4]),
131
                        :time     => time,
132
                        :author   => ''
133
                      })
118 134
                  })
119
                })
120 135
              else
121
                entries << Entry.new({:name => fields[1],
122
                  :path => "#{path}/#{fields[1]}",
123
                  :kind => 'dir',
124
                  :size => nil,
136
                entries << Entry.new(
137
                 {
138
                  :name    => scm_iconv('UTF-8', @path_encoding, fields[1]),
139
                  :path    => scm_iconv('UTF-8', @path_encoding, "#{path_locale}/#{fields[1]}"),
140
                  :kind    => 'dir',
141
                  :size    => nil,
125 142
                  :lastrev => nil
126
                })
143
                 })
127 144
              end
128
            }
145
            end
129 146
          end
130
          return nil if $? && $?.exitstatus != 0
131 147
          entries.sort_by_name
148
        rescue ScmCommandAborted
149
          nil
132 150
        end
133 151

  
134 152
        STARTLOG="----------------------------"
......
138 156
        # in the repository. both identifier have to be dates or nil.
139 157
        # these method returns nothing but yield every result in block
140 158
        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block)
141
          logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
142

  
143
          path_with_project="#{url}#{with_leading_slash(path)}"
144
          cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rlog"
145
          cmd << " -d\">#{time_to_cvstime_rlog(identifier_from)}\"" if identifier_from
146
          cmd << " #{shell_quote path_with_project}"
147
          shellout(cmd) do |io|
148
            state="entry_start"
149
            
150
            commit_log=String.new
151
            revision=nil
152
            date=nil
153
            author=nil
154
            entry_path=nil
155
            entry_name=nil
156
            file_state=nil
157
            branch_map=nil
158
            
159
          path_with_project_utf8   = path_with_proj(path)
160
          path_with_project_locale = scm_iconv(@path_encoding, 'UTF-8', path_with_project_utf8)
161
          logger.debug "<cvs> revisions path:" +
162
              "'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
163
          cmd_args = %w|-q rlog|
164
          cmd_args << "-d" << ">#{time_to_cvstime_rlog(identifier_from)}" if identifier_from
165
          cmd_args << path_with_project_utf8
166
          scm_cmd(*cmd_args) do |io|
167
            state      = "entry_start"
168
            commit_log = String.new
169
            revision   = nil
170
            date       = nil
171
            author     = nil
172
            entry_path = nil
173
            entry_name = nil
174
            file_state = nil
175
            branch_map = nil
159 176
            io.each_line() do |line|
160
              
161
              if state!="revision" && /^#{ENDLOG}/ =~ line
162
                commit_log=String.new
163
                revision=nil
164
                state="entry_start"
177
              if state != "revision" && /^#{ENDLOG}/ =~ line
178
                commit_log = String.new
179
                revision   = nil
180
                state      = "entry_start"
165 181
              end
166
              
167
              if state=="entry_start"
168
                branch_map=Hash.new
169
                if /^RCS file: #{Regexp.escape(root_url_path)}\/#{Regexp.escape(path_with_project)}(.+),v$/ =~ line
182
              if state == "entry_start"
183
                branch_map = Hash.new
184
                if /^RCS file: #{Regexp.escape(root_url_path)}\/#{Regexp.escape(path_with_project_locale)}(.+),v$/ =~ line
170 185
                  entry_path = normalize_cvs_path($1)
171 186
                  entry_name = normalize_path(File.basename($1))
172 187
                  logger.debug("Path #{entry_path} <=> Name #{entry_name}")
173 188
                elsif /^head: (.+)$/ =~ line
174 189
                  entry_headRev = $1 #unless entry.nil?
175 190
                elsif /^symbolic names:/ =~ line
176
                  state="symbolic" #unless entry.nil?
191
                  state = "symbolic" #unless entry.nil?
177 192
                elsif /^#{STARTLOG}/ =~ line
178
                  commit_log=String.new
179
                  state="revision"
180
                end  
193
                  commit_log = String.new
194
                  state      = "revision"
195
                end
181 196
                next
182
              elsif state=="symbolic"
183
                if /^(.*):\s(.*)/ =~ (line.strip) 
184
                  branch_map[$1]=$2
197
              elsif state == "symbolic"
198
                if /^(.*):\s(.*)/ =~ (line.strip)
199
                  branch_map[$1] = $2
185 200
                else
186
                  state="tags"
201
                  state = "tags"
187 202
                  next
188
                end          
189
              elsif state=="tags"
203
                end
204
              elsif state == "tags"
190 205
                if /^#{STARTLOG}/ =~ line
191 206
                  commit_log = ""
192
                  state="revision"
207
                  state = "revision"
193 208
                elsif /^#{ENDLOG}/ =~ line
194
                  state="head"
209
                  state = "head"
195 210
                end
196 211
                next
197
              elsif state=="revision"
212
              elsif state == "revision"
198 213
                if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line
199 214
                  if revision
200

  
201
                    revHelper=CvsRevisionHelper.new(revision)
202
                    revBranch="HEAD"
203
                    
204
                    branch_map.each() do |branch_name,branch_point|
215
                    revHelper = CvsRevisionHelper.new(revision)
216
                    revBranch = "HEAD"
217
                    branch_map.each() do |branch_name, branch_point|
205 218
                      if revHelper.is_in_branch_with_symbol(branch_point)
206
                        revBranch=branch_name
219
                        revBranch = branch_name
207 220
                      end
208 221
                    end
209
                    
210 222
                    logger.debug("********** YIELD Revision #{revision}::#{revBranch}")
211
                    
212 223
                    yield Revision.new({
213
                      :time => date,
214
                      :author => author,
215
                      :message=>commit_log.chomp,
224
                      :time    => date,
225
                      :author  => author,
226
                      :message => commit_log.chomp,
216 227
                      :paths => [{
217 228
                        :revision => revision,
218
                        :branch=> revBranch,
219
                        :path=>entry_path,
220
                        :name=>entry_name,
221
                        :kind=>'file',
222
                        :action=>file_state
223
                      }]
224
                    })
229
                        :branch   => revBranch,
230
                        :path     => scm_iconv('UTF-8', @path_encoding, entry_path),
231
                        :name     => scm_iconv('UTF-8', @path_encoding, entry_name),
232
                        :kind     => 'file',
233
                        :action   => file_state
234
                           }]
235
                         })
225 236
                  end
226

  
227
                  commit_log=String.new
228
                  revision=nil
229
                  
237
                  commit_log = String.new
238
                  revision   = nil
230 239
                  if /^#{ENDLOG}/ =~ line
231
                    state="entry_start"
240
                    state = "entry_start"
232 241
                  end
233 242
                  next
234 243
                end
235 244

  
236 245
                if /^branches: (.+)$/ =~ line
237
                  #TODO: version.branch = $1
246
                  # TODO: version.branch = $1
238 247
                elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line
239
                  revision = $1   
248
                  revision = $1
240 249
                elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line
241
                  date      = Time.parse($1)
242
                  author    = /author: ([^;]+)/.match(line)[1]
243
                  file_state     = /state: ([^;]+)/.match(line)[1]
244
                  #TODO: linechanges only available in CVS.... maybe a feature our SVN implementation. i'm sure, they are
245
                  #    useful for stats or something else
250
                  date       = Time.parse($1)
251
                  line_utf8    = scm_iconv('UTF-8', options[:log_encoding], line)
252
                  author_utf8  = /author: ([^;]+)/.match(line_utf8)[1]
253
                  author       = scm_iconv(options[:log_encoding], 'UTF-8', author_utf8)
254
                  file_state   = /state: ([^;]+)/.match(line)[1]
255
                  # TODO:
256
                  #    linechanges only available in CVS....
257
                  #    maybe a feature our SVN implementation.
258
                  #    I'm sure, they are useful for stats or something else
246 259
                  #                linechanges =/lines: \+(\d+) -(\d+)/.match(line)
247 260
                  #                unless linechanges.nil?
248 261
                  #                  version.line_plus  = linechanges[1]
......
257 270
              end
258 271
            end
259 272
          end
273
        rescue ScmCommandAborted
274
          Revisions.new
260 275
        end
261 276

  
262 277
        def diff(path, identifier_from, identifier_to=nil)
263
          logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
264
          path_with_project="#{url}#{with_leading_slash(path)}"
265
          cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}"
278
          logger.debug "<cvs> diff path:'#{path}'" +
279
              ",identifier_from #{identifier_from}, identifier_to #{identifier_to}"
280
          cmd_args = %w|rdiff -u|
281
          cmd_args << "-r#{identifier_to}"
282
          cmd_args << "-r#{identifier_from}"
283
          cmd_args << path_with_proj(path)
266 284
          diff = []
267
          shellout(cmd) do |io|
285
          scm_cmd(*cmd_args) do |io|
268 286
            io.each_line do |line|
269 287
              diff << line
270 288
            end
271 289
          end
272
          return nil if $? && $?.exitstatus != 0
273 290
          diff
291
        rescue ScmCommandAborted
292
          nil
274 293
        end
275 294

  
276 295
        def cat(path, identifier=nil)
277 296
          identifier = (identifier) ? identifier : "HEAD"
278 297
          logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}"
279
          path_with_project="#{url}#{with_leading_slash(path)}"
280
          cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co"
281
          cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
282
          cmd << " -p #{shell_quote path_with_project}"
298
          cmd_args = %w|-q co|
299
          cmd_args << "-D" << time_to_cvstime(identifier) if identifier
300
          cmd_args << "-p" << path_with_proj(path)
283 301
          cat = nil
284
          shellout(cmd) do |io|
302
          scm_cmd(*cmd_args) do |io|
285 303
            io.binmode
286 304
            cat = io.read
287 305
          end
288
          return nil if $? && $?.exitstatus != 0
289 306
          cat
307
        rescue ScmCommandAborted
308
          nil
290 309
        end
291 310

  
292 311
        def annotate(path, identifier=nil)
293
          identifier = (identifier) ? identifier.to_i : "HEAD"
312
          identifier = (identifier) ? identifier : "HEAD"
294 313
          logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}"
295
          path_with_project="#{url}#{with_leading_slash(path)}"
296
          cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}"
314
          cmd_args = %w|rannotate|
315
          cmd_args << "-D" << time_to_cvstime(identifier) if identifier
316
          cmd_args << path_with_proj(path)
297 317
          blame = Annotate.new
298
          shellout(cmd) do |io|
318
          scm_cmd(*cmd_args) do |io|
299 319
            io.each_line do |line|
300 320
              next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$}
301
              blame.add_line($3.rstrip, Revision.new(:revision => $1, :author => $2.strip))
321
              blame.add_line(
322
                  $3.rstrip,
323
                  Revision.new(
324
                    :revision   => $1,
325
                    :identifier => nil,
326
                    :author     => $2.strip
327
                    ))
302 328
            end
303 329
          end
304
          return nil if $? && $?.exitstatus != 0
305 330
          blame
331
        rescue ScmCommandAborted
332
          Annotate.new
306 333
        end
307 334

  
308 335
        private
......
317 344
        # convert a date/time into the CVS-format
318 345
        def time_to_cvstime(time)
319 346
          return nil if time.nil?
320
          return Time.now if time == 'HEAD'
321
          
347
          time = Time.now if time == 'HEAD'
348

  
322 349
          unless time.kind_of? Time
323 350
            time = Time.parse(time)
324 351
          end
325
          return time.strftime("%Y-%m-%d %H:%M:%S")
352
          return time_to_cvstime_rlog(time)
326 353
        end
327 354

  
328 355
        def time_to_cvstime_rlog(time)
......
330 357
          t1 = time.clone.localtime
331 358
          return t1.strftime("%Y-%m-%d %H:%M:%S")
332 359
        end
333
          
360

  
334 361
        def normalize_cvs_path(path)
335 362
          normalize_path(path.gsub(/Attic\//,''))
336 363
        end
337
          
364

  
338 365
        def normalize_path(path)
339 366
          path.sub(/^(\/)*(.*)/,'\2').sub(/(.*)(,v)+/,'\1')
340
        end   
341
      end  
342
  
367
        end
368

  
369
        def path_with_proj(path)
370
          "#{url}#{with_leading_slash(path)}"
371
        end
372
        private :path_with_proj
373

  
374
        class Revision < Redmine::Scm::Adapters::Revision
375
          # Returns the readable identifier
376
          def format_identifier
377
            revision.to_s
378
          end
379
        end
380

  
381
        def scm_cmd(*args, &block)
382
          full_args = [CVS_BIN, '-d', root_url]
383
          full_args += args
384
          full_args_locale = []
385
          full_args.map do |e|
386
            full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e)
387
          end
388
          ret = shellout(full_args_locale.map { |e| shell_quote e.to_s }.join(' '), &block)
389
          if $? && $?.exitstatus != 0
390
            raise ScmCommandAborted, "cvs exited with non-zero status: #{$?.exitstatus}"
391
          end
392
          ret
393
        end
394
        private :scm_cmd
395
      end
396

  
343 397
      class CvsRevisionHelper
344 398
        attr_accessor :complete_rev, :revision, :base, :branchid
345
        
399

  
346 400
        def initialize(complete_rev)
347 401
          @complete_rev = complete_rev
348 402
          parseRevision()
349 403
        end
350
    
404

  
351 405
        def branchPoint
352 406
          return @base
353 407
        end
354
      
408

  
355 409
        def branchVersion
356 410
          if isBranchRevision
357 411
            return @base+"."+@branchid
358 412
          end
359 413
          return @base
360 414
        end
361
      
415

  
362 416
        def isBranchRevision
363 417
          !@branchid.nil?
364 418
        end
365
        
419

  
366 420
        def prevRev
367
          unless @revision==0
368
            return buildRevision(@revision-1)
421
          unless @revision == 0
422
            return buildRevision( @revision - 1 )
369 423
          end
370
          return buildRevision(@revision)    
424
          return buildRevision( @revision )
371 425
        end
372
        
426

  
373 427
        def is_in_branch_with_symbol(branch_symbol)
374
          bpieces=branch_symbol.split(".")
375
          branch_start="#{bpieces[0..-3].join(".")}.#{bpieces[-1]}"
376
          return (branchVersion==branch_start)
428
          bpieces = branch_symbol.split(".")
429
          branch_start = "#{bpieces[0..-3].join(".")}.#{bpieces[-1]}"
430
          return ( branchVersion == branch_start )
377 431
        end
378
    
432

  
379 433
        private
380 434
        def buildRevision(rev)
381
          if rev== 0
435
          if rev == 0
382 436
            if @branchid.nil?
383
              @base+".0"
437
              @base + ".0"
384 438
            else
385 439
              @base
386 440
            end
387
          elsif @branchid.nil? 
388
            @base+"."+rev.to_s
441
          elsif @branchid.nil?
442
            @base + "." + rev.to_s
389 443
          else
390
            @base+"."+@branchid+"."+rev.to_s
444
            @base + "." + @branchid + "." + rev.to_s
391 445
          end
392 446
        end
393
        
447

  
394 448
        # Interpretiert die cvs revisionsnummern wie z.b. 1.14 oder 1.3.0.15
395 449
        def parseRevision()
396
          pieces=@complete_rev.split(".")
397
          @revision=pieces.last.to_i
398
          baseSize=1
399
          baseSize+=(pieces.size/2)
400
          @base=pieces[0..-baseSize].join(".")
450
          pieces = @complete_rev.split(".")
451
          @revision = pieces.last.to_i
452
          baseSize = 1
453
          baseSize += (pieces.size / 2)
454
          @base = pieces[0..-baseSize].join(".")
401 455
          if baseSize > 2
402
            @branchid=pieces[-2]
403
          end     
456
            @branchid = pieces[-2]
457
          end
404 458
        end
405 459
      end
406 460
    end
lib/redmine/scm/adapters/.svn/text-base/darcs_adapter.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
76 76

  
77 77
        # Returns an Entries collection
78 78
        # or nil if the given path doesn't exist in the repository
79
        def entries(path=nil, identifier=nil)
79
        def entries(path=nil, identifier=nil, options={})
80 80
          path_prefix = (path.blank? ? '' : "#{path}/")
81 81
          if path.blank?
82 82
            path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' )
lib/redmine/scm/adapters/.svn/text-base/filesystem_adapter.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# RedMine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# FileSystem adapter
5 5
# File written by Paul Rivier, at Demotera.
......
8 8
# modify it under the terms of the GNU General Public License
9 9
# as published by the Free Software Foundation; either version 2
10 10
# of the License, or (at your option) any later version.
11
# 
11
#
12 12
# This program is distributed in the hope that it will be useful,
13 13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14 14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 15
# GNU General Public License for more details.
16
# 
16
#
17 17
# You should have received a copy of the GNU General Public License
18 18
# along with this program; if not, write to the Free Software
19 19
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
35 35
        def initialize(url, root_url=nil, login=nil, password=nil,
36 36
                       path_encoding=nil)
37 37
          @url = with_trailling_slash(url)
38
          @path_encoding = path_encoding || 'UTF-8'
38
          @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
39
        end
40

  
41
        def path_encoding
42
          @path_encoding
39 43
        end
40 44

  
41 45
        def format_path_ends(path, leading=true, trailling=true)
42
          path = leading ? with_leading_slash(path) : 
46
          path = leading ? with_leading_slash(path) :
43 47
            without_leading_slash(path)
44
          trailling ? with_trailling_slash(path) : 
45
            without_trailling_slash(path) 
48
          trailling ? with_trailling_slash(path) :
49
            without_trailling_slash(path)
46 50
        end
47 51

  
48 52
        def info
......
54 58
          return nil
55 59
        end
56 60

  
57
        def entries(path="", identifier=nil)
61
        def entries(path="", identifier=nil, options={})
58 62
          entries = Entries.new
59 63
          trgt_utf8 = target(path)
60 64
          trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8)
61 65
          Dir.new(trgt).each do |e1|
62 66
            e_utf8 = scm_iconv('UTF-8', @path_encoding, e1)
63
            relative_path_utf8 = format_path_ends((format_path_ends(path,false,true) + e_utf8),false,false)
67
            next if e_utf8.blank?
68
            relative_path_utf8 = format_path_ends(
69
                (format_path_ends(path,false,true) + e_utf8),false,false)
64 70
            t1_utf8 = target(relative_path_utf8)
65 71
            t1 = scm_iconv(@path_encoding, 'UTF-8', t1_utf8)
66 72
            relative_path = scm_iconv(@path_encoding, 'UTF-8', relative_path_utf8)
......
76 82
                          :path => utf_8_path,
77 83
                          :kind => (File.directory?(t1) ? 'dir' : 'file'),
78 84
                          :size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first),
79
                          :lastrev => 
85
                          :lastrev =>
80 86
                              Revision.new({:time => (File.mtime(t1)) })
81 87
                        })
82 88
            end
lib/redmine/scm/adapters/.svn/text-base/git_adapter.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
22 22
    module Adapters
23 23
      class GitAdapter < AbstractAdapter
24 24

  
25
        SCM_GIT_REPORT_LAST_COMMIT = true
26

  
27 25
        # Git executable name
28 26
        GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
29 27

  
......
64 62

  
65 63
        def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
66 64
          super
67
          @flag_report_last_commit = SCM_GIT_REPORT_LAST_COMMIT
65
          @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
66
        end
67

  
68
        def path_encoding
69
          @path_encoding
68 70
        end
69 71

  
70 72
        def info
......
78 80
        def branches
79 81
          return @branches if @branches
80 82
          @branches = []
81
          cmd = "#{self.class.sq_bin} --git-dir #{target('')} branch --no-color"
82
          shellout(cmd) do |io|
83
          cmd_args = %w|branch --no-color|
84
          scm_cmd(*cmd_args) do |io|
83 85
            io.each_line do |line|
84 86
              @branches << line.match('\s*\*?\s*(.*)$')[1]
85 87
            end
86 88
          end
87 89
          @branches.sort!
90
        rescue ScmCommandAborted
91
          nil
88 92
        end
89 93

  
90 94
        def tags
91 95
          return @tags if @tags
92
          cmd = "#{self.class.sq_bin} --git-dir #{target('')} tag"
93
          shellout(cmd) do |io|
96
          cmd_args = %w|tag|
97
          scm_cmd(*cmd_args) do |io|
94 98
            @tags = io.readlines.sort!.map{|t| t.strip}
95 99
          end
100
        rescue ScmCommandAborted
101
          nil
102
        end
103

  
104
        def default_branch
105
          bras = self.branches
106
          return nil if bras.nil?
107
          bras.include?('master') ? 'master' : bras.first
108
        end
109

  
110
        def entry(path=nil, identifier=nil)
111
          parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
112
          search_path = parts[0..-2].join('/')
113
          search_name = parts[-1]
114
          if search_path.blank? && search_name.blank?
115
            # Root entry
116
            Entry.new(:path => '', :kind => 'dir')
117
          else
118
            # Search for the entry in the parent directory
119
            es = entries(search_path, identifier,
120
                         options = {:report_last_commit => false})
121
            es ? es.detect {|e| e.name == search_name} : nil
122
          end
96 123
        end
97 124

  
98
        def default_branch
99
          branches.include?('master') ? 'master' : branches.first
100
        end
101

  
102
        def entries(path=nil, identifier=nil)
125
        def entries(path=nil, identifier=nil, options={})
103 126
          path ||= ''
127
          p = scm_iconv(@path_encoding, 'UTF-8', path)
104 128
          entries = Entries.new
105
          cmd = "#{self.class.sq_bin} --git-dir #{target('')} ls-tree -l "
106
          cmd << shell_quote("HEAD:" + path) if identifier.nil?
107
          cmd << shell_quote(identifier + ":" + path) if identifier
108
          shellout(cmd)  do |io|
129
          cmd_args = %w|ls-tree -l|
130
          cmd_args << "HEAD:#{p}"          if identifier.nil?
131
          cmd_args << "#{identifier}:#{p}" if identifier
132
          scm_cmd(*cmd_args) do |io|
109 133
            io.each_line do |line|
110 134
              e = line.chomp.to_s
111 135
              if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
112 136
                type = $1
113
                sha = $2
137
                sha  = $2
114 138
                size = $3
115 139
                name = $4
116
                full_path = path.empty? ? name : "#{path}/#{name}"
117
                entries << Entry.new({:name => name,
118
                 :path => full_path,
140
                if name.respond_to?(:force_encoding)
141
                  name.force_encoding(@path_encoding)
142
                end
143
                full_path = p.empty? ? name : "#{p}/#{name}"
144
                n      = scm_iconv('UTF-8', @path_encoding, name)
145
                full_p = scm_iconv('UTF-8', @path_encoding, full_path)
146
                entries << Entry.new({:name => n,
147
                 :path => full_p,
119 148
                 :kind => (type == "tree") ? 'dir' : 'file',
120 149
                 :size => (type == "tree") ? nil : size,
121
                 :lastrev => @flag_report_last_commit ? lastrev(full_path,identifier) : Revision.new
150
                 :lastrev => options[:report_last_commit] ?
151
                                 lastrev(full_path, identifier) : Revision.new
122 152
                }) unless entries.detect{|entry| entry.name == name}
123 153
              end
124 154
            end
125 155
          end
126
          return nil if $? && $?.exitstatus != 0
127 156
          entries.sort_by_name
157
        rescue ScmCommandAborted
158
          nil
128 159
        end
129 160

  
130 161
        def lastrev(path, rev)
131 162
          return nil if path.nil?
132 163
          cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
133
          cmd_args << rev if rev 
164
          cmd_args << rev if rev
134 165
          cmd_args << "--" << path unless path.empty?
135 166
          lines = []
136 167
          scm_cmd(*cmd_args) { |io| lines = io.readlines }
......
141 172

  
142 173
              Revision.new({
143 174
                :identifier => id,
144
                :scmid => id,
145
                :author => author, 
146
                :time => time,
147
                :message => nil, 
148
                :paths => nil 
175
                :scmid      => id,
176
                :author     => author,
177
                :time       => time,
178
                :message    => nil,
179
                :paths      => nil
149 180
                })
150 181
          rescue NoMethodError => e
151 182
              logger.error("The revision '#{path}' has a wrong format")
......
156 187
        end
157 188

  
158 189
        def revisions(path, identifier_from, identifier_to, options={})
159
          revisions = Revisions.new
190
          revs = Revisions.new
160 191
          cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller|
161 192
          cmd_args << "--reverse" if options[:reverse]
162 193
          cmd_args << "--all" if options[:all]
......
166 197
          from_to << "#{identifier_to}" if identifier_to
167 198
          cmd_args << from_to if !from_to.empty?
168 199
          cmd_args << "--since=#{options[:since].strftime("%Y-%m-%d %H:%M:%S")}" if options[:since]
169
          cmd_args << "--" << path if path && !path.empty?
200
          cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
170 201

  
171 202
          scm_cmd *cmd_args do |io|
172 203
            files=[]
173 204
            changeset = {}
174 205
            parsing_descr = 0  #0: not parsing desc or files, 1: parsing desc, 2: parsing files
175
            revno = 1
176 206

  
177 207
            io.each_line do |line|
178 208
              if line =~ /^commit ([0-9a-f]{40})$/
......
182 212
                  parsing_descr = 0
183 213
                  revision = Revision.new({
184 214
                    :identifier => changeset[:commit],
185
                    :scmid => changeset[:commit],
186
                    :author => changeset[:author],
187
                    :time => Time.parse(changeset[:date]),
188
                    :message => changeset[:description],
189
                    :paths => files
215
                    :scmid      => changeset[:commit],
216
                    :author     => changeset[:author],
217
                    :time       => Time.parse(changeset[:date]),
218
                    :message    => changeset[:description],
219
                    :paths      => files
190 220
                  })
191 221
                  if block_given?
192 222
                    yield revision
193 223
                  else
194
                    revisions << revision
224
                    revs << revision
195 225
                  end
196 226
                  changeset = {}
197 227
                  files = []
198
                  revno = revno + 1
199 228
                end
200 229
                changeset[:commit] = $1
201 230
              elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
......
210 239
                parsing_descr = 1
211 240
                changeset[:description] = ""
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff