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