meta_project 0.4.12 → 0.4.13
Sign up to get free protection for your applications and to get access to all the features.
- 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,50 +1,50 @@
|
|
1
|
-
require 'meta_project/tracker/xforge'
|
2
|
-
|
3
|
-
module MetaProject
|
4
|
-
module Project
|
5
|
-
module XForge
|
6
|
-
class SourceForge < XForgeBase
|
7
|
-
|
8
|
-
def initialize(unix_name, cvs_mod=nil)
|
9
|
-
super("sourceforge.net", unix_name, cvs_mod)
|
10
|
-
end
|
11
|
-
|
12
|
-
def tracker_class
|
13
|
-
::MetaProject::Tracker::XForge::SourceForgeTracker
|
14
|
-
end
|
15
|
-
|
16
|
-
protected
|
17
|
-
|
18
|
-
def create_cvs(unix_name, mod)
|
19
|
-
RSCM::Cvs.new(":pserver:anonymous@cvs.sourceforge.net:/cvsroot/#{unix_name}", mod)
|
20
|
-
end
|
21
|
-
|
22
|
-
def create_view_cvs(unix_name, mod)
|
23
|
-
view_cvs = "http://cvs.sourceforge.net/viewcvs.py/"
|
24
|
-
unix_name_mod = "#{unix_name}/#{mod}"
|
25
|
-
project_path = "#{unix_name_mod}/\#{path}"
|
26
|
-
rev = "rev=\#{revision}"
|
27
|
-
|
28
|
-
dir = "#{view_cvs}#{project_path}"
|
29
|
-
history = "#{view_cvs}#{project_path}"
|
30
|
-
raw = "#{view_cvs}*checkout*/#{project_path}?#{rev}"
|
31
|
-
html = "#{history}?#{rev}&view=markup"
|
32
|
-
diff = "#{history}?r1=\#{previous_revision}&r2=\#{revision}"
|
33
|
-
|
34
|
-
|
35
|
-
child_dirs_pattern = /<img src="\/icons\/small\/dir.gif"\s+alt="\(dir\)"\s+border=0\s+width=16\s+height=16>[\r\n\s]*([^\/]+)\/<\/a>/
|
36
|
-
child_files_pattern = /href="[^\?]+\/([^\?]+)\?rev=([^&]+)&view=log">/
|
37
|
-
|
38
|
-
ScmWeb::Browser.new(dir, history, raw, html, diff, child_dirs_pattern, child_files_pattern)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Regexp used to find projects' home page
|
42
|
-
def home_page_regexp
|
43
|
-
# This seems a little volatile
|
44
|
-
/<A href=\"(\w*:\/\/[^\"]*)\"> Project Home Page<\/A>/
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
1
|
+
require 'meta_project/tracker/xforge'
|
2
|
+
|
3
|
+
module MetaProject
|
4
|
+
module Project
|
5
|
+
module XForge
|
6
|
+
class SourceForge < XForgeBase
|
7
|
+
|
8
|
+
def initialize(unix_name, cvs_mod=nil)
|
9
|
+
super("sourceforge.net", unix_name, cvs_mod)
|
10
|
+
end
|
11
|
+
|
12
|
+
def tracker_class
|
13
|
+
::MetaProject::Tracker::XForge::SourceForgeTracker
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def create_cvs(unix_name, mod)
|
19
|
+
RSCM::Cvs.new(":pserver:anonymous@cvs.sourceforge.net:/cvsroot/#{unix_name}", mod)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_view_cvs(unix_name, mod)
|
23
|
+
view_cvs = "http://cvs.sourceforge.net/viewcvs.py/"
|
24
|
+
unix_name_mod = "#{unix_name}/#{mod}"
|
25
|
+
project_path = "#{unix_name_mod}/\#{path}"
|
26
|
+
rev = "rev=\#{revision}"
|
27
|
+
|
28
|
+
dir = "#{view_cvs}#{project_path}"
|
29
|
+
history = "#{view_cvs}#{project_path}"
|
30
|
+
raw = "#{view_cvs}*checkout*/#{project_path}?#{rev}"
|
31
|
+
html = "#{history}?#{rev}&view=markup"
|
32
|
+
diff = "#{history}?r1=\#{previous_revision}&r2=\#{revision}"
|
33
|
+
|
34
|
+
|
35
|
+
child_dirs_pattern = /<img src="\/icons\/small\/dir.gif"\s+alt="\(dir\)"\s+border=0\s+width=16\s+height=16>[\r\n\s]*([^\/]+)\/<\/a>/
|
36
|
+
child_files_pattern = /href="[^\?]+\/([^\?]+)\?rev=([^&]+)&view=log">/
|
37
|
+
|
38
|
+
ScmWeb::Browser.new(dir, history, raw, html, diff, child_dirs_pattern, child_files_pattern)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Regexp used to find projects' home page
|
42
|
+
def home_page_regexp
|
43
|
+
# This seems a little volatile
|
44
|
+
/<A href=\"(\w*:\/\/[^\"]*)\"> Project Home Page<\/A>/
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
50
|
end
|
@@ -1,45 +1,45 @@
|
|
1
|
-
module MetaProject
|
2
|
-
module Project
|
3
|
-
module XForge
|
4
|
-
|
5
|
-
class XFile # :nodoc:
|
6
|
-
|
7
|
-
# extension => [mime_type, rubyforge_bin_type_id, rubyforge_src_type_id]
|
8
|
-
FILE_TYPES = {
|
9
|
-
".deb" => ["application/octet-stream", 1000],
|
10
|
-
|
11
|
-
# all of these can be source or binary
|
12
|
-
".rpm" => ["application/octet-stream", 2000, 5100],
|
13
|
-
".zip" => ["application/octet-stream", 3000, 5000],
|
14
|
-
".bz2" => ["application/octet-stream", 3100, 5010],
|
15
|
-
".gz" => ["application/octet-stream", 3110, 5020],
|
16
|
-
".jpg" => ["application/octet-stream", 8000],
|
17
|
-
".jpeg" => ["application/octet-stream", 8000],
|
18
|
-
".txt" => ["text/plain", 8100, 8100],
|
19
|
-
".html" => ["text/html", 8200, 8200],
|
20
|
-
".pdf" => ["application/octet-stream", 8300],
|
21
|
-
".ebuild" => ["application/octet-stream", 1300],
|
22
|
-
".exe" => ["application/octet-stream", 1100],
|
23
|
-
".dmg" => ["application/octet-stream", 1200],
|
24
|
-
".gem" => ["application/octet-stream", 1400],
|
25
|
-
".sig" => ["application/octet-stream", 8150]
|
26
|
-
}
|
27
|
-
FILE_TYPES.default = ["application/octet-stream", 9999, 5900] # default to "other", "other source"
|
28
|
-
|
29
|
-
attr_reader :basename, :ext, :content_type, :bin_type_id, :src_type_id
|
30
|
-
|
31
|
-
def initialize(filename)
|
32
|
-
@filename = filename
|
33
|
-
@basename = File.basename(filename)
|
34
|
-
@ext = File.extname(filename)
|
35
|
-
@content_type = FILE_TYPES[@ext][0]
|
36
|
-
@bin_type_id = FILE_TYPES[@ext][1]
|
37
|
-
end
|
38
|
-
|
39
|
-
def data
|
40
|
-
File.open(@filename, "rb") { |file| file.read }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
1
|
+
module MetaProject
|
2
|
+
module Project
|
3
|
+
module XForge
|
4
|
+
|
5
|
+
class XFile # :nodoc:
|
6
|
+
|
7
|
+
# extension => [mime_type, rubyforge_bin_type_id, rubyforge_src_type_id]
|
8
|
+
FILE_TYPES = {
|
9
|
+
".deb" => ["application/octet-stream", 1000],
|
10
|
+
|
11
|
+
# all of these can be source or binary
|
12
|
+
".rpm" => ["application/octet-stream", 2000, 5100],
|
13
|
+
".zip" => ["application/octet-stream", 3000, 5000],
|
14
|
+
".bz2" => ["application/octet-stream", 3100, 5010],
|
15
|
+
".gz" => ["application/octet-stream", 3110, 5020],
|
16
|
+
".jpg" => ["application/octet-stream", 8000],
|
17
|
+
".jpeg" => ["application/octet-stream", 8000],
|
18
|
+
".txt" => ["text/plain", 8100, 8100],
|
19
|
+
".html" => ["text/html", 8200, 8200],
|
20
|
+
".pdf" => ["application/octet-stream", 8300],
|
21
|
+
".ebuild" => ["application/octet-stream", 1300],
|
22
|
+
".exe" => ["application/octet-stream", 1100],
|
23
|
+
".dmg" => ["application/octet-stream", 1200],
|
24
|
+
".gem" => ["application/octet-stream", 1400],
|
25
|
+
".sig" => ["application/octet-stream", 8150]
|
26
|
+
}
|
27
|
+
FILE_TYPES.default = ["application/octet-stream", 9999, 5900] # default to "other", "other source"
|
28
|
+
|
29
|
+
attr_reader :basename, :ext, :content_type, :bin_type_id, :src_type_id
|
30
|
+
|
31
|
+
def initialize(filename)
|
32
|
+
@filename = filename
|
33
|
+
@basename = File.basename(filename)
|
34
|
+
@ext = File.extname(filename)
|
35
|
+
@content_type = FILE_TYPES[@ext][0]
|
36
|
+
@bin_type_id = FILE_TYPES[@ext][1]
|
37
|
+
end
|
38
|
+
|
39
|
+
def data
|
40
|
+
File.open(@filename, "rb") { |file| file.read }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
45
|
end
|
@@ -1,81 +1,81 @@
|
|
1
|
-
module MetaProject
|
2
|
-
module Project
|
3
|
-
module XForge
|
4
|
-
class XForgeBase < Base
|
5
|
-
|
6
|
-
attr_reader :host, :unix_name
|
7
|
-
|
8
|
-
# TODO: hash based constructor (big now)
|
9
|
-
def initialize(host, unix_name, cvs_mod)
|
10
|
-
@host = host
|
11
|
-
@unix_name = unix_name
|
12
|
-
@name = unix_name
|
13
|
-
@cvs_mod = cvs_mod
|
14
|
-
|
15
|
-
@tracker = tracker_class.new(group_id_uri("tracker"), self)
|
16
|
-
|
17
|
-
unless(cvs_mod.nil?)
|
18
|
-
@scm = create_cvs(unix_name, @cvs_mod)
|
19
|
-
@scm_web = create_view_cvs(unix_name, @cvs_mod)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_yaml_properties
|
24
|
-
["@host", "@unix_name"]
|
25
|
-
end
|
26
|
-
|
27
|
-
# Logs in and returns a Session
|
28
|
-
def login(user_name, password)
|
29
|
-
http = Net::HTTP.new(@host, 80)
|
30
|
-
|
31
|
-
login_response = http.start do |http|
|
32
|
-
data = [
|
33
|
-
"login=1",
|
34
|
-
"form_loginname=#{user_name}",
|
35
|
-
"form_pw=#{password}"
|
36
|
-
].join("&")
|
37
|
-
http.post("/account/login.php", data)
|
38
|
-
end
|
39
|
-
|
40
|
-
cookie = login_response["set-cookie"]
|
41
|
-
raise "Login failed" unless cookie
|
42
|
-
Session.new(@host, self, cookie)
|
43
|
-
end
|
44
|
-
|
45
|
-
# The group_id of this project
|
46
|
-
def group_id
|
47
|
-
unless(@group_id)
|
48
|
-
html = better_open(xforge_project_url).read
|
49
|
-
group_id_pattern = /project\/memberlist.php\?group_id=(\d+)/
|
50
|
-
@group_id = html[group_id_pattern, 1]
|
51
|
-
raise "Couldn't get group_id from #{xforge_project_url}. I was looking for /#{group_id_pattern.source}/" unless @group_id
|
52
|
-
end
|
53
|
-
@group_id
|
54
|
-
end
|
55
|
-
|
56
|
-
def xforge_project_url
|
57
|
-
"http://#{@host}/projects/#{@unix_name}/"
|
58
|
-
end
|
59
|
-
|
60
|
-
def group_id_uri(path, postfix="")
|
61
|
-
"http://#{@host}/#{path}/?group_id=#{group_id}#{postfix}"
|
62
|
-
end
|
63
|
-
|
64
|
-
# The home page of this project
|
65
|
-
def home_page
|
66
|
-
unless(@home_page)
|
67
|
-
html = better_open(xforge_project_url).read
|
68
|
-
@home_page = html[home_page_regexp, 1]
|
69
|
-
unless @home_page
|
70
|
-
STDERR.puts "WARNING: Couldn't get home_page from #{xforge_project_url}. I was looking for /#{home_page_regexp.source}/"
|
71
|
-
STDERR.puts "Will use #{xforge_project_url} as home page instead."
|
72
|
-
@home_page = xforge_project_url
|
73
|
-
end
|
74
|
-
end
|
75
|
-
@home_page
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
1
|
+
module MetaProject
|
2
|
+
module Project
|
3
|
+
module XForge
|
4
|
+
class XForgeBase < Base
|
5
|
+
|
6
|
+
attr_reader :host, :unix_name
|
7
|
+
|
8
|
+
# TODO: hash based constructor (big now)
|
9
|
+
def initialize(host, unix_name, cvs_mod)
|
10
|
+
@host = host
|
11
|
+
@unix_name = unix_name
|
12
|
+
@name = unix_name
|
13
|
+
@cvs_mod = cvs_mod
|
14
|
+
|
15
|
+
@tracker = tracker_class.new(group_id_uri("tracker"), self)
|
16
|
+
|
17
|
+
unless(cvs_mod.nil?)
|
18
|
+
@scm = create_cvs(unix_name, @cvs_mod)
|
19
|
+
@scm_web = create_view_cvs(unix_name, @cvs_mod)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_yaml_properties
|
24
|
+
["@host", "@unix_name"]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Logs in and returns a Session
|
28
|
+
def login(user_name, password)
|
29
|
+
http = Net::HTTP.new(@host, 80)
|
30
|
+
|
31
|
+
login_response = http.start do |http|
|
32
|
+
data = [
|
33
|
+
"login=1",
|
34
|
+
"form_loginname=#{user_name}",
|
35
|
+
"form_pw=#{password}"
|
36
|
+
].join("&")
|
37
|
+
http.post("/account/login.php", data)
|
38
|
+
end
|
39
|
+
|
40
|
+
cookie = login_response["set-cookie"]
|
41
|
+
raise "Login failed" unless cookie
|
42
|
+
Session.new(@host, self, cookie)
|
43
|
+
end
|
44
|
+
|
45
|
+
# The group_id of this project
|
46
|
+
def group_id
|
47
|
+
unless(@group_id)
|
48
|
+
html = better_open(xforge_project_url).read
|
49
|
+
group_id_pattern = /project\/memberlist.php\?group_id=(\d+)/
|
50
|
+
@group_id = html[group_id_pattern, 1]
|
51
|
+
raise "Couldn't get group_id from #{xforge_project_url}. I was looking for /#{group_id_pattern.source}/" unless @group_id
|
52
|
+
end
|
53
|
+
@group_id
|
54
|
+
end
|
55
|
+
|
56
|
+
def xforge_project_url
|
57
|
+
"http://#{@host}/projects/#{@unix_name}/"
|
58
|
+
end
|
59
|
+
|
60
|
+
def group_id_uri(path, postfix="")
|
61
|
+
"http://#{@host}/#{path}/?group_id=#{group_id}#{postfix}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# The home page of this project
|
65
|
+
def home_page
|
66
|
+
unless(@home_page)
|
67
|
+
html = better_open(xforge_project_url).read
|
68
|
+
@home_page = html[home_page_regexp, 1]
|
69
|
+
unless @home_page
|
70
|
+
STDERR.puts "WARNING: Couldn't get home_page from #{xforge_project_url}. I was looking for /#{home_page_regexp.source}/"
|
71
|
+
STDERR.puts "Will use #{xforge_project_url} as home page instead."
|
72
|
+
@home_page = xforge_project_url
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@home_page
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -1,36 +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[:trac_svn_root_url], svn_path)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Codehaus SVN
|
27
|
-
if(url =~ /http:\/\/svn.(.*).codehaus.org\/(.*)/)
|
28
|
-
unix_name = $1
|
29
|
-
svn_path = $2[-1..-1] == "/" ? $2[0..-2] : $2
|
30
|
-
return Project::Codehaus::CodehausProjectSvn.new(unix_name, svn_path, options[:jira_project_id])
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
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[:trac_svn_root_url], svn_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Codehaus SVN
|
27
|
+
if(url =~ /http:\/\/svn.(.*).codehaus.org\/(.*)/)
|
28
|
+
unix_name = $1
|
29
|
+
svn_path = $2[-1..-1] == "/" ? $2[0..-2] : $2
|
30
|
+
return Project::Codehaus::CodehausProjectSvn.new(unix_name, svn_path, options[:jira_project_id])
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
36
|
end
|
@@ -1,267 +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
|
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
|