##// END OF EJS Templates
SVN integration: reposman.rb can now register created repositories in Redmine, so that the administrator doesn't have to enter the repository url in Redmine once it's created....
Jean-Philippe Lang -
r847:cedca57620e3
parent child
Show More
@@ -1,25 +1,25
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class SysApi < ActionWebService::API::Base
19 19 api_method :projects,
20 20 :expects => [],
21 21 :returns => [[Project]]
22 22 api_method :repository_created,
23 :expects => [:int, :string],
23 :expects => [:string, :string],
24 24 :returns => [:int]
25 25 end
@@ -1,44 +1,47
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class SysController < ActionController::Base
19 19 wsdl_service_name 'Sys'
20 20 web_service_api SysApi
21 21 web_service_scaffold :invoke
22 22
23 23 before_invocation :check_enabled
24 24
25 # Returns the projects list, with their repositories
25 26 def projects
26 27 Project.find(:all, :include => :repository)
27 28 end
28 29
29 def repository_created(project_id, url)
30 project = Project.find_by_id(project_id)
30 # Registers a repository for the given project identifier
31 # (Subversion specific)
32 def repository_created(identifier, url)
33 project = Project.find_by_identifier(identifier)
34 # Do not create the repository if the project has already one
31 35 return 0 unless project && project.repository.nil?
32 logger.debug "Repository for #{project.name} created"
33 repository = Repository.new(:project => project, :url => url)
34 repository.root_url = url
36 logger.debug "Repository for #{project.name} was created"
37 repository = Repository.factory('Subversion', :project => project, :url => url)
35 38 repository.save
36 repository.id
39 repository.id || 0
37 40 end
38 41
39 42 protected
40 43
41 44 def check_enabled(name, args)
42 45 Setting.sys_api_enabled?
43 46 end
44 47 end
@@ -1,157 +1,213
1 1 #!/usr/bin/ruby
2 2
3 3 # == Synopsis
4 4 #
5 # reposman: manages your svn repositories with redMine
5 # reposman: manages your svn repositories with Redmine
6 6 #
7 7 # == Usage
8 8 #
9 9 # reposman [ -h | --help ] [ -v | --verbose ] [ -V | --version ] [ -q | --quiet ] -s /var/svn -r redmine.host.org
10 10 # example: reposman --svn-dir=/var/svn --redmine-host=redmine.mydomain.foo
11 11 # reposman -s /var/svn -r redmine.mydomain.foo
12 12 #
13 13 # == Arguments (mandatory)
14 14 #
15 15 # -s, --svn-dir=DIR
16 16 # use DIR as base directory for svn repositories
17 17 #
18 18 # -r, --redmine-host=HOST
19 # assume redMine is hosted on HOST.
19 # assume Redmine is hosted on HOST.
20 20 # you can use :
21 21 # * -r redmine.mydomain.foo (will add http://)
22 22 # * -r http://redmine.mydomain.foo
23 23 # * -r https://mydomain.foo/redmine
24 24 #
25 25 # == Options
26 26 #
27 # -o, --owner=OWNER
28 # owner of the repository. using the rails login allow user to browse
29 # the repository in Redmine even for private project
30 #
31 # -u, --url=URL
32 # the base url Redmine will use to access your repositories. This
33 # will be used to register the repository in Redmine so that user
34 # doesn't need to do anything. reposman will add the identifier to this url :
35 #
36 # -u https://my.svn.server/my/reposity/root # if the repository can be access by http
37 # -u file:///var/svn/ # if the repository is local
38 # if this option isn't set, reposman won't register the repository
39 #
40 #
27 41 # -h, --help:
28 42 # show help and exit
29 43 #
30 44 # -v, --verbose
31 45 # verbose
32 46 #
33 47 # -V, --version
34 48 # print version and exit
35 49 #
36 50 # -q, --quiet
37 51 # no log
38 52 #
39 53
40 54 require 'getoptlong'
41 55 require 'rdoc/usage'
42 56 require 'soap/wsdlDriver'
43 57 require 'find'
44 58 require 'etc'
45 59
46 60 Version = "1.0"
47 61
48 62 opts = GetoptLong.new(
49 63 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
50 64 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
65 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
66 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
51 67 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
52 68 ['--version', '-V', GetoptLong::NO_ARGUMENT],
53 69 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
54 70 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
55 71 )
56 72
57 73 $verbose = 0
58 74 $quiet = false
59 75 $redmine_host = ''
60 76 $repos_base = ''
77 $svn_owner = 'root'
78 $svn_url = false
61 79
62 80 def log(text,level=0, exit=false)
63 81 return if $quiet or level > $verbose
64 82 puts text
65 83 exit 1 if exit
66 84 end
67 85
68 86 begin
69 87 opts.each do |opt, arg|
70 88 case opt
71 89 when '--svn-dir'; $repos_base = arg.dup
72 90 when '--redmine-host'; $redmine_host = arg.dup
91 when '--owner'; $svn_owner = arg.dup
92 when '--url'; $svn_url = arg.dup
73 93 when '--verbose'; $verbose += 1
74 94 when '--version'; puts Version; exit
75 95 when '--help'; RDoc::usage
76 96 when '--quiet'; $quiet = true
77 97 end
78 98 end
79 99 rescue
80 100 exit 1
81 101 end
82 102
103 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
104
83 105 if ($redmine_host.empty? or $repos_base.empty?)
84 106 RDoc::usage
85 107 end
86 108
87 109 unless File.directory?($repos_base)
88 110 log("directory '#{$repos_base}' doesn't exists", 0, true)
89 111 end
90 112
91 log("querying redMine for projects...", 1);
113 log("querying Redmine for projects...", 1);
92 114
93 115 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
94 116 $redmine_host.gsub!(/\/$/, '')
95 117
96 118 wsdl_url = "#{$redmine_host}/sys/service.wsdl";
97 119
98 120 begin
99 121 soap = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driver
100 122 rescue => e
101 123 log("Unable to connect to #{wsdl_url} : #{e}", 0, true)
102 124 end
103 125
104 126 projects = soap.Projects
105 127
106 128 if projects.nil?
107 129 log('no project found, perhaps you forgot to "Enable WS for repository management"', 0, true)
108 130 end
109 131
110 132 log("retrieved #{projects.size} projects", 1)
111 133
112 projects.each do |p|
113 log("treating project #{p.name}", 1)
134 def set_owner_and_rights(project, repos_path, &block)
135 if RUBY_PLATFORM =~ /mswin/
136 yield if block_given?
137 else
138 uid, gid = Etc.getpwnam($svn_owner).uid, Etc.getgrnam(project.identifier).gid
139 right = project.is_public ? 0575 : 0570
140 yield if block_given?
141 Find.find(repos_path) do |f|
142 File.chmod right, f
143 File.chown uid, gid, f
144 end
145 end
146 end
147
148 def other_read_right?(file)
149 (File.stat(file).mode & 0007).zero? ? false : true
150 end
151
152 def owner_name(file)
153 RUBY_PLATFORM =~ /mswin/ ?
154 $svn_owner :
155 Etc.getpwuid( File.stat(file).uid ).name
156 end
114 157
115 if p.identifier.empty?
116 log("\tno identifier for project #{p.name}")
158 projects.each do |project|
159 log("treating project #{project.name}", 1)
160
161 if project.identifier.empty?
162 log("\tno identifier for project #{project.name}")
117 163 next
118 elsif not p.identifier.match(/^[a-z0-9\-]+$/)
119 log("\tinvalid identifier for project #{p.name} : #{p.identifier}");
164 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
165 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
120 166 next;
121 167 end
122 168
123 repos_path = $repos_base + "/" + p.identifier
169 repos_path = $repos_base + "/" + project.identifier
124 170
125 171 if File.directory?(repos_path)
126 172
127 other_read = (File.stat(repos_path).mode & 0007).zero? ? false : true
128 next if p.is_public == other_read
129
130 right = p.is_public ? 0775 : 0770
173 # we must verify that repository has the good owner and the good
174 # rights before leaving
175 other_read = other_read_right?(repos_path)
176 owner = owner_name(repos_path)
177 next if project.is_public == other_read and owner == $svn_owner
131 178
132 179 begin
133 Find.find(repos_path) { |f| File.chmod right, f }
180 set_owner_and_rights(project, repos_path)
134 181 rescue Errno::EPERM => e
135 182 log("\tunable to change mode on #{repos_path} : #{e}\n")
136 183 next
137 184 end
138 185
139 186 log("\tmode change on #{repos_path}");
140 187
141 188 else
142 p.is_public ? File.umask(0002) : File.umask(0007)
189 project.is_public ? File.umask(0202) : File.umask(0207)
143 190
144 191 begin
145 uid, gid = Etc.getpwnam("root").uid, Etc.getgrnam(p.identifier).gid
192 set_owner_and_rights(project, repos_path) do
146 193 raise "svnadmin create #{repos_path} failed" unless system("svnadmin", "create", repos_path)
147 Find.find(repos_path) { |f| File.chown uid, gid, f }
194 end
148 195 rescue => e
149 196 log("\tunable to create #{repos_path} : #{e}\n")
150 197 next
151 198 end
152 199
200 if $svn_url
201 ret = soap.RepositoryCreated project.identifier, "#{$svn_url}#{project.identifier}"
202 if ret > 0
203 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
204 else
205 log("\trepository #{repos_path} not registered in Redmine. Look in your log to find why.");
206 end
207 end
208
153 209 log("\trepository #{repos_path} created");
154 210 end
155 211
156 212 end
157 213
General Comments 0
You need to be logged in to leave comments. Login now