GitBucket 4.16.0をリリースしました

Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.16.0をリリースしました。

https://github.com/takezoe/gitbucket/releases/tag/4.16.0

AdminLTEのカラースキンを選択可能に

GitBucketがUIテーマとして使用している使用しているAdminLTEはカラースキンで色を変えることができるのですが、GitBucket 4.16.0ではこのカラースキンを管理画面で選択できるようになりました。

f:id:takezoe:20170901114815p:plain

以下はgreenのスキンを選択した場合の表示例です。

f:id:takezoe:20170901114822p:plain

予期しないエラーの処理を改善

予期しないエラーはエラーログとして記録するようにし、管理者の場合はブラウザ上でもスタックトレースが表示されるようになりました。

f:id:takezoe:20170901114843p:plain

f:id:takezoe:20170901114859p:plain

コミット一覧にコミットのステータスを表示

Jenkinsなどと連携している場合、コミットの一覧画面に各コミットのステータスが表示されるようになりました。

f:id:takezoe:20170901114910p:plain

今回のバージョンではこの他にも様々な改善やバグフィックスを行っています。詳細についてはIssueの一覧をご覧ください。

最強のGitフロントエンドはForkかもしれない

f:id:takezoe:20170831094824p:plain

昨日Macで使えるGitフロントエンドの紹介を書いたところ、友人のPishenさんからForkというツールもあることを教えていただきました。

Webサイトはこちら。現時点ではMac版(動作にはMacOS X 10.11以降が必要)のみですが、Windows版も提供予定のようです。

git-fork.com

リリースノートを見ると昨年から開発されていたようですが、完全にノーマークだったので早速試してみました。

  • 1ウィンドウで複数リポジトリをタブ切り替えで操作できる
  • ブランチの状況も把握しやすい履歴ビュー(見た目的にはSourceTreeに近い)
  • コミット時点のファイルツリーを確認できる
  • 動作は軽快(ただし安定度についてはまだ不明)
  • ターミナルから起動するためのコマンドが用意されている
  • ブランチを複数選択してまとめて削除できる
  • (行単位ではなく)文字単位の差分表示、画像の差分表示も可能
  • 対話型のリベース機能が実装されている

などなど、様々なGitフロントエンドの良いとこ取りをしている感じです。これは探し求めていたものかもしれない…。

対話型のリベースはこんな感じ。このダイアログでコミットを編集してRebaseを押すと反映されます。

f:id:takezoe:20170831095352p:plain

差分はサイドバイサイドの表示も可能です。文字単位で差分表示されていることがわかります。

f:id:takezoe:20170831095407p:plain

試していませんが、GitHubの通知を表示してくれる機能などもあるようです。

安定度や細かい部分はしばらく使ってみないとわかりませんが、他のツールと比べて機能的に不足を感じるのはGitKrakenのGitHub連携機能(プルリクエスト元のリポジトリをリモートリポジトリに追加したり、ブランチを一発でチェックアウトしたりできる)くらいでしょうか。

ForkはOSSではありませんが、GitHubのIssuesを使用してバグレポートやフィーチャーリクエストを受け付けているようなので、気になる点や要望などが出てきたらこちらに投げていこうと思います。

github.com

将来的には有料化するのかもしれませんが、いまのところはベータ版ということで無料で利用できますので、Macで良いGitフロントエンドをお探しの方は是非一度試してみてください!

Macで使えるGitフロントエンド

元々IDEとか開発ツールは専門分野(?)なので、この手のものは以前からいろいろ試しているのですが、個人の感想をまとめておきたいと思います。IDEやエディタに統合されていて利用シーンが限定されるものや、GitHub for Windowsなどのように機能に制限の多いものは省いています。

SourceTree

f:id:takezoe:20170830101400p:plain

  • 信頼と実績のAtlassian製
  • 無料で使用可能(要ユーザ登録)
  • 日本語対応しており、書籍などの情報もある
  • リポジトリごとにウィンドウが開く(Windows版はタブで開くのに…)
  • 対話型リベースが可能
  • 動作がかなり重い、特にブランチが増えると実用に耐えないレベルで重くなる
  • ただし突然死などはしない

Tower2

f:id:takezoe:20170830101412p:plain

  • 有料(買い切り$79)
  • 履歴一覧でブランチの関連を把握するのが難しい気がする
  • 1ウィンドウで複数リポジトリを切り替えて使用
  • 動作はかなり軽い
  • 時々突然死することがある
  • ブランチを切り替える際に未コミットのファイルがあると自動的にスタッシュしてくれるなど細かい部分で気が利いている
  • ターミナルから起動するためのコマンドが用意されている
  • ブランチを複数選択してまとめて削除できる

GitKraken

f:id:takezoe:20170830101434p:plain

  • 非商用利用は無料、商用利用は有料($49/年)
  • 見た目がきれい、ヒストリが見やすい
  • 1ウィンドウで複数リポジトリを切り替えて使用
  • 動作はそれなりに軽い(SourceTree <<<< GitKraken < Tower2という感じ)
  • 初期の頃は不安定で突然死することも多かったが最近は安定してきた
  • 対話型リベースはできないが複数コミットを範囲選択してスカッシュできる
  • GitHub連携機能が便利(フォークしたリポジトリをリモートリポジトリに追加できたり、プルリクエストのブランチを一撃でチェックアウトするなどの機能がある)

まとめ

正直どれも一長一短という感じですが、いまのところ個人的にはGitKrakenが一番使いやすく、開発速度やマーケティングの面でも勢いを感じます。

他にもSmartGitやGitHub for WindowsなどのGUIクライアントや、EclipseIntelliJAtomなどIDEやエディタのGit連携機能を使うという方法もあります。また、GUIではありませんが、Emacsでmagitを使うなどという選択肢もあるのでいろいろ試してみて使いやすいものを選ぶといいんじゃないかと思います。

go-promptでGitのブランチをいい感じにチェックアウトするコマンドを作ってみた

先日Qiitaで以下の記事を見てこれでなにか作れないかなぁと思っていたのですが…

qiita.com

ふと思い立ってGitのブランチをチェックアウトするコマンドを作ってみました。

github.com

ブランチの一覧からチェックアウトしたいブランチをインクリメンタルサーチしてチェックアウトできるというもので、ローカルブランチの場合は普通にチェックアウト、リモートブランチの場合はローカルブランチを作成してチェックアウトしてくれます。

f:id:takezoe:20170828190434p:plain

一応目的のモノは作れたのですが、元々は以下のようなシェルスクリプトを使って、pecoを使ってチェックアウトするブランチを選択できるようにしたものを使っていたのですが、これと比べるとなんだか使いにくい気がする。

function peco-git-checkout() {
  local BRANCH=`git branch -a | peco`
  if [[ -z "$BRANCH" ]]; then
    return
  fi
  if [[ "$BRANCH" =~ remotes/([^/]*)/(.*) ]]; then
    git checkout -b ${BASH_REMATCH[2]} ${BASH_REMATCH[1]}/${BASH_REMATCH[2]}
  else
    git checkout $BRANCH
  fi
}

慣れの問題かもしれませんが…。うーん…。

Scala用のタイプセーフなSQLビルダtranquil 0.0.3をリリースしました

github.com

以前から少しずつ進めていたtranquilですが、APIもそれなりに落ち着いてきたので久しぶりにバージョンアップしてみました。ちなみに以前のものはこんな感じでした。

takezoe.hatenablog.com

テーブル定義は以下のような感じで随分シンプルに定義できるようになりました。

import com.github.takezoe.tranquil._

case class User(userId: String, userName: String, companyId: Option[Int])

class Users extends TableDef[User]("USERS") {
  val userId    = new Column[String](this, "USER_ID"),
  val userName  = new Column[String](this, "USER_NAME"),
  val companyId = new OptionalColumn[Int](this, "COMPANY_ID")

  override def toModel(rs: ResultSet): User =
    User(userId.get(rs), userName.get(rs), companyId.get(rs))
}

object Users {
  def apply() = new SingleTableAction(new Users())
}

case class Company(companyId: Int, companyName: String)

class Companies extends TableDef[Company]("COMPANIES") {
  val companyId   = new Column[Int](this, "COMPANY_ID"),
  val companyName = new Column[String](this, "COMPANY_NAME")

  override def toModel(rs: ResultSet): Company =
    Company(companyId.get(rs), companyName.get(rs))
}

object Companies {
  def apply() = new SingleTableAction(new Companies())
}

マクロで自動生成する手法も試してみたのですが、IntelliJで補完が効かなかったりなど厳しい感じだったので現状ではソースコードの自動生成で対応する感じになるかなと思います。ただ、自動生成するとはいってもシンプルにできるのであればそのほうがよいので、そういう意味ではResultSetからケースクラスを生成するメソッドや、コンパニオンオブジェクトでファクトリメソッドを定義しないといけないのがまだちょっと微妙ですね。

クエリはこんな感じです。

import com.github.takezoe.tranquil._
import com.github.takezoe.tranquil.Dialect.generic

val conn: java.sql.Connection = ...

// SELECT
val users: Seq[(User, Option[Company])] =
  Users()
    .leftJoin(Companies()){ case u ~ c => u.companyId eq c.companyId }
    .filter { case u ~ c => (u.userId eq "takezoe") || (u.userId eq "takezoen") }
    .sortBy { case u ~ c => u.userId asc }
    .list(conn)

テーブルのエイリアスを手動で指定する必要がなくなりました。が、既存のモデルを壊さずにエイリアスを自動生成できるようにしたので実装が割と微妙な感じになってしまいました。やはりDSLではASTを組み立てるだけにして、SQLに変換するフェーズとは分けるようにしたほうが良さそうです(なるべくシンプルな作りにしたかったのですが、こうやって複雑になっていくのか…)。

この他にも以前ブログに書いた時点ではまだサポートしていなかった以下のような機能が実装済みです。

  • 特定のカラムだけSELECTする
  • GROUP BY、HAVING
  • ページング(LIMIT、OFFSET的なやつ)
  • DBごとの違いを吸収するためのDialect

ただ、最初にあまり深く考えずに作り始めてしまったこともあり、無理やり辻褄をあわせるためにvarを使っていたり、ランタイムリフレクションを使っていたりと作り的に結構微妙な感じになってしまいました。また、見た目に違和感のないDSLを作ろうとするとどうしてもimplicit conversionを多用することになってしまい、コードがわかりにくくなってしまいます。

一度作ってみて感覚が掴めたので、もう一度ちゃんと設計して作り直したほうがいいかも…。

sbtとpecoでテンプレートを選択してプロジェクトを作成する

sbtではsbt new playframework/play-scala-seed.g8などのようにしてgiter8テンプレートを指定してプロジェクトを作成することができます。

しかし、プロジェクトを作るたびにテンプレートのリポジトリ名を調べるのも面倒です。そこで、giter8のWikiにまとめられているgiter8テンプレートのリストからpecoでインクリメンタルサーチしてプロジェクトを作成できるようにしてみました。

function peco-sbt-new() {
  local TEMPLATE=`curl https://github.com/foundweekends/giter8/wiki/giter8-templates -s | grep "\.g8<" | sed -e "s/</ /g" -e "s/>/ /g" | awk '{print $3}' | peco | head -n 1`
  if [[ -z "$TEMPLATE" ]]; then
    return
  fi
  sbt new $TEMPLATE
}

上記のような感じのスクリプト.bash_profileに入れておき、peco-sbt-newを実行するとテンプレートを選択してsbt newを実行できます。

f:id:takezoe:20170819163550p:plain

これでgiter8のWikiさえメンテしていれば新しいテンプレートも使えるようになります。

ちょっとしたものですが、テストやユーザサポートなどの用途などの目的でgiter8テンプレートからPlayやScalatraのプロジェクトを作成することがちょくちょくあるので割と便利な感じです。

Tower2をコマンドラインから起動する

Tower2Mac*1GUIなGitフロントエンドです。このブログでも以前紹介しましたが、有償*2なだけあり、軽快な動作が売りで使いやすいGitフロントエンドの1つだと思います。

takezoe.hatenablog.com

takezoe.hatenablog.com

で、最近気づいたのですが、Tower2ではCLIツールが用意されており、コマンドラインからディレクトリを指定して起動したりということもできるようです。CLIツールは設定のIntegrationのタブでインストールできます。

f:id:takezoe:20170817025057p:plain

するとgittowerというコマンドが利用できるようになりますので、Gitリポジトリのルートディレクトリで

$ gittower .

などとするとそのリポジトリをTower2で開くことができます。ちょっとしたことなのですが、ターミナル族には嬉しい機能なのではないでしょうか。

*1:現在はWindows版もリリースされています

*2:$79の買い切りモデル