meta_project 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +14 -2
- data/Rakefile +1 -1
- data/lib/meta_project/patois/parser.rb +99 -0
- data/lib/meta_project/patois.rb +1 -0
- data/lib/meta_project/project/xforge/xforge_base.rb +2 -2
- data/lib/meta_project/release/freshmeat.rb +267 -0
- data/lib/meta_project/release/raa.rb +572 -0
- data/lib/meta_project/tracker/base.rb +5 -0
- data/lib/meta_project/tracker/digit_issues.rb +12 -4
- data/lib/meta_project/tracker/issue.rb +45 -3
- data/lib/meta_project/tracker/jira/jira_issues.rb +34 -0
- data/lib/meta_project/tracker/jira/jira_tracker.rb +42 -31
- data/lib/meta_project/tracker/jira.rb +1 -0
- data/lib/meta_project/tracker/trac/trac_tracker.rb +16 -2
- data/lib/meta_project/tracker/xforge/ruby_forge_tracker.rb +1 -1
- data/lib/meta_project/tracker/xforge/source_forge_tracker.rb +1 -1
- data/lib/meta_project/tracker/xforge/xforge_tracker.rb +8 -13
- data/lib/meta_project.rb +1 -0
- metadata +7 -2
data/CHANGES
CHANGED
@@ -1,12 +1,24 @@
|
|
1
|
-
=
|
1
|
+
= MetaProject Changelog
|
2
|
+
|
3
|
+
== Version 0.4.4
|
4
|
+
|
5
|
+
This release introduces a new Domain Specific Language (DSL) for SCM commit messages similar to Trac's post-commit hook for updating tickets.
|
6
|
+
Patois is supported in a tracker-agnostic way (although it's only half implemented for JIRA only ATM).
|
7
|
+
There is also initial support for FreshMeat and RAA thanks to Thomas Leitner.
|
8
|
+
|
9
|
+
* Added support for Patois parsing (See RubyDoc).
|
10
|
+
* Gave the Patois DSL its name.
|
11
|
+
* Improved the Tracker::Issue API to be more OO and uniform across trackers.
|
12
|
+
* Adds support for FreshMeat and RAA (Fixes #2323). This is not aligned with the rest of the MetaProject API yet.
|
2
13
|
|
3
14
|
== Version 0.4.3
|
4
15
|
|
5
|
-
This
|
16
|
+
This release fixes some bugs and implements some new issue tracker features.
|
6
17
|
|
7
18
|
* Aligned properties between TracTracker and JiraTracker with ProjectAnalyzer.
|
8
19
|
* Stripping leading and trailing whitespace from issue summaries (SF seems to have changed).
|
9
20
|
* Added name to XForge projects.
|
21
|
+
* Added create_issue to JiraTracker.
|
10
22
|
|
11
23
|
== Version 0.4.2
|
12
24
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
module MetaProject
|
2
|
+
# Patois is a domain specific language (DSL)
|
3
|
+
# for configuration and release management. It was first implemented by
|
4
|
+
# <a href="http://projects.edgewall.com/trac/browser/trunk/contrib/trac-post-commit-hook">Trac</a>
|
5
|
+
# and this class is a Ruby port of that Python code.
|
6
|
+
#
|
7
|
+
# A similar idea was created by the DamageControl team in <a href="http://jira.codehaus.org/browse/DC-159">DC-159</a>
|
8
|
+
# before it was implemented in Trac, but the Trac team beat the DamageControl to implement it.
|
9
|
+
#
|
10
|
+
# Anyhow, by giving this mini DSL a name and some better profiling we hope its adoption
|
11
|
+
# will increase. Patois means:
|
12
|
+
#
|
13
|
+
# * a dialect other than the standard or literary dialect
|
14
|
+
# * uneducated or provincial speech
|
15
|
+
# * the characteristic special language of an occupational or social group
|
16
|
+
#
|
17
|
+
# Patois' intended usage is in SCM commit messages. A patois-aware system can parse the commit
|
18
|
+
# messages and try to recognise patois expressions and take appropriate actions.
|
19
|
+
#
|
20
|
+
# Here is a little taste of what you can say and do with Patois.
|
21
|
+
#
|
22
|
+
# == General form
|
23
|
+
#
|
24
|
+
# command #1
|
25
|
+
# command #1, #2
|
26
|
+
# command #1 & #2
|
27
|
+
# command #1 and #2 # == Closing issues in an issue tracker
|
28
|
+
#
|
29
|
+
# You can have more than one command in a message. The following commands
|
30
|
+
# are supported. There is more than one spelling for each command, to make
|
31
|
+
# this as user-friendly as possible.
|
32
|
+
#
|
33
|
+
# close, closed, closes, fix, fixed, fixes
|
34
|
+
# The specified issues are closed with the contents of the
|
35
|
+
# commit message being added to it.
|
36
|
+
#
|
37
|
+
# addresses, re, ref, references, refs, see
|
38
|
+
# The specified issues are left in their current status, but
|
39
|
+
# the contents of the commit message are added to their notes.
|
40
|
+
#
|
41
|
+
# A fairly complicated example of what you can do is with a commit message
|
42
|
+
# of:
|
43
|
+
#
|
44
|
+
# Changed blah and foo to do this or that. Fixes #10 and #12, and refs #12.
|
45
|
+
#
|
46
|
+
# This will close #10 and #12, and add a note to #12
|
47
|
+
#
|
48
|
+
module Patois
|
49
|
+
|
50
|
+
# Parses Patois
|
51
|
+
#
|
52
|
+
class Parser
|
53
|
+
|
54
|
+
SUPPORTED_COMMANDS = {
|
55
|
+
'close' => ':close',
|
56
|
+
'closed' => ':close',
|
57
|
+
'closes' => ':close',
|
58
|
+
'fix' => ':close',
|
59
|
+
'fixed' => ':close',
|
60
|
+
'fixes' => ':close',
|
61
|
+
'addresses' => ':comment',
|
62
|
+
're' => ':comment',
|
63
|
+
'ref' => ':comment',
|
64
|
+
'references' => ':comment',
|
65
|
+
'refs' => ':comment',
|
66
|
+
'see' => ':comment'
|
67
|
+
}
|
68
|
+
|
69
|
+
# Creates a new parser that will parse commands with +command_pattern+
|
70
|
+
# and emit individual commands with +issue_pattern+.
|
71
|
+
def initialize(command_pattern, issue_pattern)
|
72
|
+
@command_pattern = command_pattern
|
73
|
+
@issue_pattern = issue_pattern
|
74
|
+
end
|
75
|
+
|
76
|
+
# Parses a patois String and yields commands.
|
77
|
+
# Each operation can be executed with +execute+
|
78
|
+
def parse(msg)
|
79
|
+
msg.scan(@command_pattern) do |cmd_group|
|
80
|
+
cmd = SUPPORTED_COMMANDS[cmd_group[0].downcase]
|
81
|
+
if(cmd)
|
82
|
+
cmd_group[1].scan(@issue_pattern) do |issue_id_array|
|
83
|
+
yield Command.new(cmd, issue_id_array[0].upcase, msg)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Command
|
90
|
+
|
91
|
+
attr_reader :cmd, :issue_id, :msg
|
92
|
+
|
93
|
+
def initialize(cmd, issue_id, msg)
|
94
|
+
@cmd, @issue_id, @msg = cmd, issue_id, msg
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'meta_project/patois/parser'
|
@@ -46,7 +46,7 @@ module MetaProject
|
|
46
46
|
def group_id
|
47
47
|
unless(@group_id)
|
48
48
|
regexp = /stats\/[?&]group_id=(\d+)/
|
49
|
-
html = open(xforge_project_url)
|
49
|
+
html = open(xforge_project_url).read
|
50
50
|
@group_id = html[regexp, 1]
|
51
51
|
raise "Couldn't get group_id" unless @group_id
|
52
52
|
end
|
@@ -64,7 +64,7 @@ module MetaProject
|
|
64
64
|
# The home page of this project
|
65
65
|
def home_page
|
66
66
|
unless(@home_page)
|
67
|
-
html = open(xforge_project_url)
|
67
|
+
html = open(xforge_project_url).read
|
68
68
|
@home_page = html[home_page_regexp, 1]
|
69
69
|
raise "Couldn't get home_page" unless @home_page
|
70
70
|
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
# Copyright (C) 2005 Thomas Leitner
|
2
|
+
#
|
3
|
+
# See LICENCE for details
|
4
|
+
|
5
|
+
require "xmlrpc/client"
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module DevTools
|
9
|
+
|
10
|
+
module Freshmeat
|
11
|
+
|
12
|
+
class FreshmeatException < StandardError; end
|
13
|
+
|
14
|
+
# Describes a freshmeat project.
|
15
|
+
class Project
|
16
|
+
|
17
|
+
# The short name of the project
|
18
|
+
attr_reader :shortName
|
19
|
+
|
20
|
+
# The full name of the project
|
21
|
+
attr_reader :fullName
|
22
|
+
|
23
|
+
# The status of the project (alpha, beta, ...)
|
24
|
+
attr_reader :status
|
25
|
+
|
26
|
+
# The current version string of the project
|
27
|
+
attr_reader :version
|
28
|
+
|
29
|
+
def initialize( shortName, fullName, status, version )
|
30
|
+
@shortName, @fullName, @status, @version = shortName, fullName, status, version
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"Project: short name = #{@shortName}, full name = #{@fullName}, status = #{@status}, version = #{@version}"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# Provides information about a release.
|
40
|
+
class ReleaseInfo
|
41
|
+
|
42
|
+
# Version string of release
|
43
|
+
attr_reader :version
|
44
|
+
|
45
|
+
# Change list of release
|
46
|
+
attr_reader :changes
|
47
|
+
|
48
|
+
# Release focus
|
49
|
+
attr_reader :release_focus
|
50
|
+
|
51
|
+
# True, if hidden from frontpage
|
52
|
+
attr_reader :hidden
|
53
|
+
|
54
|
+
# Returns a new ReleaseInfo object
|
55
|
+
def initialize( version, changes, release_focus, hidden )
|
56
|
+
@version, @changes, @release_focus, @hidden = version, changes, release_focus, hidden
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
"ReleaseInfo: version = #{@version}, release focus = #{ReleaseFocusID::NAMES[@release_focus]}, hidden = #{hidden}\nChanges = #{@changes}"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
# Holds all information about a release which should be published.
|
66
|
+
class Release
|
67
|
+
|
68
|
+
#Project name to submit a release for
|
69
|
+
attr_accessor :project_name
|
70
|
+
|
71
|
+
#Branch name to submit a release for
|
72
|
+
attr_accessor :branch_name
|
73
|
+
|
74
|
+
#Version string of new release
|
75
|
+
attr_accessor :version
|
76
|
+
|
77
|
+
#Changes list, no HTML, character limit 600 chars
|
78
|
+
attr_accessor :changes
|
79
|
+
|
80
|
+
#Release focus ID of new release
|
81
|
+
attr_accessor :release_focus
|
82
|
+
|
83
|
+
#Set to 'Y' if release is to be hidden from frontpage, everything else does not hide it
|
84
|
+
attr_accessor :hide_from_frontpage
|
85
|
+
|
86
|
+
#Optional: Branch license
|
87
|
+
attr_accessor :license
|
88
|
+
|
89
|
+
#Optional: Homepage
|
90
|
+
attr_accessor :url_homepage
|
91
|
+
|
92
|
+
#Optional: Tar/GZ
|
93
|
+
attr_accessor :url_tgz
|
94
|
+
|
95
|
+
#Optional: Tar/BZ2
|
96
|
+
attr_accessor :url_bz2
|
97
|
+
|
98
|
+
#Optional: Zip
|
99
|
+
attr_accessor :url_zip
|
100
|
+
|
101
|
+
#Optional: Changelog
|
102
|
+
attr_accessor :url_changelog
|
103
|
+
|
104
|
+
#Optional: RPM package
|
105
|
+
attr_accessor :url_rpm
|
106
|
+
|
107
|
+
#Optional: Debian package
|
108
|
+
attr_accessor :url_deb
|
109
|
+
|
110
|
+
#Optional: OS X package
|
111
|
+
attr_accessor :url_osx
|
112
|
+
|
113
|
+
#Optional: BSD Ports URL
|
114
|
+
attr_accessor :url_bsdport
|
115
|
+
|
116
|
+
#Optional: Purchase
|
117
|
+
attr_accessor :url_purchase
|
118
|
+
|
119
|
+
#Optional: CVS tree (cvsweb)
|
120
|
+
attr_accessor :url_cvs
|
121
|
+
|
122
|
+
#Optional: Mailing list archive
|
123
|
+
attr_accessor :url_list
|
124
|
+
|
125
|
+
#Optional: Mirror site
|
126
|
+
attr_accessor :url_mirror
|
127
|
+
|
128
|
+
#Optional: Demo site
|
129
|
+
attr_accessor :url_demo
|
130
|
+
|
131
|
+
def self.from_data( data=nil )
|
132
|
+
YAML::load( data )
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_rpc_data
|
136
|
+
rpc_data = {}
|
137
|
+
instance_variables.each do |iv|
|
138
|
+
rpc_data[iv[1..-1]] = eval( iv )
|
139
|
+
end
|
140
|
+
rpc_data
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_yaml_type
|
144
|
+
"!thomasleitner,2005/FreshmeatRelease"
|
145
|
+
end
|
146
|
+
|
147
|
+
YAML::add_domain_type( 'thomasleitner,2005', 'FreshmeatRelease' ) do |type, val|
|
148
|
+
YAML::object_maker( Release, val )
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
# Provides constants for all release focus ids
|
154
|
+
module ReleaseFocusID
|
155
|
+
NA = 0
|
156
|
+
INITIAL_ANNOUNCEMENT = 1
|
157
|
+
DOCUMENTATION = 2
|
158
|
+
CODE_CLEANUP = 3
|
159
|
+
MINOR_FEATURES = 4
|
160
|
+
MAJOR_FEATURES = 5
|
161
|
+
MINOR_BUGFIXES = 6
|
162
|
+
MAJOR_BUGFIXES = 7
|
163
|
+
MINOR_SECFIXES = 8
|
164
|
+
MAJOR_SECFIXES = 9
|
165
|
+
|
166
|
+
NAMES = {0=>'N/A',
|
167
|
+
1=>'Initial freshmeat announcement',
|
168
|
+
2=>'Documentation',
|
169
|
+
3=>'Code cleanup',
|
170
|
+
4=>'Minor feature enhancements',
|
171
|
+
5=>'Major feature enhancements',
|
172
|
+
6=>'Minor bugfixes',
|
173
|
+
7=>'Major bugfixes',
|
174
|
+
8=>'Minor security fixes',
|
175
|
+
9=>'Major security fixes'
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
# Provides access to the Freshmeat XML-RPC API via a nice interface.
|
181
|
+
# API reference at http://freshmeat.net/faq/view/49/
|
182
|
+
#
|
183
|
+
# Example:
|
184
|
+
#
|
185
|
+
# fm = DevTools::FreshmeatService.new( username, password )
|
186
|
+
# fm.get_project_list.each do |p|
|
187
|
+
# puts p
|
188
|
+
# branches = fm.get_branch_list( p.shortName )
|
189
|
+
# puts branches.inspect
|
190
|
+
# release = fm.get_release( p.shortName, branches[0], p.version )
|
191
|
+
# puts release
|
192
|
+
# end
|
193
|
+
# puts fm.logout
|
194
|
+
class FreshmeatService
|
195
|
+
|
196
|
+
# The URL for the Freshmeat RPC service
|
197
|
+
RPCURL = 'http://freshmeat.net/xmlrpc/'
|
198
|
+
|
199
|
+
# The major version of the freshmeat API with which this library works
|
200
|
+
API_VERSION_MAJOR = '1'
|
201
|
+
|
202
|
+
# The minor version of the freshmeat API with which this library works
|
203
|
+
API_VERSION_MINOR = '03'
|
204
|
+
|
205
|
+
# Use +username+ and +password+ to log into Freshmeat service.
|
206
|
+
def initialize( username, password )
|
207
|
+
@session = XMLRPC::Client.new2( RPCURL )
|
208
|
+
ret = @session.call( :login, :username=>username, :password=>password )
|
209
|
+
@sid = ret['SID']
|
210
|
+
major, minor = ret['API Version'].split( '.' )
|
211
|
+
if major != API_VERSION_MAJOR or minor < API_VERSION_MINOR
|
212
|
+
raise FreshmeatException, 'Incompatible API versions'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns all available licenses
|
217
|
+
def self.get_licenses
|
218
|
+
XMLRPC::Client.new2( RPCURL ).call( :fetch_available_licenses )
|
219
|
+
end
|
220
|
+
|
221
|
+
# Returns all available release focus types
|
222
|
+
def self.get_release_focus_types
|
223
|
+
XMLRPC::Client.new2( RPCURL ).call( :fetch_available_release_foci )
|
224
|
+
end
|
225
|
+
|
226
|
+
# Returns an array of Project objects which are assigned to the logged in user
|
227
|
+
def get_project_list
|
228
|
+
ret = @session.call( :fetch_project_list, :SID=>@sid )
|
229
|
+
ret.collect! {|p| Project.new( p['projectname_short'], p['projectname_full'], p['project_status'], p['project_version'] ) }
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns an array of branch names for the project +project+.
|
233
|
+
def get_branch_list( project )
|
234
|
+
@session.call( :fetch_branch_list, :SID=>@sid, :project_name=>project )
|
235
|
+
end
|
236
|
+
|
237
|
+
# Returns a ReleaseInfo object which has the information about the requested release.
|
238
|
+
def get_release( project, branch, version )
|
239
|
+
ret = @session.call( :fetch_release, :SID=>@sid, :project_name=>project, :branch_name=>branch, :version=>version )
|
240
|
+
releaseFocus = ret['release_focus'].split( ' - ' )[0].to_i
|
241
|
+
hidden = (ret['hide_from_frontpage'] == 'Y' )
|
242
|
+
ReleaseInfo.new( ret['version'], ret['changes'], releaseFocus, hidden )
|
243
|
+
end
|
244
|
+
|
245
|
+
# Publishes a new release of a project. The parameter +release+ has to be a Release object!
|
246
|
+
def publish_release( release )
|
247
|
+
ret = @session.call( :publish_release, {:SID=>@sid}.update( release.to_rpc_data ) )
|
248
|
+
ret['OK'] == 'submission successful'
|
249
|
+
end
|
250
|
+
|
251
|
+
# Withdraws the specified release.
|
252
|
+
def withdraw_release( project, branch, version )
|
253
|
+
ret = @session.call( :withdraw_release, :SID=>@sid, :project_name=>project, :branch_name=>branch, :version=>version )
|
254
|
+
ret['OK'] == 'Withdraw successful.'
|
255
|
+
end
|
256
|
+
|
257
|
+
# Logs out from the Freshmeat service.
|
258
|
+
def logout
|
259
|
+
ok, ret = @session.call2( :logout, :SID=>@sid )
|
260
|
+
ok && ret['OK'] == 'Logout successful.'
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|