annotate extra/soundsoftware/create-repo-authormaps.rb @ 1628:9c5f8e24dadc live tip

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