Skip to content

A Common Lisp implementation of parsers for the git object file formats

License

Notifications You must be signed in to change notification settings

fiddlerwoaroof/cl-git

Repository files navigation

CL-GIT: the pure lisp interface to Git objects

Introduction

Git libraries for Common Lisp common in a couple forms. Some attempt to wrap the libgit2 git library (e.g. https://github.com/russell/cl-git). Others wrap the git binary in a subprocess (e.g. http://shinmera.github.io/legit/). Such libraries work well in cases where you control the environment but not all lisp programs run in such circumstances. This library, on the contrary, attempts to implement parsers for git’s file formats as well as a thin “porcelain” interface for manipulating git objects.

Contributing

This project uses (loosely) conventional-commits: https://www.conventionalcommits.org/en/v1.0.0/

Also, some use of https://github.com/fiddlerwoaroof/git-issue has been made

To run the tests in a clean environment, you can do (this will eventually be a Github Action):

docker run \
  -v $PWD/docker-run:/code fiddlerwoaroof/sbcl-static:latest \
  --load /code/main.lisp

Installation

% git clone https://github.com/fiddlerwoaroof/fwoar.lisputils.git "$HOME/quicklisp/local-projects/fwoar-lisputils"
% git clone https://github.com/fiddlerwoaroof/cl-git.git "$HOME/quicklisp/local-projects/cl-git"
% sbcl --load "$HOME/quicklisp/setup.lisp"
CL-USER> (ql:quickload :cl-git)

Example usage

Get the commit id of the master branch for a specific repository:

(co.fwoar.git:in-repository ".")
(co.fwoar.git:branch "master") ;; the argument to branch defaults to "master"
#<FWOAR.CL-GIT::LOOSE-REF f5f888 of #<GIT-REPOSITORY {700E286593}> {700E298AA3}>

Show the commit message

(co.fwoar.git:in-repository ".")
(co.fwoar.git:component :message (co.fwoar.git:branch "master"))
feat: repository generic function turns a repository into itself

Show the messages of the commit’s parent

(co.fwoar.git:in-repository ".")
(let* ((branch (co.fwoar.git:branch "master"))
       (parents (co.fwoar.git:parents branch)))
  (mapcar (lambda (it)
            (co.fwoar.git:component :message it))
          parents))
("feat: fix graphing
")

Show the files in a commit

  • Note taken on [2020-11-15 Sun 01:49]
    If the table comes out wrong, *print-case* must be :downcase
(co.fwoar.git:in-repository ".")
(list* '("Name" "Mode" "Hash")
       'hline
       (co.fwoar.git:git (branch "master")
                         (component :tree :entries)
                         (map (juxt (component :name)
                                    (component :mode)
                                    (component :hash)))))
NameModeHash
.github400008a2d4357c2ecb8658006f638df28dea78079e438
.gitignore1006448a9fe9f77149f74fed5c05388be8e5ffd4a31678
.projectile100644e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
LICENSE1006440306819e780fa57dc3bf6b99a0a059670b605ae0
README.org100644228549f2ddd3fff60fa45ca13c4dd1d84476ae0e
branch.lisp1006446ee2b1e254e7895d55ecd534b2fa16267ec14389
co.fwoar.cl-git.asd100644b46a0006889e11b609a3712e3580056613e29adc
commit.lisp10064401a443c09232db495b1babfeef98e708a0d3e0b5
delta.lisp1006441e6be7f65fa732646316d72a9a725c0145a84758
docker-run400004703dc01430d67c5d60f00ad412fddfa22f60764
docs400009fe62496fc4ab6debd3c5e1b26f844b5566c36d5
extract.lisp100644c3acabc2c2b7ec9427ccf9a96bce582c52f985cd
git.lisp100644b28579d23e87866f05635b666074e445ba26883f
graph.lisp100644513606d9eb9eb9a5a3891d7307cb071034d84b59
model.lisp100644f305b81a1781579c5570d5bc5209048a0e3fe9dc
package.lisp100644c532eeeeca12e48e02999ce0ffcbd0bba8768867
porcelain.lisp10064400ecaacea7ebcd57746198b248c3a3f5b89f21a5
protocol.lisp100644a9c317a589516da0a9d88113bb56a28b73f2d41e
repository.lisp100644f367c22c6c7fb59fec1b514f2fe71fe78465e878
tests400005d7ec1c0804dc910ddd9b42c5e53552034aaccac
tree.lisp100644c798b0c4d0b5f552548bac98f44b5b5c19334e66
types.lisp1006443f53e0f33ee260a962b97ef26de1d66b32a12a15
undelta.lisp100644ae0a070133d1a14d6e940a0f790f40b37e885b22
util.lisp10064402cf7436032dd6adec92d42d3ed9b7f6307860f7

Show the files that match a pattern

  • Note taken on [2020-11-15 Sun 01:49]
    If the table comes out wrong, *print-case* must be :downcase
(co.fwoar.git:with-repository (".")
  (let* ((branch (co.fwoar.git:branch "master"))
         (tree (co.fwoar.git:tree branch))
         (tree-entries (co.fwoar.git:filter-tree "^.....?[.]lisp" tree)))
    (flet ((component (component)
             (lambda (it)
               (co.fwoar.git:component component it))))
      (list* '("Name" "Mode" "Hash")
             'hline
             (mapcar (data-lens:juxt (component :name)
                                     (component :mode)
                                     (component :hash))
                     tree-entries)))))
NameModeHash
delta.lisp1006441e6be7f65fa732646316d72a9a725c0145a84758
graph.lisp100644513606d9eb9eb9a5a3891d7307cb071034d84b59
model.lisp100644f305b81a1781579c5570d5bc5209048a0e3fe9dc
tree.lisp100644c798b0c4d0b5f552548bac98f44b5b5c19334e66
types.lisp1006443f53e0f33ee260a962b97ef26de1d66b32a12a15
util.lisp10064402cf7436032dd6adec92d42d3ed9b7f6307860f7

Partially Implemented:

Delta refs

Git uses a delta calculation routine to compress some of the blobs in a pack file. This delta stores a reference to a base object and a sequence of commands for transforming the base object into the new object. My plan to support this is to first just extract the commands from the pack file and store them as a delta object. When this works adequately, I’ll write an interpreter to do the actual merge.

A workaround for the moment is to manually unpack the pack files:

mkdir tmp
mv .git/objects/pack/* tmp
for pack in tmp/*.pack; do
  git unpack-objects < "$pack";
done

Or, you can undeltify the packs by, first unpacking the packfile as above and then doing:

git repack --window=0

git:git porcelain

I have some thoughts abound a (git:git ...) form that can be used as a lQuery-like DSL for manipulating git repositories, and this is partially implemented in porcelain.lisp, but the details need more thought before it is ready.

TODOs

start implementing Pharo-like git integration (read-only first, commits later)

(mapcar (lambda (it)
          (if (equal it 'HLINE)
              'hline
            it))
        data)

About

A Common Lisp implementation of parsers for the git object file formats

Topics

Resources

License

Stars

Watchers

Forks