xforge 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/README +5 -1
- data/Rakefile +3 -3
- data/lib/scm_web/view_cvs.rb +1 -0
- data/lib/tracker/jira.rb +2 -0
- data/lib/tracker/jira/host.rb +40 -0
- data/lib/tracker/jira/project.rb +41 -0
- data/lib/tracker/trac.rb +1 -0
- data/lib/tracker/trac/project.rb +37 -0
- data/lib/tracker/xforge.rb +2 -0
- data/lib/tracker/xforge/base.rb +84 -0
- data/lib/tracker/xforge/rubyforge.rb +6 -0
- data/lib/xforge.rb +3 -1
- data/lib/xforge/project.rb +1 -1
- data/lib/xforge/rubyforge.rb +9 -4
- data/lib/xforge/sourceforge.rb +4 -3
- metadata +10 -4
- data/lib/tracker/rubyforge.rb +0 -63
data/CHANGES
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
= XForge Changelog
|
2
2
|
|
3
|
+
== Version 0.3.1
|
4
|
+
|
5
|
+
This XForge release adds initial support for Trac and JIRA.
|
6
|
+
|
7
|
+
* Added support for formatting of text containing issue identifiers
|
8
|
+
* Refactored trackers into other modules
|
9
|
+
* Added support for JIRA issue tracker
|
10
|
+
* Added support for Trac's issue tracker
|
11
|
+
* Added support for diff URLs on SourceForge and RubyForge
|
12
|
+
|
3
13
|
== Version 0.2.1
|
4
14
|
|
5
15
|
This XForge release adds support for tracker meta info
|
data/README
CHANGED
@@ -30,7 +30,11 @@ Download and install XForge with the following.
|
|
30
30
|
|
31
31
|
== Usage
|
32
32
|
|
33
|
-
|
33
|
+
XForge itself is released with XForge. so check out XForge's own Rakefile (http://tinyurl.com/a23u5) and CHANGES (http://tinyurl.com/9qxxf) files for the best examples on how to use it.
|
34
|
+
|
35
|
+
XForge can parse release summary and changes from CHANGES if you format it the way XForge's own CHANGES is formatted. Also make sure your Rakefile's PKG_VERSION is in sync with the latest version specified in the CHANGES file.
|
36
|
+
|
37
|
+
If you're writing an application that interacts with XForge, check out the RDoc API.
|
34
38
|
|
35
39
|
---
|
36
40
|
|
data/Rakefile
CHANGED
@@ -24,7 +24,7 @@ require 'rake/rdoctask'
|
|
24
24
|
#
|
25
25
|
# REMEMBER TO KEEP PKG_VERSION IN SYNC WITH CHANGELOG
|
26
26
|
PKG_NAME = "xforge"
|
27
|
-
PKG_VERSION = "0.
|
27
|
+
PKG_VERSION = "0.3.1"
|
28
28
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
29
29
|
PKG_FILES = FileList[
|
30
30
|
'[A-Z]*',
|
@@ -48,7 +48,7 @@ rd = Rake::RDocTask.new("rdoc") do |rdoc|
|
|
48
48
|
# rdoc.template = 'doc/jamis.rb'
|
49
49
|
rdoc.title = "XForge"
|
50
50
|
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
51
|
-
rdoc.rdoc_files.include('README', 'MIT-LICENSE', '
|
51
|
+
rdoc.rdoc_files.include('README', 'MIT-LICENSE', 'CHANGES')
|
52
52
|
rdoc.rdoc_files.include('lib/**/*.rb', 'doc/**/*.rdoc')
|
53
53
|
rdoc.rdoc_files.exclude('doc/**/*_attrs.rdoc')
|
54
54
|
end
|
@@ -117,7 +117,7 @@ task :todo do
|
|
117
117
|
egrep /#.*(FIXME|TODO|TBD)/
|
118
118
|
end
|
119
119
|
|
120
|
-
task :release => [:verify_env_vars, :release_files, :publish_doc, :publish_news]
|
120
|
+
task :release => [:verify_env_vars, :release_files, :publish_doc, :publish_news, :tag]
|
121
121
|
|
122
122
|
task :verify_env_vars do
|
123
123
|
raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
|
data/lib/scm_web/view_cvs.rb
CHANGED
data/lib/tracker/jira.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'xmlrpc/client'
|
2
|
+
|
3
|
+
module Tracker
|
4
|
+
module Jira
|
5
|
+
class Host
|
6
|
+
JIRA_API = "jira1"
|
7
|
+
|
8
|
+
attr_reader :uri
|
9
|
+
|
10
|
+
def initialize(uri, username, password)
|
11
|
+
@uri, @username, @password = uri, username, password
|
12
|
+
end
|
13
|
+
|
14
|
+
def project(identifier)
|
15
|
+
Project.new(self, identifier)
|
16
|
+
end
|
17
|
+
|
18
|
+
def login
|
19
|
+
client = XMLRPC::Client.new2("#{uri}/rpc/xmlrpc")
|
20
|
+
token = client.call("#{JIRA_API}.login", @username, @password)
|
21
|
+
Session.new(client, token)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
# This wrapper around XMLRPC::Client that allows simpler method calls
|
27
|
+
# via method_missing and doesn't require to manage the token
|
28
|
+
class Session
|
29
|
+
def initialize(client, token)
|
30
|
+
@client, @token = client, token
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(sym, args, &block)
|
34
|
+
token_args = [@token] << args
|
35
|
+
xmlrpc_method = "#{Host::JIRA_API}.#{sym.to_s}"
|
36
|
+
@client.call(xmlrpc_method, *token_args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Tracker
|
2
|
+
module Jira
|
3
|
+
class Project
|
4
|
+
def initialize(host, identifier)
|
5
|
+
@host, @identifier = host, identifier
|
6
|
+
end
|
7
|
+
|
8
|
+
def identifier_regexp
|
9
|
+
/([A-Z]+-[\d]+)/
|
10
|
+
end
|
11
|
+
|
12
|
+
def identifier_examples
|
13
|
+
["DC-420", "PICO-12"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def uri
|
17
|
+
"#{@host.uri}/browse/#{@identifier}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def issue(issue_identifier)
|
21
|
+
session = @host.login
|
22
|
+
begin
|
23
|
+
issue = session.getIssue(issue_identifier)
|
24
|
+
Issue.new("#{@host.uri}/browse/#{issue_identifier}", issue["summary"])
|
25
|
+
rescue XMLRPC::FaultException
|
26
|
+
# Probably bad issue number
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def markup(text)
|
32
|
+
text.gsub(identifier_regexp) do |match|
|
33
|
+
issue_identifier = $1
|
34
|
+
issue = issue(issue_identifier)
|
35
|
+
issue ? "<a href=\"#{issue.uri}\">#{issue.summary}</a>" : issue_identifier
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/tracker/trac.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'tracker/trac/project'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Tracker
|
2
|
+
module Trac
|
3
|
+
class Project
|
4
|
+
def initialize(uri)
|
5
|
+
@uri = uri
|
6
|
+
end
|
7
|
+
|
8
|
+
def identifier_regexp
|
9
|
+
/#(\d+)/
|
10
|
+
end
|
11
|
+
|
12
|
+
def identifier_examples
|
13
|
+
["#1926", "#1446"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def issue(issue_identifier)
|
17
|
+
issue_uri = "#{@uri}/ticket/#{issue_identifier}"
|
18
|
+
begin
|
19
|
+
html = open(issue_uri) { |data| data.read }
|
20
|
+
summary = html[/Ticket ##{issue_identifier}\s*<\/h1>\s*<h2>([^<]*)<\/h2>/n, 1]
|
21
|
+
Issue.new(issue_uri, summary)
|
22
|
+
rescue OpenURI::HTTPError
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def markup(text)
|
28
|
+
text.gsub(identifier_regexp) do |match|
|
29
|
+
issue_identifier = $1
|
30
|
+
issue = issue(issue_identifier)
|
31
|
+
issue ? "<a href=\"#{issue.uri}\">#{issue.summary}</a>" : "\##{issue_identifier}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Tracker
|
2
|
+
module XForge
|
3
|
+
# TODO: rename to Project
|
4
|
+
class Base
|
5
|
+
attr_reader :uri, :project
|
6
|
+
|
7
|
+
def identifier_regexp
|
8
|
+
/#(\d+)/
|
9
|
+
end
|
10
|
+
|
11
|
+
# Examples of what will be recognised as issue identifiers in #markup
|
12
|
+
def identifier_examples
|
13
|
+
["#1462", "#872"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(uri, project)
|
17
|
+
@uri, @project = uri, project
|
18
|
+
end
|
19
|
+
|
20
|
+
# Finds an Issue by +identifier+
|
21
|
+
def issue(identifier)
|
22
|
+
sub_trackers = atids.collect {|atid| SubTracker.new(self, atid)}
|
23
|
+
sub_trackers.each do |sub_tracker|
|
24
|
+
issue = sub_tracker.issue(identifier)
|
25
|
+
return issue unless issue.nil?
|
26
|
+
end
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def markup(text)
|
31
|
+
text.gsub(identifier_regexp) do |match|
|
32
|
+
issue_identifier = $1
|
33
|
+
issue = issue(issue_identifier)
|
34
|
+
issue ? "<a href=\"#{issue.uri}\">#{issue.summary}</a>" : "\##{issue_identifier}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class SubTracker
|
39
|
+
attr_reader :uri
|
40
|
+
|
41
|
+
def initialize(rubyforge, atid)
|
42
|
+
@rubyforge = rubyforge
|
43
|
+
@atid = atid
|
44
|
+
# FIXME: This will only show open items.
|
45
|
+
@uri = "#{rubyforge.uri}&atid=#{atid}&func=browse"
|
46
|
+
end
|
47
|
+
|
48
|
+
def issue(identifier)
|
49
|
+
html = open(uri) { |data| data.read }
|
50
|
+
|
51
|
+
regexp = /<a href=\"\/tracker\/index.php\?func=detail&aid=#{identifier}&group_id=\d+&atid=\d+\">(.*)<\/a>/
|
52
|
+
if(html =~ regexp)
|
53
|
+
issue_uri = @rubyforge.project.group_id_uri("tracker/index.php", "&atid=#{@atid}&func=detail&aid=#{identifier}")
|
54
|
+
return Issue.new(issue_uri, $1)
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# The ids of the subtrackers
|
63
|
+
def atids
|
64
|
+
html = open(uri) { |data| data.read }
|
65
|
+
|
66
|
+
# TODO: there has to be a better way to extract the atids from the HTML!
|
67
|
+
atids = []
|
68
|
+
offset = 0
|
69
|
+
look_for_atid = true
|
70
|
+
while(look_for_atid)
|
71
|
+
match_data = /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/.match(html[offset..-1])
|
72
|
+
if(match_data)
|
73
|
+
offset += match_data.begin(1)
|
74
|
+
atids << match_data[1]
|
75
|
+
else
|
76
|
+
look_for_atid = false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
atids
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/xforge.rb
CHANGED
@@ -6,6 +6,8 @@ require 'xforge/project'
|
|
6
6
|
require 'xforge/session'
|
7
7
|
require 'xforge/xfile'
|
8
8
|
require 'scm_web/view_cvs'
|
9
|
-
require 'tracker/rubyforge'
|
10
9
|
require 'tracker/issue'
|
10
|
+
require 'tracker/xforge'
|
11
|
+
require 'tracker/jira'
|
12
|
+
require 'tracker/trac'
|
11
13
|
require 'rake/contrib/xforge'
|
data/lib/xforge/project.rb
CHANGED
data/lib/xforge/rubyforge.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
module XForge
|
2
2
|
class RubyForge < Host
|
3
3
|
VIEW_CVS = "http://rubyforge.org/cgi-bin/viewcvs.cgi/"
|
4
|
-
|
4
|
+
CVSROOT = "?cvsroot=\#{project_unix_name}"
|
5
|
+
PATH_CVSROOT = "\#{path}#{CVSROOT}"
|
5
6
|
PATH_CVSROOT_REV = "#{PATH_CVSROOT}&rev=\#{revision}"
|
6
7
|
|
7
8
|
OVERVIEW = "#{VIEW_CVS}#{PATH_CVSROOT}"
|
8
|
-
RAW
|
9
|
-
HTML
|
9
|
+
RAW = "#{VIEW_CVS}*checkout*/#{PATH_CVSROOT_REV}"
|
10
|
+
HTML = "#{VIEW_CVS}#{PATH_CVSROOT_REV}&content-type=text/vnd.viewcvs-markup"
|
11
|
+
DIFF = "#{VIEW_CVS}\#{path}.diff#{CVSROOT}&r1=\#{previous_revision}&r2=\#{revision}"
|
10
12
|
|
11
13
|
def initialize
|
12
14
|
super('rubyforge.org')
|
@@ -26,7 +28,7 @@ module XForge
|
|
26
28
|
|
27
29
|
def scm_web(project)
|
28
30
|
module_regexp = /href=\"(\w+)\/\?cvsroot=#{project.unix_name}/
|
29
|
-
::ScmWeb::ViewCvs.new({:overview => OVERVIEW, :raw => RAW, :html => HTML}, project, module_regexp)
|
31
|
+
::ScmWeb::ViewCvs.new({:overview => OVERVIEW, :raw => RAW, :html => HTML, :diff => DIFF}, project, module_regexp)
|
30
32
|
end
|
31
33
|
|
32
34
|
# Regexp used to find projects' home page
|
@@ -35,5 +37,8 @@ module XForge
|
|
35
37
|
/<a href=\"(\w*:\/\/[^\"]*)\"><img src=\"\/themes\/osx\/images\/ic\/home/
|
36
38
|
end
|
37
39
|
|
40
|
+
def tracker(project)
|
41
|
+
Tracker::XForge::RubyForge.new(project.group_id_uri("tracker"), project)
|
42
|
+
end
|
38
43
|
end
|
39
44
|
end
|
data/lib/xforge/sourceforge.rb
CHANGED
@@ -5,8 +5,9 @@ module XForge
|
|
5
5
|
REV = "rev=\#{revision}"
|
6
6
|
|
7
7
|
OVERVIEW = "#{VIEW_CVS}#{PROJECT_PATH}"
|
8
|
-
RAW
|
9
|
-
HTML
|
8
|
+
RAW = "#{VIEW_CVS}*checkout*/#{PROJECT_PATH}?#{REV}"
|
9
|
+
HTML = "#{OVERVIEW}?#{REV}&view=markup"
|
10
|
+
DIFF = "#{OVERVIEW}?r1=\#{previous_revision}&r2=\#{revision}"
|
10
11
|
|
11
12
|
def initialize
|
12
13
|
super("sourceforge.net")
|
@@ -26,7 +27,7 @@ module XForge
|
|
26
27
|
|
27
28
|
def scm_web(project)
|
28
29
|
module_regexp = /viewcvs\.py\/#{project.unix_name}\/(\w+)\//
|
29
|
-
::ScmWeb::ViewCvs.new({:overview => OVERVIEW, :raw => RAW, :html => HTML}, project, module_regexp)
|
30
|
+
::ScmWeb::ViewCvs.new({:overview => OVERVIEW, :raw => RAW, :html => HTML, :diff => DIFF}, project, module_regexp)
|
30
31
|
end
|
31
32
|
|
32
33
|
# Regexp used to find projects' home page
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: xforge
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2005-08-
|
6
|
+
version: 0.3.1
|
7
|
+
date: 2005-08-15 00:00:00 -04:00
|
8
8
|
summary: Ruby based make-like utility.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -42,7 +42,14 @@ files:
|
|
42
42
|
- lib/rake/contrib/xforge/release.rb
|
43
43
|
- lib/scm_web/view_cvs.rb
|
44
44
|
- lib/tracker/issue.rb
|
45
|
-
- lib/tracker/
|
45
|
+
- lib/tracker/jira.rb
|
46
|
+
- lib/tracker/trac.rb
|
47
|
+
- lib/tracker/xforge.rb
|
48
|
+
- lib/tracker/jira/host.rb
|
49
|
+
- lib/tracker/jira/project.rb
|
50
|
+
- lib/tracker/trac/project.rb
|
51
|
+
- lib/tracker/xforge/base.rb
|
52
|
+
- lib/tracker/xforge/rubyforge.rb
|
46
53
|
- lib/xforge/host.rb
|
47
54
|
- lib/xforge/project.rb
|
48
55
|
- lib/xforge/rubyforge.rb
|
@@ -61,7 +68,6 @@ rdoc_options:
|
|
61
68
|
extra_rdoc_files:
|
62
69
|
- README
|
63
70
|
- MIT-LICENSE
|
64
|
-
- TODO
|
65
71
|
- CHANGES
|
66
72
|
executables: []
|
67
73
|
extensions: []
|
data/lib/tracker/rubyforge.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
module Tracker
|
2
|
-
class RubyForge
|
3
|
-
attr_reader :uri, :project
|
4
|
-
|
5
|
-
def initialize(uri, project)
|
6
|
-
@uri, @project = uri, project
|
7
|
-
end
|
8
|
-
|
9
|
-
def issue(identifier)
|
10
|
-
sub_trackers = atids.collect {|atid| SubTracker.new(self, atid)}
|
11
|
-
sub_trackers.each do |sub_tracker|
|
12
|
-
issue = sub_tracker.issue(identifier)
|
13
|
-
return issue unless issue.nil?
|
14
|
-
end
|
15
|
-
nil
|
16
|
-
end
|
17
|
-
|
18
|
-
class SubTracker
|
19
|
-
attr_reader :uri
|
20
|
-
|
21
|
-
def initialize(rubyforge, atid)
|
22
|
-
@rubyforge = rubyforge
|
23
|
-
@atid = atid
|
24
|
-
# FIXME: This will only show open items.
|
25
|
-
@uri = "#{rubyforge.uri}&atid=#{atid}&func=browse"
|
26
|
-
end
|
27
|
-
|
28
|
-
def issue(identifier)
|
29
|
-
html = open(uri) { |data| data.read }
|
30
|
-
|
31
|
-
regexp = /<a href=\"\/tracker\/index.php\?func=detail&aid=#{identifier}&group_id=\d+&atid=\d+\">(.*)<\/a>/
|
32
|
-
if(html =~ regexp)
|
33
|
-
issue_uri = @rubyforge.project.group_id_uri("tracker/index.php", "&atid=#{@atid}&func=detail&aid=#{identifier}")
|
34
|
-
return Issue.new(issue_uri, $1)
|
35
|
-
end
|
36
|
-
nil
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
# The ids of the subtrackers
|
43
|
-
def atids
|
44
|
-
html = open(uri) { |data| data.read }
|
45
|
-
|
46
|
-
# TODO: there has to be a better way to extract the atids from the HTML!
|
47
|
-
atids = []
|
48
|
-
offset = 0
|
49
|
-
look_for_atid = true
|
50
|
-
while(look_for_atid)
|
51
|
-
match_data = /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/.match(html[offset..-1])
|
52
|
-
if(match_data)
|
53
|
-
offset += match_data.begin(1)
|
54
|
-
atids << match_data[1]
|
55
|
-
else
|
56
|
-
look_for_atid = false
|
57
|
-
end
|
58
|
-
end
|
59
|
-
atids
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|