##// END OF EJS Templates
SVN integration: reposman.rb can now register created repositories in Redmine, so that the administrator doesn't have to enter the repository url in Redmine once it's created....
Jean-Philippe Lang -
r847:cedca57620e3
parent child
Show More
@@ -20,6 +20,6 class SysApi < ActionWebService::API::Base
20 :expects => [],
20 :expects => [],
21 :returns => [[Project]]
21 :returns => [[Project]]
22 api_method :repository_created,
22 api_method :repository_created,
23 :expects => [:int, :string],
23 :expects => [:string, :string],
24 :returns => [:int]
24 :returns => [:int]
25 end
25 end
@@ -22,18 +22,21 class SysController < ActionController::Base
22
22
23 before_invocation :check_enabled
23 before_invocation :check_enabled
24
24
25 # Returns the projects list, with their repositories
25 def projects
26 def projects
26 Project.find(:all, :include => :repository)
27 Project.find(:all, :include => :repository)
27 end
28 end
28
29
29 def repository_created(project_id, url)
30 # Registers a repository for the given project identifier
30 project = Project.find_by_id(project_id)
31 # (Subversion specific)
32 def repository_created(identifier, url)
33 project = Project.find_by_identifier(identifier)
34 # Do not create the repository if the project has already one
31 return 0 unless project && project.repository.nil?
35 return 0 unless project && project.repository.nil?
32 logger.debug "Repository for #{project.name} created"
36 logger.debug "Repository for #{project.name} was created"
33 repository = Repository.new(:project => project, :url => url)
37 repository = Repository.factory('Subversion', :project => project, :url => url)
34 repository.root_url = url
35 repository.save
38 repository.save
36 repository.id
39 repository.id || 0
37 end
40 end
38
41
39 protected
42 protected
@@ -2,7 +2,7
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 #
@@ -16,14 +16,28
16 # use DIR as base directory for svn repositories
16 # use DIR as base directory for svn repositories
17 #
17 #
18 # -r, --redmine-host=HOST
18 # -r, --redmine-host=HOST
19 # assume redMine is hosted on HOST.
19 # assume Redmine is hosted on HOST.
20 # you can use :
20 # you can use :
21 # * -r redmine.mydomain.foo (will add http://)
21 # * -r redmine.mydomain.foo (will add http://)
22 # * -r http://redmine.mydomain.foo
22 # * -r http://redmine.mydomain.foo
23 # * -r https://mydomain.foo/redmine
23 # * -r https://mydomain.foo/redmine
24 #
24 #
25 # == Options
25 # == Options
26 #
26 #
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 #
27 # -h, --help:
41 # -h, --help:
28 # show help and exit
42 # show help and exit
29 #
43 #
@@ -48,6 +62,8 Version = "1.0"
48 opts = GetoptLong.new(
62 opts = GetoptLong.new(
49 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
63 ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
50 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
64 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
65 ['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
66 ['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
51 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
67 ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
52 ['--version', '-V', GetoptLong::NO_ARGUMENT],
68 ['--version', '-V', GetoptLong::NO_ARGUMENT],
53 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
69 ['--help' , '-h', GetoptLong::NO_ARGUMENT],
@@ -58,6 +74,8 $verbose = 0
58 $quiet = false
74 $quiet = false
59 $redmine_host = ''
75 $redmine_host = ''
60 $repos_base = ''
76 $repos_base = ''
77 $svn_owner = 'root'
78 $svn_url = false
61
79
62 def log(text,level=0, exit=false)
80 def log(text,level=0, exit=false)
63 return if $quiet or level > $verbose
81 return if $quiet or level > $verbose
@@ -68,8 +86,10 end
68 begin
86 begin
69 opts.each do |opt, arg|
87 opts.each do |opt, arg|
70 case opt
88 case opt
71 when '--svn-dir'; $repos_base = arg.dup
89 when '--svn-dir'; $repos_base = arg.dup
72 when '--redmine-host'; $redmine_host = arg.dup
90 when '--redmine-host'; $redmine_host = arg.dup
91 when '--owner'; $svn_owner = arg.dup
92 when '--url'; $svn_url = arg.dup
73 when '--verbose'; $verbose += 1
93 when '--verbose'; $verbose += 1
74 when '--version'; puts Version; exit
94 when '--version'; puts Version; exit
75 when '--help'; RDoc::usage
95 when '--help'; RDoc::usage
@@ -80,6 +100,8 rescue
80 exit 1
100 exit 1
81 end
101 end
82
102
103 $svn_url += "/" if $svn_url and not $svn_url.match(/\/$/)
104
83 if ($redmine_host.empty? or $repos_base.empty?)
105 if ($redmine_host.empty? or $repos_base.empty?)
84 RDoc::usage
106 RDoc::usage
85 end
107 end
@@ -88,7 +110,7 unless File.directory?($repos_base)
88 log("directory '#{$repos_base}' doesn't exists", 0, true)
110 log("directory '#{$repos_base}' doesn't exists", 0, true)
89 end
111 end
90
112
91 log("querying redMine for projects...", 1);
113 log("querying Redmine for projects...", 1);
92
114
93 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
115 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
94 $redmine_host.gsub!(/\/$/, '')
116 $redmine_host.gsub!(/\/$/, '')
@@ -109,28 +131,53 end
109
131
110 log("retrieved #{projects.size} projects", 1)
132 log("retrieved #{projects.size} projects", 1)
111
133
112 projects.each do |p|
134 def set_owner_and_rights(project, repos_path, &block)
113 log("treating project #{p.name}", 1)
135 if RUBY_PLATFORM =~ /mswin/
136 yield if block_given?
137 else
138 uid, gid = Etc.getpwnam($svn_owner).uid, Etc.getgrnam(project.identifier).gid
139 right = project.is_public ? 0575 : 0570
140 yield if block_given?
141 Find.find(repos_path) do |f|
142 File.chmod right, f
143 File.chown uid, gid, f
144 end
145 end
146 end
147
148 def other_read_right?(file)
149 (File.stat(file).mode & 0007).zero? ? false : true
150 end
151
152 def owner_name(file)
153 RUBY_PLATFORM =~ /mswin/ ?
154 $svn_owner :
155 Etc.getpwuid( File.stat(file).uid ).name
156 end
114
157
115 if p.identifier.empty?
158 projects.each do |project|
116 log("\tno identifier for project #{p.name}")
159 log("treating project #{project.name}", 1)
160
161 if project.identifier.empty?
162 log("\tno identifier for project #{project.name}")
117 next
163 next
118 elsif not p.identifier.match(/^[a-z0-9\-]+$/)
164 elsif not project.identifier.match(/^[a-z0-9\-]+$/)
119 log("\tinvalid identifier for project #{p.name} : #{p.identifier}");
165 log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
120 next;
166 next;
121 end
167 end
122
168
123 repos_path = $repos_base + "/" + p.identifier
169 repos_path = $repos_base + "/" + project.identifier
124
170
125 if File.directory?(repos_path)
171 if File.directory?(repos_path)
126
172
127 other_read = (File.stat(repos_path).mode & 0007).zero? ? false : true
173 # we must verify that repository has the good owner and the good
128 next if p.is_public == other_read
174 # rights before leaving
129
175 other_read = other_read_right?(repos_path)
130 right = p.is_public ? 0775 : 0770
176 owner = owner_name(repos_path)
177 next if project.is_public == other_read and owner == $svn_owner
131
178
132 begin
179 begin
133 Find.find(repos_path) { |f| File.chmod right, f }
180 set_owner_and_rights(project, repos_path)
134 rescue Errno::EPERM => e
181 rescue Errno::EPERM => e
135 log("\tunable to change mode on #{repos_path} : #{e}\n")
182 log("\tunable to change mode on #{repos_path} : #{e}\n")
136 next
183 next
@@ -139,17 +186,26 projects.each do |p|
139 log("\tmode change on #{repos_path}");
186 log("\tmode change on #{repos_path}");
140
187
141 else
188 else
142 p.is_public ? File.umask(0002) : File.umask(0007)
189 project.is_public ? File.umask(0202) : File.umask(0207)
143
190
144 begin
191 begin
145 uid, gid = Etc.getpwnam("root").uid, Etc.getgrnam(p.identifier).gid
192 set_owner_and_rights(project, repos_path) do
146 raise "svnadmin create #{repos_path} failed" unless system("svnadmin", "create", repos_path)
193 raise "svnadmin create #{repos_path} failed" unless system("svnadmin", "create", repos_path)
147 Find.find(repos_path) { |f| File.chown uid, gid, f }
194 end
148 rescue => e
195 rescue => e
149 log("\tunable to create #{repos_path} : #{e}\n")
196 log("\tunable to create #{repos_path} : #{e}\n")
150 next
197 next
151 end
198 end
152
199
200 if $svn_url
201 ret = soap.RepositoryCreated project.identifier, "#{$svn_url}#{project.identifier}"
202 if ret > 0
203 log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
204 else
205 log("\trepository #{repos_path} not registered in Redmine. Look in your log to find why.");
206 end
207 end
208
153 log("\trepository #{repos_path} created");
209 log("\trepository #{repos_path} created");
154 end
210 end
155
211
General Comments 0
You need to be logged in to leave comments. Login now