xforge 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/CHANGES +34 -0
  2. data/Rakefile +5 -5
  3. data/lib/meta_project.rb +6 -0
  4. data/lib/meta_project/project.rb +4 -0
  5. data/lib/meta_project/project/base.rb +7 -0
  6. data/lib/meta_project/project/codehaus.rb +1 -0
  7. data/lib/meta_project/project/codehaus/codehaus_project_svn.rb +26 -0
  8. data/lib/meta_project/project/trac.rb +1 -0
  9. data/lib/meta_project/project/trac/trac_project.rb +26 -0
  10. data/lib/meta_project/project/xforge.rb +5 -0
  11. data/lib/meta_project/project/xforge/ruby_forge.rb +46 -0
  12. data/lib/meta_project/project/xforge/session.rb +162 -0
  13. data/lib/meta_project/project/xforge/source_forge.rb +46 -0
  14. data/lib/meta_project/project/xforge/xfile.rb +45 -0
  15. data/lib/meta_project/project/xforge/xforge_base.rb +76 -0
  16. data/lib/meta_project/project_analyzer.rb +36 -0
  17. data/lib/meta_project/scm_web.rb +53 -0
  18. data/lib/meta_project/tracker.rb +6 -0
  19. data/lib/meta_project/tracker/base.rb +18 -0
  20. data/lib/meta_project/tracker/digit_issues.rb +24 -0
  21. data/lib/meta_project/tracker/issue.rb +11 -0
  22. data/lib/meta_project/tracker/jira.rb +1 -0
  23. data/lib/meta_project/tracker/jira/jira_tracker.rb +68 -0
  24. data/lib/meta_project/tracker/trac.rb +1 -0
  25. data/lib/meta_project/tracker/trac/trac_tracker.rb +29 -0
  26. data/lib/meta_project/tracker/xforge.rb +3 -0
  27. data/lib/meta_project/tracker/xforge/ruby_forge_tracker.rb +17 -0
  28. data/lib/meta_project/tracker/xforge/source_forge_tracker.rb +17 -0
  29. data/lib/meta_project/tracker/xforge/xforge_tracker.rb +83 -0
  30. data/lib/{xforge → meta_project}/version_parser.rb +6 -6
  31. data/lib/rake/contrib/xforge/base.rb +2 -3
  32. data/lib/rake/contrib/xforge/news_publisher.rb +1 -5
  33. data/lib/rake/contrib/xforge/release.rb +3 -7
  34. data/lib/xforge.rb +0 -1
  35. metadata +30 -27
  36. data/lib/scm_web/base.rb +0 -12
  37. data/lib/scm_web/file_uri.rb +0 -21
  38. data/lib/scm_web/view_cvs.rb +0 -44
  39. data/lib/tracker/base.rb +0 -16
  40. data/lib/tracker/bugzilla/project.rb +0 -8
  41. data/lib/tracker/digit_issues.rb +0 -22
  42. data/lib/tracker/fog_bugz/project.rb +0 -8
  43. data/lib/tracker/issue.rb +0 -9
  44. data/lib/tracker/jira.rb +0 -2
  45. data/lib/tracker/jira/host.rb +0 -40
  46. data/lib/tracker/jira/project.rb +0 -43
  47. data/lib/tracker/mantis/project.rb +0 -8
  48. data/lib/tracker/scarab/project.rb +0 -8
  49. data/lib/tracker/trac.rb +0 -1
  50. data/lib/tracker/trac/project.rb +0 -35
  51. data/lib/tracker/xforge.rb +0 -2
  52. data/lib/tracker/xforge/base.rb +0 -77
  53. data/lib/tracker/xforge/rubyforge.rb +0 -7
  54. data/lib/xforge/host.rb +0 -26
  55. data/lib/xforge/project.rb +0 -87
  56. data/lib/xforge/rubyforge.rb +0 -50
  57. data/lib/xforge/session.rb +0 -158
  58. data/lib/xforge/sourceforge.rb +0 -46
  59. data/lib/xforge/xfile.rb +0 -41
@@ -0,0 +1,76 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'open-uri'
4
+
5
+ module MetaProject
6
+ module Project
7
+ module XForge
8
+ class XForgeBase < Base
9
+
10
+ def initialize(host, unix_name, cvs_mod)
11
+ @host = host
12
+ @unix_name = unix_name
13
+
14
+ @tracker = tracker_class.new(group_id_uri("tracker"), self)
15
+
16
+ unless(cvs_mod.nil?)
17
+ @scm = create_cvs(unix_name, cvs_mod)
18
+ @scm_web = create_view_cvs(unix_name, cvs_mod)
19
+ end
20
+ end
21
+
22
+ def to_yaml_properties
23
+ ["@host", "@unix_name"]
24
+ end
25
+
26
+ # Logs in and returns a Session
27
+ def login(user_name, password)
28
+ http = Net::HTTP.new(@host, 80)
29
+
30
+ login_response = http.start do |http|
31
+ data = [
32
+ "login=1",
33
+ "form_loginname=#{user_name}",
34
+ "form_pw=#{password}"
35
+ ].join("&")
36
+ http.post("/account/login.php", data)
37
+ end
38
+
39
+ cookie = login_response["set-cookie"]
40
+ raise "Login failed" unless cookie
41
+ Session.new(@host, self, cookie)
42
+ end
43
+
44
+ # The group_id of this project
45
+ def group_id
46
+ unless(@group_id)
47
+ regexp = /stats\/[?&]group_id=(\d+)/
48
+ html = open(project_uri) { |data| data.read }
49
+ @group_id = html[regexp, 1]
50
+ raise "Couldn't get group_id" unless @group_id
51
+ end
52
+ @group_id
53
+ end
54
+
55
+ def project_uri
56
+ "http://#{@host}/projects/#{@unix_name}/"
57
+ end
58
+
59
+ def group_id_uri(path, postfix="")
60
+ "http://#{@host}/#{path}/?group_id=#{group_id}#{postfix}"
61
+ end
62
+
63
+ # The home page of this project
64
+ def home_page
65
+ unless(@home_page)
66
+ html = open(project_uri) { |data| data.read }
67
+ @home_page = html[home_page_regexp, 1]
68
+ raise "Couldn't get home_page" unless @home_page
69
+ end
70
+ @home_page
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,36 @@
1
+ module MetaProject
2
+ module ProjectAnalyzer
3
+ # Creates a project from an scm web url. The project has a +tracker+, +scm+ and +scm_web+.
4
+ def project_from_scm_web(url, options=nil)
5
+ # RubyForge
6
+ if(url =~ /http:\/\/rubyforge.org\/cgi-bin\/viewcvs.cgi\/(.*)[\/]?\?cvsroot=(.*)/)
7
+ unix_name = $2
8
+ mod = $1[-1..-1] == "/" ? $1[0..-2] : $1
9
+ return Project::XForge::RubyForge.new(unix_name, mod)
10
+ end
11
+
12
+ # SourceForge
13
+ if(url =~ /http:\/\/cvs.sourceforge.net\/viewcvs.py\/([^\/]*)\/(.*)/)
14
+ unix_name = $1
15
+ mod = $2[-1..-1] == "/" ? $2[0..-2] : $2
16
+ return Project::XForge::SourceForge.new(unix_name, mod)
17
+ end
18
+
19
+ # Trac
20
+ if(url =~ /(http:\/\/.*)\/browser\/(.*)/)
21
+ trac_base_url = $1
22
+ svn_path = $2[-1..-1] == "/" ? $2[0..-2] : $2
23
+ return Project::Trac::TracProject.new(trac_base_url, options[:svn_root_url], svn_path)
24
+ end
25
+
26
+ # Codehaus SVN
27
+ if(url =~ /http:\/\/svn.(.*).codehaus.org\/(.*)/)
28
+ svn_id = $1
29
+ svn_path = $2[-1..-1] == "/" ? $2[0..-2] : $2
30
+ return Project::Codehaus::CodehausProjectSvn.new(svn_id, svn_path, options[:jira_id])
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,53 @@
1
+ module MetaProject
2
+
3
+ # An ScmWeb instance is capable of generating URLs to various files and diffs
4
+ # in an online scm web interface.
5
+ class ScmWeb
6
+
7
+ # The variables to use in +uri_specs+ are:
8
+ #
9
+ # * path
10
+ # * revision
11
+ # * previous_revision
12
+ #
13
+ def initialize(overview_spec, history_spec, raw_spec, html_spec, diff_spec)
14
+ @overview_spec, @history_spec, @raw_spec, @html_spec, @diff_spec = overview_spec, history_spec, raw_spec, html_spec, diff_spec
15
+ end
16
+
17
+ def overview
18
+ file_uri(nil, nil, @overview_spec)
19
+ end
20
+
21
+ def history(path)
22
+ file_uri(path, nil, @history_spec)
23
+ end
24
+
25
+ def raw(path, revision)
26
+ file_uri(path, revision, @raw_spec)
27
+ end
28
+
29
+ def html(path, revision)
30
+ file_uri(path, revision, @html_spec)
31
+ end
32
+
33
+ def diff(path, revision, previous_revision)
34
+ file_uri(path, revision, @diff_spec, previous_revision)
35
+ end
36
+
37
+ private
38
+
39
+ # Returns the file URI for +path+. Valid options are:
40
+ #
41
+ # * :type => ["overview"|"html"|"diff"|"raw"]
42
+ # * :revision
43
+ # * :previous_revision
44
+ def file_uri(path="", revision=nil, spec=@overview_spec, previous_revision=nil)
45
+ begin
46
+ eval("\"#{spec}\"", binding)
47
+ rescue NameError
48
+ raise "Couldn't evaluate '#{spec}'"
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ require 'meta_project/tracker/base'
2
+ require 'meta_project/tracker/digit_issues'
3
+ require 'meta_project/tracker/issue'
4
+ require 'meta_project/tracker/trac'
5
+ require 'meta_project/tracker/xforge'
6
+ require 'meta_project/tracker/jira'
@@ -0,0 +1,18 @@
1
+ module MetaProject
2
+ module Tracker
3
+
4
+ # Tracker objects are responsible for interacting with issue trackers (bug trackers).
5
+ # They know how to recognise issue identifiers in strings (typically from SCM commit
6
+ # messages) and turn these into HTML links that point to the associated issue on an
7
+ # issue tracker installation running somewhere else.
8
+ class Base
9
+ def self.classes
10
+ [
11
+ ::Tracker::Jira::JiraProject,
12
+ ::Tracker::XForge::RubyForgeProject,
13
+ ::Tracker::Trac::TracProject
14
+ ]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module MetaProject
2
+ module Tracker
3
+ # This module should be included by trackers that follow a digit-based issue scheme
4
+ module DigitIssues
5
+ def identifier_regexp
6
+ /#(\d+)/
7
+ end
8
+
9
+ def identifier_examples
10
+ ["#1926", "#1446"]
11
+ end
12
+
13
+ # TODO: find a way to extract just the issue summaries so they can be stored in dc as an array
14
+ # embedded in the revision object. that way we don't alter the original commit message
15
+ def markup(text)
16
+ text.gsub(identifier_regexp) do |match|
17
+ issue_identifier = $1
18
+ issue = issue(issue_identifier)
19
+ issue ? "<a href=\"#{issue.uri}\">#{issue.summary}</a>" : "\##{issue_identifier}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module MetaProject
2
+ module Tracker
3
+ class Issue
4
+ attr_reader :uri, :summary
5
+
6
+ def initialize(uri, summary)
7
+ @uri, @summary = uri, summary
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ require 'meta_project/tracker/jira/jira_tracker'
@@ -0,0 +1,68 @@
1
+ require 'xmlrpc/client'
2
+
3
+ module MetaProject
4
+ module Tracker
5
+ module Jira
6
+ class JiraTracker
7
+ JIRA_API = "jira1"
8
+
9
+ def initialize(rooturl=nil, identifier=nil, username=nil, password=nil)
10
+ @rooturl, @identifier, @username, @password = rooturl, identifier, username, password
11
+ end
12
+
13
+ def identifier_regexp
14
+ /([A-Z]+-[\d]+)/
15
+ end
16
+
17
+ def identifier_examples
18
+ ["DC-420", "PICO-12"]
19
+ end
20
+
21
+ def overview
22
+ "#{@rooturl}/browse/#{@identifier}"
23
+ end
24
+
25
+ def issue(issue_identifier)
26
+ session = login
27
+ begin
28
+ issue = session.getIssue(issue_identifier)
29
+ Issue.new("#{@rooturl}/browse/#{issue_identifier}", issue["summary"])
30
+ rescue XMLRPC::FaultException
31
+ # Probably bad issue number
32
+ nil
33
+ end
34
+ end
35
+
36
+ def markup(text)
37
+ text.gsub(identifier_regexp) do |match|
38
+ issue_identifier = $1
39
+ issue = issue(issue_identifier)
40
+ issue ? "<a href=\"#{issue.uri}\">#{issue_identifier}: #{issue.summary}</a>" : issue_identifier
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def login
47
+ client = XMLRPC::Client.new2("#{@rooturl}/rpc/xmlrpc")
48
+ token = client.call("#{JIRA_API}.login", @username, @password)
49
+ Session.new(client, token)
50
+ end
51
+
52
+ # This wrapper around XMLRPC::Client that allows simpler method calls
53
+ # via method_missing and doesn't require to manage the token
54
+ class Session
55
+ def initialize(client, token)
56
+ @client, @token = client, token
57
+ end
58
+
59
+ def method_missing(sym, args, &block)
60
+ token_args = [@token] << args
61
+ xmlrpc_method = "#{JIRA_API}.#{sym.to_s}"
62
+ @client.call(xmlrpc_method, *token_args)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1 @@
1
+ require 'meta_project/tracker/trac/trac_tracker'
@@ -0,0 +1,29 @@
1
+ module MetaProject
2
+ module Tracker
3
+ module Trac
4
+ class TracTracker < ::MetaProject::Tracker::Base
5
+ include ::MetaProject::Tracker::DigitIssues
6
+
7
+ def initialize(trac_base_url)
8
+ @trac_base_url = trac_base_url
9
+ end
10
+
11
+ def overview
12
+ "#{@trac_base_url}/report"
13
+ end
14
+
15
+ def issue(issue_identifier)
16
+ issue_uri = "#{@trac_base_url}/ticket/#{issue_identifier}"
17
+ begin
18
+ html = open(issue_uri) { |data| data.read }
19
+ summary = html[/Ticket ##{issue_identifier}\s*<\/h1>\s*<h2>([^<]*)<\/h2>/n, 1]
20
+ ::MetaProject::Tracker::Issue.new(issue_uri, summary)
21
+ rescue OpenURI::HTTPError
22
+ nil
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ require 'meta_project/tracker/xforge/xforge_tracker'
2
+ require 'meta_project/tracker/xforge/ruby_forge_tracker'
3
+ require 'meta_project/tracker/xforge/source_forge_tracker'
@@ -0,0 +1,17 @@
1
+ module MetaProject
2
+ module Tracker
3
+ module XForge
4
+ class RubyForgeTracker < XForgeTracker
5
+
6
+ def subtracker_regexp
7
+ /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/
8
+ end
9
+
10
+ def issue_regexp(identifier)
11
+ /<a href=\"\/tracker\/index.php\?func=detail&aid=#{identifier}&group_id=\d+&atid=\d+\">([^<]*)<\/a>/
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module MetaProject
2
+ module Tracker
3
+ module XForge
4
+ class SourceForgeTracker < XForgeTracker
5
+
6
+ def subtracker_regexp
7
+ /\/tracker\/\?atid=(\d+)&amp;group_id=\d*&amp;func=browse/
8
+ end
9
+
10
+ def issue_regexp(identifier)
11
+ /<a href=\"\/tracker\/index.php\?func=detail&amp;aid=#{identifier}&amp;group_id=\d+&amp;atid=\d+\">([^<]*)<\/a>/
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,83 @@
1
+ require 'meta_project/tracker/base'
2
+ require 'meta_project/tracker/digit_issues'
3
+ require 'meta_project/tracker/issue'
4
+
5
+ module MetaProject
6
+ module Tracker
7
+ module XForge
8
+ class XForgeTracker < Base
9
+ include ::MetaProject::Tracker::DigitIssues
10
+
11
+ attr_accessor :overview, :project
12
+
13
+ # TODO: don't pass in project!! pass in hostname and id!
14
+ def initialize(overview, project)
15
+ @overview, @project = overview, project
16
+ end
17
+
18
+ # Finds an Issue by +identifier+
19
+ def issue(identifier)
20
+ sub_trackers = atids.collect {|atid| SubTracker.new(self, atid)}
21
+ sub_trackers.each do |sub_tracker|
22
+ issue = sub_tracker.issue(identifier)
23
+ return issue unless issue.nil?
24
+ end
25
+ nil
26
+ end
27
+
28
+ def markup(text)
29
+ text.gsub(identifier_regexp) do |match|
30
+ issue_identifier = $1
31
+ issue = issue(issue_identifier)
32
+ issue ? "<a href=\"#{issue.uri}\">\##{issue_identifier}: #{issue.summary}</a>" : "\##{issue_identifier}"
33
+ end
34
+ end
35
+
36
+ class SubTracker
37
+ attr_reader :uri
38
+
39
+ def initialize(tracker, atid)
40
+ @tracker = tracker
41
+ @atid = atid
42
+ # FIXME: This will only show open items.
43
+ @uri = "#{tracker.overview}&atid=#{atid}&func=browse"
44
+ end
45
+
46
+ def issue(identifier)
47
+ html = open(uri) { |data| data.read }
48
+
49
+ regexp = @tracker.issue_regexp(identifier)
50
+ if(html =~ regexp)
51
+ issue_uri = @tracker.project.group_id_uri("tracker/index.php", "&atid=#{@atid}&func=detail&aid=#{identifier}")
52
+ return Issue.new(issue_uri, $1)
53
+ end
54
+ nil
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ # The ids of the subtrackers
61
+ def atids
62
+ html = open(overview) { |data| data.read }
63
+
64
+ # TODO: there has to be a better way to extract the atids from the HTML!
65
+ atids = []
66
+ offset = 0
67
+ look_for_atid = true
68
+ while(look_for_atid)
69
+ match_data = subtracker_regexp.match(html[offset..-1])
70
+ if(match_data)
71
+ offset += match_data.begin(1)
72
+ atids << match_data[1]
73
+ else
74
+ look_for_atid = false
75
+ end
76
+ end
77
+ atids
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+ end