kaakaa Blog

この世は極楽 空にはとんぼ

Gitでパスワードなどが入力されたファイルを履歴管理するとき

備忘録。

Gitを使って開発を進めている時に、なんらかのサービスのIDやパスワードなどの認証情報が記述されたファイルを扱いたいときがあります。

auth.conf

{
    "ID": "foo",
    "PASS": "bar"
}

開発中は自分のID/PASSを入力しますが、それをバージョン管理に乗せて公開したくはありません。
.gitignoreに記述すると、そもそも認証ファイル自体がバージョン管理に乗らないか、もしくは既にバージョン管理下にあるファイルに対しては.gitignore設定が効きません。

そんな時に使えるのがGitのskip-worktree。
既に git 管理しているファイルをあえて無視したい

最初にauth.confのサンプルファイルをadd/commitして、auth.confに対してskip-worktreeを設定すると、その後auth.confに自分のID/PASSを入力するなどの変更を加えてもステージングの対象とならないようになります。

MP3を結合してYouTubeにアップするものを作った

複数のMP3ファイルをくっつけてYouTubeにアップするものを作りました。
kaakaa/GroovyYouTubeUploader

バンドの練習で撮ったMP3群をYouTubeにアップする時に

  • 複数のMP3を結合
  • YouTubeにアップできるようビデオ形式に変換
  • 手作業でアップロード

とかやってて、不毛だと思ったので作りました。


mp3の結合とビデオ形式への変換はFFmpegを使ってます。
FFmpeg

YouTubeにアップする部分はYouTube Data APIのサンプルをちょっといじって。
youtube-api-samples - YouTube API Sample Applications - Google Project Hosting

詳しい説明はGithubに書いてるつもり…

      • -

作ってる間に色々調べすぎてブラウザのタブ数がエラいことなっていたので吐き出しておきます。。

MP3ファイルに静止画を付けてビデオファイルに変換する

How to Encode Videos for YouTube and other Video Sharing Sites

Create a video with a still image (input.png) and an audio file (audio.ogg):

  ffmpeg -loop 1 -r 2 -i input.png -i audio.ogg -c:v libx264 -preset medium -tune stillimage -crf 18 -c:a copy -shortest -pix_fmt yuv420p output.mkv

ffmpegはオプションが多くて難しいけど、凄く便利そう。

Google Developer Consoleでアプリケーションを登録したのに、ファイルがアップロードできない

google api - Error: invalid_client no application name - Stack Overflow

"PRODUCT NAME"と"Email address"の設定も必要らしい。

YouTube Data APIでアップロードする動画の公開範囲を変更したい

VideoStatus (YouTube Data API v3 (Rev. 94) 1.17.0-rc)

VideoStatus#setPrivacyStatus(String privacyStatus)で設定可能。
設定出来るのは

  • public(公開)
  • unlisted(限定公開)
  • private(非公開)

一応、今回作ったアプリではconfファイルで設定可能にしました。

MavenプロジェクトをGradleプロジェクトに変更する

Gradle1.9でsetupBuildがinitに - 日々常々

PowerPoint資料のアップローダ的なもの

Linux上で動作するパワポアップローダを作ってる。
kaakaa/PPTGallery

パワポの資料共有にファイルの配布じゃなく、Web上で完結できるように出来ないかな〜というのが始まり。
ファイルダウンロードして開くのが面倒に感じたのと、Sinatraと諸々のツール使えば出来そうだったので。


今のところこんな感じのBootstrap色全開の画面。

ppt/pptxのファイルをアップロードすると、諸々変換かかって、PNGをスライド形式で閲覧できるHTMLのビューワが生成されます。



現状、CentOS6.3での動作を確認しています。
環境構築はChefのcookbook化しようとしてるけど、イマイチ上手く動かない…。
kaakaa/PPTGallery_vagrant
まぁ、とりあえず必要なツール一覧として残しています。


内部構造としては諸々の変換ツールのWebインタフェースをSinatraで作っただけな感じ。


Rubyっぽくないコードの海で溺れてます。
さすがにRubyの本読まないと。

GStringの評価タイミングを勘違いしてた

GStringヒアドキュメント?で記述したスクリプトをGroovyShell#evaluateで評価しようとした時に、GString内のプレースホルダーが評価される場所を勘違いしていてハマったという話。

GString内のプレースホルダーはevaluateの前で評価される。
GString interpolation not working with GroovyShell ?


以下、経緯。

GroovyDSLを作ろうとしてGStringでハマった。

あとから要素を追加しやすいよう、methodMissingを使って動的にプロパティを追加できるようにしました。

def dsl = """\
person {
    name('Foo')
    age('28')
}
"""

def script = """\
def person(Closure closure) {
    def person = new Person()
    closure.delegate = person
    closure()
    
    println person.profile()
}

class Person {
    Person() {
        def mc = new ExpandoMetaClass( Person, false, true)
        mc.initialize()
        this.metaClass = mc
    }
    
    // ここで動的にプロパティを追加したい
    def methodMissing(String name, args) {
        this.metaClass."${name}" = args[0]
    }
    
    def profile(){
        this.properties
    }
}
"""

new GroovyShell().evaluate("""\
${dsl}
${script}
""")

実行するとエラー。

Exception thrown

groovy.lang.MissingPropertyException: No such property: methodName for class: ConsoleScript30

	at ConsoleScript30.run(ConsoleScript30:8)

methodMissingに引数methodNameが上手く渡って無いのが原因かと思い、

    def methodMissing(String methodName, args) {
        def methodName = 'hello'
        this.metaClass."${methodName}" = args[0]
    }

とかしてみたけど変わらず。

エラーの原因は一番上に書いた通りなので、変数dsl,scriptの宣言をGStringでなくシングルクォートのヒアドキュメントにしたら動きました。

def dsl = '''\
person {
    name('Foo')
    age('28')
}
'''

def script = '''\
def person(Closure closure) {
    def person = new Person()
    closure.delegate = person
    closure()
    
    println person.profile()
}

class Person {
    Person() {
        def mc = new ExpandoMetaClass( Person, false, true)
        mc.initialize()
        this.metaClass = mc
    }
    
    // ここで動的にプロパティを追加したい
    def methodMissing(String methodName, args) {
        this.metaClass."${methodName}" = args[0]
    }
    
    def profile(){
        this.properties
    }
}
'''

new GroovyShell().evaluate("""\
${dsl}
${script}
""")
[class:class Person, age:28, name:Foo]

TracWikiで投稿時間を表示するマクロについて考える

とりあえず調べたところまでを残しておく。


TracWikiに書き込んだ時間を残しておける機能が欲しくて色々調べてる。
Pukiwikiの"time?"みたいな記法。

TimestampMacroなんてのもあるけど、コレはページを更新した時間を表示するものなので、目的とは違う。
あくまでも表示したいのは書き込んだ時間。

TracDBのWikiテーブルを見ると、Wiki記法から生成されるHTMLは保存されておらず、TracWiki記法のテキスト保存されていないようなので、ページをレンダリングする時にparseなりしてHTMLを生成しているんだと思う。
(パーサを調べてみるのも面白そうだなぁ… TracのWikiパーサを読むAdd Star)
なので、DBに格納される前にちょろまかさないとレンダリングされる度に時刻が更新されてしまうことになる。

とりあえずTracのソースをちょろちょろ見てみると、${TRAC_HOME}\python-lib\trac\trac\wiki\model.pyのsaveメソッドWikiに書き込んだ情報をDBに格納しているみたい。

    def save(self, author, comment, remote_addr, t=None, db=None):
        if not validate_page_name(self.name):
            raise TracError(_("Invalid Wiki page name '%(name)s'",
                              name=self.name))

        new_text = self.text != self.old_text
        if not new_text and self.readonly == self.old_readonly:
            raise TracError(_('Page not modified'))
        t = t or datetime.now(utc)

        @self.env.with_transaction(db)
        def do_save(db):
            cursor = db.cursor()
            if new_text:
                cursor.execute("""
                    INSERT INTO wiki (name,version,time,author,ipnr,text,
                                      comment,readonly)
                    VALUES (%s,%s,%s,%s,%s,%s,%s,%s)
                    """, (self.name, self.version + 1, to_utimestamp(t),
                          author, remote_addr, self.text, comment,
                          self.readonly))
                self.version += 1
                self.resource = self.resource(version=self.version)
            else:
                cursor.execute("UPDATE wiki SET readonly=%s WHERE name=%s",
                               (self.readonly, self.name))
            if self.version == 1:
                # Invalidate page name cache
                del WikiSystem(self.env).pages
        
        self.author = author
        self.comment = comment
        self.time = t

        for listener in WikiSystem(self.env).change_listeners:
            if self.version == 1:
                listener.wiki_page_added(self)
            else:
                listener.wiki_page_changed(self, self.version, t, comment,
                                           author, remote_addr)

        self.old_readonly = self.readonly
        self.old_text = self.text

DBに格納する前にself.text内の「time?」だか何だかの正規表現でひっかけて置換かければ出来ないことはなさそうだけど、悪手な臭いがしてためらっている。

Tracが用意してる拡張ポイントでも無いし、{{{ 〜 }}}で囲んだ部分のも置換してしまうだろうし。

まぁ、とりあえず今日はここまで。

Middleman-blogとGithub Pagesを利用したブログ

勉強会用資料。

広く浅く。


質問

Webサービスの値段はどれぐらい?

GitHub · Build software better, together.
Travis CI: Continuous Integration and Deployment That Just Works
Coveralls - Test Coverage History & Statistics
Gemnasium
Pricing - Code Climate

TraviceCIとCode Climateは特段高価。
他は、まぁ恩恵あるなら払っても良いかぐらいな値段ですね。

払わないけど。

静的HTML生成ツールであるMiddlemanでコメント欄とかどうすんの?

Disqusというサービスと使ったりするらしいです。
Using Disqus

ただ、1ページに1枠しか設置できないみたいなので、ブログもそれに合わせたレイアウトになりそう。
各日ごとにコメントがそれぞれ保存できたりするんかな?ちょっと使ってみないと分からない。

TravisCIなどからGithubへのPushはどうやってフックする?

Step four - Trigger Your First Build With a Git Push

Once GitHub hook is set up, push your commit that adds .travis.yml to your repository. That should add a build into one of the queues on Travis CI and your build will start as soon as one worker for your language is available.

リポジトリへのPushによってビルドキューに貯まる」という記述を見ると、Github側からビルドキューを投げてる感じでしょうか?

はてなダイアリーの記事をMarkdown形式に一括変換

はじめに

はてな記法があまり好きになれないのとフロントエンドを触るために、ブログをGithub Pagesに移行しようと思っている。
middleman-blogをgithubでホストする

middlemanを使えば好きなエディタで記事書けるし、記法も最近よく使うMarkdownを使えるので便利そうだな、と。

そのために今まではてなで書いてきた記事を、Markdown形式にして移行できないか調べてみた。

調査

とりあえずはてなの記事を取得するのはAtomPub使えば良さそう。
はてなダイアリーAtomPub - Hatena Developer Center

認証突破にはwsseを使う。
RubyでAtompubのWSSE認証 - Panty's
取得したAtomの解析にはREXMLを。
XML処理 REXMLの使い方 - プログラムメモ

記事HTMLをMarkdown形式に変更するにはPandocを使うと良さそう。
Pandoc - About pandoc
Rubyのラッパーもあるし。
alphabetum/pandoc-ruby

成果物

作ってみた。
kaakaa/hatena2md

とりあえず大まかには変換できてるけど、middleman-blogに読み込ませると表示がおかしな部分が多々…。まぁ、昔の記事へのリンク貼っておけば良いか。
あと、middleman-blog用のMarkdownなのでタイトルやタグなどのヘッダがついてます。