rscm 0.2.1.1404 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,95 +0,0 @@
1
- require 'open-uri'
2
- require 'net/http'
3
- require 'cgi'
4
-
5
- # Adds multipart support to Net::HTTP
6
- # based on Code from Patrick May
7
- # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/113774
8
- module Net
9
- class Param
10
- def initialize(k, v)
11
- @k = k
12
- @v = v
13
- end
14
-
15
- def to_multipart
16
- "Content-Disposition: form-data; name=\"#{CGI::escape(@k)}\"\r\n\r\n#{@v}\r\n"
17
- end
18
- end
19
-
20
- class FileParam
21
- def initialize(k, file, mime_type)
22
- @k = k
23
- @file = file
24
- @mime_type = mime_type
25
- end
26
-
27
- def to_multipart
28
- content = File.open(@file).read
29
- "Content-Disposition: form-data; name=\"#{CGI::escape(@k)}\"; filename=\"#{File.basename(@file)}\"\r\n" +
30
- "Content-Type: #{@mime_type}\r\n\r\n" + content + "\r\n"
31
- end
32
- end
33
-
34
- class HTTP
35
-
36
- def post_multipart(path, params, header={}, dest=nil, boundary="----------ThIs_Is_tHe_bouNdaRY_$") # :yield: self
37
- body = params.collect { |p|
38
- "--" + boundary + "\r\n" + p.to_multipart
39
- }.join("") + "--" + boundary + "--" + "\r\n"
40
-
41
- header["Content-Type"] = "multipart/form-data; boundary=" + boundary
42
- header["Content-Length"] = "#{body.length}"
43
-
44
- post(path, body, header, dest)
45
- end
46
-
47
- alias :old_post :post
48
- def post(path, data, initheader = nil, dest = nil)
49
- puts "----POST----"
50
- puts path
51
- puts "------------"
52
- if(initheader)
53
- initheader.each {|k,v|
54
- puts "#{k}: #{v}"
55
- }
56
- end
57
- puts
58
- puts data
59
-
60
- response, data = old_post(path, data, initheader, dest)
61
-
62
- puts "----POST RESP----"
63
- puts response.class.name
64
- puts "------------"
65
- response.each {|k,v|
66
- puts "#{k}: #{v}"
67
- }
68
-
69
- return response, data
70
- end
71
-
72
- alias :old_get :get
73
- def get(path, initheader = nil, dest = nil)
74
- puts "----GET-----"
75
- puts path
76
- puts "------------"
77
- if(initheader)
78
- initheader.each {|k,v|
79
- puts "#{k}: #{v}"
80
- }
81
- end
82
-
83
- response, data = old_get(path, initheader, dest)
84
-
85
- puts "----GET RESP----"
86
- puts response.class.name
87
- puts "------------"
88
- response.each {|k,v|
89
- puts "#{k}: #{v}"
90
- }
91
-
92
- return response, data
93
- end
94
- end
95
- end
@@ -1,41 +0,0 @@
1
- Sketch of RSS layout for DC and RSCM
2
-
3
- rss
4
- channel
5
- title:
6
- link:
7
- description:
8
- item
9
- pubDate:
10
- title:
11
- link:
12
- description
13
- xxx:
14
-
15
- rss
16
- channel
17
- title: PicoContainer Builds
18
- link: http://builds.codehaus.org/build/damagecontrol/project/picocontainer
19
- description: DamageControl build of PicoContainer
20
- item (one per build)
21
- pubDate: <dc_creation_time>
22
- title: PicoContainer Build FAILED
23
- link: http://builds.codehaus.org/build/damagecontrol/project/picocontainer/build/<dc_creation_time>
24
- description
25
- "Blurb about why it failed (tail from logs)"
26
- "who broke it (from changesets)"
27
- "Changesets"
28
-
29
- rss
30
- channel
31
- title: PicoContainer CVS
32
- link: http://cvs.picocontainer.org/
33
- description: Changesets for PicoContainer (viewcvs/fisheye etc)
34
- item (one per changeset)
35
- pubDate: <changeset_time>
36
- title: changeset commit message (trunkated - w/o links)
37
- link: Link to changeset page (if supported - fisheye etc). otherwise to root of scm_web
38
- description
39
- "changeset message with tracker URLs (newline-escaped)"
40
- "|revision|path (with links)|"
41
-
@@ -1,268 +0,0 @@
1
- require 'xmlrpc/utils'
2
- require 'rscm/time_ext'
3
-
4
- module RSCM
5
-
6
- # A collection of ChangeSet.
7
- class ChangeSets
8
- include Enumerable
9
- include XMLRPC::Marshallable
10
-
11
- attr_reader :changesets
12
-
13
- def initialize(changesets=[])
14
- @changesets = changesets
15
- end
16
-
17
- # Accepts a visitor that will receive callbacks while
18
- # iterating over this instance's internal structure.
19
- # The visitor should respond to the following methods:
20
- #
21
- # * visit_changesets(changesets)
22
- # * visit_changeset(changeset)
23
- # * visit_change(change)
24
- #
25
- def accept(visitor)
26
- visitor.visit_changesets(self)
27
- self.each{|changeset| changeset.accept(visitor)}
28
- end
29
-
30
- def [](change)
31
- @changesets[change]
32
- end
33
-
34
- def each(&block)
35
- @changesets.each(&block)
36
- end
37
-
38
- def reverse
39
- ChangeSets.new(@changesets.dup.reverse)
40
- end
41
-
42
- def length
43
- @changesets.length
44
- end
45
-
46
- def ==(other)
47
- return false if !other.is_a?(self.class)
48
- @changesets == other.changesets
49
- end
50
-
51
- def empty?
52
- @changesets.empty?
53
- end
54
-
55
- # The set of developers that contributed to all of the contained ChangeSet s.
56
- def developers
57
- result = []
58
- each do |changeset|
59
- result << changeset.developer unless result.index(changeset.developer)
60
- end
61
- result
62
- end
63
-
64
- # The latest ChangeSet (with the latest time)
65
- # or nil if there are none.
66
- def latest
67
- result = nil
68
- each do |changeset|
69
- result = changeset if result.nil? || result.time < changeset.time
70
- end
71
- result
72
- end
73
-
74
- # Adds a Change or a ChangeSet.
75
- # If the argument is a Change and no corresponding ChangeSet exists,
76
- # a new ChangeSet is created, added, and the Change is added to that ChangeSet -
77
- # and then finally the newly created ChangeSet is returned.
78
- # Otherwise nil is returned.
79
- def add(change_or_changeset)
80
- if(change_or_changeset.is_a?(ChangeSet))
81
- @changesets << change_or_changeset
82
- return change_or_changeset
83
- else
84
- changeset = @changesets.find { |a_changeset| a_changeset.can_contain?(change_or_changeset) }
85
- if(changeset.nil?)
86
- changeset = ChangeSet.new
87
- @changesets << changeset
88
- changeset << change_or_changeset
89
- return changeset
90
- end
91
- changeset << change_or_changeset
92
- return nil
93
- end
94
- end
95
-
96
- def push(*change_or_changesets)
97
- change_or_changesets.each { |change_or_changeset| self << (change_or_changeset) }
98
- self
99
- end
100
-
101
- # The most recent time of all the ChangeSet s.
102
- def time
103
- time = nil
104
- changesets.each do |changeset|
105
- time = changeset.time if @time.nil? || @time < changeset.time
106
- end
107
- time
108
- end
109
-
110
- # Sorts the changesets according to time
111
- def sort!
112
- @changesets.sort!
113
- self
114
- end
115
-
116
- end
117
-
118
- # Represents a collection of Change that were committed at the same time.
119
- # Non-transactional SCMs (such as CVS and StarTeam) emulate ChangeSet
120
- # by grouping Change s that were committed by the same developer, with the
121
- # same commit message, and within a "reasonably" small timespan.
122
- class ChangeSet
123
- include Enumerable
124
- include XMLRPC::Marshallable
125
-
126
- attr_reader :changes
127
- attr_accessor :revision
128
- attr_accessor :developer
129
- attr_accessor :message
130
- attr_accessor :time
131
-
132
- def initialize(changes=[])
133
- @changes = changes
134
- end
135
-
136
- def accept(visitor)
137
- visitor.visit_changeset(self)
138
- @changes.each{|change| change.accept(visitor)}
139
- end
140
-
141
- def << (change)
142
- @changes << change
143
- self.time = change.time if self.time.nil? || self.time < change.time unless change.time.nil?
144
- self.developer = change.developer if change.developer
145
- self.message = change.message if change.message
146
- end
147
-
148
- def [] (change)
149
- @changes[change]
150
- end
151
-
152
- def each(&block)
153
- @changes.each(&block)
154
- end
155
-
156
- def length
157
- @changes.length
158
- end
159
-
160
- def time=(t)
161
- raise "time must be a Time object - it was a #{t.class.name} with the string value #{t}" unless t.is_a?(Time)
162
- raise "can't set time to an inferiour value than the previous value" if @time && (t < @time)
163
- @time = t
164
- end
165
-
166
- def ==(other)
167
- return false if !other.is_a?(self.class)
168
- @changes == other.changes
169
- end
170
-
171
- def <=>(other)
172
- @time <=> other.time
173
- end
174
-
175
- # Whether this instance can contain a Change. Used
176
- # by non-transactional SCMs.
177
- def can_contain?(change)
178
- self.developer == change.developer &&
179
- self.message == change.message &&
180
- (self.time - change.time).abs < 60
181
- end
182
-
183
- # String representation that can be used for debugging.
184
- def to_s
185
- result = "#{revision} | #{developer} | #{time} | #{message}\n"
186
- self.each do |change|
187
- result << " " << change.to_s << "\n"
188
- end
189
- result
190
- end
191
-
192
- # Returns the identifier of the changeset. This is the revision
193
- # (if defined) or an UTC time if revision is undefined.
194
- def identifier
195
- @revision || @time
196
- end
197
-
198
- end
199
-
200
- # Represents a change to an individual file.
201
- class Change
202
- include XMLRPC::Marshallable
203
-
204
- MODIFIED = "MODIFIED"
205
- DELETED = "DELETED"
206
- ADDED = "ADDED"
207
- MOVED = "MOVED"
208
-
209
- attr_accessor :status
210
- attr_accessor :path
211
- attr_accessor :previous_revision
212
- attr_accessor :revision
213
-
214
- # TODO: Remove redundant attributes that are in ChangeSet
215
- attr_accessor :developer
216
- attr_accessor :message
217
- # This is a UTC ruby time
218
- attr_accessor :time
219
-
220
- def initialize(path=nil, status=nil, developer=nil, message=nil, revision=nil, time=nil)
221
- @path, @developer, @message, @revision, @time, @status = path, developer, message, revision, time, status
222
- end
223
-
224
- def accept(visitor)
225
- visitor.visit_change(self)
226
- end
227
-
228
- def to_s
229
- "#{path} | #{revision}"
230
- end
231
-
232
- def developer=(developer)
233
- raise "can't be null" if developer.nil?
234
- @developer = developer
235
- end
236
-
237
- def message=(message)
238
- raise "can't be null" if message.nil?
239
- @message = message
240
- end
241
-
242
- def path=(path)
243
- raise "can't be null" if path.nil?
244
- @path = path
245
- end
246
-
247
- def revision=(revision)
248
- raise "can't be null" if revision.nil?
249
- @revision = revision
250
- end
251
-
252
- def time=(time)
253
- raise "time must be a Time object" unless time.is_a?(Time)
254
- @time = time
255
- end
256
-
257
- def ==(other)
258
- return false if !other.is_a?(self.class)
259
- self.path == other.path &&
260
- self.developer == other.developer &&
261
- self.message == other.message &&
262
- self.revision == other.revision &&
263
- self.time == other.time
264
- end
265
-
266
- end
267
-
268
- end
@@ -1,21 +0,0 @@
1
- --- !ruby/object:RSCM::RssService
2
- rss_file: target/ngst.xml
3
- title: NGST Changesets
4
- url: http://damagecontrol.codehaus.org/
5
- description: StarTeam changes for NGST
6
- checkout_dir: target/ngst
7
- interval: 10
8
- port: 9090
9
- scm: !ruby/object:RSCM::StarTeam
10
- st_user_name: jimmitchell
11
- st_password: gandalf1
12
- st_server_name: "192.168.254.21"
13
- st_server_port: 49201
14
- st_project_name: "NGST Application"
15
- st_view_name: "NGST Application"
16
- st_folder_name: "java"
17
- scm_web: !ruby/object:RSCM::SCMWeb::ViewCVS
18
- view_cvs_url: http://cvs.damagecontrol.codehaus.org/
19
- tracker: !ruby/object:RSCM::Tracker::JIRA
20
- jira_project_id: NGST
21
- jira_url: http://jira.ctcdcx.local:8080/
@@ -1,176 +0,0 @@
1
- # Copyright 2005 by Aslak Hellesoy (aslak.hellesoy@gmail.com)
2
- # All rights reserved.
3
- #
4
- # Permission is granted for use, copying, modification, distribution,
5
- # and distribution of modified versions of this work as long as the
6
- # above copyright notice is included.
7
-
8
- require 'lib/multipart'
9
-
10
- module Rake
11
-
12
- # This publisher allows scripted submission of RubyForge's release files form.
13
- class RubyForgeFilePublisher
14
- # extension => [mime_type, rubyforge_bin_type_id, rubyforge_src_type_id]
15
- FILE_TYPES = Hash.new(["application/octet-stream", 9999, 5900]) # default to "other", "other source"
16
- FILE_TYPES.merge!(
17
- ".deb" => ["application/octet-stream", 1000],
18
-
19
- # all of these can be source or binary
20
- ".rpm" => ["application/octet-stream", 2000, 5100],
21
- ".zip" => ["application/octet-stream", 3000, 5000],
22
- ".bz2" => ["application/octet-stream", 3100, 5010],
23
- ".gz" => ["application/octet-stream", 3110, 5020],
24
- ".jpg" => ["application/octet-stream", 8000],
25
- ".jpeg" => ["application/octet-stream", 8000],
26
- ".txt" => ["text/plain", 8100],
27
- ".html" => ["text/html", 8200],
28
- ".pdf" => ["application/octet-stream", 8300],
29
- ".ebuild" => ["application/octet-stream", 1300],
30
- ".exe" => ["application/octet-stream", 1100],
31
- ".dmg" => ["application/octet-stream", 1200],
32
- ".gem" => ["application/octet-stream", 1400],
33
- ".sig" => ["application/octet-stream", 8150]
34
- )
35
-
36
- # Returns an array of 2 elements where 1st is mime-type and 2nd is rubyforge-type
37
- def types(filename, source)
38
- extension = nil
39
- if(filename =~ /.*(\.[a-zA-Z]*)/)
40
- extension = $1
41
- end
42
-
43
- types = FILE_TYPES[extension]
44
- if(types.length == 3 && source)
45
- [types[0], types[2]]
46
- else
47
- types
48
- end
49
- end
50
-
51
- # processor_id
52
- I386 = 1000
53
- IA64 = 6000
54
- ALPHA = 7000
55
- ANY = 8000
56
- PPC = 2000
57
- MIPS = 3000
58
- SPARC = 4000
59
- ULTRA_SPARC = 5000
60
- OTHER_PLATFORM = 9999
61
-
62
- # Create a publisher for a RubyForge project with id +group_id+.
63
- # The RubyForge +user+'s password must be specified in the environment
64
- # variable RUBYFORGE_PASSWORD.
65
- #
66
- # This publisher will upload/release a +file+ for a RubyForge project
67
- # with id +group_id+, under the release package +package_id+ and
68
- # name the release +release_name+.
69
- #
70
- # The package_id can be found by viewing the source of the HTML page
71
- # http://rubyforge.org/frs/admin/qrs.php?package=&group_id=YOUR_GROUP_ID
72
- # Look for a select tag named package_id and see what the alternatives are.
73
- #
74
- # The optional argument +source+ can be set to true if the file
75
- # pointed to by +filename+ is a source file of some sort. This is
76
- # to make sure RubyForge lists the file as the appropriate type.
77
- # (This task will figure out the correct mime-type and rubyforge type
78
- # based on the file's extension and the source parameter).
79
- #
80
- # If called with a block, the file will be uploaded at the end of the
81
- # construction of this object. Otherwise, the +upload+ method will
82
- # have to be called explicitly.
83
- #
84
- # The following attributes (which represent form data) have default
85
- # values, but can be set/overridden explicitly:
86
- #
87
- # * processor_id
88
- # * release_date
89
- # * release_notes
90
- # * change_log
91
- #
92
- def initialize(group_id, user, file, package_id, release_name, source=false) # :yield: self
93
-
94
- @group_id = group_id
95
- @user = user
96
- @file = file
97
-
98
- @form_data = {"preformatted" => "1", "submit" => "Release File" }
99
-
100
- self.package_id = package_id
101
- self.release_name = release_name
102
-
103
- @types = types(file, source)
104
- self.type_id = @types[1]
105
- self.processor_id = ANY
106
- self.release_date = Time.now.utc
107
- self.release_notes = "Uploaded by Rake::RubyforgeFilePublisher"
108
- self.release_changes = "This is a change log"
109
-
110
- yield self if block_given?
111
- upload if block_given?
112
- end
113
-
114
- def package_id=(s)
115
- @form_data["package_id"] = s
116
- end
117
- def package_id
118
- @form_data["package_id"]
119
- end
120
- def release_name=(s)
121
- @form_data["release_name"] = s
122
- end
123
- def type_id=(s)
124
- @form_data["type_id"] = s
125
- end
126
- def processor_id=(s)
127
- @form_data["processor_id"] = s
128
- end
129
- def release_date=(t)
130
- @form_data["release_date"] = t.strftime("%Y-%m-%d %H:%M")
131
- end
132
- def release_notes=(s)
133
- @form_data["release_notes"] = s
134
- end
135
- def release_changes=(s)
136
- @form_data["release_changes"] = s
137
- end
138
- def preformatted=(b)
139
- @form_data["preformatted"] = b ? "1" : "0"
140
- end
141
-
142
- def upload
143
- Net::HTTP.start('rubyforge.org', 80) do |http|
144
-
145
- # log in so we get a cookie. we need it to post the upload form.
146
- password = ENV['RUBYFORGE_PASSWORD']
147
- raise "The RUBYFORGE_PASSWORD environment variable is not set.\n" +
148
- "It can be passed on the Rake command line with RUBYFORGE_PASSWORD=<your password>" if password.nil?
149
-
150
- response, data = http.post("/account/login.php", "form_loginname=#{@user}&form_pw=#{password}&login=Login")
151
- cookie = CGI::Cookie.parse(response['set-cookie'])['session_ser'].to_s
152
- header = {"Cookie" => cookie, "Host" => "rubyforge.org"}
153
-
154
- response, data = http.get(response['location'], header)
155
-
156
- upload_form = "/frs/admin/qrs.php?package=#{package_id}&group_id=#{@group_id}"
157
- response, data = http.get(upload_form, header)
158
-
159
- params = []
160
- @form_data.each do |k, v|
161
- params << Net::Param.new(k,v)
162
- end
163
- params << Net::FileParam.new("userfile", @file, @types[0])
164
- header["Referer"] = "http://rubyforge.org#{upload_form}"
165
- response, data = http.post_multipart(upload_form, params, header)
166
-
167
- File.open("rf.html", "w") { |io|
168
- io.write data
169
- }
170
- # upload_redirect = response['location']
171
- # response, data = http.get(upload_redirect, header)
172
- end
173
- end
174
-
175
- end
176
- end