##// END OF EJS Templates
Adds on optional API key to repositories management controller and reposman.rb....
Jean-Philippe Lang -
r3087:cf9bb2699fa1
parent child
Show More
@@ -1,67 +1,67
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class SysController < ActionController::Base
18 class SysController < ActionController::Base
19 before_filter :check_enabled
19 before_filter :check_enabled
20
20
21 def projects
21 def projects
22 p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier')
22 p = Project.active.has_module(:repository).find(:all, :include => :repository, :order => 'identifier')
23 render :xml => p.to_xml(:include => :repository)
23 render :xml => p.to_xml(:include => :repository)
24 end
24 end
25
25
26 def create_project_repository
26 def create_project_repository
27 project = Project.find(params[:id])
27 project = Project.find(params[:id])
28 if project.repository
28 if project.repository
29 render :nothing => true, :status => 409
29 render :nothing => true, :status => 409
30 else
30 else
31 logger.info "Repository for #{project.name} was reported to be created by #{request.remote_ip}."
31 logger.info "Repository for #{project.name} was reported to be created by #{request.remote_ip}."
32 project.repository = Repository.factory(params[:vendor], params[:repository])
32 project.repository = Repository.factory(params[:vendor], params[:repository])
33 if project.repository && project.repository.save
33 if project.repository && project.repository.save
34 render :xml => project.repository, :status => 201
34 render :xml => project.repository, :status => 201
35 else
35 else
36 render :nothing => true, :status => 422
36 render :nothing => true, :status => 422
37 end
37 end
38 end
38 end
39 end
39 end
40
40
41 def fetch_changesets
41 def fetch_changesets
42 projects = []
42 projects = []
43 if params[:id]
43 if params[:id]
44 projects << Project.active.has_module(:repository).find(params[:id])
44 projects << Project.active.has_module(:repository).find(params[:id])
45 else
45 else
46 projects = Project.active.has_module(:repository).find(:all, :include => :repository)
46 projects = Project.active.has_module(:repository).find(:all, :include => :repository)
47 end
47 end
48 projects.each do |project|
48 projects.each do |project|
49 if project.repository
49 if project.repository
50 project.repository.fetch_changesets
50 project.repository.fetch_changesets
51 end
51 end
52 end
52 end
53 render :nothing => true, :status => 200
53 render :nothing => true, :status => 200
54 rescue ActiveRecord::RecordNotFound
54 rescue ActiveRecord::RecordNotFound
55 render :nothing => true, :status => 404
55 render :nothing => true, :status => 404
56 end
56 end
57
57
58 protected
58 protected
59
59
60 def check_enabled
60 def check_enabled
61 User.current = nil
61 User.current = nil
62 unless Setting.sys_api_enabled?
62 unless Setting.sys_api_enabled? && params[:key].to_s == Setting.sys_api_key
63 render :nothing => 'Access denied. Repository management WS is disabled.', :status => 403
63 render :text => 'Access denied. Repository management WS is disabled or key is invalid.', :status => 403
64 return false
64 return false
65 end
65 end
66 end
66 end
67 end
67 end
@@ -1,29 +1,37
1 <% form_tag({:action => 'edit', :tab => 'repositories'}) do %>
1 <% form_tag({:action => 'edit', :tab => 'repositories'}) do %>
2
2
3 <div class="box tabular settings">
3 <div class="box tabular settings">
4 <p><%= setting_check_box :autofetch_changesets %></p>
4 <p><%= setting_check_box :autofetch_changesets %></p>
5
5
6 <p><%= setting_check_box :sys_api_enabled %></p>
6 <p><%= setting_check_box :sys_api_enabled,
7 :onclick => "if (this.checked) { Form.Element.enable('settings_sys_api_key'); } else { Form.Element.disable('settings_sys_api_key'); }" %></p>
8
9 <p><%= setting_text_field :sys_api_key, :size => 30,
10 :id => 'settings_sys_api_key',
11 :disabled => !Setting.sys_api_enabled?,
12 :label => :setting_mail_handler_api_key %>
13 <%= link_to_function l(:label_generate_key), "if ($('settings_sys_api_key').disabled == false) { $('settings_sys_api_key').value = randomKey(20) }" %>
14 </p>
7
15
8 <p><%= setting_multiselect(:enabled_scm, REDMINE_SUPPORTED_SCM) %></p>
16 <p><%= setting_multiselect(:enabled_scm, REDMINE_SUPPORTED_SCM) %></p>
9
17
10 <p><%= setting_text_field :repositories_encodings, :size => 60 %><br />
18 <p><%= setting_text_field :repositories_encodings, :size => 60 %><br />
11 <em><%= l(:text_comma_separated) %></em></p>
19 <em><%= l(:text_comma_separated) %></em></p>
12
20
13 <p><%= setting_select :commit_logs_encoding, Setting::ENCODINGS %></p>
21 <p><%= setting_select :commit_logs_encoding, Setting::ENCODINGS %></p>
14
22
15 <p><%= setting_text_field :repository_log_display_limit, :size => 6 %></p>
23 <p><%= setting_text_field :repository_log_display_limit, :size => 6 %></p>
16 </div>
24 </div>
17
25
18 <fieldset class="box tabular settings"><legend><%= l(:text_issues_ref_in_commit_messages) %></legend>
26 <fieldset class="box tabular settings"><legend><%= l(:text_issues_ref_in_commit_messages) %></legend>
19 <p><%= setting_text_field :commit_ref_keywords, :size => 30 %><br />
27 <p><%= setting_text_field :commit_ref_keywords, :size => 30 %><br />
20 <em><%= l(:text_comma_separated) %></em></p>
28 <em><%= l(:text_comma_separated) %></em></p>
21
29
22 <p><%= setting_text_field :commit_fix_keywords, :size => 30 %>
30 <p><%= setting_text_field :commit_fix_keywords, :size => 30 %>
23 &nbsp;<%= l(:label_applied_status) %>: <%= setting_select :commit_fix_status_id, [["", 0]] + IssueStatus.find(:all).collect{|status| [status.name, status.id.to_s]}, :label => false %>
31 &nbsp;<%= l(:label_applied_status) %>: <%= setting_select :commit_fix_status_id, [["", 0]] + IssueStatus.find(:all).collect{|status| [status.name, status.id.to_s]}, :label => false %>
24 &nbsp;<%= l(:field_done_ratio) %>: <%= setting_select :commit_fix_done_ratio, (0..10).to_a.collect {|r| ["#{r*10} %", "#{r*10}"] }, :blank => :label_no_change_option, :label => false %>
32 &nbsp;<%= l(:field_done_ratio) %>: <%= setting_select :commit_fix_done_ratio, (0..10).to_a.collect {|r| ["#{r*10} %", "#{r*10}"] }, :blank => :label_no_change_option, :label => false %>
25 <br /><em><%= l(:text_comma_separated) %></em></p>
33 <br /><em><%= l(:text_comma_separated) %></em></p>
26 </fieldset>
34 </fieldset>
27
35
28 <%= submit_tag l(:button_save) %>
36 <%= submit_tag l(:button_save) %>
29 <% end %>
37 <% end %>
@@ -1,176 +1,178
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18
18
19 # DO NOT MODIFY THIS FILE !!!
19 # DO NOT MODIFY THIS FILE !!!
20 # Settings can be defined through the application in Admin -> Settings
20 # Settings can be defined through the application in Admin -> Settings
21
21
22 app_title:
22 app_title:
23 default: Redmine
23 default: Redmine
24 app_subtitle:
24 app_subtitle:
25 default: Project management
25 default: Project management
26 welcome_text:
26 welcome_text:
27 default:
27 default:
28 login_required:
28 login_required:
29 default: 0
29 default: 0
30 self_registration:
30 self_registration:
31 default: '2'
31 default: '2'
32 lost_password:
32 lost_password:
33 default: 1
33 default: 1
34 password_min_length:
34 password_min_length:
35 format: int
35 format: int
36 default: 4
36 default: 4
37 attachment_max_size:
37 attachment_max_size:
38 format: int
38 format: int
39 default: 5120
39 default: 5120
40 issues_export_limit:
40 issues_export_limit:
41 format: int
41 format: int
42 default: 500
42 default: 500
43 activity_days_default:
43 activity_days_default:
44 format: int
44 format: int
45 default: 30
45 default: 30
46 per_page_options:
46 per_page_options:
47 default: '25,50,100'
47 default: '25,50,100'
48 mail_from:
48 mail_from:
49 default: redmine@example.net
49 default: redmine@example.net
50 bcc_recipients:
50 bcc_recipients:
51 default: 1
51 default: 1
52 plain_text_mail:
52 plain_text_mail:
53 default: 0
53 default: 0
54 text_formatting:
54 text_formatting:
55 default: textile
55 default: textile
56 wiki_compression:
56 wiki_compression:
57 default: ""
57 default: ""
58 default_language:
58 default_language:
59 default: en
59 default: en
60 host_name:
60 host_name:
61 default: localhost:3000
61 default: localhost:3000
62 protocol:
62 protocol:
63 default: http
63 default: http
64 feeds_limit:
64 feeds_limit:
65 format: int
65 format: int
66 default: 15
66 default: 15
67 # Maximum size of files that can be displayed
67 # Maximum size of files that can be displayed
68 # inline through the file viewer (in KB)
68 # inline through the file viewer (in KB)
69 file_max_size_displayed:
69 file_max_size_displayed:
70 format: int
70 format: int
71 default: 512
71 default: 512
72 diff_max_lines_displayed:
72 diff_max_lines_displayed:
73 format: int
73 format: int
74 default: 1500
74 default: 1500
75 enabled_scm:
75 enabled_scm:
76 serialized: true
76 serialized: true
77 default:
77 default:
78 - Subversion
78 - Subversion
79 - Darcs
79 - Darcs
80 - Mercurial
80 - Mercurial
81 - Cvs
81 - Cvs
82 - Bazaar
82 - Bazaar
83 - Git
83 - Git
84 autofetch_changesets:
84 autofetch_changesets:
85 default: 1
85 default: 1
86 sys_api_enabled:
86 sys_api_enabled:
87 default: 0
87 default: 0
88 sys_api_key:
89 default: ''
88 commit_ref_keywords:
90 commit_ref_keywords:
89 default: 'refs,references,IssueID'
91 default: 'refs,references,IssueID'
90 commit_fix_keywords:
92 commit_fix_keywords:
91 default: 'fixes,closes'
93 default: 'fixes,closes'
92 commit_fix_status_id:
94 commit_fix_status_id:
93 format: int
95 format: int
94 default: 0
96 default: 0
95 commit_fix_done_ratio:
97 commit_fix_done_ratio:
96 default: 100
98 default: 100
97 # autologin duration in days
99 # autologin duration in days
98 # 0 means autologin is disabled
100 # 0 means autologin is disabled
99 autologin:
101 autologin:
100 format: int
102 format: int
101 default: 0
103 default: 0
102 # date format
104 # date format
103 date_format:
105 date_format:
104 default: ''
106 default: ''
105 time_format:
107 time_format:
106 default: ''
108 default: ''
107 user_format:
109 user_format:
108 default: :firstname_lastname
110 default: :firstname_lastname
109 format: symbol
111 format: symbol
110 cross_project_issue_relations:
112 cross_project_issue_relations:
111 default: 0
113 default: 0
112 notified_events:
114 notified_events:
113 serialized: true
115 serialized: true
114 default:
116 default:
115 - issue_added
117 - issue_added
116 - issue_updated
118 - issue_updated
117 mail_handler_api_enabled:
119 mail_handler_api_enabled:
118 default: 0
120 default: 0
119 mail_handler_api_key:
121 mail_handler_api_key:
120 default:
122 default:
121 issue_list_default_columns:
123 issue_list_default_columns:
122 serialized: true
124 serialized: true
123 default:
125 default:
124 - tracker
126 - tracker
125 - status
127 - status
126 - priority
128 - priority
127 - subject
129 - subject
128 - assigned_to
130 - assigned_to
129 - updated_on
131 - updated_on
130 display_subprojects_issues:
132 display_subprojects_issues:
131 default: 1
133 default: 1
132 issue_done_ratio:
134 issue_done_ratio:
133 default: 'issue_field'
135 default: 'issue_field'
134 default_projects_public:
136 default_projects_public:
135 default: 1
137 default: 1
136 default_projects_modules:
138 default_projects_modules:
137 serialized: true
139 serialized: true
138 default:
140 default:
139 - issue_tracking
141 - issue_tracking
140 - time_tracking
142 - time_tracking
141 - news
143 - news
142 - documents
144 - documents
143 - files
145 - files
144 - wiki
146 - wiki
145 - repository
147 - repository
146 - boards
148 - boards
147 # Role given to a non-admin user who creates a project
149 # Role given to a non-admin user who creates a project
148 new_project_user_role_id:
150 new_project_user_role_id:
149 format: int
151 format: int
150 default: ''
152 default: ''
151 sequential_project_identifiers:
153 sequential_project_identifiers:
152 default: 0
154 default: 0
153 # encodings used to convert repository files content to UTF-8
155 # encodings used to convert repository files content to UTF-8
154 # multiple values accepted, comma separated
156 # multiple values accepted, comma separated
155 repositories_encodings:
157 repositories_encodings:
156 default: ''
158 default: ''
157 # encoding used to convert commit logs to UTF-8
159 # encoding used to convert commit logs to UTF-8
158 commit_logs_encoding:
160 commit_logs_encoding:
159 default: 'UTF-8'
161 default: 'UTF-8'
160 repository_log_display_limit:
162 repository_log_display_limit:
161 format: int
163 format: int
162 default: 100
164 default: 100
163 ui_theme:
165 ui_theme:
164 default: ''
166 default: ''
165 emails_footer:
167 emails_footer:
166 default: |-
168 default: |-
167 You have received this notification because you have either subscribed to it, or are involved in it.
169 You have received this notification because you have either subscribed to it, or are involved in it.
168 To change your notification preferences, please click here: http://hostname/my/account
170 To change your notification preferences, please click here: http://hostname/my/account
169 gravatar_enabled:
171 gravatar_enabled:
170 default: 0
172 default: 0
171 openid:
173 openid:
172 default: 0
174 default: 0
173 gravatar_default:
175 gravatar_default:
174 default: ''
176 default: ''
175 start_of_week:
177 start_of_week:
176 default: ''
178 default: ''
@@ -1,299 +1,306
1 #!/usr/bin/env ruby
1 #!/usr/bin/env ruby
2
2
3 # == Synopsis
3 # == Synopsis
4 #
4 #
5 # reposman: manages your repositories with Redmine
5 # reposman: manages your repositories with Redmine
6 #
6 #
7 # == Usage
7 # == Usage
8 #
8 #
9 # reposman [OPTIONS...] -s [DIR] -r [HOST]
9 # reposman [OPTIONS...] -s [DIR] -r [HOST]
10 #
10 #
11 # Examples:
11 # Examples:
12 # reposman --svn-dir=/var/svn --redmine-host=redmine.example.net --scm subversion
12 # reposman --svn-dir=/var/svn --redmine-host=redmine.example.net --scm subversion
13 # reposman -s /var/git -r redmine.example.net -u http://svn.example.net --scm git
13 # reposman -s /var/git -r redmine.example.net -u http://svn.example.net --scm git
14 #
14 #
15 # == Arguments (mandatory)
15 # == Arguments (mandatory)
16 #
16 #
17 # -s, --svn-dir=DIR use DIR as base directory for svn repositories
17 # -s, --svn-dir=DIR use DIR as base directory for svn repositories
18 # -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples:
18 # -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples:
19 # -r redmine.example.net
19 # -r redmine.example.net
20 # -r http://redmine.example.net
20 # -r http://redmine.example.net
21 # -r https://example.net/redmine
21 # -r https://example.net/redmine
22 # -k, --key=KEY use KEY as the Redmine API key
22 #
23 #
23 # == Options
24 # == Options
24 #
25 #
25 # -o, --owner=OWNER owner of the repository. using the rails login
26 # -o, --owner=OWNER owner of the repository. using the rails login
26 # allow user to browse the repository within
27 # allow user to browse the repository within
27 # Redmine even for private project. If you want to share repositories
28 # Redmine even for private project. If you want to
28 # through Redmine.pm, you need to use the apache owner.
29 # share repositories through Redmine.pm, you need
30 # to use the apache owner.
29 # -g, --group=GROUP group of the repository. (default: root)
31 # -g, --group=GROUP group of the repository. (default: root)
30 # --scm=SCM the kind of SCM repository you want to create (and register) in
32 # --scm=SCM the kind of SCM repository you want to create (and
31 # Redmine (default: Subversion). reposman is able to create Git
33 # register) in Redmine (default: Subversion).
32 # and Subversion repositories. For all other kind (Bazaar,
34 # reposman is able to create Git and Subversion
33 # Darcs, Filesystem, Mercurial) you must specify a --command option
35 # repositories. For all other kind, you must specify
36 # a --command option
34 # -u, --url=URL the base url Redmine will use to access your
37 # -u, --url=URL the base url Redmine will use to access your
35 # repositories. This option is used to automatically
38 # repositories. This option is used to automatically
36 # register the repositories in Redmine. The project
39 # register the repositories in Redmine. The project
37 # identifier will be appended to this url. Examples:
40 # identifier will be appended to this url. Examples:
38 # -u https://example.net/svn
41 # -u https://example.net/svn
39 # -u file:///var/svn/
42 # -u file:///var/svn/
40 # if this option isn't set, reposman won't register
43 # if this option isn't set, reposman won't register
41 # the repositories in Redmine
44 # the repositories in Redmine
42 # -c, --command=COMMAND use this command instead of "svnadmin create" to
45 # -c, --command=COMMAND use this command instead of "svnadmin create" to
43 # create a repository. This option can be used to
46 # create a repository. This option can be used to
44 # create repositories other than subversion and git kind.
47 # create repositories other than subversion and git
45 # This command override the default creation for git and subversion.
48 # kind.
49 # This command override the default creation for git
50 # and subversion.
46 # -f, --force force repository creation even if the project
51 # -f, --force force repository creation even if the project
47 # repository is already declared in Redmine
52 # repository is already declared in Redmine
48 # -t, --test only show what should be done
53 # -t, --test only show what should be done
49 # -h, --help show help and exit
54 # -h, --help show help and exit
50 # -v, --verbose verbose
55 # -v, --verbose verbose
51 # -V, --version print version and exit
56 # -V, --version print version and exit
52 # -q, --quiet no log
57 # -q, --quiet no log
53 #
58 #
54 # == References
59 # == References
55 #
60 #
56 # You can find more information on the redmine's wiki : http://www.redmine.org/wiki/redmine/HowTos
61 # You can find more information on the redmine's wiki : http://www.redmine.org/wiki/redmine/HowTos
57
62
58
63
59 require 'getoptlong'
64 require 'getoptlong'
60 require 'rdoc/usage'
65 require 'rdoc/usage'
61 require 'find'
66 require 'find'
62 require 'etc'
67 require 'etc'
63
68
64 Version = "1.3"
69 Version = "1.3"
65 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
70 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
66
71
67 opts = GetoptLong.new(
72 opts = GetoptLong.new(
68 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
73 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
69 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
74 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
75 ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
70 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
76 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
71 ['--group', '-g', GetoptLong::REQUIRED_ARGUMENT],
77 ['--group', '-g', GetoptLong::REQUIRED_ARGUMENT],
72 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
78 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
73 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
79 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
74 ['--scm', GetoptLong::REQUIRED_ARGUMENT],
80 ['--scm', GetoptLong::REQUIRED_ARGUMENT],
75 ['--test', '-t', GetoptLong::NO_ARGUMENT],
81 ['--test', '-t', GetoptLong::NO_ARGUMENT],
76 ['--force', '-f', GetoptLong::NO_ARGUMENT],
82 ['--force', '-f', GetoptLong::NO_ARGUMENT],
77 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
83 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
78 ['--version', '-V', GetoptLong::NO_ARGUMENT],
84 ['--version', '-V', GetoptLong::NO_ARGUMENT],
79 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
85 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
80 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
86 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
81 )
87 )
82
88
83 $verbose = 0
89 $verbose = 0
84 $quiet = false
90 $quiet = false
85 $redmine_host = ''
91 $redmine_host = ''
86 $repos_base = ''
92 $repos_base = ''
87 $svn_owner = 'root'
93 $svn_owner = 'root'
88 $svn_group = 'root'
94 $svn_group = 'root'
89 $use_groupid = true
95 $use_groupid = true
90 $svn_url = false
96 $svn_url = false
91 $test = false
97 $test = false
92 $force = false
98 $force = false
93 $scm = 'Subversion'
99 $scm = 'Subversion'
94
100
95 def log(text, options={})
101 def log(text, options={})
96 level = options[:level] || 0
102 level = options[:level] || 0
97 puts text unless $quiet or level > $verbose
103 puts text unless $quiet or level > $verbose
98 exit 1 if options[:exit]
104 exit 1 if options[:exit]
99 end
105 end
100
106
101 def system_or_raise(command)
107 def system_or_raise(command)
102 raise "\"#{command}\" failed" unless system command
108 raise "\"#{command}\" failed" unless system command
103 end
109 end
104
110
105 module SCM
111 module SCM
106
112
107 module Subversion
113 module Subversion
108 def self.create(path)
114 def self.create(path)
109 system_or_raise "svnadmin create #{path}"
115 system_or_raise "svnadmin create #{path}"
110 end
116 end
111 end
117 end
112
118
113 module Git
119 module Git
114 def self.create(path)
120 def self.create(path)
115 Dir.mkdir path
121 Dir.mkdir path
116 Dir.chdir(path) do
122 Dir.chdir(path) do
117 system_or_raise "git --bare init --shared"
123 system_or_raise "git --bare init --shared"
118 system_or_raise "git update-server-info"
124 system_or_raise "git update-server-info"
119 end
125 end
120 end
126 end
121 end
127 end
122
128
123 end
129 end
124
130
125 begin
131 begin
126 opts.each do |opt, arg|
132 opts.each do |opt, arg|
127 case opt
133 case opt
128 when '--svn-dir'; $repos_base = arg.dup
134 when '--svn-dir'; $repos_base = arg.dup
129 when '--redmine-host'; $redmine_host = arg.dup
135 when '--redmine-host'; $redmine_host = arg.dup
136 when '--key'; $api_key = arg.dup
130 when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
137 when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
131 when '--group'; $svn_group = arg.dup; $use_groupid = false;
138 when '--group'; $svn_group = arg.dup; $use_groupid = false;
132 when '--url'; $svn_url = arg.dup
139 when '--url'; $svn_url = arg.dup
133 when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm)
140 when '--scm'; $scm = arg.dup.capitalize; log("Invalid SCM: #{$scm}", :exit => true) unless SUPPORTED_SCM.include?($scm)
134 when '--command'; $command = arg.dup
141 when '--command'; $command = arg.dup
135 when '--verbose'; $verbose += 1
142 when '--verbose'; $verbose += 1
136 when '--test'; $test = true
143 when '--test'; $test = true
137 when '--force'; $force = true
144 when '--force'; $force = true
138 when '--version'; puts Version; exit
145 when '--version'; puts Version; exit
139 when '--help'; RDoc::usage
146 when '--help'; RDoc::usage
140 when '--quiet'; $quiet = true
147 when '--quiet'; $quiet = true
141 end
148 end
142 end
149 end
143 rescue
150 rescue
144 exit 1
151 exit 1
145 end
152 end
146
153
147 if $test
154 if $test
148 log("running in test mode")
155 log("running in test mode")
149 end
156 end
150
157
151 # Make sure command is overridden if SCM vendor is not handled internally (for the moment Subversion and Git)
158 # Make sure command is overridden if SCM vendor is not handled internally (for the moment Subversion and Git)
152 if $command.nil?
159 if $command.nil?
153 begin
160 begin
154 scm_module = SCM.const_get($scm)
161 scm_module = SCM.const_get($scm)
155 rescue
162 rescue
156 log("Please use --command option to specify how to create a #{$scm} repository.", :exit => true)
163 log("Please use --command option to specify how to create a #{$scm} repository.", :exit => true)
157 end
164 end
158 end
165 end
159
166
160 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
167 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
161
168
162 if ($redmine_host.empty? or $repos_base.empty?)
169 if ($redmine_host.empty? or $repos_base.empty?)
163 RDoc::usage
170 RDoc::usage
164 end
171 end
165
172
166 unless File.directory?($repos_base)
173 unless File.directory?($repos_base)
167 log("directory '#{$repos_base}' doesn't exists", :exit => true)
174 log("directory '#{$repos_base}' doesn't exists", :exit => true)
168 end
175 end
169
176
170 begin
177 begin
171 require 'activeresource'
178 require 'activeresource'
172 rescue LoadError
179 rescue LoadError
173 log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true)
180 log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true)
174 end
181 end
175
182
176 class Project < ActiveResource::Base; end
183 class Project < ActiveResource::Base; end
177
184
178 log("querying Redmine for projects...", :level => 1);
185 log("querying Redmine for projects...", :level => 1);
179
186
180 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
187 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
181 $redmine_host.gsub!(/\/$/, '')
188 $redmine_host.gsub!(/\/$/, '')
182
189
183 Project.site = "#{$redmine_host}/sys";
190 Project.site = "#{$redmine_host}/sys";
184
191
185 begin
192 begin
186 # Get all active projects that have the Repository module enabled
193 # Get all active projects that have the Repository module enabled
187 projects = Project.find(:all)
194 projects = Project.find(:all, :params => {:key => $api_key})
188 rescue => e
195 rescue => e
189 log("Unable to connect to #{Project.site}: #{e}", :exit => true)
196 log("Unable to connect to #{Project.site}: #{e}", :exit => true)
190 end
197 end
191
198
192 if projects.nil?
199 if projects.nil?
193 log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
200 log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
194 end
201 end
195
202
196 log("retrieved #{projects.size} projects", :level => 1)
203 log("retrieved #{projects.size} projects", :level => 1)
197
204
198 def set_owner_and_rights(project, repos_path, &block)
205 def set_owner_and_rights(project, repos_path, &block)
199 if RUBY_PLATFORM =~ /mswin/
206 if RUBY_PLATFORM =~ /mswin/
200 yield if block_given?
207 yield if block_given?
201 else
208 else
202 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
209 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
203 right = project.is_public ? 0775 : 0770
210 right = project.is_public ? 0775 : 0770
204 yield if block_given?
211 yield if block_given?
205 Find.find(repos_path) do |f|
212 Find.find(repos_path) do |f|
206 File.chmod right, f
213 File.chmod right, f
207 File.chown uid, gid, f
214 File.chown uid, gid, f
208 end
215 end
209 end
216 end
210 end
217 end
211
218
212 def other_read_right?(file)
219 def other_read_right?(file)
213 (File.stat(file).mode & 0007).zero? ? false : true
220 (File.stat(file).mode & 0007).zero? ? false : true
214 end
221 end
215
222
216 def owner_name(file)
223 def owner_name(file)
217 RUBY_PLATFORM =~ /mswin/ ?
224 RUBY_PLATFORM =~ /mswin/ ?
218 $svn_owner :
225 $svn_owner :
219 Etc.getpwuid( File.stat(file).uid ).name
226 Etc.getpwuid( File.stat(file).uid ).name
220 end
227 end
221
228
222 projects.each do |project|
229 projects.each do |project|
223 log("treating project #{project.name}", :level => 1)
230 log("treating project #{project.name}", :level => 1)
224
231
225 if project.identifier.empty?
232 if project.identifier.empty?
226 log("\tno identifier for project #{project.name}")
233 log("\tno identifier for project #{project.name}")
227 next
234 next
228 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
235 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
229 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
236 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
230 next;
237 next;
231 end
238 end
232
239
233 repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
240 repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
234
241
235 if File.directory?(repos_path)
242 if File.directory?(repos_path)
236
243
237 # we must verify that repository has the good owner and the good
244 # we must verify that repository has the good owner and the good
238 # rights before leaving
245 # rights before leaving
239 other_read = other_read_right?(repos_path)
246 other_read = other_read_right?(repos_path)
240 owner = owner_name(repos_path)
247 owner = owner_name(repos_path)
241 next if project.is_public == other_read and owner == $svn_owner
248 next if project.is_public == other_read and owner == $svn_owner
242
249
243 if $test
250 if $test
244 log("\tchange mode on #{repos_path}")
251 log("\tchange mode on #{repos_path}")
245 next
252 next
246 end
253 end
247
254
248 begin
255 begin
249 set_owner_and_rights(project, repos_path)
256 set_owner_and_rights(project, repos_path)
250 rescue Errno::EPERM => e
257 rescue Errno::EPERM => e
251 log("\tunable to change mode on #{repos_path} : #{e}\n")
258 log("\tunable to change mode on #{repos_path} : #{e}\n")
252 next
259 next
253 end
260 end
254
261
255 log("\tmode change on #{repos_path}");
262 log("\tmode change on #{repos_path}");
256
263
257 else
264 else
258 # if repository is already declared in redmine, we don't create
265 # if repository is already declared in redmine, we don't create
259 # unless user use -f with reposman
266 # unless user use -f with reposman
260 if $force == false and project.respond_to?(:repository)
267 if $force == false and project.respond_to?(:repository)
261 log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
268 log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
262 next
269 next
263 end
270 end
264
271
265 project.is_public ? File.umask(0002) : File.umask(0007)
272 project.is_public ? File.umask(0002) : File.umask(0007)
266
273
267 if $test
274 if $test
268 log("\tcreate repository #{repos_path}")
275 log("\tcreate repository #{repos_path}")
269 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
276 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
270 next
277 next
271 end
278 end
272
279
273 begin
280 begin
274 set_owner_and_rights(project, repos_path) do
281 set_owner_and_rights(project, repos_path) do
275 if scm_module.nil?
282 if scm_module.nil?
276 system_or_raise "#{$command} #{repos_path}"
283 system_or_raise "#{$command} #{repos_path}"
277 else
284 else
278 scm_module.create(repos_path)
285 scm_module.create(repos_path)
279 end
286 end
280 end
287 end
281 rescue => e
288 rescue => e
282 log("\tunable to create #{repos_path} : #{e}\n")
289 log("\tunable to create #{repos_path} : #{e}\n")
283 next
290 next
284 end
291 end
285
292
286 if $svn_url
293 if $svn_url
287 begin
294 begin
288 project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"})
295 project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"}, :key => $api_key)
289 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
296 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
290 rescue => e
297 rescue => e
291 log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
298 log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
292 end
299 end
293 end
300 end
294
301
295 log("\trepository #{repos_path} created");
302 log("\trepository #{repos_path} created");
296 end
303 end
297
304
298 end
305 end
299
306
@@ -1,71 +1,92
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'sys_controller'
19 require 'sys_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class SysController; def rescue_action(e) raise e end; end
22 class SysController; def rescue_action(e) raise e end; end
23
23
24 class SysControllerTest < ActionController::TestCase
24 class SysControllerTest < ActionController::TestCase
25 fixtures :projects, :repositories
25 fixtures :projects, :repositories
26
26
27 def setup
27 def setup
28 @controller = SysController.new
28 @controller = SysController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 Setting.sys_api_enabled = '1'
31 Setting.sys_api_enabled = '1'
32 Setting.enabled_scm = %w(Subversion Git)
32 Setting.enabled_scm = %w(Subversion Git)
33 end
33 end
34
34
35 def test_projects_with_repository_enabled
35 def test_projects_with_repository_enabled
36 get :projects
36 get :projects
37 assert_response :success
37 assert_response :success
38 assert_equal 'application/xml', @response.content_type
38 assert_equal 'application/xml', @response.content_type
39 with_options :tag => 'projects' do |test|
39 with_options :tag => 'projects' do |test|
40 test.assert_tag :children => { :count => Project.active.has_module(:repository).count }
40 test.assert_tag :children => { :count => Project.active.has_module(:repository).count }
41 end
41 end
42 end
42 end
43
43
44 def test_create_project_repository
44 def test_create_project_repository
45 assert_nil Project.find(4).repository
45 assert_nil Project.find(4).repository
46
46
47 post :create_project_repository, :id => 4,
47 post :create_project_repository, :id => 4,
48 :vendor => 'Subversion',
48 :vendor => 'Subversion',
49 :repository => { :url => 'file:///create/project/repository/subproject2'}
49 :repository => { :url => 'file:///create/project/repository/subproject2'}
50 assert_response :created
50 assert_response :created
51
51
52 r = Project.find(4).repository
52 r = Project.find(4).repository
53 assert r.is_a?(Repository::Subversion)
53 assert r.is_a?(Repository::Subversion)
54 assert_equal 'file:///create/project/repository/subproject2', r.url
54 assert_equal 'file:///create/project/repository/subproject2', r.url
55 end
55 end
56
56
57 def test_fetch_changesets
57 def test_fetch_changesets
58 get :fetch_changesets
58 get :fetch_changesets
59 assert_response :success
59 assert_response :success
60 end
60 end
61
61
62 def test_fetch_changesets_one_project
62 def test_fetch_changesets_one_project
63 get :fetch_changesets, :id => 'ecookbook'
63 get :fetch_changesets, :id => 'ecookbook'
64 assert_response :success
64 assert_response :success
65 end
65 end
66
66
67 def test_fetch_changesets_unknown_project
67 def test_fetch_changesets_unknown_project
68 get :fetch_changesets, :id => 'unknown'
68 get :fetch_changesets, :id => 'unknown'
69 assert_response 404
69 assert_response 404
70 end
70 end
71
72 def test_disabled_ws_should_respond_with_403_error
73 with_settings :sys_api_enabled => '0' do
74 get :projects
75 assert_response 403
76 end
77 end
78
79 def test_api_key
80 with_settings :sys_api_key => 'my_secret_key' do
81 get :projects, :key => 'my_secret_key'
82 assert_response :success
83 end
84 end
85
86 def test_wrong_key_should_respond_with_403_error
87 with_settings :sys_api_enabled => 'my_secret_key' do
88 get :projects, :key => 'wrong_key'
89 assert_response 403
90 end
91 end
71 end
92 end
General Comments 0
You need to be logged in to leave comments. Login now