##// END OF EJS Templates
change owner rights to work with mod_perl authentication. add a test option that just connect to WS and say what should be done...
Nicolas Chuche -
r898:d6e8121ef1bd
parent child
Show More
@@ -1,213 +1,233
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 # == Synopsis
3 # == Synopsis
4 #
4 #
5 # reposman: manages your svn repositories with Redmine
5 # reposman: manages your svn repositories with Redmine
6 #
6 #
7 # == Usage
7 # == Usage
8 #
8 #
9 # reposman [ -h | --help ] [ -v | --verbose ] [ -V | --version ] [ -q | --quiet ] -s /var/svn -r redmine.host.org
9 # reposman [ -h | --help ] [ -v | --verbose ] [ -V | --version ] [ -q | --quiet ] -s /var/svn -r redmine.host.org
10 # example: reposman --svn-dir=/var/svn --redmine-host=redmine.mydomain.foo
10 # example: reposman --svn-dir=/var/svn --redmine-host=redmine.mydomain.foo
11 # reposman -s /var/svn -r redmine.mydomain.foo
11 # reposman -s /var/svn -r redmine.mydomain.foo
12 #
12 #
13 # == Arguments (mandatory)
13 # == Arguments (mandatory)
14 #
14 #
15 # -s, --svn-dir=DIR
15 # -s, --svn-dir=DIR
16 # use DIR as base directory for svn repositories
16 # use DIR as base directory for svn repositories
17 #
17 #
18 # -r, --redmine-host=HOST
18 # -r, --redmine-host=HOST
19 # assume Redmine is hosted on HOST.
19 # assume Redmine is hosted on HOST.
20 # you can use :
20 # you can use :
21 # * -r redmine.mydomain.foo (will add http://)
21 # * -r redmine.mydomain.foo (will add http://)
22 # * -r http://redmine.mydomain.foo
22 # * -r http://redmine.mydomain.foo
23 # * -r https://mydomain.foo/redmine
23 # * -r https://mydomain.foo/redmine
24 #
24 #
25 # == Options
25 # == Options
26 #
26 #
27 # -o, --owner=OWNER
27 # -o, --owner=OWNER
28 # owner of the repository. using the rails login allow user to browse
28 # owner of the repository. using the rails login allow user to browse
29 # the repository in Redmine even for private project
29 # the repository in Redmine even for private project
30 #
30 #
31 # -u, --url=URL
31 # -u, --url=URL
32 # the base url Redmine will use to access your repositories. This
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
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 :
34 # doesn't need to do anything. reposman will add the identifier to this url :
35 #
35 #
36 # -u https://my.svn.server/my/reposity/root # if the repository can be access by http
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
37 # -u file:///var/svn/ # if the repository is local
38 # if this option isn't set, reposman won't register the repository
38 # if this option isn't set, reposman won't register the repository
39 #
39 #
40 # -t, --test
41 # only show what should be done
40 #
42 #
41 # -h, --help:
43 # -h, --help:
42 # show help and exit
44 # show help and exit
43 #
45 #
44 # -v, --verbose
46 # -v, --verbose
45 # verbose
47 # verbose
46 #
48 #
47 # -V, --version
49 # -V, --version
48 # print version and exit
50 # print version and exit
49 #
51 #
50 # -q, --quiet
52 # -q, --quiet
51 # no log
53 # no log
52 #
54 #
53
55
54 require 'getoptlong'
56 require 'getoptlong'
55 require 'rdoc/usage'
57 require 'rdoc/usage'
56 require 'soap/wsdlDriver'
58 require 'soap/wsdlDriver'
57 require 'find'
59 require 'find'
58 require 'etc'
60 require 'etc'
59
61
60 Version = "1.0"
62 Version = "1.0"
61
63
62 opts = GetoptLong.new(
64 opts = GetoptLong.new(
63 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
65 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
64 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
66 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
65 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
67 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
66 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
68 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
69 ['--test', '-t', GetoptLong::NO_ARGUMENT],
67 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
70 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
68 ['--version', '-V', GetoptLong::NO_ARGUMENT],
71 ['--version', '-V', GetoptLong::NO_ARGUMENT],
69 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
72 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
70 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
73 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
71 )
74 )
72
75
73 $verbose = 0
76 $verbose = 0
74 $quiet = false
77 $quiet = false
75 $redmine_host = ''
78 $redmine_host = ''
76 $repos_base = ''
79 $repos_base = ''
77 $svn_owner = 'root'
80 $svn_owner = 'root'
78 $svn_url = false
81 $svn_url = false
82 $test = false
79
83
80 def log(text,level=0, exit=false)
84 def log(text,level=0, exit=false)
81 return if $quiet or level > $verbose
85 return if $quiet or level > $verbose
82 puts text
86 puts text
83 exit 1 if exit
87 exit 1 if exit
84 end
88 end
85
89
86 begin
90 begin
87 opts.each do |opt, arg|
91 opts.each do |opt, arg|
88 case opt
92 case opt
89 when '--svn-dir'; $repos_base = arg.dup
93 when '--svn-dir'; $repos_base = arg.dup
90 when '--redmine-host'; $redmine_host = arg.dup
94 when '--redmine-host'; $redmine_host = arg.dup
91 when '--owner'; $svn_owner = arg.dup
95 when '--owner'; $svn_owner = arg.dup
92 when '--url'; $svn_url = arg.dup
96 when '--url'; $svn_url = arg.dup
93 when '--verbose'; $verbose += 1
97 when '--verbose'; $verbose += 1
98 when '--test'; $test = true
94 when '--version'; puts Version; exit
99 when '--version'; puts Version; exit
95 when '--help'; RDoc::usage
100 when '--help'; RDoc::usage
96 when '--quiet'; $quiet = true
101 when '--quiet'; $quiet = true
97 end
102 end
98 end
103 end
99 rescue
104 rescue
100 exit 1
105 exit 1
101 end
106 end
102
107
108 if $test
109 log("running in test mode")
110 end
111
103 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
112 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
104
113
105 if ($redmine_host.empty? or $repos_base.empty?)
114 if ($redmine_host.empty? or $repos_base.empty?)
106 RDoc::usage
115 RDoc::usage
107 end
116 end
108
117
109 unless File.directory?($repos_base)
118 unless File.directory?($repos_base)
110 log("directory '#{$repos_base}' doesn't exists", 0, true)
119 log("directory '#{$repos_base}' doesn't exists", 0, true)
111 end
120 end
112
121
113 log("querying Redmine for projects...", 1);
122 log("querying Redmine for projects...", 1);
114
123
115 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
124 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
116 $redmine_host.gsub!(/\/$/, '')
125 $redmine_host.gsub!(/\/$/, '')
117
126
118 wsdl_url = "#{$redmine_host}/sys/service.wsdl";
127 wsdl_url = "#{$redmine_host}/sys/service.wsdl";
119
128
120 begin
129 begin
121 soap = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driver
130 soap = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driver
122 rescue => e
131 rescue => e
123 log("Unable to connect to #{wsdl_url} : #{e}", 0, true)
132 log("Unable to connect to #{wsdl_url} : #{e}", 0, true)
124 end
133 end
125
134
126 projects = soap.Projects
135 projects = soap.Projects
127
136
128 if projects.nil?
137 if projects.nil?
129 log('no project found, perhaps you forgot to "Enable WS for repository management"', 0, true)
138 log('no project found, perhaps you forgot to "Enable WS for repository management"', 0, true)
130 end
139 end
131
140
132 log("retrieved #{projects.size} projects", 1)
141 log("retrieved #{projects.size} projects", 1)
133
142
134 def set_owner_and_rights(project, repos_path, &block)
143 def set_owner_and_rights(project, repos_path, &block)
135 if RUBY_PLATFORM =~ /mswin/
144 if RUBY_PLATFORM =~ /mswin/
136 yield if block_given?
145 yield if block_given?
137 else
146 else
138 uid, gid = Etc.getpwnam($svn_owner).uid, Etc.getgrnam(project.identifier).gid
147 uid, gid = Etc.getpwnam($svn_owner).uid, Etc.getgrnam(project.identifier).gid
139 right = project.is_public ? 0575 : 0570
148 right = project.is_public ? 0775 : 0770
140 yield if block_given?
149 yield if block_given?
141 Find.find(repos_path) do |f|
150 Find.find(repos_path) do |f|
142 File.chmod right, f
151 File.chmod right, f
143 File.chown uid, gid, f
152 File.chown uid, gid, f
144 end
153 end
145 end
154 end
146 end
155 end
147
156
148 def other_read_right?(file)
157 def other_read_right?(file)
149 (File.stat(file).mode & 0007).zero? ? false : true
158 (File.stat(file).mode & 0007).zero? ? false : true
150 end
159 end
151
160
152 def owner_name(file)
161 def owner_name(file)
153 RUBY_PLATFORM =~ /mswin/ ?
162 RUBY_PLATFORM =~ /mswin/ ?
154 $svn_owner :
163 $svn_owner :
155 Etc.getpwuid( File.stat(file).uid ).name
164 Etc.getpwuid( File.stat(file).uid ).name
156 end
165 end
157
166
158 projects.each do |project|
167 projects.each do |project|
159 log("treating project #{project.name}", 1)
168 log("treating project #{project.name}", 1)
160
169
161 if project.identifier.empty?
170 if project.identifier.empty?
162 log("\tno identifier for project #{project.name}")
171 log("\tno identifier for project #{project.name}")
163 next
172 next
164 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
173 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
165 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
174 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
166 next;
175 next;
167 end
176 end
168
177
169 repos_path = $repos_base + "/" + project.identifier
178 repos_path = $repos_base + "/" + project.identifier
170
179
171 if File.directory?(repos_path)
180 if File.directory?(repos_path)
172
181
173 # we must verify that repository has the good owner and the good
182 # we must verify that repository has the good owner and the good
174 # rights before leaving
183 # rights before leaving
175 other_read = other_read_right?(repos_path)
184 other_read = other_read_right?(repos_path)
176 owner = owner_name(repos_path)
185 owner = owner_name(repos_path)
177 next if project.is_public == other_read and owner == $svn_owner
186 next if project.is_public == other_read and owner == $svn_owner
178
187
188 if $test
189 log("\tchange mode on #{repos_path}")
190 next
191 end
192
179 begin
193 begin
180 set_owner_and_rights(project, repos_path)
194 set_owner_and_rights(project, repos_path)
181 rescue Errno::EPERM => e
195 rescue Errno::EPERM => e
182 log("\tunable to change mode on #{repos_path} : #{e}\n")
196 log("\tunable to change mode on #{repos_path} : #{e}\n")
183 next
197 next
184 end
198 end
185
199
186 log("\tmode change on #{repos_path}");
200 log("\tmode change on #{repos_path}");
187
201
188 else
202 else
189 project.is_public ? File.umask(0202) : File.umask(0207)
203 project.is_public ? File.umask(0002) : File.umask(0007)
204
205 if $test
206 log("\tcreate repository #{repos_path}")
207 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
208 next
209 end
190
210
191 begin
211 begin
192 set_owner_and_rights(project, repos_path) do
212 set_owner_and_rights(project, repos_path) do
193 raise "svnadmin create #{repos_path} failed" unless system("svnadmin", "create", repos_path)
213 raise "svnadmin create #{repos_path} failed" unless system("svnadmin", "create", repos_path)
194 end
214 end
195 rescue => e
215 rescue => e
196 log("\tunable to create #{repos_path} : #{e}\n")
216 log("\tunable to create #{repos_path} : #{e}\n")
197 next
217 next
198 end
218 end
199
219
200 if $svn_url
220 if $svn_url
201 ret = soap.RepositoryCreated project.identifier, "#{$svn_url}#{project.identifier}"
221 ret = soap.RepositoryCreated project.identifier, "#{$svn_url}#{project.identifier}"
202 if ret > 0
222 if ret > 0
203 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
223 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
204 else
224 else
205 log("\trepository #{repos_path} not registered in Redmine. Look in your log to find why.");
225 log("\trepository #{repos_path} not registered in Redmine. Look in your log to find why.");
206 end
226 end
207 end
227 end
208
228
209 log("\trepository #{repos_path} created");
229 log("\trepository #{repos_path} created");
210 end
230 end
211
231
212 end
232 end
213
233
General Comments 0
You need to be logged in to leave comments. Login now