class Md2site::Setup
setupサブコマンドクラス
Constants
- ACCESS_WAIT_SEC
WEBサイトへのアクセス待ち時間(秒単位)
Public Class Methods
初期化
@param env [Env] 環境クラスのメソッド @param mes [Messagex] Messagexクラスのインスタンス
# File lib/md2site/setup.rb, line 26 def initialize(env, mes) @env = env @mes = mes @category_target = @env.category_target absolute_path_status_file = env.conf_hs["ABSOLUTE_PATH_STATUS_FILE"] @url = @env.conf_hs["URL"] @res = {} @mes.add_exitcode("EXIT_CODE_BY_EXCEPTION") @mes.add_exitcode("EXIT_CODE_EXECUTE_SETUP_BEFORE_UPDATE_HTMLFILES") @mes.add_exitcode("EXIT_CODE_CANNOT_FIND_DEST_DIR") @mes.add_exitcode("EXIT_CODE_CANNOT_CONVERT_FROM_HTML_TO_MD") @mes.add_exitcode("EXIT_CODE_PANDOC_EXIT_ABNORMALLY") @status_file = StatusFile.new(absolute_path_status_file, @env.absolutepath_root, @url, @mes) end
Public Instance Methods
サブコマンド実行
@param option [String] サブコマンドのオプション @return [void]
# File lib/md2site/setup.rb, line 47 def execute_subcommand(option) case option.name when "contentUpdate" update_htmlfiles when "zcontents" dir = @env.get_filepath(option.value) unless dir @mes.exc_make_directory(option.value) { FileUtils.mkdir_p(option.value) } dir = @env.get_filepath(option.value) end unless dir || FileTest.directory?(dir) @mes.output_fatal("Can't find drectory(=#{dir}") exit(@mes.ec("EXIT_CODE_CANNOT_FIND_DIRECTORY")) end get_remote_contents(dir) when "getfiles" dir = @env.get_filepath(option.value) get_remote_file_headers(dir) end end
Private Instance Methods
現在時刻をDatetimeクラスのインスタンスと文字列にする
@return [Array] 第0要素: Datetimeクラスのインスタンス 第1要素: “年月日-時分秒”の形式の文字列
# File lib/md2site/setup.rb, line 177 def current_time datetime = DateTime.now datetimestr = get_datestring(datetime) [datetime, datetimestr] end
HTTPヘッダのdateフィールドの値を文字列とUNITタイムで取得
@param headers [Hash] HTTPヘッダを表すハッシュ @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
# File lib/md2site/setup.rb, line 132 def get_date_in_datetime_from_header(headers) get_header_value_of_datetime(headers, "date") end
時刻を“年月日-時分秒”の形式の文字列にする
@param datetime [Datetime] Datetimeクラスのインスタンス @return [String] “年月日-時分秒”の形式の文字列
# File lib/md2site/setup.rb, line 169 def get_datestring(datetime) datetime.strftime("%Y%m%d-%H%M%S") end
HTTPヘッダの指定フィールドの値を文字列とUNITタイムで取得する
@param headers [Hash] HTTPヘッダを表すハッシュ @param key [String] HTTPヘッダのフィールドを指定するキー @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
# File lib/md2site/setup.rb, line 92 def get_header_value_of_datetime(headers, key) @res[key] ||= Regexp.compile(Regexp.escape(key)) keys = headers.keys.select {|x| @res[key].match?(x.downcase) } if keys.size == 1 k = keys.first s = headers[k] begin dt = DateTime.httpdate(s) unixtime = dt.to_time.to_i rescue ArgumentError => e @mes.output_exception(e) @mes.output_fatal("s=#{s}") exit(@mes.ec("EXIT_CODE_BY_EXCEPTION")) rescue Error => e @mes.output_exception(e) @mes.output_fatal("s=#{s}") exit(@mes.ec("EXIT_CODE_BY_EXCEPTION")) end else s = nil unixtime = nil end [s, unixtime] end
HTTPヘッダのlast-modifiedフィールドの値を文字列とUNITタイムで取得
@param headers [Hash] HTTPヘッダを表すハッシュ @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
# File lib/md2site/setup.rb, line 123 def get_modified_in_datetime_from_header(headers) get_header_value_of_datetime(headers, "last-modified") end
指定URLのHTTPヘッダから時刻を表すlast-modifiedフィールドまたはdateフィールのの値を文字列とUNIXタイムで取得
@param url [String] HTTPヘッダを取得したいURL @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
# File lib/md2site/setup.rb, line 154 def get_modified_in_datetime_or_date_in_datetime(url) connection = Faraday.new(url) do |conn| conn.use(FaradayMiddleware::FollowRedirects) conn.adapter(:net_http) end @mes.output_debug("url=#{url}") res = connection.head(url) get_modified_in_datetime_or_date_in_datetime_from_header(res.headers) end
HTTPヘッダから時刻を表すlast-modifiedフィールドまたはdateフィールのの値を文字列とUNIXタイムで取得
@param headers [Hash] HTTPヘッダを表すハッシュ @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
# File lib/md2site/setup.rb, line 141 def get_modified_in_datetime_or_date_in_datetime_from_header(headers) ary = get_modified_in_datetime_from_header(headers) unless ary.all? ary = get_date_in_datetime_from_header(headers) end ary end
指定サイトでダウンロード指定された全URLのをファイルとして、指定ディレクトリ下にダウンロードし、
ダウンロードファイル一覧ファイルを作成し、ダウンロードステータスファイルを更新
@param dir [String] ダウンロードファイルの保存先ディレクトリ @return [void]
# File lib/md2site/setup.rb, line 305 def get_remote_contents(dir) _, datetimestr = current_time @mes.output_info("dir=#{dir}") @mes.output_info("datetimestr=#{datetimestr}") last_contents_path = File.absolute_path(File.join(dir, datetimestr)) @mes.exc_make_directory(last_contents_path) { FileUtils.mkdir_p(last_contents_path) } # 保存先ディレクトリ内にダウンロードファイル一覧ファイルを作成 lf = ListFile.new(last_contents_path, @mes) @category_target.each do |_, target_struct| # 各ターゲット毎にファイルをダウンロード get_remote_contents_subtargets(target_struct[:subTargets], lf, last_contents_path) end lf.close # ダウンロードステータスファイルを更新 @status_file.last_contents_path = last_contents_path @status_file.update end
指定サイトでダウンロード指定された全URLのをファイルとして、保存先ディレクトリにダウンロードし、
ダウンロードステータスファイルを更新
@param subtarget_hash [Hash] サブターゲット名をキーとしてサブターゲットストラクトを値とするハッシュ @param listfile [Listfile] ダウンロードファイル一覧ファイル @param last_contents_path [String] ダウンロード保存先ディレクトリ @return [void]
# File lib/md2site/setup.rb, line 258 def get_remote_contents_subtargets(subtarget_hash, listfile, last_contents_path) subtarget_hash.each do |_, subtarget_struct| # filename = target_def[@env.htmlfile_index] unless subtarget_struct.htmldir&.empty? filename = File.join(subtarget_struct.htmldir, subtarget_struct.htmlfile) else filename = subtarget_struct.htmlfile end next unless subtarget_struct.aliashtmlfile&.empty? # file_urlが'//'とならないようにする if %r{/$}.match?(@url) file_url = URI.join(@url, filename) else file_url = URI.join(@url, "/", filename) end # file_urlをダウンロードする remote_datetime_str, remote_datetime_unixtime, content = get_remote_file(file_url) # ダウンロードできなかった場合はエラーメッセージを表示して、次のサブターゲットのダウンロードに移る unless [remote_datetime_str, remote_datetime_unixtime].all? @mes.output_error("Can't get content from #{file_url}") listfile.add([filename, remote_datetime_str, remote_datetime_unixtime, nil]) sleep(ACCESS_WAIT_SEC) next end # ダウンロードした内容をファイルに書き込む fpath = prepare_new_write_path(last_contents_path, filename) @mes.exc_file_write(fpath) do File.open(fpath, "w") do |ofile| if content ofile.puts(content) end end end # ダウンロードファイル一覧に追加 listfile.add([filename, remote_datetime_str, remote_datetime_unixtime, Digest::MD5.hexdigest(content)]) end end
リモートサイトのファイル取得
@param url [String] 取得先URL @return [Array] 第0要素:Datetime 第1要素:UNIXタイム 第2要素:HTTPボディ
# File lib/md2site/setup.rb, line 75 def get_remote_file(url) connection = Faraday.new(url) do |conn| conn.use(FaradayMiddleware::FollowRedirects) conn.adapter(:net_http) end @mes.output_debug("url=#{url}") res = connection.get(url) datetime_str, datetime_unix_time = get_modified_in_datetime_or_date_in_datetime_from_header(res.headers) [datetime_str, datetime_unix_time, res.body] end
指定サイトでダウンロード指定された全URLのHTTPヘッダの時刻を取得して一覧をファイルに保存
@param dir [String] HTTPヘッダ時刻一覧ファイルの保存先ディレクトリ @return [Array] 第0要素: Datetimeクラスのインスタンス 第1要素: “年月日-時分秒”の形式の文字列 @note 一覧を保存するファイルのファイル名はsite-年月日-時分秒.tsvである
# File lib/md2site/setup.rb, line 189 def get_remote_file_headers(dir) _, datetimestr = current_time fname = %Q(site-#{datetimestr}.tsv) fpath = File.join(dir, fname) @mes.exc_file_write(fpath) do File.open(fpath, "w") do |ofile| @category_target.each do |_k, v| v[:subTargets].each do |_k2, subtarget| filename = subtarget.htmlfile next unless subtarget.aliashtmlfile && !subtarget.aliashtmlfile&.empty? if %r{/$}.match?(@url) file_url = URI.join(@url, filename) else file_url = URI.join(@url, "/", filename) end ary = get_modified_in_datetime_or_date_in_datetime(file_url) unless ary.all? @mes.output_error("Can't find last-modified header from #{@url}") end ofile.puts([file_url].join("\t")) end end end end @status_file.fname = fname @status_file.fpath = fpath @status_file.last_datetime = datetimestr @status_file.update end
引数で指定したファイルが書込み可能であるように書込み先ディレクトリを作成
@param dir [String] ディレクトリ @param filename [String] ファイルへのパス(ファイル名のみも可)
# File lib/md2site/setup.rb, line 228 def prepare_new_write_path(dir, filename, postfix=nil) if postfix extname = File.extname(filename) basename = File.basename(filename, extname) new_fname = %Q(#{basename}#{postfix}#{extname}) else basename = File.basename(filename) new_fname = basename end dirname = File.dirname(filename) if dirname != "." dirpath = File.join(dir, dirname) @mes.exc_make_directory(dirpath) { FileUtils.mkdir_p(dirpath) } fpath = File.join(dirpath, new_fname) else fpath = File.join(dir, new_fname) end fpath end
HTMLファイルをMarkdown形式に変換する
@param input_htmlfname [String] 変換元HTMLファイル名 @param outputmd [String] 変換したMakrdown形式ファイル名 @return [void] @note HTMLファイルからMarkdown形式ファイルへの変換にはpandocを利用するため、pandoc
がインストールされていることが前提
# File lib/md2site/setup.rb, line 415 def simple_html2md(input_htmlfname, outputmd) ret = false _, _, s = Open3.capture3(%Q(pandoc -o #{outputmd} -t markdown #{input_htmlfname})) if s.exited? if s.exitstatus == 0 ret = true else @mes.output_error("Can't convert from html to md by pandoc(IN:#{input_htmlfname} OUT:#{outputmd}(exit_code=#{s.exitstatus})") exit(@mes.ec("EXIT_CODE_CANNOT_CONVERT_FROM_HTML_TO_MD")) end else @mes.output_error("Pandoc exit abnormally") exit(@mes.ec("EXIT_CODE_PANDOC_EXIT_ABNORMALLY")) end ret end
ダウンロードステータスファイルを更新ダウンロード保存先ディレクトリから指定サブターゲットのHTMLファイルをサブターゲットで
指定されてディレクトリにコピーし、3分割し、中間部分をMarkdown形式に変換する
@return [void]
# File lib/md2site/setup.rb, line 375 def update_htmlfiles # 有効なダウンロードステータスファイルが存在しなければexitする if @status_file.nil? || @status_file.last_contents_path.nil? || @status_file.last_contents_path.empty? @mes.output_info("@status_file=#{@status_file}") unless @status_file.nil? @mes.output_info("@status_file.last_contents_path=#{@status_file.last_contents_path}") end exit(@mes.ec("EXIT_CODE_EXECUTE_SETUP_BEFORE_UPDATE_HTMLFILES")) else # 全ターゲットの全サブターゲットのうち、エイリアスHTMLファイルが指定されておらず、かつ未ダウンロード # のもののみをダウンロードする @category_target.each do |_name, category_struct| category_struct.subTargets.each do |_k, v| # エイリアスHTMLファイルが指定されていても、ワークディレクトリは必要なため、ここで作成する path = File.join(@env.absolutepath_root, v.workDir) @mes.exc_make_directory(path) { FileUtils.mkdir_p(path) } next unless v.aliashtmlfile.empty? filename = v.htmlfile next if filename.empty? src_fpath = File.join(@status_file.last_contents_path, filename) unless File.exist?(src_fpath) @mes.output_info("#{src_fpath} doesn't exist") next end update_htmlfiles_subtarget(v, src_fpath) end end end end
ダウンロード保存先ディレクトリから指定サブターゲットのHTMLファイルをサブターゲットで
指定されてディレクトリにコピーし、3分割し、中間部分をMarkdown形式に変換する
@param subtarget [String] サブターゲットストラクト @param src_fpath [String] コピー元ファイルパス @return [void] @note HTMLファイルからMarkdown形式ファイルへの変換にはpandocを利用するため、pandoc
がインストールされていることが前提
# File lib/md2site/setup.rb, line 336 def update_htmlfiles_subtarget(subtarget, src_fpath) dest_fpath = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.html_input) unless dest_fpath dir = File.dirname(subtarget.filedir.html_input) path = File.join(@env.absolutepath_root, dir) @mes.exc_make_directory(path) { FileUtils.mkdir_p(path) } dest_fpath2 = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.html_input) if dest_fpath2 dest_fpath = dest_fpath2 else @mes.output_fatal("Can't find dest dir(#{path})") exit(@mes.ec("EXIT_CODE_CANNOT_FIND_DEST_DIR")) end end @mes.exc_file_copy(src_fpath, dest_fpath) { FileUtils.cp(src_fpath, dest_fpath) } @mes.output_info("HtmlUtils.divideHtml dest_fpath=#{dest_fpath}") ary = HTMLUtils.new(dest_fpath, @mes).divide_html dir = File.dirname(dest_fpath) (0..2).each do |x| ofname = File.join(dir, %Q(#{x}.html)) @mes.exc_file_write(ofname) { File.open(ofname, "w") {|f| f.puts(ary[x]) } } end in_html = File.join(dir, %Q(1.html)) unless File.exist?(in_html) @mes.output_fatal("Can't find file(=#{in_html}") exit(@mes.ec("EXIT_CODE_CANNOT_FIND_FILE")) end out_orig_md = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.input_md, "_orig") simple_html2md(in_html, out_orig_md) out_md = File.join(@env.absolutepath_root, subtarget.filedir.input_md) @mes.exc_file_copy(out_orig_md, out_md) { FileUtils.cp(out_orig_md, out_md) } unless File.exist?(out_md) end