Mercurial > hg > soundsoftware-site
comparison extra/soundsoftware/convert-external-repos.rb @ 524:1248a47e81b3 feature_36
Merge from branch "luisf"
author | luisf <luis.figueira@eecs.qmul.ac.uk> |
---|---|
date | Mon, 25 Jul 2011 14:39:38 +0100 |
parents | 102056ec2de9 |
children | b61a51fb42b9 |
comparison
equal
deleted
inserted
replaced
519:3be6bc3c2a17 | 524:1248a47e81b3 |
---|---|
1 #!/usr/bin/env ruby | |
2 | |
3 # == Synopsis | |
4 # | |
5 # convert-external-repos: Update local Mercurial mirrors of external repos, | |
6 # by running an external command for each project requiring an update. | |
7 # | |
8 # == Usage | |
9 # | |
10 # convert-external-repos [OPTIONS...] -s [DIR] -r [HOST] | |
11 # | |
12 # == Arguments (mandatory) | |
13 # | |
14 # -s, --scm-dir=DIR use DIR as base directory for repositories | |
15 # -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples: | |
16 # -r redmine.example.net | |
17 # -r http://redmine.example.net | |
18 # -r https://example.net/redmine | |
19 # -k, --key=KEY use KEY as the Redmine API key | |
20 # -c, --command=COMMAND use this command to update each external | |
21 # repository: command is called with the name | |
22 # of the project, the path to its repo, and | |
23 # its external repo url as its three args | |
24 # | |
25 # == Options | |
26 # | |
27 # --http-user=USER User for HTTP Basic authentication with Redmine WS | |
28 # --http-pass=PASSWORD Password for Basic authentication with Redmine WS | |
29 # -t, --test only show what should be done | |
30 # -h, --help show help and exit | |
31 # -v, --verbose verbose | |
32 # -V, --version print version and exit | |
33 # -q, --quiet no log | |
34 | |
35 | |
36 require 'getoptlong' | |
37 require 'rdoc/usage' | |
38 require 'find' | |
39 require 'etc' | |
40 | |
41 Version = "1.0" | |
42 | |
43 opts = GetoptLong.new( | |
44 ['--scm-dir', '-s', GetoptLong::REQUIRED_ARGUMENT], | |
45 ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT], | |
46 ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT], | |
47 ['--http-user', GetoptLong::REQUIRED_ARGUMENT], | |
48 ['--http-pass', GetoptLong::REQUIRED_ARGUMENT], | |
49 ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT], | |
50 ['--test', '-t', GetoptLong::NO_ARGUMENT], | |
51 ['--verbose', '-v', GetoptLong::NO_ARGUMENT], | |
52 ['--version', '-V', GetoptLong::NO_ARGUMENT], | |
53 ['--help' , '-h', GetoptLong::NO_ARGUMENT], | |
54 ['--quiet' , '-q', GetoptLong::NO_ARGUMENT] | |
55 ) | |
56 | |
57 $verbose = 0 | |
58 $quiet = false | |
59 $redmine_host = '' | |
60 $repos_base = '' | |
61 $http_user = '' | |
62 $http_pass = '' | |
63 $test = false | |
64 | |
65 $mirrordir = '/var/mirror' | |
66 | |
67 def log(text, options={}) | |
68 level = options[:level] || 0 | |
69 puts text unless $quiet or level > $verbose | |
70 exit 1 if options[:exit] | |
71 end | |
72 | |
73 def system_or_raise(command) | |
74 raise "\"#{command}\" failed" unless system command | |
75 end | |
76 | |
77 begin | |
78 opts.each do |opt, arg| | |
79 case opt | |
80 when '--scm-dir'; $repos_base = arg.dup | |
81 when '--redmine-host'; $redmine_host = arg.dup | |
82 when '--key'; $api_key = arg.dup | |
83 when '--http-user'; $http_user = arg.dup | |
84 when '--http-pass'; $http_pass = arg.dup | |
85 when '--command'; $command = arg.dup | |
86 when '--verbose'; $verbose += 1 | |
87 when '--test'; $test = true | |
88 when '--version'; puts Version; exit | |
89 when '--help'; RDoc::usage | |
90 when '--quiet'; $quiet = true | |
91 end | |
92 end | |
93 rescue | |
94 exit 1 | |
95 end | |
96 | |
97 if $test | |
98 log("running in test mode") | |
99 end | |
100 | |
101 if ($redmine_host.empty? or $repos_base.empty? or $command.empty?) | |
102 RDoc::usage | |
103 end | |
104 | |
105 unless File.directory?($repos_base) | |
106 log("directory '#{$repos_base}' doesn't exist", :exit => true) | |
107 end | |
108 | |
109 begin | |
110 require 'active_resource' | |
111 rescue LoadError | |
112 log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true) | |
113 end | |
114 | |
115 class Project < ActiveResource::Base | |
116 self.headers["User-agent"] = "SoundSoftware external repository converter/#{Version}" | |
117 end | |
118 | |
119 log("querying Redmine for projects...", :level => 1); | |
120 | |
121 $redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://") | |
122 $redmine_host.gsub!(/\/$/, '') | |
123 | |
124 Project.site = "#{$redmine_host}/sys"; | |
125 Project.user = $http_user; | |
126 Project.password = $http_pass; | |
127 | |
128 begin | |
129 # Get all active projects that have the Repository module enabled | |
130 projects = Project.find(:all, :params => {:key => $api_key}) | |
131 rescue => e | |
132 log("Unable to connect to #{Project.site}: #{e}", :exit => true) | |
133 end | |
134 | |
135 if projects.nil? | |
136 log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true) | |
137 end | |
138 | |
139 log("retrieved #{projects.size} projects", :level => 1) | |
140 | |
141 projects.each do |project| | |
142 log("treating project #{project.name}", :level => 1) | |
143 | |
144 if project.identifier.empty? | |
145 log("\tno identifier for project #{project.name}") | |
146 next | |
147 elsif not project.identifier.match(/^[a-z0-9\-]+$/) | |
148 log("\tinvalid identifier for project #{project.name} : #{project.identifier}"); | |
149 next | |
150 end | |
151 | |
152 if !project.respond_to?(:repository) or !project.repository.is_external? | |
153 log("\tproject #{project.identifier} does not use an external repository"); | |
154 next | |
155 end | |
156 | |
157 external_url = project.repository.external_url; | |
158 log("\tproject #{project.identifier} has external repository url #{external_url}"); | |
159 | |
160 if !external_url.match(/^[a-z][a-z+]{0,8}[a-z]:\/\//) | |
161 log("\tthis doesn't look like a plausible url to me, skipping") | |
162 next | |
163 end | |
164 | |
165 repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR) | |
166 | |
167 unless File.directory?(repos_path) | |
168 log("\tproject repo directory '#{repos_path}' doesn't exist") | |
169 next | |
170 end | |
171 | |
172 system($command, project.identifier, repos_path, external_url) | |
173 | |
174 $cache_clearance_file = File.join($mirrordir, project.identifier, 'url_changed') | |
175 if File.file?($cache_clearance_file) | |
176 log("\tproject repo url has changed, requesting cache clearance") | |
177 if project.post(:repository_cache, :key => $api_key) | |
178 File.delete($cache_clearance_file) | |
179 end | |
180 end | |
181 | |
182 end | |
183 |