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