To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / extra / soundsoftware / convert-external-repos.rb @ 400:4ad6499d7998

History | View | Annotate | Download (5.49 KB)

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
def log(text, options={})
66
  level = options[:level] || 0
67
  puts text unless $quiet or level > $verbose
68
  exit 1 if options[:exit]
69
end
70

    
71
def system_or_raise(command)
72
  raise "\"#{command}\" failed" unless system command
73
end
74

    
75
begin
76
  opts.each do |opt, arg|
77
    case opt
78
    when '--scm-dir';        $repos_base   = arg.dup
79
    when '--redmine-host';   $redmine_host = arg.dup
80
    when '--key';            $api_key      = arg.dup
81
    when '--http-user';      $http_user    = arg.dup
82
    when '--http-pass';      $http_pass    = arg.dup
83
    when '--command';        $command      = arg.dup
84
    when '--verbose';        $verbose += 1
85
    when '--test';           $test = true
86
    when '--version';        puts Version; exit
87
    when '--help';           RDoc::usage
88
    when '--quiet';          $quiet = true
89
    end
90
  end
91
rescue
92
  exit 1
93
end
94

    
95
if $test
96
  log("running in test mode")
97
end
98

    
99
if ($redmine_host.empty? or $repos_base.empty? or $command.empty?)
100
  RDoc::usage
101
end
102

    
103
unless File.directory?($repos_base)
104
  log("directory '#{$repos_base}' doesn't exist", :exit => true)
105
end
106

    
107
begin
108
  require 'active_resource'
109
rescue LoadError
110
  log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true)
111
end
112

    
113
class Project < ActiveResource::Base
114
  self.headers["User-agent"] = "SoundSoftware external repository converter/#{Version}"
115
end
116

    
117
log("querying Redmine for projects...", :level => 1);
118

    
119
$redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
120
$redmine_host.gsub!(/\/$/, '')
121

    
122
Project.site = "#{$redmine_host}/sys";
123
Project.user = $http_user;
124
Project.password = $http_pass;
125

    
126
begin
127
  # Get all active projects that have the Repository module enabled
128
  projects = Project.find(:all, :params => {:key => $api_key})
129
rescue => e
130
  log("Unable to connect to #{Project.site}: #{e}", :exit => true)
131
end
132

    
133
if projects.nil?
134
  log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
135
end
136

    
137
log("retrieved #{projects.size} projects", :level => 1)
138

    
139
projects.each do |project|
140
  log("treating project #{project.name}", :level => 1)
141

    
142
  if project.identifier.empty?
143
    log("\tno identifier for project #{project.name}")
144
    next
145
  elsif not project.identifier.match(/^[a-z0-9\-]+$/)
146
    log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
147
    next
148
  end
149

    
150
  if !project.respond_to?(:repository) or !project.repository.is_external?
151
    log("\tproject #{project.identifier} does not use an external repository");
152
    next
153
  end
154

    
155
  external_url = project.repository.external_url;
156
  log("\tproject #{project.identifier} has external repository url #{external_url}");
157

    
158
  if !external_url.match(/^[a-z][a-z+]{0,8}[a-z]:\/\//)
159
    log("\tthis doesn't look like a plausible url to me, skipping")
160
    next
161
  end
162

    
163
  repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
164

    
165
  unless File.directory?(repos_path)
166
    log("\tproject repo directory '#{repos_path}' doesn't exist")
167
    next
168
  end
169

    
170
  system($command, project.identifier, repos_path, external_url)
171

    
172
end
173