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