##// END OF EJS Templates
Fixed #set_scm in reposman (#10837)....
Jean-Philippe Lang -
r9492:a59257dfb69c
parent child
Show More
@@ -1,288 +1,288
1 1 #!/usr/bin/env ruby
2 2
3 3 require 'optparse'
4 4 require 'find'
5 5 require 'etc'
6 6
7 7 Version = "1.4"
8 8 SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
9 9
10 10 $verbose = 0
11 11 $quiet = false
12 12 $redmine_host = ''
13 13 $repos_base = ''
14 14 $svn_owner = 'root'
15 15 $svn_group = 'root'
16 16 $use_groupid = true
17 17 $svn_url = false
18 18 $test = false
19 19 $force = false
20 20 $scm = 'Subversion'
21 21
22 22 def log(text, options={})
23 23 level = options[:level] || 0
24 24 puts text unless $quiet or level > $verbose
25 25 exit 1 if options[:exit]
26 26 end
27 27
28 28 def system_or_raise(command)
29 29 raise "\"#{command}\" failed" unless system command
30 30 end
31 31
32 32 module SCM
33 33
34 34 module Subversion
35 35 def self.create(path)
36 36 system_or_raise "svnadmin create #{path}"
37 37 end
38 38 end
39 39
40 40 module Git
41 41 def self.create(path)
42 42 Dir.mkdir path
43 43 Dir.chdir(path) do
44 44 system_or_raise "git --bare init --shared"
45 45 system_or_raise "git update-server-info"
46 46 end
47 47 end
48 48 end
49 49
50 50 end
51 51
52 52 def read_key_from_file(filename)
53 53 begin
54 54 $api_key = File.read(filename).strip
55 55 rescue Exception => e
56 56 $stderr.puts "Unable to read the key from #{filename}: #{e.message}"
57 57 exit 1
58 58 end
59 59 end
60 60
61 61 def set_scm(scm)
62 $scm = v.capitalize
62 $scm = scm.capitalize
63 63 unless SUPPORTED_SCM.include?($scm)
64 64 log("Invalid SCM: #{$scm}\nValid SCM are: #{SUPPORTED_SCM.join(', ')}", :exit => true)
65 65 end
66 66 end
67 67
68 68 optparse = OptionParser.new do |opts|
69 69 opts.banner = "Usage: reposman.rb [OPTIONS...] -s [DIR] -r [HOST] -k [KEY]"
70 70 opts.separator("")
71 71 opts.separator("Manages your repositories with Redmine.")
72 72 opts.separator("")
73 73 opts.separator("Required arguments:")
74 74 opts.on("-s", "--svn-dir DIR", "use DIR as base directory for svn repositories") {|v| $repos_base = v}
75 75 opts.on("-r", "--redmine-host HOST","assume Redmine is hosted on HOST. Examples:",
76 76 " -r redmine.example.net",
77 77 " -r http://redmine.example.net",
78 78 " -r https://redmine.example.net") {|v| $redmine_host = v}
79 79 opts.on("-k", "--key KEY", "use KEY as the Redmine API key",
80 80 "(you can use --key-file option as an alternative)") {|v| $api_key = v}
81 81 opts.separator("")
82 82 opts.separator("Options:")
83 83 opts.on("-o", "--owner OWNER", "owner of the repository. using the rails login",
84 84 "allows users to browse the repository within",
85 85 "Redmine even for private projects. If you want to",
86 86 "share repositories through Redmine.pm, you need",
87 87 "to use the apache owner.") {|v| $svn_owner = v; $use_groupid = false}
88 88 opts.on("-g", "--group GROUP", "group of the repository (default: root)") {|v| $svn_group = v; $use_groupid = false}
89 89 opts.on("-u", "--url URL", "the base url Redmine will use to access your",
90 90 "repositories. This option is used to register",
91 91 "the repositories in Redmine automatically. The",
92 92 "project identifier will be appended to this url.",
93 93 "Examples:",
94 94 " -u https://example.net/svn",
95 95 " -u file:///var/svn/",
96 96 "if this option isn't set, reposman won't register",
97 97 "the repositories in Redmine") {|v| $svn_url = v}
98 98 opts.on( "--scm SCM", "the kind of SCM repository you want to create",
99 99 "(and register) in Redmine (default: Subversion).",
100 100 "reposman is able to create Git and Subversion",
101 101 "repositories.",
102 102 "For all other kind, you must specify a --command",
103 103 "option") {|v| set_scm(v)}
104 104 opts.on("-c", "--command COMMAND", "use this command instead of `svnadmin create` to",
105 105 "create a repository. This option can be used to",
106 106 "create repositories other than subversion and git",
107 107 "kind.",
108 108 "This command override the default creation for",
109 109 "git and subversion.") {|v| $command = v}
110 110 opts.on( "--key-file FILE", "path to a file that contains the Redmine API key",
111 111 "(use this option instead of --key if you don't",
112 112 "want the key to appear in the command line)") {|v| read_key_from_file(v)}
113 113 opts.on("-t", "--test", "only show what should be done") {$test = true}
114 114 opts.on("-f", "--force", "force repository creation even if the project", "repository is already declared in Redmine") {$force = true}
115 115 opts.on("-v", "--verbose", "verbose") {$verbose += 1}
116 116 opts.on("-V", "--version", "show version and exit") {puts Version; exit}
117 117 opts.on("-h", "--help", "show help and exit") {puts opts; exit 1}
118 118 opts.on("-q", "--quiet", "no log") {$quiet = true}
119 119 opts.separator("")
120 120 opts.separator("Examples:")
121 121 opts.separator(" reposman.rb --svn-dir=/var/svn --redmine-host=redmine.host")
122 122 opts.separator(" reposman.rb -s /var/git -r redmine.host -u http://git.host --scm git")
123 123 opts.separator("")
124 124 opts.separator("You can find more information on the redmine's wiki:\nhttp://www.redmine.org/projects/redmine/wiki/HowTos")
125 125
126 126 opts.summary_width = 25
127 127 end
128 128 optparse.parse!
129 129
130 130 if $test
131 131 log("running in test mode")
132 132 end
133 133
134 134 # Make sure command is overridden if SCM vendor is not handled internally (for the moment Subversion and Git)
135 135 if $command.nil?
136 136 begin
137 137 scm_module = SCM.const_get($scm)
138 138 rescue
139 139 log("Please use --command option to specify how to create a #{$scm} repository.", :exit => true)
140 140 end
141 141 end
142 142
143 143 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
144 144
145 145 if ($redmine_host.empty? or $repos_base.empty?)
146 146 puts "Some arguments are missing. Use reposman.rb --help for getting help."
147 147 exit 1
148 148 end
149 149
150 150 unless File.directory?($repos_base)
151 151 log("directory '#{$repos_base}' doesn't exists", :exit => true)
152 152 end
153 153
154 154 begin
155 155 require 'active_resource'
156 156 rescue LoadError
157 157 log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true)
158 158 end
159 159
160 160 class Project < ActiveResource::Base
161 161 self.headers["User-agent"] = "Redmine repository manager/#{Version}"
162 162 self.format = :xml
163 163 end
164 164
165 165 log("querying Redmine for projects...", :level => 1);
166 166
167 167 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
168 168 $redmine_host.gsub!(/\/$/, '')
169 169
170 170 Project.site = "#{$redmine_host}/sys";
171 171
172 172 begin
173 173 # Get all active projects that have the Repository module enabled
174 174 projects = Project.find(:all, :params => {:key => $api_key})
175 175 rescue ActiveResource::ForbiddenAccess
176 176 log("Request was denied by your Redmine server. Make sure that 'WS for repository management' is enabled in application settings and that you provided the correct API key.")
177 177 rescue => e
178 178 log("Unable to connect to #{Project.site}: #{e}", :exit => true)
179 179 end
180 180
181 181 if projects.nil?
182 182 log('No project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
183 183 end
184 184
185 185 log("retrieved #{projects.size} projects", :level => 1)
186 186
187 187 def set_owner_and_rights(project, repos_path, &block)
188 188 if mswin?
189 189 yield if block_given?
190 190 else
191 191 uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : Etc.getgrnam($svn_group).gid)
192 192 right = project.is_public ? 0775 : 0770
193 193 yield if block_given?
194 194 Find.find(repos_path) do |f|
195 195 File.chmod right, f
196 196 File.chown uid, gid, f
197 197 end
198 198 end
199 199 end
200 200
201 201 def other_read_right?(file)
202 202 (File.stat(file).mode & 0007).zero? ? false : true
203 203 end
204 204
205 205 def owner_name(file)
206 206 mswin? ?
207 207 $svn_owner :
208 208 Etc.getpwuid( File.stat(file).uid ).name
209 209 end
210 210
211 211 def mswin?
212 212 (RUBY_PLATFORM =~ /(:?mswin|mingw)/) || (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
213 213 end
214 214
215 215 projects.each do |project|
216 216 log("treating project #{project.name}", :level => 1)
217 217
218 218 if project.identifier.empty?
219 219 log("\tno identifier for project #{project.name}")
220 220 next
221 221 elsif not project.identifier.match(/^[a-z0-9\-_]+$/)
222 222 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
223 223 next;
224 224 end
225 225
226 226 repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
227 227
228 228 if File.directory?(repos_path)
229 229 # we must verify that repository has the good owner and the good
230 230 # rights before leaving
231 231 other_read = other_read_right?(repos_path)
232 232 owner = owner_name(repos_path)
233 233 next if project.is_public == other_read and owner == $svn_owner
234 234
235 235 if $test
236 236 log("\tchange mode on #{repos_path}")
237 237 next
238 238 end
239 239
240 240 begin
241 241 set_owner_and_rights(project, repos_path)
242 242 rescue Errno::EPERM => e
243 243 log("\tunable to change mode on #{repos_path} : #{e}\n")
244 244 next
245 245 end
246 246
247 247 log("\tmode change on #{repos_path}");
248 248
249 249 else
250 250 # if repository is already declared in redmine, we don't create
251 251 # unless user use -f with reposman
252 252 if $force == false and project.respond_to?(:repository)
253 253 log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
254 254 next
255 255 end
256 256
257 257 project.is_public ? File.umask(0002) : File.umask(0007)
258 258
259 259 if $test
260 260 log("\tcreate repository #{repos_path}")
261 261 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
262 262 next
263 263 end
264 264
265 265 begin
266 266 set_owner_and_rights(project, repos_path) do
267 267 if scm_module.nil?
268 268 system_or_raise "#{$command} #{repos_path}"
269 269 else
270 270 scm_module.create(repos_path)
271 271 end
272 272 end
273 273 rescue => e
274 274 log("\tunable to create #{repos_path} : #{e}\n")
275 275 next
276 276 end
277 277
278 278 if $svn_url
279 279 begin
280 280 project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"}, :key => $api_key)
281 281 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
282 282 rescue => e
283 283 log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
284 284 end
285 285 end
286 286 log("\trepository #{repos_path} created");
287 287 end
288 288 end
General Comments 0
You need to be logged in to leave comments. Login now