##// END OF EJS Templates
remove trailing white-spaces and empty lines from extra/svn/reposman.rb....
Toshi MARUYAMA -
r5705:574511fcedee
parent child
Show More
@@ -1,312 +1,308
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 # -k, --key=KEY use KEY as the Redmine API key
23 #
23 #
24 # == Options
24 # == Options
25 #
25 #
26 # -o, --owner=OWNER owner of the repository. using the rails login
26 # -o, --owner=OWNER owner of the repository. using the rails login
27 # allow user to browse the repository within
27 # allow user to browse the repository within
28 # Redmine even for private project. If you want to
28 # Redmine even for private project. If you want to
29 # share repositories through Redmine.pm, you need
29 # share repositories through Redmine.pm, you need
30 # to use the apache owner.
30 # to use the apache owner.
31 # -g, --group=GROUP group of the repository. (default: root)
31 # -g, --group=GROUP group of the repository. (default: root)
32 # --scm=SCM the kind of SCM repository you want to create (and
32 # --scm=SCM the kind of SCM repository you want to create (and
33 # register) in Redmine (default: Subversion).
33 # register) in Redmine (default: Subversion).
34 # reposman is able to create Git and Subversion
34 # reposman is able to create Git and Subversion
35 # repositories. For all other kind, you must specify
35 # repositories. For all other kind, you must specify
36 # a --command option
36 # a --command option
37 # -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
38 # repositories. This option is used to automatically
38 # repositories. This option is used to automatically
39 # register the repositories in Redmine. The project
39 # register the repositories in Redmine. The project
40 # identifier will be appended to this url. Examples:
40 # identifier will be appended to this url. Examples:
41 # -u https://example.net/svn
41 # -u https://example.net/svn
42 # -u file:///var/svn/
42 # -u file:///var/svn/
43 # if this option isn't set, reposman won't register
43 # if this option isn't set, reposman won't register
44 # the repositories in Redmine
44 # the repositories in Redmine
45 # -c, --command=COMMAND use this command instead of "svnadmin create" to
45 # -c, --command=COMMAND use this command instead of "svnadmin create" to
46 # create a repository. This option can be used to
46 # create a repository. This option can be used to
47 # create repositories other than subversion and git
47 # create repositories other than subversion and git
48 # kind.
48 # kind.
49 # This command override the default creation for git
49 # This command override the default creation for git
50 # and subversion.
50 # and subversion.
51 # -f, --force force repository creation even if the project
51 # -f, --force force repository creation even if the project
52 # repository is already declared in Redmine
52 # repository is already declared in Redmine
53 # -t, --test only show what should be done
53 # -t, --test only show what should be done
54 # -h, --help show help and exit
54 # -h, --help show help and exit
55 # -v, --verbose verbose
55 # -v, --verbose verbose
56 # -V, --version print version and exit
56 # -V, --version print version and exit
57 # -q, --quiet no log
57 # -q, --quiet no log
58 #
58 #
59 # == References
59 # == References
60 #
60 #
61 # 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
62
62
63
63
64 require 'getoptlong'
64 require 'getoptlong'
65 require 'rdoc/usage'
65 require 'rdoc/usage'
66 require 'find'
66 require 'find'
67 require 'etc'
67 require 'etc'
68
68
69 Version = "1.3"
69 Version = "1.3"
70 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
70 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
71
71
72 opts = GetoptLong.new(
72 opts = GetoptLong.new(
73 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
73 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
74 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
74 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
75 ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
75 ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
76 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
76 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
77 ['--group', '-g', GetoptLong::REQUIRED_ARGUMENT],
77 ['--group', '-g', GetoptLong::REQUIRED_ARGUMENT],
78 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
78 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
79 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
79 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
80 ['--scm', GetoptLong::REQUIRED_ARGUMENT],
80 ['--scm', GetoptLong::REQUIRED_ARGUMENT],
81 ['--test', '-t', GetoptLong::NO_ARGUMENT],
81 ['--test', '-t', GetoptLong::NO_ARGUMENT],
82 ['--force', '-f', GetoptLong::NO_ARGUMENT],
82 ['--force', '-f', GetoptLong::NO_ARGUMENT],
83 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
83 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
84 ['--version', '-V', GetoptLong::NO_ARGUMENT],
84 ['--version', '-V', GetoptLong::NO_ARGUMENT],
85 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
85 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
86 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
86 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
87 )
87 )
88
88
89 $verbose = 0
89 $verbose = 0
90 $quiet = false
90 $quiet = false
91 $redmine_host = ''
91 $redmine_host = ''
92 $repos_base = ''
92 $repos_base = ''
93 $svn_owner = 'root'
93 $svn_owner = 'root'
94 $svn_group = 'root'
94 $svn_group = 'root'
95 $use_groupid = true
95 $use_groupid = true
96 $svn_url = false
96 $svn_url = false
97 $test = false
97 $test = false
98 $force = false
98 $force = false
99 $scm = 'Subversion'
99 $scm = 'Subversion'
100
100
101 def log(text, options={})
101 def log(text, options={})
102 level = options[:level] || 0
102 level = options[:level] || 0
103 puts text unless $quiet or level > $verbose
103 puts text unless $quiet or level > $verbose
104 exit 1 if options[:exit]
104 exit 1 if options[:exit]
105 end
105 end
106
106
107 def system_or_raise(command)
107 def system_or_raise(command)
108 raise "\"#{command}\" failed" unless system command
108 raise "\"#{command}\" failed" unless system command
109 end
109 end
110
110
111 module SCM
111 module SCM
112
112
113 module Subversion
113 module Subversion
114 def self.create(path)
114 def self.create(path)
115 system_or_raise "svnadmin create #{path}"
115 system_or_raise "svnadmin create #{path}"
116 end
116 end
117 end
117 end
118
118
119 module Git
119 module Git
120 def self.create(path)
120 def self.create(path)
121 Dir.mkdir path
121 Dir.mkdir path
122 Dir.chdir(path) do
122 Dir.chdir(path) do
123 system_or_raise "git --bare init --shared"
123 system_or_raise "git --bare init --shared"
124 system_or_raise "git update-server-info"
124 system_or_raise "git update-server-info"
125 end
125 end
126 end
126 end
127 end
127 end
128
128
129 end
129 end
130
130
131 begin
131 begin
132 opts.each do |opt, arg|
132 opts.each do |opt, arg|
133 case opt
133 case opt
134 when '--svn-dir'; $repos_base = arg.dup
134 when '--svn-dir'; $repos_base = arg.dup
135 when '--redmine-host'; $redmine_host = arg.dup
135 when '--redmine-host'; $redmine_host = arg.dup
136 when '--key'; $api_key = arg.dup
136 when '--key'; $api_key = arg.dup
137 when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
137 when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
138 when '--group'; $svn_group = arg.dup; $use_groupid = false;
138 when '--group'; $svn_group = arg.dup; $use_groupid = false;
139 when '--url'; $svn_url = arg.dup
139 when '--url'; $svn_url = arg.dup
140 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)
141 when '--command'; $command = arg.dup
141 when '--command'; $command = arg.dup
142 when '--verbose'; $verbose += 1
142 when '--verbose'; $verbose += 1
143 when '--test'; $test = true
143 when '--test'; $test = true
144 when '--force'; $force = true
144 when '--force'; $force = true
145 when '--version'; puts Version; exit
145 when '--version'; puts Version; exit
146 when '--help'; RDoc::usage
146 when '--help'; RDoc::usage
147 when '--quiet'; $quiet = true
147 when '--quiet'; $quiet = true
148 end
148 end
149 end
149 end
150 rescue
150 rescue
151 exit 1
151 exit 1
152 end
152 end
153
153
154 if $test
154 if $test
155 log("running in test mode")
155 log("running in test mode")
156 end
156 end
157
157
158 # 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)
159 if $command.nil?
159 if $command.nil?
160 begin
160 begin
161 scm_module = SCM.const_get($scm)
161 scm_module = SCM.const_get($scm)
162 rescue
162 rescue
163 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)
164 end
164 end
165 end
165 end
166
166
167 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
167 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
168
168
169 if ($redmine_host.empty? or $repos_base.empty?)
169 if ($redmine_host.empty? or $repos_base.empty?)
170 RDoc::usage
170 RDoc::usage
171 end
171 end
172
172
173 unless File.directory?($repos_base)
173 unless File.directory?($repos_base)
174 log("directory '#{$repos_base}' doesn't exists", :exit => true)
174 log("directory '#{$repos_base}' doesn't exists", :exit => true)
175 end
175 end
176
176
177 begin
177 begin
178 require 'active_resource'
178 require 'active_resource'
179 rescue LoadError
179 rescue LoadError
180 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)
181 end
181 end
182
182
183 class Project < ActiveResource::Base
183 class Project < ActiveResource::Base
184 self.headers["User-agent"] = "Redmine repository manager/#{Version}"
184 self.headers["User-agent"] = "Redmine repository manager/#{Version}"
185 end
185 end
186
186
187 log("querying Redmine for projects...", :level => 1);
187 log("querying Redmine for projects...", :level => 1);
188
188
189 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
189 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
190 $redmine_host.gsub!(/\/$/, '')
190 $redmine_host.gsub!(/\/$/, '')
191
191
192 Project.site = "#{$redmine_host}/sys";
192 Project.site = "#{$redmine_host}/sys";
193
193
194 begin
194 begin
195 # Get all active projects that have the Repository module enabled
195 # Get all active projects that have the Repository module enabled
196 projects = Project.find(:all, :params => {:key => $api_key})
196 projects = Project.find(:all, :params => {:key => $api_key})
197 rescue => e
197 rescue => e
198 log("Unable to connect to #{Project.site}: #{e}", :exit => true)
198 log("Unable to connect to #{Project.site}: #{e}", :exit => true)
199 end
199 end
200
200
201 if projects.nil?
201 if projects.nil?
202 log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
202 log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
203 end
203 end
204
204
205 log("retrieved #{projects.size} projects", :level => 1)
205 log("retrieved #{projects.size} projects", :level => 1)
206
206
207 def set_owner_and_rights(project, repos_path, &block)
207 def set_owner_and_rights(project, repos_path, &block)
208 if mswin?
208 if mswin?
209 yield if block_given?
209 yield if block_given?
210 else
210 else
211 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
211 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
212 right = project.is_public ? 0775 : 0770
212 right = project.is_public ? 0775 : 0770
213 yield if block_given?
213 yield if block_given?
214 Find.find(repos_path) do |f|
214 Find.find(repos_path) do |f|
215 File.chmod right, f
215 File.chmod right, f
216 File.chown uid, gid, f
216 File.chown uid, gid, f
217 end
217 end
218 end
218 end
219 end
219 end
220
220
221 def other_read_right?(file)
221 def other_read_right?(file)
222 (File.stat(file).mode & 0007).zero? ? false : true
222 (File.stat(file).mode & 0007).zero? ? false : true
223 end
223 end
224
224
225 def owner_name(file)
225 def owner_name(file)
226 mswin? ?
226 mswin? ?
227 $svn_owner :
227 $svn_owner :
228 Etc.getpwuid( File.stat(file).uid ).name
228 Etc.getpwuid( File.stat(file).uid ).name
229 end
229 end
230
230
231 def mswin?
231 def mswin?
232 (RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
232 (RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
233 end
233 end
234
234
235 projects.each do |project|
235 projects.each do |project|
236 log("treating project #{project.name}", :level => 1)
236 log("treating project #{project.name}", :level => 1)
237
237
238 if project.identifier.empty?
238 if project.identifier.empty?
239 log("\tno identifier for project #{project.name}")
239 log("\tno identifier for project #{project.name}")
240 next
240 next
241 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
241 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
242 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
242 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
243 next;
243 next;
244 end
244 end
245
245
246 repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
246 repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
247
247
248 if File.directory?(repos_path)
248 if File.directory?(repos_path)
249
250 # we must verify that repository has the good owner and the good
249 # we must verify that repository has the good owner and the good
251 # rights before leaving
250 # rights before leaving
252 other_read = other_read_right?(repos_path)
251 other_read = other_read_right?(repos_path)
253 owner = owner_name(repos_path)
252 owner = owner_name(repos_path)
254 next if project.is_public == other_read and owner == $svn_owner
253 next if project.is_public == other_read and owner == $svn_owner
255
254
256 if $test
255 if $test
257 log("\tchange mode on #{repos_path}")
256 log("\tchange mode on #{repos_path}")
258 next
257 next
259 end
258 end
260
259
261 begin
260 begin
262 set_owner_and_rights(project, repos_path)
261 set_owner_and_rights(project, repos_path)
263 rescue Errno::EPERM => e
262 rescue Errno::EPERM => e
264 log("\tunable to change mode on #{repos_path} : #{e}\n")
263 log("\tunable to change mode on #{repos_path} : #{e}\n")
265 next
264 next
266 end
265 end
267
266
268 log("\tmode change on #{repos_path}");
267 log("\tmode change on #{repos_path}");
269
268
270 else
269 else
271 # if repository is already declared in redmine, we don't create
270 # if repository is already declared in redmine, we don't create
272 # unless user use -f with reposman
271 # unless user use -f with reposman
273 if $force == false and project.respond_to?(:repository)
272 if $force == false and project.respond_to?(:repository)
274 log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
273 log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
275 next
274 next
276 end
275 end
277
276
278 project.is_public ? File.umask(0002) : File.umask(0007)
277 project.is_public ? File.umask(0002) : File.umask(0007)
279
278
280 if $test
279 if $test
281 log("\tcreate repository #{repos_path}")
280 log("\tcreate repository #{repos_path}")
282 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
281 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
283 next
282 next
284 end
283 end
285
284
286 begin
285 begin
287 set_owner_and_rights(project, repos_path) do
286 set_owner_and_rights(project, repos_path) do
288 if scm_module.nil?
287 if scm_module.nil?
289 system_or_raise "#{$command} #{repos_path}"
288 system_or_raise "#{$command} #{repos_path}"
290 else
289 else
291 scm_module.create(repos_path)
290 scm_module.create(repos_path)
292 end
291 end
293 end
292 end
294 rescue => e
293 rescue => e
295 log("\tunable to create #{repos_path} : #{e}\n")
294 log("\tunable to create #{repos_path} : #{e}\n")
296 next
295 next
297 end
296 end
298
297
299 if $svn_url
298 if $svn_url
300 begin
299 begin
301 project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"}, :key => $api_key)
300 project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"}, :key => $api_key)
302 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
301 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
303 rescue => e
302 rescue => e
304 log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
303 log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
305 end
304 end
306 end
305 end
307
308 log("\trepository #{repos_path} created");
306 log("\trepository #{repos_path} created");
309 end
307 end
310
311 end
308 end
312 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now