Hatena::ブログ(Diary)

shouhの日記

2016-12-28

GitHub で Issue を削除することはできるのか

結論: Issue 単体では削除できない

詳細

  • Issue を削除する機能はない
  • ただし、別の内容で上書きしてしまえば、擬似的に削除できないこともない
    • ただし、上書きした場合、Issue のページでは「Title については」履歴が記録されるため意味ない
    • 実は GitHub Events API を使えば Body や IssueComment についても、ある程度の期間なら履歴が取れる

別案: 消すのではなく隠す

消したい Issue を持つリポジトリを Private にすればよい。ただし月額7ドルプランが必要。

どうしても消したい場合はリポジトリごと

リポジトリ自体を削除すれば、そこに含まれる Issue も消せる。

GitHub を使ってブラウザだけでブログ(っぽいもの)書けるかチャレンジしてみた

成果物はこれ → shouh/githublog

GitHub Issues を使って、ブラウザだけでブログみたいなことがどこまで出来るのか挑戦してみた。

感想

  • ブログとおおよそ同等のポテンシャルを持っているように思う
  • 軽い、広告がない、業者がいないってのは快適でいい
  • 記事を削除できないなど、クセの強い欠陥を抱えている
  • SEO 的にアクセス数集めづらいのがツライ

ぶっちゃけはてなダイアリーから移行しようと思ったけど、アクセス数集まらないのでやめた。

逆に、アクセス数とか気にせず、本当に備忘録として使いたい人には向いてると思う。見られたくないなら Private にすればいいし(月額7ドルだけど)。

以下、細かい調査結果を一部書く。全容は上記成果物に書いた(無理して拙い英語だけど)。

できること(ブログ機能との対応)

  • 記事 → Issue
  • コメント → IssueComment
  • カテゴリ → Label
  • 画像 → D&Dアップロード可能(ただし削除は不可能!)
  • アーカイブ → Issue 一覧。ただし1ページ25件固定
  • インポート/エクスポートGitHub APIを使えば可能だがハードル高い。つか Import は一件ずつしか行えないのでめちゃ時間かかる&同時リクエストは無いらいし(GitHub Supportに問い合わせたらそう言われた)

できないこと

  • 記事削除
    • Issue は削除できない!
  • デザインを変えること
  • TOC(見出し目次)
  • フォントサイズや色の設定
    • というか Markdown で表現できないことは出来ない
  • 匿名コメント
  • 管理人のみの投稿
    • Issue って誰でも書けるんですよね。自分のブログなのに他人も書けることになる(爆笑)
  • ping 送信など更新通知

できること(Github Issues の強み)

  • Markdown が使える
  • Label や Filter など絞り込みが豊富
  • 記事(Issue)単位でコメント凍結ができる
    • Lock conversation を使う
  • 連載モノ
    • Milestone を使う。かなり強引だが。
  • 下書きと清書の区別
    • Status(Openが下書き、Closedが清書)を使う。かなり強引だが。
  • 対応しているコードハイライトが豊富

TortoiseSVN でコンテキストメニューが表示されない件

TortoiseSVNインストールされている。だけどコンテキストメニューが表示されない。どうやって出せばいい?

手順

こうしたら表示されるようになった。いつの間に設定したんだろ。

ちなみに、この方法は万人に当てはまる解決策ではないと思う。通常はレジストリをあれこれいじって頑張って復旧(?)するみたいだ。

ちなみに: 「次のパスではコンテキストメニューを表示しない」に関する調査やら

Ruby で end のエラーに苦戦する件(syntax error, unexpected keyword_end エラーなど)

だいぶ苦戦したけど、何とか対処できるようになった。なお、専用ツールは使ってない(探せばあるかも)。

まとめ

  • ruby -cw hoge.rb」で 「hoge.rb」の構文チェックができる
  • end 系のエラーが出た時は、行末でない「warning: mismatched indentations」と「syntax error, unexpected keyword_end」を探して、その行をよく見てみる
  • よくあるミス
    • 「for ... in ...」は間違い。正しくは「for ... in ... do」のように do が必要
    • 「if ... do」は間違い。正しくは「if ... then」のように then が必要

特に Python メインだった私は do や then には未だになれない。

以下調査メモ 簡単に調べた内容

end がどっかで漏れてるとこうなる(838は末尾行)

$ ruby -cw hoge.rb
hoge.rb:507: warning: mismatched indentations at 'end' with 'def' at 503
hoge.rb:838: syntax error, unexpected end-of-input, expecting keyword_end

end が余分にあるとこうなる。

hoge.rb:507: warning: mismatched indentations at 'end' with 'class' at 474
hoge.rb:508: syntax error, unexpected keyword_end, expecting end-of-input

if ... do と書いてしまったらこう。

hoge.rb:508: syntax error, unexpected keyword_do, expecting keyword_then or ';' or '\n'
hoge.rb:513: syntax error, unexpected keyword_end, expecting end-of-input

if の最後の end が抜けたらこう。

hoge.rb:510: warning: mismatched indentations at 'end' with 'if' at 508
hoge.rb:512: warning: mismatched indentations at 'end' with 'def' at 507

RSpec で Example Group や Example 内スコープの実行順序がよくわからんので調べてみた

ちょっと直感的じゃなかった(まだ RubyRSpec の文化?に慣れてないだけだろうが)ので、調べてみた。

続きを読む

WinSCP のミラーリングアップロードで手元 Windows マシンからサーバ Linux マシンへの SCP アップロードを自動化する

私は使い慣れた自分の Windows マシンでコード書いて、それを評価環境の Linux マシンに SCP で転送する、みたいなことをしているのだが、いちいち手作業アップロードするのはだるい。

WinSCP にこの手間を軽減する機能があった。

なお、確認時の WinSCP バージョンは 5.1.7(ビルド3446)。

手順

  1. Ctrl + U を押す
    • すると「リモートディレクトリを最新に保つ」ウィンドウが出てくる
  2. 「サブディレクトリも更新」と「ファイルの削除」にチェック入れて、開始ボタン押す
    • 「.git」フォルダなど不要なディレクトリを除外したい場合は、その設定も行っておくこと(方法失念。気が向いたら更新する)
  3. 確認ダイアログ「完全同期機能を先に実行しますか?……」が出るので、はいを押す

先にローカルとリモートのディレクトリは同一に保っておくこと。そうしないと「〜〜のディレクトリが見当たらないよ!」みたいなエラーが出てミラーリングが停止する。

無事成功したら、手元の Windows 側でファイルを更新するたびに、すぐさま WinSCPアップロードが働いて Linux 側も反映されるはず。これマジ便利。

Python で呼び出し時のコマンドライン文字列を生で取得する

結論: Python の機能だけでは不可能なので OSAPI を使いましょう

Python の機能だけでは不可能?

Python の機能だけでコマンドライン文字列を取得するには sys モジュールの sys.argv を使う。

が、こやつには生のコマンドライン文字列を加工した結果が入っている。

その加工処理を Python インタプリタは問答無用で実行してしまう。だから生では取れない。

生で取得する for Windows

winapi の GetCommandLine() を使う。

pywin32 モジュールを使うなら win32api.GetCommandLine() で取れる。

生で取得する for Linux(調べてないです)

必要無かったので調べてないです。ごめんなさい。

おまけ: GetCommandLine() の仕様

GetCommandLine() の実行結果はよく調べておかないとハマると思う。つーかハマった。

具体的に言うと、PATH や PATHEXT が補われる場合に、ちょっと中身が変わる。以下参照。

$ python print_getcommandline.py hoge fuga 1
[python  print_getcommandline.py hoge fuga 1]

$ print_getcommandline.py hoge fuga 1
["c:\bin1\Python27\python.exe" "c:\work\slot\python\print_getcommandline.py"  hoge fuga 1]

$ print_getcommandline hoge fuga 1
["c:\bin1\Python27\python.exe" "c:\work\slot\python\print_getcommandline.py"  hoge fuga 1]

2016-12-15

RSpec で Example 間で状態変数を共有したい

たとえば変数変数 state に対して、一つ目の it 内で state に結果を入れ、二つ目の it 内でその中身を検証する、みたいなケース。

RSpec は使い方も仕組みもテスト実行順序もカオスで正直意味不明なので、かなり苦戦した。

結論

Example(it や example)を並べてるスコープ(ブロック)の中で、使いたい変数を空定義しておく。

サンプル

# Responce と API は便宜上のテキトーなもの.
class Responce
  attr_accessor :status_code, :body
  def initialize()
    @status_code = nil
    @body = nil
  end

  def valid?()
    if @body.nil? then
      return false
    end
    return true
  end
end

class API
  def self.get()
    responce = Responce.new()
    responce.status_code = 200
    responce.body = "Information from API!"
    responce
  end
end

describe "上位スコープで空定義" do

  # ★ ここで空定義しておく.
  responce = nil

  it "項番1. APIから情報を取得できること" do
    responce = API.get()
    expect(responce.status_code).to equal(200)
  end

  it "項番2. APIから取得した情報が正しいこと" do
    # ★ 変数 responce を空定義しているおかげで, 
    #    項番1で取得した情報を利用できる.
    #
    #    空定義がない場合, 未定義ローカル変数とみなされ
    #    undefined local variable or method `responce' エラー.
    expect(responce).not_to be nil
    ret = responce.valid?
    expect(ret).to be true
  end
end

なんでこの結論?

代替案に関する疑問。

  • Q: before じゃダメなの?
    • A: ダメ。before はテストケース(it)毎に毎回実行されるので、項番1テストで取得した結果を項番2テストから使えない
  • Q: let じゃダメなの?
    • A: ダメ。let には遅延評価キャッシュの仕組みがあるが、それは同一テストケースの話であって、上記みたいに項番1と2でテストケース分けてる時は before と同じく毎回 let 内ブロックが評価されてしまい、やはり項番1テストで取った結果を項番2テスト時に見れない
  • Q: shared_context はダメなの?
    • A: ダメ。shared_context 内で空定義したものは includee 側の example group 内では認識されない。認識させるなら before や let を使う必要があるが、上記と同じ問題にぶち当たる
  • Q: じゃあ項番1と2を同じテストケースにぶちこんだら?
    • A: テストコード及びテスト実行結果出力の可読性が損なわれるからヤダ。まさか「puts "項番1..."」を書く、とか言わないよね。

仕組みに関する疑問

  • Q: 空定義は必要なの?
    • A: 必要。そうしないと項番2テストで「undefined local variable or method `responce'」エラーが出る。
  • Q: なんでこういう動作になるかがわからん。RSpec どうなってんの?
    • A: 想像だけど、RSpec はたぶんこんな動きになってる。
      • 1.example group(describeなど)を全て辿ってテスト実行順序及び階層関係をつくる。この時、describe 直下に書かれているコードは全て実行される
      • 2. 辿り終えたら、作った実行順序及び階層関係のデータに従い、example(itなど)を順番に実行していく

所感

  • RSpec の慣習にこだわらず、さっさと外側スコープに空定義するだけという簡易的なやり方にしておくべきだった。まあ RSpec についてちょっとは勉強になったのでよしとしよう。
  • そもそも外側スコープで変数定義するという書き方が想定されてない or おかしいんだろうけど。