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 / create-repo-authormaps.rb @ 1563:171c31a5cca4

History | View | Annotate | Download (3.37 KB)

1 1538:87bea4981d6d Chris
#!/usr/bin/env ruby
2
3
# Create authormap files for hg repos based on the changeset & project
4
# member info available to Redmine.
5
#
6
# We have a set of hg repos in a given directory:
7
#
8
# /var/hg/repo_1
9
# /var/hg/repo_2
10
# /var/hg/repo_3
11
#
12
# and we want to produce authormap files in another directory:
13
#
14
# /var/repo-export/authormap/authormap_repo_1
15
# /var/repo-export/authormap/authormap_repo_2
16
# /var/repo-export/authormap/authormap_repo_3
17
#
18
# This script does that, if given the two directory names as arguments
19
# to the -s and -o options. In the above example:
20
#
21 1543:05d639e5d59b Chris
# ./script/rails runner -e production extra/soundsoftware/create-repo-authormaps.rb -s /var/hg -o /var/repo-export/authormap
22 1538:87bea4981d6d Chris
#
23
# Note that this script will overwrite any existing authormap
24
# files. (That's why the output files are given an authormap_ prefix,
25
# so we're less likely to clobber something else if the user gets the
26
# arguments wrong.)
27
28
require 'getoptlong'
29
30
opts = GetoptLong.new(
31 1543:05d639e5d59b Chris
                      ['--scm-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
32
                      ['--out-dir', '-o', GetoptLong::REQUIRED_ARGUMENT],
33
                      ['--environment', '-e', GetoptLong::OPTIONAL_ARGUMENT]
34 1538:87bea4981d6d Chris
)
35
36
$repos_base   = ''
37
$out_base     = ''
38
39
def usage
40
  puts "See source code for supported options"
41
  exit
42
end
43
44
begin
45
  opts.each do |opt, arg|
46
    case opt
47
    when '--scm-dir';   $repos_base   = arg.dup
48
    when '--out-dir';   $out_base     = arg.dup
49
    end
50
  end
51
rescue
52
  exit 1
53
end
54
55
if ($repos_base.empty? or $out_base.empty?)
56
  usage
57
end
58
59
unless File.directory?($repos_base)
60 1540:322d7b57e5f0 chris
  puts "input directory '#{$repos_base}' doesn't exist"
61
  exit 1
62 1538:87bea4981d6d Chris
end
63
64
unless File.directory?($out_base)
65 1540:322d7b57e5f0 chris
  puts "output directory '#{$out_base}' doesn't exist"
66
  exit 1
67 1538:87bea4981d6d Chris
end
68
69
projects = Project.find(:all)
70
71
if projects.nil?
72 1540:322d7b57e5f0 chris
  puts 'No projects found'
73
  exit 1
74 1538:87bea4981d6d Chris
end
75
76
projects.each do |proj|
77 1548:fd4cc11ae096 Chris
78
  next unless proj.is_public
79
80 1538:87bea4981d6d Chris
  next unless proj.respond_to?(:repository)
81
82
  repo = proj.repository
83 1539:22d57b0e0a77 chris
  next if repo.nil? or repo.url.empty?
84 1538:87bea4981d6d Chris
85
  repo_url = repo.url
86
  repo_url = repo_url.gsub(/^file:\/*/, "/");
87
  if repo_url != File.join($repos_base, proj.identifier)
88 1542:60acfbd8f6d6 Chris
    puts "Project #{proj.identifier} has repo in unsupported location #{repo_url}, skipping"
89 1538:87bea4981d6d Chris
    next
90
  end
91
92 1542:60acfbd8f6d6 Chris
  committers = repo.committers
93 1538:87bea4981d6d Chris
94
  authormap = ""
95 1542:60acfbd8f6d6 Chris
  committers.each do |c, uid|
96 1552:3a2254124fa8 Chris
97
    # Some of our repos have broken email addresses in them: e.g. one
98
    # changeset has a committer name of the form
99
    #
100
    # NAME <name <NAME <name@example.com">
101
    #
102
    # I don't know how it got like that... If the committer has more
103
    # than one '<' in it, truncate it just before the first one, and
104 1553:baac54711ee9 Chris
    # then look up the author name again.
105
    #
106 1552:3a2254124fa8 Chris
    if c =~ /<.*</ then
107 1553:baac54711ee9 Chris
      # So this is a completely pathological case
108
      user = User.find_by_id uid
109
      if user.nil? then
110
        # because the given committer is bogus, we must write something in the map
111 1554:e5c9809534a2 Chris
        name = c.sub(/\s*<.*$/, "")
112
        authormap << "#{c}=#{name} <unknown@example.com>\n"
113 1553:baac54711ee9 Chris
      else
114
        authormap << "#{c}=#{user.name} <#{user.mail}>\n"
115
      end
116
    elsif not c =~ /[^<]+<.*@.*>/ then
117
      # This is the "normal" case that needs work, where a user has
118
      # their name in the commit but no email address
119 1542:60acfbd8f6d6 Chris
      user = User.find_by_id uid
120 1539:22d57b0e0a77 chris
      authormap << "#{c}=#{user.name} <#{user.mail}>\n" unless user.nil?
121 1538:87bea4981d6d Chris
    end
122
  end
123
124 1539:22d57b0e0a77 chris
  File.open(File.join($out_base, "authormap_#{proj.identifier}"), "w") do |f|
125 1538:87bea4981d6d Chris
    f.puts(authormap)
126
  end
127
128
end