IntelliJ Ideaでgradleのサブブロジェクト構成をビルドするとエラーになる問題

Error:scalac: Error: object scala.runtime in compiler mirror not found.
scala.reflect.internal.MissingRequirementError: object scala.runtime in compiler mirror not found.
	at scala.reflect.internal.MissingRequirementError$.signal(MissingRequirementError.scala:16)
	at scala.reflect.internal.MissingRequirementError$.notFound(MissingRequirementError.scala:17)
	at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:48)
	at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:40)
	at scala.reflect.internal.Mirrors$RootsBase.getModuleOrClass(Mirrors.scala:61)
	at scala.reflect.internal.Mirrors$RootsBase.getPackage(Mirrors.scala:172)
	at scala.reflect.internal.Mirrors$RootsBase.getRequiredPackage(Mirrors.scala:175)
	at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage$lzycompute(Definitions.scala:183)
	at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackage(Definitions.scala:183)
	at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass$lzycompute(Definitions.scala:184)
	at scala.reflect.internal.Definitions$DefinitionsClass.RuntimePackageClass(Definitions.scala:184)
	at scala.reflect.internal.Definitions$DefinitionsClass.AnnotationDefaultAttr$lzycompute(Definitions.scala:1024)
	at scala.reflect.internal.Definitions$DefinitionsClass.AnnotationDefaultAttr(Definitions.scala:1023)
	at scala.reflect.internal.Definitions$DefinitionsClass.syntheticCoreClasses$lzycompute(Definitions.scala:1153)
	at scala.reflect.internal.Definitions$DefinitionsClass.syntheticCoreClasses(Definitions.scala:1152)
	at scala.reflect.internal.Definitions$DefinitionsClass.symbolsNotPresentInBytecode$lzycompute(Definitions.scala:1196)
	at scala.reflect.internal.Definitions$DefinitionsClass.symbolsNotPresentInBytecode(Definitions.scala:1196)
	at scala.reflect.internal.Definitions$DefinitionsClass.init(Definitions.scala:1261)
	at scala.tools.nsc.Global$Run.<init>(Global.scala:1290)
	at xsbt.CachedCompiler0$$anon$2.<init>(CompilerInterface.scala:116)
	at xsbt.CachedCompiler0.run(CompilerInterface.scala:116)
	at xsbt.CachedCompiler0.run(CompilerInterface.scala:102)
	at xsbt.CompilerInterface.run(CompilerInterface.scala:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:102)
	at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:48)
	at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:41)
	at org.jetbrains.jps.incremental.scala.local.IdeaIncrementalCompiler.compile(IdeaIncrementalCompiler.scala:28)
	at org.jetbrains.jps.incremental.scala.local.LocalServer.compile(LocalServer.scala:25)
	at org.jetbrains.jps.incremental.scala.remote.Main$.make(Main.scala:58)
	at org.jetbrains.jps.incremental.scala.remote.Main$.nailMain(Main.scala:21)
	at org.jetbrains.jps.incremental.scala.remote.Main.nailMain(Main.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.martiansoftware.nailgun.NGSession.run(NGSession.java:319)

対応方法

$ cd {project_root}
$ find . -name "*.iml" | xargs rm -rf      #idea設定を全削除
$ find . -name ".idea" | xargs rm -rf      # ideaプロジェクト設定を削除
$ gradle clean                                       # gradleきれいにしてから
$ gradle build -x test                          # 一度、全ビルドしてからの
$ gradle idea                                        # idea設定を作成

IntelliJ IDEA13 CEのコード実行(Run)の種類

ささっと書いて実行するときにどのショートカットキー(keymap)を使っていいのかわからなかったので。
MacOSです


コンフィグレーションを選択して実行

Option  + Shift + F10



(前回と同じものを)実行

Shift   + F10



現在の状況を実行
※現在の状況 = アクティブなエディタや選択中のファイルで実行可能な形式(extends AppなのかUnitTestなのかとかをよしなに判断してくれるっぽい)

Ctrl + Shift + F10


なので、基本はCtrl + Shift + F10を連打しときゃいいのかな

IntelliJ 13 CE + Scala + Gradleでのプロジェクト作成


こんなクールな操作で開発ができるようになりたい

intellij CEをダウンロード

コミュニティエディションをダウンロードしてきます
http://www.jetbrains.com/idea/download/index.html

vimプラグインScalaプラグインを追加

ググると出てくるのでその通りに。

Gradleプロジェクトを作成

  • Use Auto-import(build.gradleを修正すると各種インポートが自動的に行われるっぽい)
  • Create directories for empty content roots automatically(今回で言うとScalaプラグインを作成した時のディレクトリ構造が自動的に追加されるっぽい)
  • User default gradle warpper(Mac上のgraldeではなくgradle-wrapperを使う)

f:id:flick-flick:20140216233722p:plain

build.graldeにscala Pluginを追加

build.graldeをエディタで開いて

apply plugin: 'scala'

を追記する

「Create directories for empty content roots automatically」が有効になっていると自動的にsrc/main/scalaディレクトリが自動で作成される

build.gradleにscala-compilerまわりのdependencyを追加

gradleでScalaコンパイルするために追加

apply plugin: 'java'
apply plugin: 'scala'

sourceCompatibility = 1.5
version = '1.0'


repositories {
    mavenCentral()
}

ext {
    scalaVersion = '2.10'
    scalaVersionRevision = '3'
    scalazVersion = '7.0.5'
    specs2Version = '2.3.4'
}

dependencies {
    compile "org.scala-lang:scala-compiler:$scalaVersion.$scalaVersionRevision"
    compile "org.scala-lang:scala-library:$scalaVersion.$scalaVersionRevision"
    compile "org.scala-lang:scala-reflect:$scalaVersion.$scalaVersionRevision"
}

Scalaコンパイラをライブラリとして設定する

IntelliJのGradle対応の問題なのか、Scalaプラグインの問題なのかしらんがgraldeでのscalacompilerへの依存をIntelliJが認識してくれないので、ライブラリとして
インストールして認識させる。

mavenを使ってscala-compilerをダウンロード
f:id:flick-flick:20140216234608p:plain
プロジェクト設定でFacetにScalaを追加してCompiler Libraryとして認識させる
f:id:flick-flick:20140216234808p:plain

試しに実行してみる

src/main/scalaにMain.scalaみたいな適当objectを作る

object Main extends App{
  println("hoge")
}

Main.scala上でRun(Ctrl + Shift + F10)してhogeがコンソールに表示されればOK

eclipseを使ってvert.xを起動する

Eclipseでvert.xをローカルで起動するのに、 Gradle テンプレートを使うってのは見かけたけどmavenプロジェクトの記事があまり見当たらなかったので覚え書き。
Eclipse Java EE IDE for Web Developers.Version: Juno Service Release 2
mavenはm2eプラグインを使用。


eclipsemavenプロジェクトを作成して、Archetypeをvertxを選択する。
f:id:flick-flick:20130911015640p:plain
f:id:flick-flick:20130911015641p:plain

maven-dependency-plugin (goals “copy-dependencies”, “unpack”) is not supported by m2e

というpom.xmlのエラーが出るので
こちらの書き込みに従いタグの直下にpluginManagement以下を追記する

これでプロジェクトのエラーが消えるので、試しにfooパッケージに

package foo;
import org.vertx.java.core.Handler;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.platform.Verticle;

public class HelloWorldVerticle extends Verticle {
	public void start() {
		container.logger().info("Verticle start.");
		vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
			public void handle(HttpServerRequest req) {
				req.response().headers().set("Content-Type", "text/plain");
				req.response().end("Hello World!");
			}
		}).listen(8080);
	}
}

というテストコードをServer.javaという名前で置いてみる。
さらに
src/main/resources/mod.jsonの

  "main":"foo.PingVerticle",

    "main":"foo.Server",

に変更する

eclipseのプロジェクトを右クリックRunからmaven buildで起動する。
f:id:flick-flick:20130911015642p:plain
※CLIの場合はmvn vertx:runModEclipseを叩く。

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Project - testio 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- vertx-maven-plugin:2.0.0-final:runModEclipse (default-cli) @ testio ---
[INFO] CTRL-C to stop server

とかログが出るので,ブラウザからlocalhost:8080でhello worldが出ればおk

pythonでJpeg画像のexifを編集する

ある時子供を撮影するのによく使っているデジカメNEX-5の初期設定を誤ったらしく、全部の写真の日付が一年前になっていることに気づいた。

印刷する時に日付を入れる場合は全部一年ずれて日付がついてしまうので、今までNEX-5で撮った写真のexifを書き換えるためのスクリプトを書いた。



とりあえずpythonexifをいじるために調べて最初に出てきたのはPython Imaging Libraryだったが、どうやらexifを読み込む機能しかないらしい。
http://www.pythonware.com/products/pil/

pyexiv2というのがイケてるらしいのでこれでスクリプトを書くことにする。
Python で JPEG の Exif などを扱う
チュートリアル


Mac上にvagrantでubuntu12環境を用意した上でpyexiv2をインストールする

apt-get install python-pyexiv2

これで終わり。
あとはpyexiv2を使った普通にexifの日付情報を一年進めて書き換えた上で保存すればOK

import sys
import os
import stat
import datetime
import pyexiv2

targetDir = "/home/vagrant/100MSDCF_2/"
count = 0
for fileName in os.listdir(targetDir):
	f = targetDir + fileName
	s = os.stat(f)
	times = (s[stat.ST_MTIME], s[stat.ST_MTIME])
	mtime = datetime.datetime.fromtimestamp(s[stat.ST_MTIME])

	metadata = pyexiv2.ImageMetadata(f)
	metadata.read()
	dateTimeTag = metadata['Exif.Image.DateTime']
	dateTimeOriginalTag = metadata['Exif.Photo.DateTimeOriginal']
	dateTimeDigitizedTag = metadata['Exif.Photo.DateTimeDigitized']
	thumbnailDateTimeTag = metadata['Exif.Thumbnail.DateTime']

	dateTimeTag.value = dateTimeTag.value + datetime.timedelta(days = 366)
	dateTimeOriginalTag.value = dateTimeOriginalTag.value + datetime.timedelta(days = 366)
	dateTimeDigitizedTag.value = dateTimeDigitizedTag.value + datetime.timedelta(days = 366)
	thumbnailDateTimeTag.value = thumbnailDateTimeTag.value + datetime.timedelta(days = 366)

	print "convert done " + f + " ->" + dateTimeTag.raw_value
	metadata.write()
	count += 1
print str(count) + " files done"

それにしてもぱぱっとubuntuとか必要な環境を作れちゃうvagrantはほんと便利ですなー。

subversionを使ったA successful Git branching modelの運用


現在のプロジェクトではsubversionを使っているのですが、10人ほどの開発メンバーで並行開発をしているためA successful Git branching modelを参考にFeature branchesを活用した開発スタイルにしています。

A successful Git branching model を翻訳しました


しかしどうしてもブランチの統合時に意味不明なコンフリクト(競合)が発生してしまい、その度に手動(というか目視やメンバー同士の確認)でのマージを行なっておりリリースや統合が高コストになっていました。


例えば以下のような場合

2.のマージの時にfeature1ブランチにhello.jpgがコミットされたという変更履歴が残るため、3.のdevelopへのマージの際にはfeature1ブランチの変更点(コミット)を全てマージしようとするため、再度developにhello.jpgをコミットしてしまうようです。


調べた所reintegrateというオプションを見つけました。

Subversion 1.5 以降での機能ブランチのマージ

ブランチをトランクにマージするときは、--reintegrate オプションを付ける。

    • reintegrate オプションを使うこの形式のマージは一つのブランチにつき一回だけ行える (その後ブランチを更新してもそれをトランクにマージできないので、ブランチはただちに削除するとよい)。ブランチでの変更のうち、トランクからブランチへのマージによるもの以外の変更がトランクに適用され、自動的に svn:mergeinfo 属性が更新される

Eclipsesubversiveを使っている場合はマージウィンドウのタブに該当の機能がありました。

ここからマージ作業を行えば、晴れてブランチでの修正分のみがdevelopに取り込めましたとさ!


追記:
mergeの方法についてなのですがdevelop -> featureブランチへの取り込み時に手動でマージ(ファイルを上書きするとか差分エディタで書き込むとか)すると、svn管理上のmergeinfoというプロパティがセットされません。
そのため、reintegrateマージの際に上記コミットがマージコミットとして認識されずに、developへのマージ時にコンフリクトしてしまいます。

developからfeatureブランチへの取り込みの際は必ずmergeコマンド(or eclipseのマージ機能)を使うようにしましょう。
http://www.asahi-net.or.jp/~iu9m-tcym/svndoc/svn_mergeinfo.html

Ubuntu 12.04 LTS上にjsアプリケーション環境構築

  • vimとtmuxの設定ファイルをcloneして設定
git clone https://github.com/waysaku/dotfiles.git
cp ~/ ~/dotfiles/.vimrc
cp ~/ ~/dotfiles/.tmux.conf
  • vimのvundle環境構築
git clone http://github.com/gmarik/vundle.git ~/.vim/vundle.git
  • nvmインストール

ここみてインストールする

  • nvmを使ってnodeの最新版をインストール
$ nvm install v0.11.2
  • gruntインストール
npm install -g grunt-cli
  • ruby1.9とrubygemをインストール
apt-get install ruby1.9.1 rubygems
  • sassをインストール
gem install sass
  • compassをインストール
gem install compass
  • hostを書き換え
echo "[ip] [host]" >> /etc/hosts
  • ssh-key作成してGHEに登録
ssh-keygen -t rsa