facebook / sapling

A Scalable, User-Friendly Source Control System.

Home Page:https://sapling-scm.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Using .sl/store/git for transparent git interop?

adamh-oai opened this issue · comments

Like a lot of orgs we have all sorts of tools that expect you're working in a git repo (for pre-commit, deploy etc), which is a blocker for sapling adoption. I've played around some with hooks and scripts to transparently sync a git repo from sapling though it's all sort of slow and fragile.

I noticed .sl/store/git has an existing git repo that (?) mirrors the sapling contents. Is there any existing support for this I'm missing? Any suggestions for a good way to implement it?

Some specific git operations I run into:

  • What Is HEAD?
  • Is the working directory dirty?
  • List modified files, run a linter on them

I've ended up at a solution with these two hooks:

[hooks]
txnclose = sl-git
update = sl-git

And sl-git looks like:

# point git HEAD to sapling HEAD
case $HG_HOOKTYPE in
    "txnclose")
        git update-ref HEAD `sl whereami`
        ;;
    "update")
        git update-ref HEAD $HG_PARENT1
        ;;
esac

# update the index without changing the working directory
git read-tree HEAD

This seems to keep git in sync with sapling in all the cases I tried, but I'm a little uneasy there might be cases I'm not aware of.

Now I'm wondering about pre-commit hooks (eg formatters), and how to make them work across all the paths that update a commit (amend, rebase, etc)

The .sl/store/git is an implementation detail that we plan to change. While you can ln -s .sl/store/git .git and get something working, it's not an officially supported setup and will likely break in the future.

See #182 for more discussions. We don't want to support .git/ file format compatibility, but are happy to accept patches that provide a command-line git shim even if it's imperfect. If your use-case is automation (ex. the GitLens extension), they might just need a subset of git features and a shim could be a feasible solution.

@ahupp @adamh-oai just out of curiosity...are you using Sapling with a large repo? When I use your approach on a large repo it's quite slow to run git status after changing a commit in sapling as it has to refresh the index...

Not sure what you count as "large", its 33k files. The first git status does take a bit but this isn't on my critical path.

Yah fair enough. Mine is > 10 times that, so it's more noticeable. I really like your solution -- was previously doing this with a separate worktree from .sl/git/store and then would rsync on demand + various other cmds to get the repo in the correct state. The problem with that is similar I think to what you experienced -- it can be finicky.

We have a lot of scripts that use git status/git diff to determine changed files, and so this is kind of on the critical path for me. But it's not necessarily a deal breaker as it's only a one-time thing after a ref change.