⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commit-email.rb

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 RB
字号:
#!/usr/bin/env rubyrequire "optparse"require "ostruct"require "stringio"require "tempfile"SENDMAIL = "/usr/sbin/sendmail"def parse(args)  options = OpenStruct.new  options.to = []  options.error_to = []  options.from = nil  options.add_diff = true  options.repository_uri = nil  options.rss_path = nil  options.rss_uri = nil  options.name = nil  opts = OptionParser.new do |opts|    opts.separator ""    opts.on("-I", "--include [PATH]",            "Add [PATH] to load path") do |path|      $LOAD_PATH.unshift(path)    end        opts.on("-t", "--to [TO]",            "Add [TO] to to address") do |to|      options.to << to unless to.nil?    end        opts.on("-e", "--error-to [TO]",            "Add [TO] to to address when error is occurred") do |to|      options.error_to << to unless to.nil?    end        opts.on("-f", "--from [FROM]",            "Use [FROM] as from address") do |from|      options.from = from    end        opts.on("-n", "--no-diff",            "Don't add diffs") do |from|      options.add_diff = false    end        opts.on("-r", "--repository-uri [URI]",            "Use [URI] as URI of repository") do |uri|      options.repository_uri = uri    end        opts.on("--rss-path [PATH]",            "Use [PATH] as output RSS path") do |path|      options.rss_path = path    end        opts.on("--rss-uri [URI]",            "Use [URI] as output RSS URI") do |uri|      options.rss_uri = uri    end        opts.on("--name [NAME]",            "Use [NAME] as repository name") do |name|      options.name = name    end        opts.on_tail("--help", "Show this message") do      puts opts      exit!    end  end  opts.parse!(args)  optionsenddef make_body(info, params)  body = ""  body << "#{info.author}\t#{format_time(info.date)}\n"  body << "\n"  body << "  New Revision: #{info.revision}\n"  body << "\n"  body << added_dirs(info)  body << added_files(info)  body << copied_dirs(info)  body << copied_files(info)  body << deleted_dirs(info)  body << deleted_files(info)  body << modified_dirs(info)  body << modified_files(info)  body << "\n"  body << "  Log:\n"  info.log.each_line do |line|    body << "    #{line}"  end  body << "\n"  body << change_info(info, params[:repository_uri], params[:add_diff])  bodyenddef format_time(time)  time.strftime('%Y-%m-%d %X %z (%a, %d %b %Y)')enddef changed_items(title, type, items)  rv = ""  unless items.empty?    rv << "  #{title} #{type}:\n"    if block_given?      yield(rv, items)    else      rv << items.collect {|item| "    #{item}\n"}.join('')    end  end  rvenddef changed_files(title, files, &block)  changed_items(title, "files", files, &block)enddef added_files(info)  changed_files("Added", info.added_files)enddef deleted_files(info)  changed_files("Removed", info.deleted_files)enddef modified_files(info)  changed_files("Modified", info.updated_files)enddef copied_files(info)  changed_files("Copied", info.copied_files) do |rv, files|    rv << files.collect do |file, from_file, from_rev|      <<-INFO    #{file}      (from rev #{from_rev}, #{from_file})INFO    end.join("")  endenddef changed_dirs(title, files, &block)  changed_items(title, "directories", files, &block)enddef added_dirs(info)  changed_dirs("Added", info.added_dirs)enddef deleted_dirs(info)  changed_dirs("Removed", info.deleted_dirs)enddef modified_dirs(info)  changed_dirs("Modified", info.updated_dirs)enddef copied_dirs(info)  changed_dirs("Copied", info.copied_dirs) do |rv, dirs|    rv << dirs.collect do |dir, from_dir, from_rev|      "    #{dir} (from rev #{from_rev}, #{from_dir})\n"    end.join("")  endendCHANGED_TYPE = {  :added => "Added",  :modified => "Modified",  :deleted => "Deleted",  :copied => "Copied",  :property_changed => "Property changed",}CHANGED_MARK = Hash.new("=")CHANGED_MARK[:property_changed] = "_"def change_info(info, uri, add_diff)  result = changed_dirs_info(info, uri)  result = "\n#{result}" unless result.empty?  result << "\n"  diff_info(info, uri, add_diff).each do |key, infos|    infos.each do |desc, link|      result << "#{desc}\n"    end  end  resultenddef changed_dirs_info(info, uri)  rev = info.revision  (info.added_dirs.collect do |dir|     "  Added: #{dir}\n"   end + info.copied_dirs.collect do |dir, from_dir, from_rev|     <<-INFO  Copied: #{dir}    (from rev #{from_rev}, #{from_dir})INFO   end + info.deleted_dirs.collect do |dir|     <<-INFO  Deleted: #{dir}    % svn ls #{[uri, dir].compact.join("/")}@#{rev - 1}INFO   end + info.updated_dirs.collect do |dir|     "  Modified: #{dir}\n"   end).join("\n")enddef diff_info(info, uri, add_diff)  info.diffs.collect do |key, values|    [      key,      values.collect do |type, value|        args = []        rev = info.revision        case type        when :added          command = "cat"        when :modified, :property_changed          command = "diff"          args.concat(["-r", "#{info.revision - 1}:#{info.revision}"])        when :deleted          command = "cat"          rev -= 1        when :copied          command = "cat"        else          raise "unknown diff type: #{value.type}"        end        command += " #{args.join(' ')}" unless args.empty?        link = [uri, key].compact.join("/")        line_info = "+#{value.added_line} -#{value.deleted_line}"        desc = <<-HEADER  #{CHANGED_TYPE[value.type]}: #{key} (#{line_info})#{CHANGED_MARK[value.type] * 67}HEADER        if add_diff          desc << value.body        else          desc << <<-CONTENT    % svn #{command} #{link}@#{rev}CONTENT        end              [desc, link]      end    ]  endenddef make_header(to, from, info, params)  headers = []  headers << x_author(info)  headers << x_repository(info)  headers << x_id(info)  headers << x_sha256(info)  headers << "Content-Type: text/plain; charset=UTF-8"  headers << "Content-Transfer-Encoding: 8bit"  headers << "From: #{from}"  headers << "To: #{to.join(' ')}"  headers << "Subject: #{make_subject(params[:name], info)}"  headers.find_all do |header|    /\A\s*\z/ !~ header  end.join("\n")enddef make_subject(name, info)  subject = ""  subject << "#{name}:" if name  subject << "r#{info.revision}: "  subject << info.log.lstrip.to_a.first.to_s.chomp  NKF.nkf("-WM", subject)enddef x_author(info)  "X-SVN-Author: #{info.author}"enddef x_repository(info)  # "X-SVN-Repository: #{info.path}"  "X-SVN-Repository: XXX"enddef x_id(info)  "X-SVN-Commit-Id: #{info.entire_sha256}"enddef x_sha256(info)  info.sha256.collect do |name, inf|    "X-SVN-SHA256-Info: #{name}, #{inf[:revision]}, #{inf[:sha256]}"  end.join("\n")enddef make_mail(to, from, info, params)  make_header(to, from, info, params) + "\n" + make_body(info, params)enddef sendmail(to, from, mail)  args = to.collect {|address| address.dump}.join(' ')  open("| #{SENDMAIL} #{args}", "w") do |f|    f.print(mail)  endenddef output_rss(name, file, rss_uri, repos_uri, info)  prev_rss = nil  begin    if File.exist?(file)      File.open(file) do |f|        prev_rss = RSS::Parser.parse(f)      end    end  rescue RSS::Error  end  File.open(file, "w") do |f|    f.print(make_rss(prev_rss, name, rss_uri, repos_uri, info).to_s)  endenddef make_rss(base_rss, name, rss_uri, repos_uri, info)  RSS::Maker.make("1.0") do |maker|    maker.encoding = "UTF-8"    maker.channel.about = rss_uri    maker.channel.title = rss_title(name || repos_uri)    maker.channel.link = repos_uri    maker.channel.description = rss_title(name || repos_uri)    maker.channel.dc_date = info.date    if base_rss      base_rss.items.each do |item|        item.setup_maker(maker)       end    end        diff_info(info, repos_uri, true).each do |name, infos|      infos.each do |desc, link|        item = maker.items.new_item        item.title = name        item.description = info.log        item.content_encoded = "<pre>#{h(desc)}</pre>"        item.link = link        item.dc_date = info.date        item.dc_creator = info.author      end    end    maker.items.do_sort = true    maker.items.max_size = 15  endenddef rss_title(name)  "Repository of #{name}"enddef rss_items(items, info, repos_uri)  diff_info(info, repos_uri).each do |name, infos|    infos.each do |desc, link|      items << [link, name, desc, info.date]    end  end    items.sort_by do |uri, title, desc, date|    date  end.reverseenddef main  if ARGV.find {|arg| arg == "--help"}    parse(ARGV)  else    repos, revision, to, *rest = ARGV    options = parse(rest)  end    require "svn/info"  info = Svn::Info.new(repos, revision)  from = options.from || info.author  to = [to, *options.to]  params = {    :repository_uri => options.repository_uri,    :name => options.name,    :add_diff => options.add_diff,  }  sendmail(to, from, make_mail(to, from, info, params))  if options.repository_uri and      options.rss_path and      options.rss_uri    require "rss/1.0"    require "rss/dublincore"    require "rss/content"    require "rss/maker"    include RSS::Utils    output_rss(options.name,               options.rss_path,               options.rss_uri,               options.repository_uri,               info)  endendbegin  mainrescue Exception  _, _, to, *rest = ARGV  to = [to]  from = ENV["USER"]  begin    options = parse(rest)    to = options.error_to unless options.error_to.empty?    from = options.from  rescue Exception  end  sendmail(to, from, <<-MAIL)From: #{from}To: #{to.join(', ')}Subject: Error#{$!.class}: #{$!.message}#{$@.join("\n")}MAILend

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -