##// END OF EJS Templates
bugfix...
Nicolas Chuche -
r1858:90dc93b81c17
parent child
Show More
@@ -1,255 +1,254
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 [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
12 # reposman --svn-dir=/var/svn --redmine-host=redmine.example.net
13 # reposman -s /var/svn -r redmine.example.net -u http://svn.example.net
13 # reposman -s /var/svn -r redmine.example.net -u http://svn.example.net
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 #
22 #
23 # == Options
23 # == Options
24 #
24 #
25 # -o, --owner=OWNER owner of the repository. using the rails login
25 # -o, --owner=OWNER owner of the repository. using the rails login
26 # allow user to browse the repository within
26 # allow user to browse the repository within
27 # Redmine even for private project
27 # Redmine even for private project
28 # -u, --url=URL the base url Redmine will use to access your
28 # -u, --url=URL the base url Redmine will use to access your
29 # repositories. This option is used to automatically
29 # repositories. This option is used to automatically
30 # register the repositories in Redmine. The project
30 # register the repositories in Redmine. The project
31 # identifier will be appended to this url. Examples:
31 # identifier will be appended to this url. Examples:
32 # -u https://example.net/svn
32 # -u https://example.net/svn
33 # -u file:///var/svn/
33 # -u file:///var/svn/
34 # if this option isn't set, reposman won't register
34 # if this option isn't set, reposman won't register
35 # the repositories in Redmine
35 # the repositories in Redmine
36 # -c, --command=COMMAND use this command instead of "svnadmin create" to
36 # -c, --command=COMMAND use this command instead of "svnadmin create" to
37 # create a repository. This option can be used to
37 # create a repository. This option can be used to
38 # create non-subversion repositories
38 # create non-subversion repositories
39 # --scm SCM vendor used to register the repository in
39 # --scm SCM vendor used to register the repository in
40 # Redmine (default: Subversion). Can be one of the
40 # Redmine (default: Subversion). Can be one of the
41 # other supported SCM: Bazaar, Darcs, Filesystem,
41 # other supported SCM: Bazaar, Darcs, Filesystem,
42 # Git, Mercurial (case sensitive).
42 # Git, Mercurial (case sensitive).
43 # This option should be used when both options --url
43 # This option should be used when both options --url
44 # and --command are used.
44 # and --command are used.
45 # -f, --force force repository creation even if the project
45 # -f, --force force repository creation even if the project
46 # repository is already declared in Redmine
46 # repository is already declared in Redmine
47 # -t, --test only show what should be done
47 # -t, --test only show what should be done
48 # -h, --help show help and exit
48 # -h, --help show help and exit
49 # -v, --verbose verbose
49 # -v, --verbose verbose
50 # -V, --version print version and exit
50 # -V, --version print version and exit
51 # -q, --quiet no log
51 # -q, --quiet no log
52
52
53 require 'getoptlong'
53 require 'getoptlong'
54 require 'rdoc/usage'
54 require 'rdoc/usage'
55 require 'soap/wsdlDriver'
55 require 'soap/wsdlDriver'
56 require 'find'
56 require 'find'
57 require 'etc'
57 require 'etc'
58
58
59 Version = "1.1"
59 Version = "1.1"
60 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
60 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
61
61
62 opts = GetoptLong.new(
62 opts = GetoptLong.new(
63 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
63 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
64 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
64 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
65 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
65 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
66 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
66 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
67 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
67 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
68 ['--scm', GetoptLong::REQUIRED_ARGUMENT],
68 ['--scm', GetoptLong::REQUIRED_ARGUMENT],
69 ['--test', '-t', GetoptLong::NO_ARGUMENT],
69 ['--test', '-t', GetoptLong::NO_ARGUMENT],
70 ['--force', '-f', GetoptLong::NO_ARGUMENT],
70 ['--force', '-f', GetoptLong::NO_ARGUMENT],
71 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
71 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
72 ['--version', '-V', GetoptLong::NO_ARGUMENT],
72 ['--version', '-V', GetoptLong::NO_ARGUMENT],
73 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
73 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
74 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
74 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
75 )
75 )
76
76
77 $verbose = 0
77 $verbose = 0
78 $quiet = false
78 $quiet = false
79 $redmine_host = ''
79 $redmine_host = ''
80 $repos_base = ''
80 $repos_base = ''
81 $svn_owner = 'root'
81 $svn_owner = 'root'
82 $use_groupid = true
82 $use_groupid = true
83 $svn_url = false
83 $svn_url = false
84 $test = false
84 $test = false
85 $command = "svnadmin create"
85 $command = "svnadmin create"
86 $force = false
86 $force = false
87 $scm = 'Subversion'
87 $scm = 'Subversion'
88
88
89 def log(text,level=0, exit=false)
89 def log(text,level=0, exit=false)
90 return if $quiet or level > $verbose
90 puts text unless $quiet or level > $verbose
91 puts text
92 exit 1 if exit
91 exit 1 if exit
93 end
92 end
94
93
95 begin
94 begin
96 opts.each do |opt, arg|
95 opts.each do |opt, arg|
97 case opt
96 case opt
98 when '--svn-dir'; $repos_base = arg.dup
97 when '--svn-dir'; $repos_base = arg.dup
99 when '--redmine-host'; $redmine_host = arg.dup
98 when '--redmine-host'; $redmine_host = arg.dup
100 when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
99 when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
101 when '--url'; $svn_url = arg.dup
100 when '--url'; $svn_url = arg.dup
102 when '--scm'; $scm = arg.dup; log("Invalid SCM: #{$scm}", 0, true) unless SUPPORTED_SCM.include?($scm)
101 when '--scm'; $scm = arg.dup; log("Invalid SCM: #{$scm}", 0, true) unless SUPPORTED_SCM.include?($scm)
103 when '--command'; $command = arg.dup
102 when '--command'; $command = arg.dup
104 when '--verbose'; $verbose += 1
103 when '--verbose'; $verbose += 1
105 when '--test'; $test = true
104 when '--test'; $test = true
106 when '--force'; $force = true
105 when '--force'; $force = true
107 when '--version'; puts Version; exit
106 when '--version'; puts Version; exit
108 when '--help'; RDoc::usage
107 when '--help'; RDoc::usage
109 when '--quiet'; $quiet = true
108 when '--quiet'; $quiet = true
110 end
109 end
111 end
110 end
112 rescue
111 rescue
113 exit 1
112 exit 1
114 end
113 end
115
114
116 if $test
115 if $test
117 log("running in test mode")
116 log("running in test mode")
118 end
117 end
119
118
120 # Make sure command is overridden if SCM vendor is not Subversion
119 # Make sure command is overridden if SCM vendor is not Subversion
121 if $scm != 'Subversion' && $command == 'svnadmin create'
120 if $scm != 'Subversion' && $command == 'svnadmin create'
122 log("Please use --command option to specify how to create a #{$scm} repository.", 0, true)
121 log("Please use --command option to specify how to create a #{$scm} repository.", 0, true)
123 end
122 end
124
123
125
124
126 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
125 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
127
126
128 if ($redmine_host.empty? or $repos_base.empty?)
127 if ($redmine_host.empty? or $repos_base.empty?)
129 RDoc::usage
128 RDoc::usage
130 end
129 end
131
130
132 unless File.directory?($repos_base)
131 unless File.directory?($repos_base)
133 log("directory '#{$repos_base}' doesn't exists", 0, true)
132 log("directory '#{$repos_base}' doesn't exists", 0, true)
134 end
133 end
135
134
136 log("querying Redmine for projects...", 1);
135 log("querying Redmine for projects...", 1);
137
136
138 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
137 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
139 $redmine_host.gsub!(/\/$/, '')
138 $redmine_host.gsub!(/\/$/, '')
140
139
141 wsdl_url = "#{$redmine_host}/sys/service.wsdl";
140 wsdl_url = "#{$redmine_host}/sys/service.wsdl";
142
141
143 begin
142 begin
144 soap = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driver
143 soap = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driver
145 rescue => e
144 rescue => e
146 log("Unable to connect to #{wsdl_url} : #{e}", 0, true)
145 log("Unable to connect to #{wsdl_url} : #{e}", 0, true)
147 end
146 end
148
147
149 projects = soap.ProjectsWithRepositoryEnabled
148 projects = soap.ProjectsWithRepositoryEnabled
150
149
151 if projects.nil?
150 if projects.nil?
152 log('no project found, perhaps you forgot to "Enable WS for repository management"', 0, true)
151 log('no project found, perhaps you forgot to "Enable WS for repository management"', 0, true)
153 end
152 end
154
153
155 log("retrieved #{projects.size} projects", 1)
154 log("retrieved #{projects.size} projects", 1)
156
155
157 def set_owner_and_rights(project, repos_path, &block)
156 def set_owner_and_rights(project, repos_path, &block)
158 if RUBY_PLATFORM =~ /mswin/
157 if RUBY_PLATFORM =~ /mswin/
159 yield if block_given?
158 yield if block_given?
160 else
159 else
161 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : 0)
160 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : 0)
162 right = project.is_public ? 0775 : 0770
161 right = project.is_public ? 0775 : 0770
163 yield if block_given?
162 yield if block_given?
164 Find.find(repos_path) do |f|
163 Find.find(repos_path) do |f|
165 File.chmod right, f
164 File.chmod right, f
166 File.chown uid, gid, f
165 File.chown uid, gid, f
167 end
166 end
168 end
167 end
169 end
168 end
170
169
171 def other_read_right?(file)
170 def other_read_right?(file)
172 (File.stat(file).mode & 0007).zero? ? false : true
171 (File.stat(file).mode & 0007).zero? ? false : true
173 end
172 end
174
173
175 def owner_name(file)
174 def owner_name(file)
176 RUBY_PLATFORM =~ /mswin/ ?
175 RUBY_PLATFORM =~ /mswin/ ?
177 $svn_owner :
176 $svn_owner :
178 Etc.getpwuid( File.stat(file).uid ).name
177 Etc.getpwuid( File.stat(file).uid ).name
179 end
178 end
180
179
181 projects.each do |project|
180 projects.each do |project|
182 log("treating project #{project.name}", 1)
181 log("treating project #{project.name}", 1)
183
182
184 if project.identifier.empty?
183 if project.identifier.empty?
185 log("\tno identifier for project #{project.name}")
184 log("\tno identifier for project #{project.name}")
186 next
185 next
187 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
186 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
188 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
187 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
189 next;
188 next;
190 end
189 end
191
190
192 repos_path = $repos_base + "/" + project.identifier
191 repos_path = $repos_base + "/" + project.identifier
193
192
194 if File.directory?(repos_path)
193 if File.directory?(repos_path)
195
194
196 # we must verify that repository has the good owner and the good
195 # we must verify that repository has the good owner and the good
197 # rights before leaving
196 # rights before leaving
198 other_read = other_read_right?(repos_path)
197 other_read = other_read_right?(repos_path)
199 owner = owner_name(repos_path)
198 owner = owner_name(repos_path)
200 next if project.is_public == other_read and owner == $svn_owner
199 next if project.is_public == other_read and owner == $svn_owner
201
200
202 if $test
201 if $test
203 log("\tchange mode on #{repos_path}")
202 log("\tchange mode on #{repos_path}")
204 next
203 next
205 end
204 end
206
205
207 begin
206 begin
208 set_owner_and_rights(project, repos_path)
207 set_owner_and_rights(project, repos_path)
209 rescue Errno::EPERM => e
208 rescue Errno::EPERM => e
210 log("\tunable to change mode on #{repos_path} : #{e}\n")
209 log("\tunable to change mode on #{repos_path} : #{e}\n")
211 next
210 next
212 end
211 end
213
212
214 log("\tmode change on #{repos_path}");
213 log("\tmode change on #{repos_path}");
215
214
216 else
215 else
217 # if repository is already declared in redmine, we don't create
216 # if repository is already declared in redmine, we don't create
218 # unless user use -f with reposman
217 # unless user use -f with reposman
219 if $force == false and not project.repository.nil?
218 if $force == false and not project.repository.nil?
220 log("\trepository for project #{project.identifier} already exists in Redmine", 1)
219 log("\trepository for project #{project.identifier} already exists in Redmine", 1)
221 next
220 next
222 end
221 end
223
222
224 project.is_public ? File.umask(0002) : File.umask(0007)
223 project.is_public ? File.umask(0002) : File.umask(0007)
225
224
226 if $test
225 if $test
227 log("\tcreate repository #{repos_path}")
226 log("\tcreate repository #{repos_path}")
228 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
227 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
229 next
228 next
230 end
229 end
231
230
232 begin
231 begin
233 set_owner_and_rights(project, repos_path) do
232 set_owner_and_rights(project, repos_path) do
234 command = "#{$command} #{repos_path}"
233 command = "#{$command} #{repos_path}"
235 raise "#{command} failed" unless system( command )
234 raise "#{command} failed" unless system( command )
236 end
235 end
237 rescue => e
236 rescue => e
238 log("\tunable to create #{repos_path} : #{e}\n")
237 log("\tunable to create #{repos_path} : #{e}\n")
239 next
238 next
240 end
239 end
241
240
242 if $svn_url
241 if $svn_url
243 ret = soap.RepositoryCreated project.identifier, $scm, "#{$svn_url}#{project.identifier}"
242 ret = soap.RepositoryCreated project.identifier, $scm, "#{$svn_url}#{project.identifier}"
244 if ret > 0
243 if ret > 0
245 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
244 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
246 else
245 else
247 log("\trepository #{repos_path} not registered in Redmine. Look in your log to find why.");
246 log("\trepository #{repos_path} not registered in Redmine. Look in your log to find why.");
248 end
247 end
249 end
248 end
250
249
251 log("\trepository #{repos_path} created");
250 log("\trepository #{repos_path} created");
252 end
251 end
253
252
254 end
253 end
255
254
General Comments 0
You need to be logged in to leave comments. Login now