xforge 0.2.1 → 0.3.1

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 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
- See XForge, Rake::XForge::Release and Rake::XForge::NewsPublisher.
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.2.1"
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', 'TODO', 'CHANGES')
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']
@@ -42,6 +42,7 @@ module ScmWeb
42
42
 
43
43
  project_unix_name = project.unix_name
44
44
  revision = options[:revision]
45
+ previous_revision = options[:previous_revision]
45
46
  eval("\"#{uri_spec}\"", binding)
46
47
  end
47
48
  end
@@ -0,0 +1,2 @@
1
+ require 'tracker/jira/host'
2
+ require 'tracker/jira/project'
@@ -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
@@ -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,2 @@
1
+ require 'tracker/xforge/base'
2
+ require 'tracker/xforge/rubyforge'
@@ -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
@@ -0,0 +1,6 @@
1
+ module Tracker
2
+ module XForge
3
+ class RubyForge < Base
4
+ end
5
+ end
6
+ 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'
@@ -76,7 +76,7 @@ module XForge
76
76
  end
77
77
 
78
78
  def tracker
79
- @tracker ||= Tracker::RubyForge.new(group_id_uri("tracker"), self)
79
+ @tracker ||= @host.tracker(self)
80
80
  end
81
81
  end
82
82
 
@@ -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
- PATH_CVSROOT = "\#{path}?cvsroot=\#{project_unix_name}"
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 = "#{VIEW_CVS}*checkout*/#{PATH_CVSROOT_REV}"
9
- HTML = "#{VIEW_CVS}#{PATH_CVSROOT_REV}&content-type=text/vnd.viewcvs-markup"
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
@@ -5,8 +5,9 @@ module XForge
5
5
  REV = "rev=\#{revision}"
6
6
 
7
7
  OVERVIEW = "#{VIEW_CVS}#{PROJECT_PATH}"
8
- RAW = "#{VIEW_CVS}*checkout*/#{PROJECT_PATH}?#{REV}"
9
- HTML = "#{OVERVIEW}?#{REV}&view=markup"
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.2.1
7
- date: 2005-08-14 00:00:00 -04:00
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/rubyforge.rb
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: []
@@ -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