Saplingを触ってみる



本記事は、[IKEAのサメアイコンが一人で完走を目指す Advent Calendar 2022](https://qiita.com/advent-calendar/2022/blahaj-ikea-shark-calendar)の1日目記事です。

最近出てきたコード管理ツールSaplingの公式ドキュメントを上から順にそれっぽいところまで触ってみる記事です。
Saplingを触ってみた感じの所感としては、Git互換ではあるけども便利なGit代替ツールというよりかは、Gitとは類似の思想を持っているが異なる思想を有するシステムという印象です。

## Sapling is 何

Meta社内で開発・使用されているらしいソースコード管理システムです。

> Sapling is a source control system developed and used at Meta that places special emphasis on usability and scalability. Git and Mercurial users will find many of the basic concepts familiar, and that workflows like understanding your repository, working with stacks of commits, and recovering from mistakes, are substantially easier.
> --- Saplingの[公式ドキュメント](https://sapling-scm.com/docs/introduction/)より引用

上記の訳文 (DeepL)

> Saplingは、ユーザビリティとスケーラビリティに特に重点を置いてメタ社で開発・使用されているソース管理システムです。GitやMercurialのユーザーは、基本的な概念の多くがなじみのあるものであり、リポジトリの理解、コミットの積み重ね、ミスからの回復といったワークフローが大幅に容易になることに気づくでしょう。

ざっくり読むと、Gitと大体同じ概念で使えるGitより便利なGitみたいな感じらしい。
コンフリクトで時たま苦しむ人間としては、これだけでもちょっと気になる存在。Meta製だから著しくポンコツってこともなさそうだし。


## インストール

とりあえず入れます。手を動かします。
以下の話は公式ドキュメントのパクリなので、不安なら[公式ドキュメントのInstallation](https://sapling-scm.com/docs/introduction/installation)を参照。
WSL使ってない人やintel macから更新してない人はドキュメントを読んでください。

### Ubuntuの場合

[ここ](https://github.com/facebook/sapling/releases/latest)から`Ubuntu2x.04.deb`をとってきてダウンロードディレクトリに放り込み以下のコマンドを読み替えて実行

```
sudo apt install -y ~/Downloads/path-to-the-Ubuntu.deb
```

### macOS

#### M1,M2の場合

curlでfacebookのリポジトリから最新のを持ってきてbrewでインストール。

```
curl -L -O https://github.com/facebook/sapling/releases/download/0.1.20221118-210929-cfbb68aa/sapling_0.1.20221118-210929-cfbb68aa.arm64_monterey.bottle.tar.gz
brew install ./sapling_0.1.20221118-210929-cfbb68aa.arm64_monterey.bottle.tar.gz
```

ちなみに、curlではなくWebブラウザからやると色々面倒なので気をつけてねってドキュメントに書いてあるんで、CLIが嫌いな人も大人しくcurlから入れるといいよ。

:::note 
別にやらなくてもいいけど、公式ドキュメントにはバカデカいリポジトリをcloneして苦しむ前に、オープンファイルの制限を緩和しておこうね！と書かれているのでやっておくと吉かも。
```
echo "ulimit -n 1048576 1048576" >> ~/.bash_profile
echo "ulimit -n 1048576 1048576" >> ~/.zshrc
```
ところで公式ではbashとzshには触れてるんだけどfish君は……？ 
(fish_configに突っ込めばいいだけなんだが、解説がないのはfishユーザーとしてちょっと悲しい。よくあることだけども)
:::

### ソースからビルドする場合

Ubuntu以外のLinuxディストリビューションをPCに入れてる人や、私のようなWSLの開発環境にUbuntu以外を採用している人は、大人しくビルドしましょう。
makeとg++とrustとnodeとyarnがあればいけるいける！ってドキュメントに書いてありますが、実際に試してみたところこれに追加してpython3-devel等を入れる羽目になりました。
失敗したら`.github/workflows/`配下のそれっぽいDockerfile見に行けってあるので頑張りましょう。

```
git clone https://github.com/facebook/sapling
cd sapling/eden/scm
make oss
./sl --help
```

### Nixpkgsによるインストール

この[issue](https://github.com/facebook/sapling/issues/246)でNixpkgsで取ってこれるようにしてるよ！とあったので確認したところひとまずは該当のPRはマージされたっぽいので試してみました。
私の手元の環境(Almalinux)ではビルドがかなり詰まったので、CentOS系はNixpkgsをインストールする時間を含めてもたぶんこちらが早いです。
nixpkgsを入れるところから始める場合、fishのひとはnixpkgsのインストールコマンドとして書かれているcurlのコマンドが`<`を含んでいるので`bash`か何かに切り替えてから実行する必要があります。
入れた後にコマンドの案内が出ますが、こちらはfish用になってくれているので`exit`してから該当のコマンドをたたきましょう。

Nixpkgsが入ってからは以下を実行。

```
nix-env --install sapling
```

saplingのコマンドが`sl`だからってslにすると、`ls`のタイポで遊ぶための汽車が走る方が降ってくるので注意

## init

`sl configfile --user`を実行して設定ファイルが存在することを確認したら、以下のようなコマンドを読み替えて実行して設定をします。
`git config --global user.name "hogehoge"`みたいなアレですね。

```
sl config --user ui.username 'Alyssa P. Hacker <alyssa@example.com>'
```

### githubのアクセストークン発行

`gh`(Github CLI)をインストールしてアクセストークンを発行。

```
gh auth login --git-protocol https
```

トークンは勝手にキャッシュしてくれてるっぽいので保存して〜とかの取り扱いは気にしなくていいです。

### Github上にリポジトリを作って触ってみる

ドキュメントではfacebookのリポジトリを触っていますが、まっさらな環境から触りたいので自分のアカウントにまっさらなリポジトリを作成して試してみます。

ghコマンドを用いてリポジトリを作成

```bash
gh repo create
```

ほいほいと入力してプライベートリポジトリを作成してクローンしてくる。以下参考例。

```
hogehoge ~/a/study> gh repo create
 What would you like to do? Create a new repository on GitHub from scratch
? Repository name try_sapling
? Description 
? Visibility Private
? Would you like to add a README file? No
? Would you like to add a .gitignore? No
? Would you like to add a license? No
? This will create "try_sapling" as a private repository on GitHub. Continue? Yes
✓ Created repository hogehoge/try_sapling on GitHub
? Clone the new repository locally? No
```

Saplitngを使用する場合、最後のcloneの質問でYesを選択すると色々面倒なのでNoを選択しましょう。sl使用時オプションを追加してくれー (リリース時期を無視した無茶ぶり)。

`sl clone`でclone
この時、SSHではなくHTTPSを用いる

```
sl clone https://github.com/hogehoge/try_sapling.git
cd try_sapling
```

readmeを作成し、commitを作る。

```bash
$ touch readme.md
$ sl add .
$ echo '# hello world' > readme.md
$ sl commit -m 'first commit'
$ sl
@  f3fd82525  18 minutes ago  hogehoge
   add: readme
```

`commit`のaliasとして`ci`があるので、今後はそちらを使用します。

addの挙動に関しては、Gitとは異なるらしい。

> Note that unlike Git, there was no need to explicitly declare a new branch before creating a commit. Sapling tracks heads automatically, which are readily visible when you run sl.
>
> Another important difference from Git is that there is no index where changes must be staged for commit. If you had run the above commands using git instead of sl, the Git commit would contain an empty hello.txt file with the non-empty version of the file waiting to be staged.
> --- [公式ドキュメント](https://sapling-scm.com/docs/introduction/getting-started#creating-your-first-commit)より引用


> Gitとは異なり、コミットを作成する前に明示的に新しいブランチを宣言する必要がないことに注意してください。Saplingは自動的にヘッドを追跡し、それはslを実行したときに容易に見ることができます。
> Gitとのもうひとつの重要な違いは、コミットするために変更をステージングしなければならないインデックスが存在しないことです。もし上記のコマンドを sl ではなく git を使って実行した場合、Git のコミットには空の hello.txt ファイルが含まれ、空でないバージョンのファイルがステージングされるのを待っていることになります。
> ---DeepL翻訳

ざっくり読むと、ブランチの作成を宣言しない、編集を都度ステージングする必要はなくファイルをステージング対象に追加する形をとるといった感じなんだろうなと思います。

"first commitを"mainにpush

```
sl push --to main
```

## Stackを移動する

foo, bar, bazをcommitしてコミット間を移動してみる

```
$ echo foo > foo.txt ; sl add foo.txt ; sl ci -m 'adding foo'
$ echo bar > bar.txt ; sl add bar.txt ; sl ci -m 'adding bar'
$ echo baz > baz.txt ; sl add baz.txt ; sl ci -m 'adding baz'
$ sl
  @  f933dfd79  62 minutes ago  hogehoge
  │  adding baz
  │
  o  eeaf6d351  62 minutes ago  hogehoge
  │  adding bar
  │
  o  1abb2049d  62 minutes ago  hogehoge
╭─╯  adding foo
│
o  f3fd82525  Today at 10:59  hogehoge  remote/main
   add: readme
``` 

`@`が現在の位置です。
ここから、`sl prev`, `sl next`などでcommitを移動できます。
`sl go top`や`sl go bottom`などで一気に一番上や下に移動することも可能です。

## Pull Requestを作成する

`sl pr`でPull Requestを作成できます。
これを実行すると、作成したコミットが積み重なったPull Requestとして作成されます。

![sl_github.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532032/c8b4f598-0570-7085-b028-05cbc3627557.png)

Githubだと見づらいので、コメントにあるReviewStackに行ってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532032/368c39dc-fc34-5244-284f-80bc3a44cc50.png)

適当にコメントを足すとこんな感じ。
コメントとCodeのページを同時に見れる感じなんだろうか。個人的には見やすく思えますが、優れているかどうかは判断が分かれそうです。

ドキュメントに以下のようにあるので、どんなツールなのかを見るにはそちらを見た方がこんな貧弱なサンプルリポジトリよりかはわかりやすい気がします。

> To try it out, take the URL for an existing pull request on github.com and change the domain to reviewstack.dev, so:
> 
> https://github.com/bolinfest/monaco-tm/pull/39 on GitHub is available at
> https://reviewstack.dev/bolinfest/monaco-tm/pull/39 on ReviewStack.

## おわりに

とりあえず一通り触ってみた感じとしては、うまいこと使いこなせれば便利そうな片鱗は感じます。
記事中には書いていませんが各種コマンドがいろいろ便利で、特に`undo`コマンドがあるところが最高に便利です。
コマンドを忘れたときに、`sl git <git-command>`でSaplingのコマンドを出してくれるところとかも面白いと思いました。まあ考え方が違うんで、出してくれてもな感は若干あるんですが。

ただいまいちドキュメントの導入がわかっている人向け感あるので、こうして少し触ってみただけではいまいちよく理解できない気がします。
悪いツールではないので、なんかこう、もっとドキュメントがしっかりしてくると違うのかもしれません。
ひとまずは、組織で使うにはまだ遠いような気がします。

使うにしても、しばらくは個人でって感じですね。