rscm 0.2.1.1404 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/README +34 -23
  2. data/Rakefile +24 -29
  3. data/bin/touch.exe +0 -0
  4. data/lib/rscm.rb +6 -3
  5. data/lib/rscm/annotations.rb +26 -7
  6. data/lib/rscm/{abstract_scm.rb → base.rb} +109 -71
  7. data/lib/rscm/better.rb +16 -0
  8. data/lib/rscm/logging.rb +11 -5
  9. data/lib/rscm/path_converter.rb +9 -16
  10. data/lib/rscm/revision.rb +201 -0
  11. data/lib/rscm/revision_file.rb +71 -0
  12. data/lib/rscm/scm/clearcase.rb +7 -7
  13. data/lib/rscm/scm/cvs.rb +69 -70
  14. data/lib/rscm/scm/cvs_log_parser.rb +29 -29
  15. data/lib/rscm/scm/darcs.rb +82 -34
  16. data/lib/rscm/scm/darcs_log_parser.rb +65 -0
  17. data/lib/rscm/scm/monotone.rb +249 -77
  18. data/lib/rscm/scm/monotone_log_parser.rb +57 -43
  19. data/lib/rscm/scm/mooky.rb +3 -3
  20. data/lib/rscm/scm/perforce.rb +196 -134
  21. data/lib/rscm/scm/star_team.rb +10 -10
  22. data/lib/rscm/scm/subversion.rb +106 -77
  23. data/lib/rscm/scm/subversion_log_parser.rb +76 -47
  24. data/lib/rscm/time_ext.rb +2 -116
  25. data/test/rscm/annotations_test.rb +15 -2
  26. data/test/rscm/{abstract_scm_test.rb → base_test.rb} +3 -3
  27. data/test/rscm/difftool_test.rb +9 -3
  28. data/test/rscm/generic_scm_tests.rb +195 -124
  29. data/test/rscm/revision_fixture.rb +20 -0
  30. data/test/rscm/revision_test.rb +129 -0
  31. data/test/rscm/{changesets.yaml → revisions.yaml} +10 -10
  32. data/test/rscm/scm/clearcase.log +608 -0
  33. data/test/rscm/scm/clearcase_test.rb +39 -0
  34. data/test/rscm/scm/cvs_log_parser_test.rb +73 -73
  35. data/test/rscm/scm/cvs_test.rb +1 -1
  36. data/test/rscm/scm/darcs_log_parser_test.rb +171 -0
  37. data/test/rscm/scm/monotone_log_parser_test.rb +49 -31
  38. data/test/rscm/scm/monotone_test.rb +3 -2
  39. data/test/rscm/scm/p4client_test.rb +33 -0
  40. data/test/rscm/scm/perforce_test.rb +25 -3
  41. data/test/rscm/scm/star_team.rb +9 -9
  42. data/test/rscm/scm/subversion_log_parser_test.rb +107 -47
  43. metadata +17 -13
  44. data/lib/multipart.rb +0 -95
  45. data/lib/rscm/RSS.txt +0 -41
  46. data/lib/rscm/changes.rb +0 -268
  47. data/lib/rscm/example.yaml +0 -21
  48. data/lib/rubyforge_file_publisher.rb +0 -176
  49. data/test/rscm/changes_fixture.rb +0 -20
  50. data/test/rscm/changes_test.rb +0 -129
@@ -1,7 +1,7 @@
1
1
  require 'fileutils'
2
2
  require 'tempfile'
3
- require 'rscm/changes'
4
- require 'rscm/abstract_scm'
3
+ require 'rscm/revision'
4
+ require 'rscm/base'
5
5
  require 'yaml'
6
6
 
7
7
  class Time
@@ -17,8 +17,8 @@ module RSCM
17
17
  # * StarTeam SDK
18
18
  # * Apache Ant (http://ant.apache.org/)
19
19
  #
20
- class StarTeam < AbstractSCM
21
- register self
20
+ class StarTeam < Base
21
+ #register self
22
22
 
23
23
  ann :description => "User name"
24
24
  attr_accessor :user_name
@@ -49,23 +49,23 @@ module RSCM
49
49
  "StarTeam"
50
50
  end
51
51
 
52
- def changesets(checkout_dir, from_identifier=Time.epoch, to_identifier=Time.infinity, &proc)
52
+ def revisions(checkout_dir, from_identifier=Time.epoch, to_identifier=Time.infinity, &proc)
53
53
  # just assuming it is a Time for now, may support labels later.
54
54
  # the java class really wants rfc822 and not rfc2822, but this works ok anyway.
55
55
  from = from_identifier.to_rfc2822
56
56
  to = to_identifier.to_rfc2822
57
57
 
58
- changesets = java("getChangeSets(\"#{from}\";\"#{to}\")", &proc)
59
- raise "changesets must be of type #{ChangeSets.name} - was #{changesets.class.name}" unless changesets.is_a?(::RSCM::ChangeSets)
58
+ revisions = java("getRevisions(\"#{from}\";\"#{to}\")", &proc)
59
+ raise "revisions must be of type #{Revisions.name} - was #{revisions.class.name}" unless revisions.is_a?(::RSCM::Revisions)
60
60
 
61
61
  # Just a little sanity check
62
- if(changesets.latest)
63
- latetime = changesets.latest.time
62
+ if(revisions.latest)
63
+ latetime = revisions.latest.time
64
64
  if(latetime < from_identifier || to_identifier < latetime)
65
65
  raise "Latest time (#{latetime}) is not within #{from_identifier}-#{to_identifier}"
66
66
  end
67
67
  end
68
- changesets
68
+ revisions
69
69
  end
70
70
 
71
71
  def checkout(checkout_dir, to_identifier, &proc)
@@ -1,4 +1,4 @@
1
- require 'rscm/abstract_scm'
1
+ require 'rscm/base'
2
2
  require 'rscm/path_converter'
3
3
  require 'rscm/line_editor'
4
4
  require 'rscm/scm/subversion_log_parser'
@@ -10,22 +10,29 @@ module RSCM
10
10
  # You need the svn/svnadmin executable on the PATH in order for it to work.
11
11
  #
12
12
  # NOTE: On Cygwin these have to be the win32 builds of svn/svnadmin and not the Cygwin ones.
13
- class Subversion < AbstractSCM
13
+ class Subversion < Base
14
14
  register self
15
15
 
16
16
  include FileUtils
17
17
  include PathConverter
18
18
 
19
19
  ann :description => "Repository URL"
20
- # ann :tip => "If you specify a local URL (starting with file://) DamageControl can create the repository for you after you save (unless the repository already exists).<br>Using a file:// URL will also give you the option to have DamageControl install a trigger in Subversion, so that you don't have to use polling to detect changes.<br>On Windows, file URLs must look like file:///C:/jupiter/mars"
21
20
  ann :tip => "If you use ssh, specify the URL as svn+ssh://username@server/path/to/repo"
22
21
  attr_accessor :url
23
22
 
23
+ ann :description => "Username"
24
+ ann :tip => "This only applies to svn:// URLs."
25
+ attr_accessor :username
26
+
27
+ ann :description => "Password"
28
+ ann :tip => "This only applies to svn:// URLs."
29
+ attr_accessor :password
30
+
24
31
  ann :description => "Path"
25
- ann :tip => "This is the relative path from the start of the repository <br>to the end of the URL. For example, if your URL is <br>svn://your.server/path/to/repository/path/within/repository <br>then this value should be path/within/repository."
32
+ ann :tip => "You only need to specify this if you want to be able to automatically create the repository. This should be the relative path from the start of the repository <br>to the end of the URL. For example, if your URL is <br>svn://your.server/path/to/repository/path/within/repository <br>then this value should be path/within/repository."
26
33
  attr_accessor :path
27
34
 
28
- def initialize(url="", path="trunk")
35
+ def initialize(url="", path="")
29
36
  @url, @path = url, path
30
37
  end
31
38
 
@@ -33,21 +40,21 @@ module RSCM
33
40
  "Subversion"
34
41
  end
35
42
 
36
- def add(checkout_dir, relative_filename)
37
- svn(checkout_dir, "add #{relative_filename}")
43
+ def add(relative_filename)
44
+ svn(@checkout_dir, "add #{relative_filename}")
38
45
  end
39
46
 
40
47
  def transactional?
41
48
  true
42
49
  end
43
50
 
44
- def checkout(checkout_dir, to_identifier=nil)
45
- checkout_dir = PathConverter.filepath_to_nativepath(checkout_dir, false)
46
- mkdir_p(checkout_dir)
51
+ def checkout(to_identifier=nil)
52
+ checkout_dir = PathConverter.filepath_to_nativepath(@checkout_dir, false)
53
+ mkdir_p(@checkout_dir)
47
54
  checked_out_files = []
48
55
  path_regex = /^[A|D|U]\s+(.*)/
49
- if(checked_out?(checkout_dir))
50
- svn(checkout_dir, update_command(to_identifier)) do |line|
56
+ if(checked_out?)
57
+ svn(@checkout_dir, update_command(to_identifier)) do |line|
51
58
  if(line =~ path_regex)
52
59
  absolute_path = "#{checkout_dir}/#{$1}"
53
60
  relative_path = $1.chomp
@@ -57,14 +64,15 @@ module RSCM
57
64
  end
58
65
  end
59
66
  else
60
- svn(checkout_dir, checkout_command(checkout_dir, to_identifier)) do |line|
67
+ svn(@checkout_dir, checkout_command(to_identifier)) do |line|
61
68
  if(line =~ path_regex)
62
69
  native_absolute_path = $1
63
- native_checkout_dir = $1
64
- absolute_path = PathConverter.nativepath_to_filepath($1)
65
- native_checkout_dir = PathConverter.filepath_to_nativepath(checkout_dir, false)
70
+ absolute_path = PathConverter.nativepath_to_filepath(native_absolute_path)
66
71
  if(File.exist?(absolute_path) && !File.directory?(absolute_path))
67
- relative_path = native_absolute_path[native_checkout_dir.length+1..-1].chomp
72
+ native_checkout_dir = PathConverter.filepath_to_nativepath(@checkout_dir, false)
73
+ # relative_path = native_absolute_path[native_checkout_dir.length+1..-1].chomp
74
+ # not sure about this old code - this seems to work. keep it here till it's verified on win32
75
+ relative_path = absolute_path
68
76
  relative_path = relative_path.gsub(/\\/, "/") if WINDOWS
69
77
  checked_out_files << relative_path
70
78
  yield relative_path if block_given?
@@ -83,60 +91,43 @@ module RSCM
83
91
  "svn update #{url} #{checkout_dir}"
84
92
  end
85
93
 
86
- def uptodate?(checkout_dir, from_identifier)
87
- if(!checked_out?(checkout_dir))
94
+ def uptodate?(identifier)
95
+ if(!checked_out?)
88
96
  false
89
97
  else
90
- lr = local_revision(checkout_dir)
91
- hr = head_revision(checkout_dir)
92
- lr == hr
93
- end
94
- end
95
-
96
- def local_revision(checkout_dir)
97
- local_revision = nil
98
- svn(checkout_dir, "info") do |line|
99
- if(line =~ /Revision: ([0-9]*)/)
100
- return $1.to_i
101
- end
98
+ rev = identifier ? identifier : head_revision_identifier
99
+ local_revision_identifier == rev
102
100
  end
103
101
  end
104
102
 
105
- def head_revision(checkout_dir)
106
- cmd = "svn log #{repourl} -r HEAD"
107
- with_working_dir(checkout_dir) do
108
- safer_popen(cmd) do |stdout|
109
- parser = SubversionLogParser.new(stdout, path, checkout_dir)
110
- changesets = parser.parse_changesets
111
- changesets[0].revision.to_i
112
- end
113
- end
114
- end
115
-
116
- def commit(checkout_dir, message)
117
- svn(checkout_dir, commit_command(message))
103
+ def commit(message)
104
+ svn(@checkout_dir, commit_command(message))
118
105
  # We have to do an update to get the local revision right
119
- svn(checkout_dir, "update")
106
+ svn(@checkout_dir, "update")
120
107
  end
121
108
 
122
- def label(checkout_dir)
123
- local_revision(checkout_dir).to_s
109
+ def label
110
+ local_revision_identifier.to_s
124
111
  end
125
112
 
126
- def diff(checkout_dir, change, &block)
127
- with_working_dir(checkout_dir) do
128
- cmd = "svn diff -r #{change.previous_revision}:#{change.revision} \"#{url}/#{change.path}\""
129
- safer_popen(cmd) do |io|
113
+ def diff(file, &block)
114
+ with_working_dir(@checkout_dir) do
115
+ cmd = "svn diff -r #{file.previous_native_revision_identifier}:#{file.native_revision_identifier} \"#{url}/#{file.path}\""
116
+ Better.popen(cmd) do |io|
130
117
  return(yield(io))
131
118
  end
132
119
  end
133
120
  end
134
121
 
135
- def can_create?
122
+ def can_create_central?
136
123
  local?
137
124
  end
138
125
 
139
- def exists?
126
+ def destroy_central
127
+ FileUtils.rm_rf(svnrootdir)
128
+ end
129
+
130
+ def central_exists?
140
131
  if(local?)
141
132
  File.exists?("#{svnrootdir}/db")
142
133
  else
@@ -145,7 +136,7 @@ module RSCM
145
136
  # on stdout (and an error msg on std err).
146
137
  exists = false
147
138
  cmd = "svn log #{url} -r HEAD"
148
- IO.popen(cmd) do |stdout|
139
+ Better.popen(cmd) do |stdout|
149
140
  stdout.each_line do |line|
150
141
  exists = true
151
142
  end
@@ -158,7 +149,7 @@ module RSCM
158
149
  local?
159
150
  end
160
151
 
161
- def create
152
+ def create_central
162
153
  native_path = PathConverter.filepath_to_nativepath(svnrootdir, true)
163
154
  mkdir_p(PathConverter.nativepath_to_filepath(native_path))
164
155
  svnadmin(svnrootdir, "create #{native_path}")
@@ -182,27 +173,27 @@ module RSCM
182
173
  not_already_commented
183
174
  end
184
175
 
185
- def import(dir, message)
176
+ def import_central(dir, message)
186
177
  import_cmd = "import #{url} -m \"#{message}\""
187
178
  svn(dir, import_cmd)
188
179
  end
189
180
 
190
- def changesets(checkout_dir, from_identifier, to_identifier=Time.infinity)
191
- # Return empty changeset if the requested revision doesn't exist yet.
192
- return ChangeSets.new if(from_identifier.is_a?(Integer) && head_revision(checkout_dir) < from_identifier)
181
+ def revisions(from_identifier, to_identifier=Time.infinity)
182
+ # Return empty revision if the requested revision doesn't exist yet.
183
+ return Revisions.new if(from_identifier.is_a?(Integer) && head_revision_identifier <= from_identifier)
193
184
 
194
- checkout_dir = PathConverter.filepath_to_nativepath(checkout_dir, false)
195
- changesets = nil
185
+ checkout_dir = PathConverter.filepath_to_nativepath(@checkout_dir, false)
186
+ revisions = nil
196
187
  command = "svn #{changes_command(from_identifier, to_identifier)}"
197
188
  yield command if block_given?
198
189
 
199
- with_working_dir(checkout_dir) do
200
- safer_popen(command) do |stdout|
201
- parser = SubversionLogParser.new(stdout, path, checkout_dir)
202
- changesets = parser.parse_changesets
190
+ with_working_dir(@checkout_dir) do
191
+ Better.popen(command) do |stdout|
192
+ parser = SubversionLogParser.new(stdout, @url)
193
+ revisions = parser.parse_revisions
203
194
  end
204
195
  end
205
- changesets
196
+ revisions
206
197
  end
207
198
 
208
199
  # url pointing to the root of the repo
@@ -211,7 +202,7 @@ module RSCM
211
202
  url[0..last]
212
203
  end
213
204
 
214
- def checked_out?(checkout_dir)
205
+ def checked_out?
215
206
  rootentries = File.expand_path("#{checkout_dir}/.svn/entries")
216
207
  result = File.exists?(rootentries)
217
208
  result
@@ -219,6 +210,30 @@ module RSCM
219
210
 
220
211
  private
221
212
 
213
+ def local_revision_identifier
214
+ local_revision_identifier = nil
215
+ svn(@checkout_dir, "info") do |line|
216
+ if(line =~ /Revision: ([0-9]*)/)
217
+ return $1.to_i
218
+ end
219
+ end
220
+ end
221
+
222
+ def head_revision_identifier
223
+ # This command only seems to yield any changesets if the url is the root of
224
+ # the repo, which we don't know in the case where path is not specified (likely)
225
+ # We therefore don't specify it and get the latest revision from the full url instead.
226
+ # cmd = "svn log #{login_options} #{repourl} -r HEAD"
227
+ cmd = "svn log #{login_options} #{url}"
228
+ with_working_dir(@checkout_dir) do
229
+ Better.popen(cmd) do |stdout|
230
+ parser = SubversionLogParser.new(stdout, @url)
231
+ revisions = parser.parse_revisions
232
+ revisions[0].identifier.to_i
233
+ end
234
+ end
235
+ end
236
+
222
237
  def install_unix_trigger(trigger_command, damagecontrol_install_dir)
223
238
  post_commit_exists = File.exists?(post_commit_file)
224
239
  mode = post_commit_exists ? File::APPEND|File::WRONLY : File::CREAT|File::WRONLY
@@ -227,7 +242,7 @@ module RSCM
227
242
  file.puts("#!/bin/sh") unless post_commit_exists
228
243
  file.puts("#{trigger_command}\n" )
229
244
  end
230
- system("chmod g+x #{post_commit_file}")
245
+ File.chmod(0744, post_commit_file)
231
246
  rescue
232
247
  raise "Didn't have permission to write to #{post_commit_file}. " +
233
248
  "Try to manually add the following line:\n\n#{trigger_command}\n\n" +
@@ -265,7 +280,7 @@ module RSCM
265
280
  command_line = "#{executable} #{cmd}"
266
281
  dir = File.expand_path(dir)
267
282
  with_working_dir(dir) do
268
- safer_popen(command_line) do |stdout|
283
+ Better.popen(command_line) do |stdout|
269
284
  stdout.each_line do |line|
270
285
  yield line if block_given?
271
286
  end
@@ -273,36 +288,50 @@ module RSCM
273
288
  end
274
289
  end
275
290
 
276
- def checkout_command(checkout_dir, to_identifier)
291
+ def checkout_command(to_identifier)
277
292
  checkout_dir = "\"#{checkout_dir}\""
278
- "checkout #{url} #{checkout_dir} #{revision_option(nil,to_identifier)}"
293
+ "checkout #{login_options} #{url} #{checkout_dir} #{revision_option(nil,to_identifier)}"
279
294
  end
280
295
 
281
296
  def update_command(to_identifier)
282
- "update #{revision_option(nil,to_identifier)}"
297
+ "update #{login_options} #{revision_option(nil,to_identifier)}"
283
298
  end
284
299
 
285
300
  def changes_command(from_identifier, to_identifier)
286
301
  # http://svnbook.red-bean.com/svnbook-1.1/svn-book.html#svn-ch-3-sect-3.3
287
302
  # file_list = files.join('\n')
288
303
  # WEIRD cygwin bug garbles this!?!?!?!
289
- cmd = "log --verbose #{revision_option(from_identifier, to_identifier)} #{url}"
304
+ cmd = "log --verbose #{login_options} #{revision_option(from_identifier, to_identifier)} #{url}"
290
305
  cmd
291
306
  end
292
307
 
308
+ def login_options
309
+ result = ""
310
+ u = @username ? @username.strip : nil
311
+ p = @password ? @password.strip : nil
312
+ result << "--username #{u} " if u
313
+ result << "--password #{p} " if p
314
+ result
315
+ end
316
+
293
317
  def revision_option(from_identifier, to_identifier)
318
+ # The inclusive start
294
319
  from = nil
295
320
  if(from_identifier.is_a?(Time))
296
- from = svndate(from_identifier)
297
- else
298
- from = from_identifier
321
+ from = svndate(from_identifier + 1)
322
+ elsif(from_identifier.is_a?(Numeric))
323
+ from = from_identifier + 1
324
+ elsif(!from_identifier.nil?)
325
+ raise "from_identifier must be Numeric, Time or nil. Was: #{from_identifier} (#{from_identifier.class.name})"
299
326
  end
300
327
 
301
328
  to = nil
302
329
  if(to_identifier.is_a?(Time))
303
330
  to = svndate(to_identifier)
304
- else
331
+ elsif(to_identifier.is_a?(Numeric))
305
332
  to = to_identifier
333
+ elsif(!from_identifier.nil?)
334
+ raise "to_identifier must be Numeric, Time or nil. Was: #{to_identifier} (#{to_identifier.class.name})"
306
335
  end
307
336
 
308
337
  revision_option = nil
@@ -1,108 +1,137 @@
1
1
  require 'rscm/parser'
2
- require 'rscm/changes'
2
+ require 'rscm/revision'
3
3
 
4
4
  module RSCM
5
5
 
6
6
  class SubversionLogParser
7
- def initialize(io, path, checkout_dir)
7
+ def initialize(io, url)
8
8
  @io = io
9
- @changeset_parser = SubversionLogEntryParser.new(path, checkout_dir)
9
+ @revision_parser = SubversionLogEntryParser.new(url)
10
10
  end
11
11
 
12
- def parse_changesets(&line_proc)
12
+ def parse_revisions(&line_proc)
13
13
  # skip over the first ------
14
- @changeset_parser.parse(@io, true, &line_proc)
15
- changesets = ChangeSets.new
14
+ @revision_parser.parse(@io, true, &line_proc)
15
+ revisions = Revisions.new
16
16
  while(!@io.eof?)
17
- changeset = @changeset_parser.parse(@io, &line_proc)
18
- if(changeset)
19
- changesets.add(changeset)
17
+ revision = @revision_parser.parse(@io, &line_proc)
18
+ if(revision)
19
+ revisions.add(revision)
20
20
  end
21
21
  end
22
- changesets
22
+ revisions
23
23
  end
24
24
  end
25
25
 
26
26
  class SubversionLogEntryParser < Parser
27
27
 
28
- def initialize(path, checkout_dir)
28
+ def initialize(url)
29
29
  super(/^------------------------------------------------------------------------/)
30
- @path = path ? path : ""
31
- @checkout_dir = checkout_dir
30
+ @url = url
32
31
  end
33
32
 
34
33
  def parse(io, skip_line_parsing=false, &line_proc)
35
34
  # We have to trim off the last newline - it's not meant to be part of the message
36
- changeset = super
37
- changeset.message = changeset.message[0..-2] if changeset
38
- changeset
35
+ revision = super
36
+ revision.message = revision.message[0..-2] if revision
37
+ revision
39
38
  end
40
39
 
40
+ def relative_path(url, repo_path)
41
+ url_tokens = url.split('/')
42
+ repo_path_tokens = repo_path.split('/')
43
+
44
+ max_similar = repo_path_tokens.length
45
+ while(max_similar > 0)
46
+ url = url_tokens[-max_similar..-1]
47
+ path = repo_path_tokens[0..max_similar-1]
48
+ if(url == path)
49
+ break
50
+ end
51
+ max_similar -= 1
52
+ end
53
+ max_similar == 0 ? nil : repo_path_tokens[max_similar..-1].join("/")
54
+ end
55
+
41
56
  protected
42
57
 
43
58
  def parse_line(line)
44
- if(@changeset.nil?)
59
+ if(@revision.nil?)
45
60
  parse_header(line)
46
61
  elsif(line.strip == "")
47
62
  @parse_state = :parse_message
48
63
  elsif(line =~ /Changed paths/)
49
- @parse_state = :parse_changes
50
- elsif(@parse_state == :parse_changes)
51
- change = parse_change(line)
52
- if change
53
- # This unless won't work for new directories or if changesets are computed before checkout (which it usually is!)
54
- fullpath = "#{@checkout_dir}/#{change.path}"
55
- @changeset << change unless File.directory?(fullpath)
64
+ @parse_state = :parse_files
65
+ elsif(@parse_state == :parse_files)
66
+ file = parse_file(line)
67
+ if(file)
68
+ previously_added_file = @revision[-1]
69
+ if(previously_added_file)
70
+ # remove previous revision_file it if it's a dir
71
+ previous_tokens = previously_added_file.path.split("/")
72
+ current_tokens = file.path.split("/")
73
+ current_tokens.pop
74
+ if(previous_tokens == current_tokens)
75
+ @revision.pop
76
+ end
77
+ end
78
+ @revision << file
56
79
  end
57
80
  elsif(@parse_state == :parse_message)
58
- @changeset.message << line.chomp << "\n"
81
+ @revision.message << line.chomp << "\n"
59
82
  end
60
83
  end
61
84
 
62
85
  def next_result
63
- result = @changeset
64
- @changeset = nil
86
+ result = @revision
87
+ @revision = nil
65
88
  result
66
89
  end
67
90
 
68
91
  private
69
92
 
70
- STATES = {"M" => Change::MODIFIED, "A" => Change::ADDED, "D" => Change::DELETED} unless defined? STATES
93
+ STATES = {"M" => RevisionFile::MODIFIED, "A" => RevisionFile::ADDED, "D" => RevisionFile::DELETED} unless defined? STATES
71
94
 
72
95
  def parse_header(line)
73
- @changeset = ChangeSet.new
74
- @changeset.message = ""
96
+ @revision = Revision.new
97
+ @revision.message = ""
75
98
  revision, developer, time, the_rest = line.split("|")
76
- @changeset.revision = revision.strip[1..-1].to_i unless revision.nil?
77
- @changeset.developer = developer.strip unless developer.nil?
78
- @changeset.time = parse_time(time.strip) unless time.nil?
99
+ @revision.identifier = revision.strip[1..-1].to_i unless revision.nil?
100
+ @revision.developer = developer.strip unless developer.nil?
101
+ @revision.time = parse_time(time.strip) unless time.nil?
79
102
  end
80
103
 
81
- def parse_change(line)
82
- change = Change.new
104
+ def parse_file(line)
105
+ file = RevisionFile.new
83
106
  path_from_root = nil
84
107
  if(line =~ /^ [M|A|D|R] ([^\s]+) \(from (.*)\)/)
85
108
  path_from_root = $1
86
- change.status = Change::MOVED
109
+ file.status = RevisionFile::MOVED
87
110
  elsif(line =~ /^ ([M|A|D|R]) (.+)$/)
88
111
  status = $1
89
112
  path_from_root = $2
90
- change.status = STATES[status]
113
+ file.status = STATES[status]
91
114
  else
92
- raise "could not parse change line: '#{line}'"
115
+ raise "could not parse file line: '#{line}'"
93
116
  end
94
117
 
95
118
  path_from_root.gsub!(/\\/, "/")
96
- return nil unless path_from_root =~ /^\/#{@path}/
97
- if(@path.length+1 == path_from_root.length)
98
- change.path = path_from_root[@path.length+1..-1]
99
- else
100
- change.path = path_from_root[@path.length+2..-1]
101
- end
102
- change.revision = @changeset.revision
119
+ path_from_root = path_from_root[1..-1]
120
+ rp = relative_path(@url, path_from_root)
121
+ return if rp.nil?
122
+ file.path = rp
123
+
124
+
125
+ # if(@path.length+1 == path_from_root.length)
126
+ # file.path = path_from_root[@path.length+1..-1]
127
+ # else
128
+ # file.path = path_from_root[@path.length+2..-1]
129
+ # end
130
+
131
+ file.native_revision_identifier = @revision.identifier
103
132
  # http://jira.codehaus.org/browse/DC-204
104
- change.previous_revision = change.revision.to_i - 1;
105
- change
133
+ file.previous_native_revision_identifier = file.native_revision_identifier.to_i - 1;
134
+ file
106
135
  end
107
136
 
108
137
  def parse_time(svn_time)