Created
April 27, 2011 21:00
-
-
Save miau/945203 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| # 外部から送られたファイルをそれらしく SVN に取り込むスクリプト | |
| # | |
| # Windows での使用例 | |
| # set EDITOR=C:/sakura/sakura.exe | |
| # ruby fetch_third_party_file.rb 201104027 current | |
| # OS の判定処理 | |
| def windows? | |
| RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|cygwin|bccwin/ | |
| end | |
| # 文字コード変換を簡単に行うためのヘルパメソッド | |
| # | |
| # 基本的に UTF-8 で統一したいが、ファイルシステムとのやりとりは Shift_JIS なので。 | |
| # "あいう".sjis で Shift_JIS に、"あいう".utf8 で UTF-8 に変換する | |
| require 'nkf' | |
| class String | |
| def sjis; NKF.nkf('-Ws', self); end | |
| def utf8; NKF.nkf('-Sw', self); end | |
| def decode_sys; windows? ? self.utf8 : self; end | |
| def encode_sys; windows? ? self.sjis : self; end | |
| end | |
| # windows の場合は Shift_JIS に変換してから stdout に出力する | |
| if windows? | |
| class StdoutHook | |
| def write(str) | |
| STDOUT.write str.to_s.sjis | |
| end | |
| $> = new | |
| end | |
| end | |
| # ファイル名確認のためにエディタを起動する | |
| def prompt_files(files_txt, from_files, svn_files, to_files) | |
| # ファイルの一覧を作成 | |
| File.open(files_txt, "wb") {|f| | |
| f.write to_files.map{|file| "#{file}\n"} | |
| f.puts "#" | |
| f.puts "# ↓元ファイルの一覧です。この順で格納先のファイル名を記載してください。" | |
| f.puts "# 「#」で始まる行は無視されます。" | |
| f.puts "#" | |
| f.write from_files.map{|file| "# #{file}\n"} | |
| f.puts "#" | |
| f.puts "# ↓SVN ディレクトリのファイル一覧です。参考にしてください。" | |
| f.puts "#" | |
| f.write svn_files.map{|file| "# #{file}\n"} | |
| } | |
| # エディタを起動してユーザに編集してもらう | |
| system $editor, files_txt | |
| # 編集後のファイルを読み込む | |
| to_files = nil | |
| File.open(files_txt, "rb") {|f| | |
| to_files = f.readlines.reject{|line| line.match(/^#/)}.map{|line| line.chomp} | |
| } | |
| # 内容が変更されていない場合はエディタの起動に失敗したとみなして警告表示して終了 | |
| if to_files == from_files | |
| puts "ファイルが変更されていません。" | |
| puts "・環境変数 EDITOR が正しく設定されていることを確認してください。(EDITOR: #{ENV['EDITOR']})" | |
| puts "・ファイル編集完了までブロックしないエディタを利用している場合は、エディタの設定を変更してください。" | |
| exit | |
| end | |
| to_files | |
| end | |
| # ファイルの移動詳細を表示し、ユーザに確認を求める | |
| def prompt_changes(from_files, to_files) | |
| from_files.zip(to_files) do|from, to| | |
| puts from | |
| if File.exist?(to.encode_sys) | |
| # 既存ファイルの編集 | |
| unless File.file?(to.encode_sys) | |
| puts "移動先がファイルではありません。再度編集してください。" | |
| puts "\tFrom(#{File.ftype(from.encode_sys)}): #{from}" | |
| puts "\tTo(#{File.ftype(to.encode_sys)}): #{to}" | |
| return false | |
| end | |
| puts " [Edit] #{to}" | |
| else | |
| puts " [Add] #{to}" | |
| end | |
| end | |
| input = "" | |
| until input.match(/^[yn]/i) | |
| puts "\n変更内容に間違いはありませんか?([Add] は新規ファイル、[Edit] は既存ファイル)" | |
| print "[y/n]: " | |
| input = STDIN.gets | |
| end | |
| return input.match(/^[Yy]/) | |
| end | |
| # SVN 作業ディレクトリの更新 | |
| def update_svn_files(from_files, to_files) | |
| from_files.zip(to_files) do|from, to| | |
| puts from | |
| # 格納先のディレクトリを作成しておく | |
| dirname = File.dirname(to) | |
| FileUtils.mkdir_p dirname.encode_sys | |
| # ファイルのコピー | |
| FileUtils.copy(from.encode_sys, to.encode_sys) | |
| # svn add も実行しておく | |
| system("svn", "add", "--parents", to.encode_sys) or print "svn add failed: #{to}" | |
| end | |
| end | |
| # 元ディレクトリの更新 | |
| def update_from_files(from_files, to_files) | |
| added = {} # svn add を実行したディレクトリを記憶するためのハッシュ | |
| from_files.zip(to_files) do|from, to| | |
| puts to | |
| # 格納先のディレクトリを作成しておく | |
| dirname = File.dirname(from) | |
| FileUtils.mkdir_p dirname.encode_sys | |
| # ディレクトリを svn add しておく | |
| unless added.has_key?(dirname) | |
| system("svn", "add", "--parents", "--depth=empty", dirname.encode_sys) or print "svn add failed: #{dirname}" | |
| added[dirname] = true | |
| end | |
| # コピー先にファイルがあると失敗するので削除しておく | |
| File.unlink(from.encode_sys) | |
| # svn copy でファイルをリネーム&コピー | |
| system("svn", "copy", to.encode_sys, from.encode_sys) or print "svn copy failed: #{to} => #{from}" | |
| end | |
| end | |
| # メイン処理 | |
| require "fileutils" | |
| # autoflush 設定 | |
| STDOUT.sync = true | |
| # 使用するエディタの設定 | |
| $editor = ENV["EDITOR"] | |
| if $editor.nil? | |
| puts "ファイル一覧の編集に使うエディタのパスを環境変数 EDITOR を設定してください。" | |
| exit | |
| end | |
| # 引数のチェック | |
| if ARGV.length != 2 | |
| print "usage: #{$0} <directory_to_import> <svn_base_directory>" | |
| exit | |
| end | |
| from_dir, svn_dir = ARGV.map{|arg| arg.decode_sys} | |
| # 元ファイルのディレクトリ、SVN ディレクトリのファイル一覧を取得 | |
| from_files = Dir.glob("#{from_dir.encode_sys}/**/*").select{|file| File.file?(file) }.map{|file| file.decode_sys } | |
| svn_files = Dir.glob("#{svn_dir.encode_sys}/**/*").select{|file| File.file?(file) }.map{|file| file.decode_sys } | |
| svn_files = [svn_dir] if svn_files.empty? | |
| # 編集後のファイル。ひとまず元ファイル名を入れておく | |
| to_files = from_files | |
| # ファイル名の編集に利用する一時ファイル | |
| files_txt = "_fetch_third_party_files.txt"; | |
| loop do | |
| # ユーザ入力の取得 | |
| to_files = prompt_files(files_txt, from_files, svn_files, to_files) | |
| # 内容が不正な場合はやり直し | |
| if to_files.length != from_files.length | |
| puts "ファイル数が異なっています。再度編集してください。" | |
| elsif prompt_changes(from_files, to_files) | |
| # ユーザ確認が OK だった場合のみループをぬける | |
| break | |
| end | |
| end | |
| # SVN 作業ディレクトリの更新 | |
| update_svn_files(from_files, to_files) | |
| puts "#{svn_dir} が更新されました。問題なければ svn commit を実行してください。" | |
| puts "svn commit が完了したら Enter を押下してください。引き続き #{from_dir} の更新が行われます。" | |
| input = STDIN.gets | |
| # 元ディレクトリの更新 | |
| update_from_files(from_files, to_files) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment