meta_project 0.4.12 → 0.4.13
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 +283 -277
- data/MIT-LICENSE +21 -21
- data/README +130 -126
- data/Rakefile +152 -152
- data/doc/base_attrs.rdoc +2 -2
- data/lib/meta_project.rb +11 -11
- data/lib/meta_project/core_ext/open_uri.rb +22 -22
- data/lib/meta_project/core_ext/pathname.rb +36 -36
- data/lib/meta_project/core_ext/string.rb +4 -4
- data/lib/meta_project/http/multipart.rb +31 -31
- data/lib/meta_project/patois/parser.rb +98 -98
- data/lib/meta_project/project.rb +4 -4
- data/lib/meta_project/project/base.rb +8 -8
- data/lib/meta_project/project/codehaus.rb +1 -1
- data/lib/meta_project/project/codehaus/codehaus_project_svn.rb +30 -30
- data/lib/meta_project/project/trac.rb +1 -1
- data/lib/meta_project/project/trac/trac_project.rb +53 -53
- data/lib/meta_project/project/xforge.rb +5 -5
- data/lib/meta_project/project/xforge/ruby_forge.rb +46 -46
- data/lib/meta_project/project/xforge/session.rb +177 -177
- data/lib/meta_project/project/xforge/source_forge.rb +49 -49
- data/lib/meta_project/project/xforge/xfile.rb +44 -44
- data/lib/meta_project/project/xforge/xforge_base.rb +81 -81
- data/lib/meta_project/project_analyzer.rb +35 -35
- data/lib/meta_project/release/freshmeat.rb +267 -267
- data/lib/meta_project/release/raa.rb +572 -572
- data/lib/meta_project/scm_web.rb +1 -1
- data/lib/meta_project/scm_web/browser.rb +111 -111
- data/lib/meta_project/scm_web/pathname.rb +88 -88
- data/lib/meta_project/tracker.rb +6 -6
- data/lib/meta_project/tracker/base.rb +23 -23
- data/lib/meta_project/tracker/digit_issues.rb +33 -33
- data/lib/meta_project/tracker/issue.rb +56 -56
- data/lib/meta_project/tracker/jira.rb +2 -2
- data/lib/meta_project/tracker/jira/jira_issues.rb +34 -34
- data/lib/meta_project/tracker/jira/jira_tracker.rb +148 -123
- data/lib/meta_project/tracker/trac.rb +1 -1
- data/lib/meta_project/tracker/trac/trac_tracker.rb +32 -32
- data/lib/meta_project/tracker/xforge.rb +3 -3
- data/lib/meta_project/tracker/xforge/ruby_forge_tracker.rb +17 -17
- data/lib/meta_project/tracker/xforge/source_forge_tracker.rb +17 -17
- data/lib/meta_project/tracker/xforge/xforge_tracker.rb +190 -190
- data/lib/meta_project/version_parser.rb +52 -52
- data/lib/rake/contrib/xforge.rb +3 -3
- data/lib/rake/contrib/xforge/base.rb +64 -64
- data/lib/rake/contrib/xforge/news_publisher.rb +97 -97
- data/lib/rake/contrib/xforge/release.rb +134 -134
- metadata +4 -3
| @@ -1 +1 @@ | |
| 1 | 
            -
            require 'meta_project/tracker/trac/trac_tracker'
         | 
| 1 | 
            +
            require 'meta_project/tracker/trac/trac_tracker'
         | 
| @@ -1,33 +1,33 @@ | |
| 1 | 
            -
            module MetaProject
         | 
| 2 | 
            -
              module Tracker
         | 
| 3 | 
            -
                module Trac
         | 
| 4 | 
            -
                  class TracTracker < Base
         | 
| 5 | 
            -
                    include DigitIssues
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                    attr_accessor :trac_base_url
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                    def initialize(trac_base_url=nil)
         | 
| 10 | 
            -
                      @trac_base_url = trac_base_url
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
                    
         | 
| 13 | 
            -
                    def overview
         | 
| 14 | 
            -
                      "#{@trac_base_url}/report"
         | 
| 15 | 
            -
                    end
         | 
| 16 | 
            -
                    
         | 
| 17 | 
            -
                    def materialize(issue)
         | 
| 18 | 
            -
                      begin
         | 
| 19 | 
            -
                        url = "#{@trac_base_url}/ticket/#{issue.identifier}"
         | 
| 20 | 
            -
                        html = better_open(url).read
         | 
| 21 | 
            -
                        summary = html[/Ticket ##{issue.identifier}\s*<\/h1>\s*<h2>([^<]*)<\/h2>/n, 1]
         | 
| 22 | 
            -
                        issue.attributes[:summary] = summary
         | 
| 23 | 
            -
                        issue.attributes[:url] = url
         | 
| 24 | 
            -
                      rescue OpenURI::HTTPError => e
         | 
| 25 | 
            -
                        STDERR.puts e.message
         | 
| 26 | 
            -
                      end
         | 
| 27 | 
            -
                      issue
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
                    
         | 
| 30 | 
            -
                  end
         | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
              end
         | 
| 1 | 
            +
            module MetaProject
         | 
| 2 | 
            +
              module Tracker
         | 
| 3 | 
            +
                module Trac
         | 
| 4 | 
            +
                  class TracTracker < Base
         | 
| 5 | 
            +
                    include DigitIssues
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    attr_accessor :trac_base_url
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def initialize(trac_base_url=nil)
         | 
| 10 | 
            +
                      @trac_base_url = trac_base_url
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                    
         | 
| 13 | 
            +
                    def overview
         | 
| 14 | 
            +
                      "#{@trac_base_url}/report"
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                    
         | 
| 17 | 
            +
                    def materialize(issue)
         | 
| 18 | 
            +
                      begin
         | 
| 19 | 
            +
                        url = "#{@trac_base_url}/ticket/#{issue.identifier}"
         | 
| 20 | 
            +
                        html = better_open(url).read
         | 
| 21 | 
            +
                        summary = html[/Ticket ##{issue.identifier}\s*<\/h1>\s*<h2>([^<]*)<\/h2>/n, 1]
         | 
| 22 | 
            +
                        issue.attributes[:summary] = summary
         | 
| 23 | 
            +
                        issue.attributes[:url] = url
         | 
| 24 | 
            +
                      rescue OpenURI::HTTPError => e
         | 
| 25 | 
            +
                        STDERR.puts e.message
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
                      issue
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                    
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 33 | 
             
            end
         | 
| @@ -1,3 +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'
         | 
| 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'
         | 
| @@ -1,17 +1,17 @@ | |
| 1 | 
            -
            module MetaProject
         | 
| 2 | 
            -
              module Tracker
         | 
| 3 | 
            -
                module XForge
         | 
| 4 | 
            -
                  class RubyForgeTracker < XForgeTracker
         | 
| 5 | 
            -
             | 
| 6 | 
            -
                    def subtracker_pattern
         | 
| 7 | 
            -
                      /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/
         | 
| 8 | 
            -
                    end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                    def issue_summary_pattern(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
         | 
| 1 | 
            +
            module MetaProject
         | 
| 2 | 
            +
              module Tracker
         | 
| 3 | 
            +
                module XForge
         | 
| 4 | 
            +
                  class RubyForgeTracker < XForgeTracker
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                    def subtracker_pattern
         | 
| 7 | 
            +
                      /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def issue_summary_pattern(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
         | 
| @@ -1,17 +1,17 @@ | |
| 1 | 
            -
            module MetaProject
         | 
| 2 | 
            -
              module Tracker
         | 
| 3 | 
            -
                module XForge
         | 
| 4 | 
            -
                  class SourceForgeTracker < XForgeTracker
         | 
| 5 | 
            -
                    
         | 
| 6 | 
            -
                    def subtracker_pattern
         | 
| 7 | 
            -
                      /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/
         | 
| 8 | 
            -
                    end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                    def issue_summary_pattern(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
         | 
| 1 | 
            +
            module MetaProject
         | 
| 2 | 
            +
              module Tracker
         | 
| 3 | 
            +
                module XForge
         | 
| 4 | 
            +
                  class SourceForgeTracker < XForgeTracker
         | 
| 5 | 
            +
                    
         | 
| 6 | 
            +
                    def subtracker_pattern
         | 
| 7 | 
            +
                      /\/tracker\/\?atid=(\d+)&group_id=\d*&func=browse/
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def issue_summary_pattern(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
         | 
| @@ -1,191 +1,191 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            require 'meta_project/tracker/base'
         | 
| 3 | 
            -
            require 'meta_project/tracker/digit_issues'
         | 
| 4 | 
            -
            require 'meta_project/tracker/issue'
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            module MetaProject
         | 
| 7 | 
            -
              module Tracker
         | 
| 8 | 
            -
                module XForge
         | 
| 9 | 
            -
                  class XForgeTracker < Base
         | 
| 10 | 
            -
                    include DigitIssues
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                    attr_accessor :overview, :project
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                    # TODO: don't pass in project!! pass in hostname and id! This won't work from DC!!
         | 
| 15 | 
            -
                    def initialize(overview=nil, project=nil)
         | 
| 16 | 
            -
                      @overview, @project = overview, project
         | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                    # Finds an Issue by +identifier+
         | 
| 20 | 
            -
                    def issue(identifier)
         | 
| 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 materialize(issue)
         | 
| 29 | 
            -
                      issue
         | 
| 30 | 
            -
                    end
         | 
| 31 | 
            -
                    
         | 
| 32 | 
            -
                    def create(issue, user_name, password)
         | 
| 33 | 
            -
                      # TODO: get the subtracker atid or name from the issue's options
         | 
| 34 | 
            -
                      subtracker = sub_trackers[0]
         | 
| 35 | 
            -
                      subtracker.create(issue, user_name, password)
         | 
| 36 | 
            -
                    end
         | 
| 37 | 
            -
                    
         | 
| 38 | 
            -
                    class SubTracker
         | 
| 39 | 
            -
                      include HTTP::Multipart
         | 
| 40 | 
            -
                      
         | 
| 41 | 
            -
                      # Issue modification constants
         | 
| 42 | 
            -
                      OPEN = 1
         | 
| 43 | 
            -
                      CLOSED = 2
         | 
| 44 | 
            -
                      DELETED = 3
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                      def initialize(tracker, atid)
         | 
| 47 | 
            -
                        @tracker = tracker
         | 
| 48 | 
            -
                        @atid = atid
         | 
| 49 | 
            -
                        # FIXME: This will only show open items.
         | 
| 50 | 
            -
                        @baseurl = "#{tracker.overview}&atid=#{atid}"
         | 
| 51 | 
            -
                        @overview = "#{@baseurl}&func=browse"
         | 
| 52 | 
            -
                      end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                      def issue(identifier)
         | 
| 55 | 
            -
                        html = better_open(@overview).read
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                        issue_summary_pattern = @tracker.issue_summary_pattern(identifier)
         | 
| 58 | 
            -
                        if(html =~ issue_summary_pattern)
         | 
| 59 | 
            -
                          issue_url = @tracker.project.group_id_uri("tracker/index.php", "&atid=#{@atid}&func=detail&aid=#{identifier}")
         | 
| 60 | 
            -
                          issue_summary = $1.strip
         | 
| 61 | 
            -
                          return Issue.new(self, :identifier => identifier,:summary => issue_summary, :url => issue_url)
         | 
| 62 | 
            -
                        else
         | 
| 63 | 
            -
                          nil
         | 
| 64 | 
            -
                        end
         | 
| 65 | 
            -
                      end
         | 
| 66 | 
            -
                      
         | 
| 67 | 
            -
                      def create(issue, user_name, password)
         | 
| 68 | 
            -
                        session = @tracker.project.login(user_name, password)
         | 
| 69 | 
            -
                        
         | 
| 70 | 
            -
                        Net::HTTP.start(@tracker.project.host, 80) do |http|
         | 
| 71 | 
            -
                          query_hash = {
         | 
| 72 | 
            -
                            "func" => "postadd",
         | 
| 73 | 
            -
                            "category_id" => "100", # seems to be standard for all trackers
         | 
| 74 | 
            -
                            "artifact_group_id" => "100", # seems to be standard for all trackers
         | 
| 75 | 
            -
                            "summary" => issue.summary,
         | 
| 76 | 
            -
                            "details" => issue.detail,
         | 
| 77 | 
            -
                            "user_email" => "",
         | 
| 78 | 
            -
                          }
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                          target = "/news/submit.php" #TODO: use this?
         | 
| 81 | 
            -
                          response = post_multipart(http, @baseurl, query_hash, session.request_headers)
         | 
| 82 | 
            -
                          
         | 
| 83 | 
            -
                          # the post brings us back to the overview page, where the new issue is the last one
         | 
| 84 | 
            -
                          response.body.scan(/aid=([\d]+)/) do |a|
         | 
| 85 | 
            -
                            issue.attributes[:identifier] = a[0]
         | 
| 86 | 
            -
                          end
         | 
| 87 | 
            -
                        end
         | 
| 88 | 
            -
                        issue
         | 
| 89 | 
            -
                      end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                      def close(issue, user_name, password)
         | 
| 92 | 
            -
                        modify(issue, user_name, password, CLOSED)
         | 
| 93 | 
            -
                      end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                      def delete(issue, user_name, password)
         | 
| 96 | 
            -
                        modify(issue, user_name, password, DELETE)
         | 
| 97 | 
            -
                      end
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                    private
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                      def modify(issue, user_name, password, status)
         | 
| 102 | 
            -
                        session = @tracker.project.login(user_name, password)
         | 
| 103 | 
            -
                        
         | 
| 104 | 
            -
                        Net::HTTP.start(@tracker.project.host, 80) do |http|
         | 
| 105 | 
            -
                          query_hash = {
         | 
| 106 | 
            -
                            "group_id" => @tracker.project.group_id,
         | 
| 107 | 
            -
                            "atid" => @atid,
         | 
| 108 | 
            -
                            "func" => "postmod",
         | 
| 109 | 
            -
                            "$result[]" => "",
         | 
| 110 | 
            -
                            "artifact_id" => issue.identifier,
         | 
| 111 | 
            -
                            "new_artifact_type_id" => @atid,
         | 
| 112 | 
            -
                            "category_id" => "100", # None
         | 
| 113 | 
            -
                            "artifact_group_id" => "100", # None
         | 
| 114 | 
            -
                            "assigned_to" => "100", # None
         | 
| 115 | 
            -
                            "priority" => "3", # None
         | 
| 116 | 
            -
                            "status_id" => status,
         | 
| 117 | 
            -
                            "resolution_id" => "100",
         | 
| 118 | 
            -
                            "canned_respnse" => "100",
         | 
| 119 | 
            -
                            "summary" => issue.summary,
         | 
| 120 | 
            -
                            "details" => issue.detail
         | 
| 121 | 
            -
                          }
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                          target = "/tracker/index.php"
         | 
| 124 | 
            -
                          response = post_multipart(http, target, query_hash, session.request_headers)
         | 
| 125 | 
            -
             | 
| 126 | 
            -
                          close_pattern = /Updated successfully/
         | 
| 127 | 
            -
                          unless(response.body =~ close_pattern)
         | 
| 128 | 
            -
                            File.open("xforge_close.html", "w") {|io| io.write response.body}
         | 
| 129 | 
            -
                            STDERR.puts "WARNING: Failed to close issue \##{issue.identifier}. I was looking for /#{close_pattern.source}/. Response written to xforge_close.html"
         | 
| 130 | 
            -
                          end
         | 
| 131 | 
            -
                        end
         | 
| 132 | 
            -
                        issue
         | 
| 133 | 
            -
                      end
         | 
| 134 | 
            -
                    end
         | 
| 135 | 
            -
             | 
| 136 | 
            -
                  private
         | 
| 137 | 
            -
                  
         | 
| 138 | 
            -
                    def sub_trackers
         | 
| 139 | 
            -
                      @sub_trackers ||= atids.collect {|atid| SubTracker.new(self, atid)}
         | 
| 140 | 
            -
                    end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                    # The ids of the subtrackers
         | 
| 143 | 
            -
                    def atids
         | 
| 144 | 
            -
            #          headers = {
         | 
| 145 | 
            -
            #            "User-Agent" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4",
         | 
| 146 | 
            -
            #            "Accept" => "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
         | 
| 147 | 
            -
            #            "Accept-Language" => "en-us,en;q=0.5",
         | 
| 148 | 
            -
            #            "Accept-Encoding" => "gzip,deflate",
         | 
| 149 | 
            -
            #            "Accept-Charset" => "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
         | 
| 150 | 
            -
            #            "Keep-Alive" => "300",
         | 
| 151 | 
            -
            #            "Connection" => "close",
         | 
| 152 | 
            -
            #            "X-Requested-With" => "XMLHttpRequest",
         | 
| 153 | 
            -
            #            "X-Prototype-Version" => "1.3.1",
         | 
| 154 | 
            -
            #            "Content-Type" => "application/x-www-form-urlencoded",
         | 
| 155 | 
            -
            #            "Content-Length" => "0",
         | 
| 156 | 
            -
            #            "Cookie" => "author=AnonymousCoward; _session_id=975a583d513190522ce3aeba315552d0",
         | 
| 157 | 
            -
            #            "Pragma" => "no-cache",
         | 
| 158 | 
            -
            #            "Cache-Control" => "no-cache"
         | 
| 159 | 
            -
            #          }
         | 
| 160 | 
            -
                      
         | 
| 161 | 
            -
                      html = better_open(overview).read
         | 
| 162 | 
            -
                      STDERR.puts "The HTML returned from #{overview} was empty! This might be because the server is trying to fool us" if html == ""
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                      # TODO: there has to be a better way to extract the atids from the HTML!
         | 
| 165 | 
            -
                      atids = []
         | 
| 166 | 
            -
                      offset = 0
         | 
| 167 | 
            -
                      look_for_atid = true
         | 
| 168 | 
            -
                      while(look_for_atid)
         | 
| 169 | 
            -
                        match_data = subtracker_pattern.match(html[offset..-1])
         | 
| 170 | 
            -
                        if(match_data)
         | 
| 171 | 
            -
                          offset += match_data.begin(1)
         | 
| 172 | 
            -
                          atids << match_data[1]
         | 
| 173 | 
            -
                        else
         | 
| 174 | 
            -
                          look_for_atid = false
         | 
| 175 | 
            -
                        end
         | 
| 176 | 
            -
                      end
         | 
| 177 | 
            -
                      if atids.empty?
         | 
| 178 | 
            -
                        debug_file = "xforge_tracker_debug.html"
         | 
| 179 | 
            -
                        File.open(debug_file, "w"){|io| io.write html}
         | 
| 180 | 
            -
                        STDERR.puts "WARNING: No subtrackers found at #{overview}."
         | 
| 181 | 
            -
                        STDERR.puts "I was looking for /#{subtracker_pattern.source}/"
         | 
| 182 | 
            -
                        STDERR.puts "Please consider filing a bug report at http://rubyforge.org/tracker/?atid=3161&group_id=801&func=browse"
         | 
| 183 | 
            -
                        STDERR.puts "The HTML has been saved to #{debug_file}"
         | 
| 184 | 
            -
                      end
         | 
| 185 | 
            -
                      atids
         | 
| 186 | 
            -
                    end
         | 
| 187 | 
            -
             | 
| 188 | 
            -
                  end
         | 
| 189 | 
            -
                end
         | 
| 190 | 
            -
              end
         | 
| 1 | 
            +
             | 
| 2 | 
            +
            require 'meta_project/tracker/base'
         | 
| 3 | 
            +
            require 'meta_project/tracker/digit_issues'
         | 
| 4 | 
            +
            require 'meta_project/tracker/issue'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module MetaProject
         | 
| 7 | 
            +
              module Tracker
         | 
| 8 | 
            +
                module XForge
         | 
| 9 | 
            +
                  class XForgeTracker < Base
         | 
| 10 | 
            +
                    include DigitIssues
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    attr_accessor :overview, :project
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    # TODO: don't pass in project!! pass in hostname and id! This won't work from DC!!
         | 
| 15 | 
            +
                    def initialize(overview=nil, project=nil)
         | 
| 16 | 
            +
                      @overview, @project = overview, project
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    # Finds an Issue by +identifier+
         | 
| 20 | 
            +
                    def issue(identifier)
         | 
| 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 materialize(issue)
         | 
| 29 | 
            +
                      issue
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                    
         | 
| 32 | 
            +
                    def create(issue, user_name, password)
         | 
| 33 | 
            +
                      # TODO: get the subtracker atid or name from the issue's options
         | 
| 34 | 
            +
                      subtracker = sub_trackers[0]
         | 
| 35 | 
            +
                      subtracker.create(issue, user_name, password)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    
         | 
| 38 | 
            +
                    class SubTracker
         | 
| 39 | 
            +
                      include HTTP::Multipart
         | 
| 40 | 
            +
                      
         | 
| 41 | 
            +
                      # Issue modification constants
         | 
| 42 | 
            +
                      OPEN = 1
         | 
| 43 | 
            +
                      CLOSED = 2
         | 
| 44 | 
            +
                      DELETED = 3
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      def initialize(tracker, atid)
         | 
| 47 | 
            +
                        @tracker = tracker
         | 
| 48 | 
            +
                        @atid = atid
         | 
| 49 | 
            +
                        # FIXME: This will only show open items.
         | 
| 50 | 
            +
                        @baseurl = "#{tracker.overview}&atid=#{atid}"
         | 
| 51 | 
            +
                        @overview = "#{@baseurl}&func=browse"
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      def issue(identifier)
         | 
| 55 | 
            +
                        html = better_open(@overview).read
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                        issue_summary_pattern = @tracker.issue_summary_pattern(identifier)
         | 
| 58 | 
            +
                        if(html =~ issue_summary_pattern)
         | 
| 59 | 
            +
                          issue_url = @tracker.project.group_id_uri("tracker/index.php", "&atid=#{@atid}&func=detail&aid=#{identifier}")
         | 
| 60 | 
            +
                          issue_summary = $1.strip
         | 
| 61 | 
            +
                          return Issue.new(self, :identifier => identifier,:summary => issue_summary, :url => issue_url)
         | 
| 62 | 
            +
                        else
         | 
| 63 | 
            +
                          nil
         | 
| 64 | 
            +
                        end
         | 
| 65 | 
            +
                      end
         | 
| 66 | 
            +
                      
         | 
| 67 | 
            +
                      def create(issue, user_name, password)
         | 
| 68 | 
            +
                        session = @tracker.project.login(user_name, password)
         | 
| 69 | 
            +
                        
         | 
| 70 | 
            +
                        Net::HTTP.start(@tracker.project.host, 80) do |http|
         | 
| 71 | 
            +
                          query_hash = {
         | 
| 72 | 
            +
                            "func" => "postadd",
         | 
| 73 | 
            +
                            "category_id" => "100", # seems to be standard for all trackers
         | 
| 74 | 
            +
                            "artifact_group_id" => "100", # seems to be standard for all trackers
         | 
| 75 | 
            +
                            "summary" => issue.summary,
         | 
| 76 | 
            +
                            "details" => issue.detail,
         | 
| 77 | 
            +
                            "user_email" => "",
         | 
| 78 | 
            +
                          }
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                          target = "/news/submit.php" #TODO: use this?
         | 
| 81 | 
            +
                          response = post_multipart(http, @baseurl, query_hash, session.request_headers)
         | 
| 82 | 
            +
                          
         | 
| 83 | 
            +
                          # the post brings us back to the overview page, where the new issue is the last one
         | 
| 84 | 
            +
                          response.body.scan(/aid=([\d]+)/) do |a|
         | 
| 85 | 
            +
                            issue.attributes[:identifier] = a[0]
         | 
| 86 | 
            +
                          end
         | 
| 87 | 
            +
                        end
         | 
| 88 | 
            +
                        issue
         | 
| 89 | 
            +
                      end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                      def close(issue, user_name, password)
         | 
| 92 | 
            +
                        modify(issue, user_name, password, CLOSED)
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                      def delete(issue, user_name, password)
         | 
| 96 | 
            +
                        modify(issue, user_name, password, DELETE)
         | 
| 97 | 
            +
                      end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    private
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                      def modify(issue, user_name, password, status)
         | 
| 102 | 
            +
                        session = @tracker.project.login(user_name, password)
         | 
| 103 | 
            +
                        
         | 
| 104 | 
            +
                        Net::HTTP.start(@tracker.project.host, 80) do |http|
         | 
| 105 | 
            +
                          query_hash = {
         | 
| 106 | 
            +
                            "group_id" => @tracker.project.group_id,
         | 
| 107 | 
            +
                            "atid" => @atid,
         | 
| 108 | 
            +
                            "func" => "postmod",
         | 
| 109 | 
            +
                            "$result[]" => "",
         | 
| 110 | 
            +
                            "artifact_id" => issue.identifier,
         | 
| 111 | 
            +
                            "new_artifact_type_id" => @atid,
         | 
| 112 | 
            +
                            "category_id" => "100", # None
         | 
| 113 | 
            +
                            "artifact_group_id" => "100", # None
         | 
| 114 | 
            +
                            "assigned_to" => "100", # None
         | 
| 115 | 
            +
                            "priority" => "3", # None
         | 
| 116 | 
            +
                            "status_id" => status,
         | 
| 117 | 
            +
                            "resolution_id" => "100",
         | 
| 118 | 
            +
                            "canned_respnse" => "100",
         | 
| 119 | 
            +
                            "summary" => issue.summary,
         | 
| 120 | 
            +
                            "details" => issue.detail
         | 
| 121 | 
            +
                          }
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                          target = "/tracker/index.php"
         | 
| 124 | 
            +
                          response = post_multipart(http, target, query_hash, session.request_headers)
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                          close_pattern = /Updated successfully/
         | 
| 127 | 
            +
                          unless(response.body =~ close_pattern)
         | 
| 128 | 
            +
                            File.open("xforge_close.html", "w") {|io| io.write response.body}
         | 
| 129 | 
            +
                            STDERR.puts "WARNING: Failed to close issue \##{issue.identifier}. I was looking for /#{close_pattern.source}/. Response written to xforge_close.html"
         | 
| 130 | 
            +
                          end
         | 
| 131 | 
            +
                        end
         | 
| 132 | 
            +
                        issue
         | 
| 133 | 
            +
                      end
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  private
         | 
| 137 | 
            +
                  
         | 
| 138 | 
            +
                    def sub_trackers
         | 
| 139 | 
            +
                      @sub_trackers ||= atids.collect {|atid| SubTracker.new(self, atid)}
         | 
| 140 | 
            +
                    end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                    # The ids of the subtrackers
         | 
| 143 | 
            +
                    def atids
         | 
| 144 | 
            +
            #          headers = {
         | 
| 145 | 
            +
            #            "User-Agent" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4",
         | 
| 146 | 
            +
            #            "Accept" => "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
         | 
| 147 | 
            +
            #            "Accept-Language" => "en-us,en;q=0.5",
         | 
| 148 | 
            +
            #            "Accept-Encoding" => "gzip,deflate",
         | 
| 149 | 
            +
            #            "Accept-Charset" => "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
         | 
| 150 | 
            +
            #            "Keep-Alive" => "300",
         | 
| 151 | 
            +
            #            "Connection" => "close",
         | 
| 152 | 
            +
            #            "X-Requested-With" => "XMLHttpRequest",
         | 
| 153 | 
            +
            #            "X-Prototype-Version" => "1.3.1",
         | 
| 154 | 
            +
            #            "Content-Type" => "application/x-www-form-urlencoded",
         | 
| 155 | 
            +
            #            "Content-Length" => "0",
         | 
| 156 | 
            +
            #            "Cookie" => "author=AnonymousCoward; _session_id=975a583d513190522ce3aeba315552d0",
         | 
| 157 | 
            +
            #            "Pragma" => "no-cache",
         | 
| 158 | 
            +
            #            "Cache-Control" => "no-cache"
         | 
| 159 | 
            +
            #          }
         | 
| 160 | 
            +
                      
         | 
| 161 | 
            +
                      html = better_open(overview).read
         | 
| 162 | 
            +
                      STDERR.puts "The HTML returned from #{overview} was empty! This might be because the server is trying to fool us" if html == ""
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                      # TODO: there has to be a better way to extract the atids from the HTML!
         | 
| 165 | 
            +
                      atids = []
         | 
| 166 | 
            +
                      offset = 0
         | 
| 167 | 
            +
                      look_for_atid = true
         | 
| 168 | 
            +
                      while(look_for_atid)
         | 
| 169 | 
            +
                        match_data = subtracker_pattern.match(html[offset..-1])
         | 
| 170 | 
            +
                        if(match_data)
         | 
| 171 | 
            +
                          offset += match_data.begin(1)
         | 
| 172 | 
            +
                          atids << match_data[1]
         | 
| 173 | 
            +
                        else
         | 
| 174 | 
            +
                          look_for_atid = false
         | 
| 175 | 
            +
                        end
         | 
| 176 | 
            +
                      end
         | 
| 177 | 
            +
                      if atids.empty?
         | 
| 178 | 
            +
                        debug_file = "xforge_tracker_debug.html"
         | 
| 179 | 
            +
                        File.open(debug_file, "w"){|io| io.write html}
         | 
| 180 | 
            +
                        STDERR.puts "WARNING: No subtrackers found at #{overview}."
         | 
| 181 | 
            +
                        STDERR.puts "I was looking for /#{subtracker_pattern.source}/"
         | 
| 182 | 
            +
                        STDERR.puts "Please consider filing a bug report at http://rubyforge.org/tracker/?atid=3161&group_id=801&func=browse"
         | 
| 183 | 
            +
                        STDERR.puts "The HTML has been saved to #{debug_file}"
         | 
| 184 | 
            +
                      end
         | 
| 185 | 
            +
                      atids
         | 
| 186 | 
            +
                    end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                  end
         | 
| 189 | 
            +
                end
         | 
| 190 | 
            +
              end
         | 
| 191 191 | 
             
            end
         |