Revision 442:753f1380d6bc lib/redmine/scm/adapters
| 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] = "" |
Also available in: Unified diff