最低限おさえておきたいEGitの使い方について
最近ソース管理にGitを使うプロジェクトがかなり増えてきました。ソース管理はSVNで十分と思っているユーザもプロジェクトの方針としてGitになった場合、最低限の操作を覚えないと作業に支障をきたしてしまいます。その際にコマンドラインで操作しても良いのですが、今までSVNでSubversiveとかSubclipseなどを使ってきたEclipseユーザは、EclipseからGitを操作したいところです。
そこでEGitを使おうと思ってもEGit自体はそこそこ歴史がある割に意外と情報が少なくて困ってしまった人もいるのではないでしょうか?。
今回はプロジェクトで使うに当たって、最低限知っておけばどうにかなりそうな操作をまとめてみることにしました。構成としては利用者側としてGitを利用することを想定してみました。実際、作業して順番とは違うのでファイルに一部矛盾するところがありますが気にしないでください。
私自身まだまだ知らないことも多いので、間違っている点やもっと効率よく出来る点などがございましたらご指摘ください。
環境としては以下で試しています。
OS:Mac
Eclipse:3.6
EGit:1.0
Gitのリモートリポジトリからプロジェクトを取得
誰かがGitに上げたプロジェクトをEclipseに取り込みます。Gitではcloneすると言います。
Package Explorerを右クリック>importを選択します。
取得するリポジトリを指定します。GitHubの場合、Webでコピー出来るurlをURL欄にコピーします。Protocol欄にSSHを選択します。するとURL欄がSSHにあわせて変更されますが、そのままでかまいません。nextをクリックします。
cloneするリポジトリを選択してnextをクリックします。
ローカルリポジトリを作成する必要があるのでパスを指定します。指定したらfinishをクリックします。
importするプロジェクトの選択が表示されます。そのままnextをクリックします。
今回はEclipseプロジェクトをGitからcloneするので、Import Existing Projectsにチェックしてnextを押します。
importしたいプロジェクトを選択してfinishをクリックします。
これでEclipseにプロジェクトをcloneすることが出来ました。
ローカルリポジトリへのcommit
Gitの場合、ファイルを修正したらまずはローカルリポジトリにcommitします。
では現在のプロジェクトをローカルリポジトリにcommitしてみます。右クリック>Team>Commitを選択します。
コミットダイアログが表示されるのでコメントの入力とコミットするファイルを選択して、commitボタンを押します。
これでローカルリポジトリにコミットが出来ました。マーク「?」が消えているのが確認出来ると思います。
Gitの場合、commitしただけではソースを反映することが出来ません。その後にリモートリポジトリに対してpushする必要があります。続いてリモートリポジトリにpushする方法についてです。
リモートリポジトリにpushする
ローカルリポジトリにcommitしたらリモートリポジトリに反映させるためにpushする必要があります。
プロジェクトを選択して、右クリック>Team>Remote>Pushをクリックします。
pushするリポジトリを設定してnextをクリックします。
選択したらAdd Specボタンをクリックします。するとSpecifications for pushに設定が反映されます。nextをクリックします。
自分や他の人が変更した内容の確認
変更を確認します。
プロジェクトを選択して右クリック>Team>Synchronize>FETCH_HEADを選択します。
Synchronizing perspectiveを表示するかとダイアログで訪ねられます。YesでもNoでもかまいません。ここではYesを選択します。
リポジトリとの差分が表示されます。ここでは、HelloWorld.scalaが他の人から編集されて、HelloWorld2.scalaが自分が新規に作成したことを表しています。
ファイルをダブルクリックすると差分を確認することが出来ます。
HelloWorld.scalaを選択して右クリック>Mergeで取り込むことが出来ます。
自分の更新は通常と同じようにcommit→pushで対応します。
ローカルリポジトリの登録
一応、プロジェクトの登録についても説明します。ここではGitTestというプロジェクトを登録してみることにします。
まずは、プロジェクトを選択して、右クリック>Team>Share Projectを選択します。
ローカルリポジトリのパスを指定してリポジトリを作成します。createボタンを押して選択ダイアログを表示されます。
ローカルのGitリポジトリのパスを選択します。好きな場所を選択しましょう。ここでは、/local_gitを指定しました。名前にGitTestを指定しました。
チェックボックス「Use or create Repository in parent folder of project」にチェックをつけると現在のプロジェクトにリポジトリを作ることも出来ます。
注意点としては、その後リモートリポジトリに登録した際にリポジトリを指定する方の方法だとGitTestリポジトリの下にEclipseのGitTestプロジェクトが配置されるような構成になるようです。チェックボックスをチェックする方法だとGitTestリポジトリの下にGitTestフォルダは作られません。GitHubで有料オプションを使用していて利用出来るリポジトリに制限がある場合などは上のパターンを利用した方がよいでしょう。
自分でリポジトリの場所を選んだ場合
チェックボックス「Use or create Repository in parent folder of project」にチェックをつけた場合
リポジトリを選択したらFinishボタンを押して終了です。
リポジトリの設定が出来ました。以下のような感じになっていると思います。
終わりに
今回はEGitについてまとめました。画像をふんだんに使用したため何気にものすごく手間がかかりました。EGitは安定していないかな?と感じることもありますが十分に実用で使用出来るレベルに達してきていると思います。私自身も知らない機能がたくさんあるのでご存知の方は色々と教えていただけるとありがたいです。
EGitについてさらに詳しく知りたい場合は、以下にUser Guideがあるので参照してみてください。
http://wiki.eclipse.org/EGit/User_Guide
忘れやすい人のためにscpコマンドメモ
いつも忘れてしまうのでメモ。いまいちネットを検索しても直感的に分かる情報がなくて困る。
リモートからローカルにコピー
scp ユーザ名@リモートのホスト名:コピーしたいリモートのファイル .
以下の場合、今いるカレントディレクトリにリモートremoteHostのユーザuserでtext.txtをコピーする。
scp user@remoteHost:/home/user/test.txt .
ローカルからリモートにコピー
scp コピーしたいローカルのファイルパス ユーザ名@リモートのホスト名:保存したいパス
ローカルのtext.txtをremoteHostのユーザuserで/home/user/tmp/にコピーする。
scp test.txt user@remoteHost:/home/user/tmp/
Ubuntuにkyoto tycoonをインストールしてみた。
色々とKVSを調べているのですが、kyoto tycoonがRDBMSとレプリケーションできたりするみたいで興味深かったので試しにインストールしてみました。
wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.52.tar.gz apt-get install g++ apt-get install zlib-devel tar -zxvf kyotocabinet-1.2.52.tar.gz cd kyotocabinet-1.2.52 ./configure →zlib.hがないと怒られる zlib.hを探して入れる apt-get install apt-file apt-file update apt-file search zlib.h apt-get install zlib1g-dev ./configure make make install wget http://fallabs.com/kyototycoon/pkg/kyototycoon-0.9.40.tar.gz tar -zxvf kyototycoon-0.9.40.tar.gz cd kyototycoon-0.9.40 ./configure make make install /user/local/bin/ktserver エラーが出た ktserver: error while loading shared libraries: libkyototycoon.so.2: cannot open shared object file: No such file or directory ldd ktserver linux-gate.so.1 => (0xb7837000) libkyototycoon.so.2 => not found libkyotocabinet.so.9 => not found libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7739000) libm.so.6 => /lib/libm.so.6 (0xb7712000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb76f4000) libc.so.6 => /lib/libc.so.6 (0xb75af000) libpthread.so.0 => /lib/libpthread.so.0 (0xb7596000) /lib/ld-linux.so.2 (0xb7838000) vim /etc/ld.so.conf /usr/local/lib←追加 ldconfig /user/local/bin/ktserver
動作確認
set ktremotemgr set japan tokyo ktremotemgr set korea seoul ktremotemgr set china beijing 確認 ktremotemgr inform get ktremotemgr get japan keyのリスト取得 ktremotemgr list
Liftの入門(lift-mapperのquery編)
今回はlift-mapperのQuery関係をまとめます。MappedFieldが先なのではと思わないでもないですがQueryです。lift-mapperは、toFormやtoHtmlであったりモデルのくせにビューにくっついていたり色々知っておかなくてはいけないことがあるのですが、まずはQuery関係に絞って説明します。リファレンス的に使えればと思います。
本題に入る前にちょっとTips
発行したSQLのログを出したい
Boot.scalaに以下を記述
class Boot extends LazyLoggable { ・・・ DB.addLogFunc { case (query, time) => { logger.info("All queries took " + time + "ms: ") query.allEntries.foreach({ case DBLogEntry(stmt, duration) => logger.info(stmt + " took " + duration + "ms")}) logger.info("End queries") } }
テーブル名やカラム名を_(アンダーバー)区切りにする
デフォルトだとemployeeNameのようなカラムでテーブルが作成されたり、sqlが発行されたりするので、それをemployee_nameに変える方法です。これもBoot.scalaに記述します。
LiftRules.stripComments.default.set(() => false) import net.liftweb.util.Helpers MapperRules.columnName = (_,name) => Helpers.snakify(name) MapperRules.tableName = (_,name) => Helpers.snakify(name)
scalaのコンソールでBoot.scalaを動かしたい。
コンソールを起動して以下を入力。
scala>(new bootstrap.liftweb.Boot).boot
では本題に入ります。なお、完全に網羅するものではないのであしからず。
データをinsertする。
戻り値がbooleanの場合。保存に成功すればtrue。
val result = Employee.create.name("test").jobType(JobType.ANALYST).salary(300).save
戻り値がmodel。
val emp = Employee.create.name("test").jobType(JobType.ANALYST).salary(300).saveMe
keyで1件取得する。
val emp: Box[Employee] = Employee.find(1)
全件取得する。
val empList : List[Employee] = Employee.findAll
条件を指定する。
SQLとしては、「where id > 5」となる。
val empList : List[Employee] = Employee.findAll(By_>(Employee.id, 5))
逆もあります。「where id < 5」
val empList : List[Employee] = Employee.findAll(By_<(Employee.id, 5))
イコールもいけます。「where id = 5」
val empList : List[Employee] = Employee.findAll(By(Employee.id, 5))
検索結果を削除する。
modelのobjectから消すにはdelete_!を使います。
val emp: Employee = Employee.find(1).open_! val result: Boolean = Employee.delete_!(emp)
※open_!はBox型から値を取得
条件指定で削除する。
条件を指定するにはbulkDelete_!!を使います。ここではLikeを使っています。findAllとかでもLike使えます。
val result: Boolean = Employee.bulkDelete_!!(Like(Employee.name, "山田%"))
件数を取得する。
件数を取得するにはcountを利用します。
val count: Long = Employee.count
条件指定も出来ます。
val count: Long = Employee.count(By(Employee.name, "山田 太郎"))
order byを指定する。
descの場合
Employee.findAll(OrderBy(Employee.name,Descending))
ascの場合(複数も指定出来ます)
Employee.findAll(OrderBy(Employee.name,Ascending),OrderBy(Employee.jobType, Ascending))
取得する件数と何件目から取得するか指定する。
以下だと10件目から5件取得する。
val empList: List[Employee] = Employee.findAll(StartAt(10),MaxRows(5))
SQLを直接発行する。
一つ目のリストにヘッダ名、二つ目のリストに値のリストが取れます。
val resultList: (List[String], List[List[String]]) = DB.runQuery("select * from employee") val headerList: List[String] = resultList._1 val bodyList: List[List[String]] = resultList._2
とりあえず、ざっくりとはこんな感じです。まだまだあるのですが僕自身がリファレンス的に参照しててあった方が便利だと感じたら追加します。
Liftの入門(intellijでの開発環境編)
※2011/4/17追記 jrebelプラグインの設定がもれていたので追記しました。
liftで開発環境を整える際に知らないと手間がかかるのでまとめておきます。ここではintellijを利用します。
IDEはintellijの他にはEclipse、Netbeans、ensimeなどがあります。ビルドツールには、sbtとmavenがあります。昔はmavenでしたが、最近はsbtの利用が推奨されているようです。
今回構築する環境のバージョンは以下の通りです。
intellij:10
sbt:0.74
lift:2.3
scala:2.8.1.final
注:OSはMacを利用しています。Windows環境とは多少異なる部分がありますがWindowsでも構築したとこがありますが問題ないと思います。
intellijのダウンロード
intellijを以下のサイトからダウンロードします。
http://www.jetbrains.com/idea/download/index.html
intellijにプラグインのインストール
intelljでIntellij IDEA>Preferencs>Pluginsを選択します。
PluginsのAvailableタブを開いて、検索窓にscalaと入力して以下のプラグインをインストールします。
jrebelプラグインもインストールします。
※jrebelとはアプリケーションサーバ(jettyとか)を再起動せずにコードに変更があった場合に自動で再読み込みをしてくれるツールです。
jrebelの入手とjrebelプラグインの設定
jrebelはhttp://www.zeroturnaround.com/jrebel/からダウンロードします。
jrebelプラグインの設定をします。メニューのIntelliJ IDEA>Preferencesでjrebelを選択して上記URLから入手したjrebel.jarのパスを指定します。
liftのブランクプロジェクトの入手
liftのサイト(http://liftweb.net/)からブランクプロジェクトをダウンロードします。
アーカイブを解凍するといくつかプロジェクトが入っています。DB接続をしたいならlift_basicかlift_xhtml辺りがいいと思います。lift_blankだとDB接続の設定がされていないです。
ブランクプロジェクトの修正
intellijで取り込めるようにするにはいくつか追加/修正が必要です。
1.sbt-idea-pluginの設定
intellijで利用するために必要なプラグインをダウンロードする設定を行います。
[プロジェクト]/project/plugins/Plugins.scalaを作成します。
Plugins.scala
import sbt._ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { val sbtIdeaRepo = "sbt-idea-repo" at "http://mpeltonen.github.com/maven/" val sbtIdea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.4.0" }
sbt-idea-pluginは現在0.4.0が最新です。0.5が開発中みたいです。
project/build/LiftProject.scalaの修正
intellijに取り込むための設定を追加します。
【修正前】
class LiftProject(info: ProjectInfo) extends DefaultWebProject(info) {
【修正後】
class LiftProject(info: ProjectInfo) extends DefaultWebProject(info) with IdeaProject {
sbtを利用してintellijプロジェクトの作成
ターミナルでプロジェクトの直下に移動します。
sbt.shがあります。windowsの場合でもsbt.batがあるので同様に動きます。
$sbt (sbtが起動)
>update
>idea
ideaと入力した際に「ideaなんて知らないぜ!」と言われる場合は、ブランクプロジェクトの修正がうまくいっておらず、プラグインがダウンロード出来ていない可能性があります。設定を見直してください。それでもダメならとりあえずsbtで「clean」をして、再度「update」をしてみてください。もしかしたらうまくいくかもしれません。
プロジェクトの取り込み
プロジェクトを取り込むには、intellijでFile>OpenProjectから作成したプロジェクトを選択します。
しばらくすると取り込まれます。この際に時々エラーダイアログが出力されることがありますが問題ないようです。いくつかソースを開いてみてエラーが出ていないことを確認してください。
アプリの動作確認
intellijで[プロジェクト]/src/test/RunWebAppを選択して右クリックから「Run with JRebel "RunWeebApp.main"」を選択してください。
下部のコンソール画面にログが出力されます。問題なければ、http://localhost:8080で画面が表示されると思います。
*[scala][lift]Liftの入門(sitemap編)
liftは若干癖があるフレームワークなので勉強を始めると最初に画面遷移あたりで引っかかるかもしれません。
最初はどのファイルが呼ばれているのかすらよくわからないかもしれません。リンクでどんなURLを指定すれば良いのか迷います。
調べているとsitemapってのを書く必要があるみたいだけど、書き方も一見よくわかりにくいため、戸惑うかもしれません。
そこで色々な指定方法があるので、一部ですがまとめていきたいと思います。
今回の本題のsitemapの前に画面が表示される流れだけ簡単に説明しときます。
sbtでプロジェクトを作成した標準的な場合を前提に話します。
まず[プロジェクト]/src/webapp/templates-hidden/default.htmlが呼ばれます。
その中にデフォルトで以下のような記述があります。
default.html
<div id="content" ></div>
上記の部分にその他のhtmlを埋め込んで表示させます。
例えば以下のような指定をします。
index.html
<div id="main" class="lift:surround?with=default;at=content"> <div class="lift:helloWorld"> </div> </div>
classで指定してあるlift:surroundがポイントでwith=default;at=contentと記述するとdefault.htmlのid、contentと入れ替わります。なお、lift:surroundの外にある部分は無視され表示されません。
かなりざっくりで読んでいる人がついて来ているか心配ですが、表示される仕組みはこんな感じです。
ではsitemapでの画面遷移についてです。
sitemapを指定するとメニューが表示されます。
sitemapの一番簡単な指定方法
一番シンプルな設定は以下のように行います。
Homeがメニューのリンク名でindexがパスになります。
def sitemap(): SiteMap = SiteMap( Menu.i("Home") / "index" )
複数指定する
複数指定する場合は、「,」区切りで指定します。
def sitemap(): SiteMap = SiteMap( Menu.i("Home") / "index", Menu.i("Home2") / "index2" )
呼び出されるhtmlの場所
画面遷移時に呼び出されるHTMLは、[プロジェクト]/src/main/webapp配下に格納します。
ファイル名はパスをindexと指定した場合、index.htmlとなります。
開発モード(liftではrunmodeというのが指定出来ます。)では、毎回画面ロード時に読み込みが行われるため即時反映されます。その他のモードでは、1度だけ読み込まれます。
毎回読み込まれるのは便利ですがコストが高いです。
メニューに表示させない方法について
メニューに表示させないようにするには、「>> Hidden」と記述します。
Menu.i("Home") / "index" >> Hidden
フッタに表示させたい場合
Menu.i("About") / "about" >> LocGroup("bottom")
LogGroup("XX")で指定します。上記例では、bottomを指定しています。グループbottomはdefault.htmlで以下のように指定します。指定した場所にリンクが表示されます。
<span class="lift:Menu.group?group=bottom"></span>
メニューには表示させないでフッタにだけ表示させたい場合は、「>> Hidden」と組み合わせて利用することも出来ます。
Menu.i("About") / "about" >> Hidden >> LocGroup("bottom")
動的なページについて
パスについて全てsitemapに指定しなくてはいけないわけではないです。
以下のようにワイルドカードで指定すると「http://localhost:8080/sample/index」のようなsample/以下の任意のパスを呼び出すことが出来ます。
Menu.i("Sample") / "sample" / **
ファイルは、[プロジェクト]/src/main/webapp/sample/XXX.htmlとして格納します。
デザインについて
liftはデザイナフレンドリなフレームワークですが、事前にsitemapで出力されるhtmlを理解しておく必要があります。
HTMLとしては、以下のようなタグが表示されます。選択されているメニューはspanタグが出力されます。選択されていないメニューはaタグが出力されます。
○lift例
<div id="menu"> <span class="lift:Menu.builder"></span> </div>
○html例
<div id="menu"> <ul> <li><span>Home</span></li> <li> <a href="/contents">Contents</a></li> <li> <a href="/contents2">Contents2</a></li> </ul> </div>
cssを指定するにはliftでは以下のような感じで記述すればよいです。
○css例
#menu ul li {xxx} #menu ul li span {xxx} #menu ul li a {xxx}
メニューの階層化
メニューの階層化を行うことが出来ます。サブメニューは初期表示された段階では非表示になっています。親メニューが選択されると表示されます。
Menu.i("Info") / "info" submenus( Menu.i("About") / "about" >> Hidden >> LocGroup("bottom"), Menu.i("Contact") / "contact", Menu.i("Feedback") / "feedback" >> LocGroup("bottom") )
HTMLは以下のようにulタグ、liタグがネストされる形で表示されます。
<ul> <li> <span>info</span> <ul> <li> <a href="/contact">Contact</a></li> <li> <a href="/feedback">Feedback</a></li> </ul> </li> </ul>
ざっと駆け足で説明しましたがsitemapについての説明は以上です!
scalaでservlet3.0を動かす
scalaで簡単にWebアプリを作る方法を考えてて、とりあえずservlet3.0で簡単に動かしてみた。
scalaで書くと以下のような感じ。
package code import java.io.IOException; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(Array("/test")) class ScalaServlet extends HttpServlet { override def doGet(req: HttpServletRequest, res: HttpServletResponse) = { res.getWriter().print(new Date()); } }
@WebServlet(Array("/test"))のようにArrayを書く必要がある点に注意が必要。
普段は、intellijを使っているけど、最近出たeclipseのScala IDE 2.0.0-beta1(http://download.scala-ide.org/)を使ってみた。
うーん。確かに動くけど、servletを生で使うのは微妙かも。
scalaであるメリットが活きてこなそう。ロジック書いてないってのもあるけど、java臭さしかない。
でもjava部分を隠すようなラップをしてあげるだけで、結構いい感じになるかも。
例えば、req.getParameter("aaa")でOption型返すようにするとか。リストの戻り値をscalaのListにするとか。
一番の収穫は、scalaでWebだとliftとかplayを使わなくてはいけないみたいな固定観念があったけど、
意外と既存のjavaでもいけるかもと考えが変わったのが良かった。
次はJPAでも試してみるか。