meta_project 0.4.3 → 0.4.4
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.
- 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
|