git.fiddlerwoaroof.com
README.org
821ddf96
 * 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.
 
f4040ce6
 ** 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
 
f16b869d
   To run the tests in a clean environment, you can do (this will eventually be a Github Action):
 
87bdd68d
   #+BEGIN_SRC sh :noeval
f16b869d
     docker run \
       -v $PWD/docker-run:/code fiddlerwoaroof/sbcl-static:latest \
       --load /code/main.lisp
   #+END_SRC
 
821ddf96
 ** Installation
b7df27f1
 
87bdd68d
    #+BEGIN_SRC sh :noeval
4d4ea31b
      % git clone https://github.com/fiddlerwoaroof/fwoar.lisputils.git "$HOME/quicklisp/local-projects/fwoar-lisputils"
e499f64d
      % git clone https://github.com/fiddlerwoaroof/cl-git.git "$HOME/quicklisp/local-projects/cl-git"
      % sbcl --load "$HOME/quicklisp/setup.lisp"
821ddf96
      CL-USER> (ql:quickload :cl-git)
    #+END_SRC
 
 ** Example usage
 
 *** Get the commit id of the master branch for a specific repository:
 
b7df27f1
     #+BEGIN_SRC lisp :exports both :results verbatim
bdf26afb
       (co.fwoar.git:in-repository ".")
       (co.fwoar.git:branch "master") ;; the argument to branch defaults to "master"
b7df27f1
     #+END_SRC
821ddf96
 
     #+RESULTS:
8a984d6e
     : #<FWOAR.CL-GIT::LOOSE-REF f5f888 of #<GIT-REPOSITORY {700E286593}> {700E298AA3}>
b7df27f1
 
821ddf96
 
 *** Show the commit message
 
b7df27f1
     #+BEGIN_SRC lisp :exports both :results verbatim
bdf26afb
       (co.fwoar.git:in-repository ".")
       (co.fwoar.git:component :message (co.fwoar.git:branch "master"))
b7df27f1
     #+END_SRC
821ddf96
 
     #+RESULTS:
8a984d6e
     : feat: repository generic function turns a repository into itself
821ddf96
 
 *** Show the messages of the commit's parent
 
b7df27f1
     #+BEGIN_SRC lisp :exports both :results verbatim
bdf26afb
       (co.fwoar.git:in-repository ".")
       (let* ((branch (co.fwoar.git:branch "master"))
              (parents (co.fwoar.git:parents branch)))
29e36f3a
         (mapcar (lambda (it)
bdf26afb
                   (co.fwoar.git:component :message it))
29e36f3a
                 parents))
b7df27f1
     #+END_SRC
821ddf96
 
     #+RESULTS:
8a984d6e
     : ("feat: fix graphing
fd1297fb
     : ")
efe60b9f
 
 *** Show the files in a commit
1869d7ea
     - Note taken on [2020-11-15 Sun 01:49] \\
       If the table comes out wrong, =*print-case*= must be =:downcase=
821ddf96
 
87bdd68d
     #+BEGIN_SRC lisp :exports both :results table :hlines yes :post proc(data=*this*)
bdf26afb
       (co.fwoar.git:in-repository ".")
       (list* '("Name" "Mode" "Hash")
1869d7ea
              'hline
bdf26afb
              (co.fwoar.git:git (branch "master")
                                (component :tree :entries)
                                (map (juxt (component :name)
                                           (component :mode)
                                           (component :hash)))))
efe60b9f
     #+END_SRC
 
     #+RESULTS:
5bdc5cff
     | Name                |   Mode | Hash                                     |
     |---------------------+--------+------------------------------------------|
b2b47089
     | .github             |  40000 | 8a2d4357c2ecb8658006f638df28dea78079e438 |
5bdc5cff
     | .gitignore          | 100644 | 8a9fe9f77149f74fed5c05388be8e5ffd4a31678 |
     | .projectile         | 100644 | e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 |
     | LICENSE             | 100644 | 0306819e780fa57dc3bf6b99a0a059670b605ae0 |
8a984d6e
     | README.org          | 100644 | 228549f2ddd3fff60fa45ca13c4dd1d84476ae0e |
5bdc5cff
     | branch.lisp         | 100644 | 6ee2b1e254e7895d55ecd534b2fa16267ec14389 |
b2b47089
     | co.fwoar.cl-git.asd | 100644 | b46a0006889e11b609a3712e3580056613e29adc |
     | commit.lisp         | 100644 | 01a443c09232db495b1babfeef98e708a0d3e0b5 |
     | delta.lisp          | 100644 | 1e6be7f65fa732646316d72a9a725c0145a84758 |
     | docker-run          |  40000 | 4703dc01430d67c5d60f00ad412fddfa22f60764 |
8a984d6e
     | docs                |  40000 | 9fe62496fc4ab6debd3c5e1b26f844b5566c36d5 |
b2b47089
     | extract.lisp        | 100644 | c3acabc2c2b7ec9427ccf9a96bce582c52f985cd |
     | git.lisp            | 100644 | b28579d23e87866f05635b666074e445ba26883f |
8a984d6e
     | graph.lisp          | 100644 | 513606d9eb9eb9a5a3891d7307cb071034d84b59 |
     | model.lisp          | 100644 | f305b81a1781579c5570d5bc5209048a0e3fe9dc |
b2b47089
     | package.lisp        | 100644 | c532eeeeca12e48e02999ce0ffcbd0bba8768867 |
5bdc5cff
     | porcelain.lisp      | 100644 | 00ecaacea7ebcd57746198b248c3a3f5b89f21a5 |
     | protocol.lisp       | 100644 | a9c317a589516da0a9d88113bb56a28b73f2d41e |
     | repository.lisp     | 100644 | f367c22c6c7fb59fec1b514f2fe71fe78465e878 |
8a984d6e
     | tests               |  40000 | 5d7ec1c0804dc910ddd9b42c5e53552034aaccac |
     | tree.lisp           | 100644 | c798b0c4d0b5f552548bac98f44b5b5c19334e66 |
b2b47089
     | types.lisp          | 100644 | 3f53e0f33ee260a962b97ef26de1d66b32a12a15 |
5bdc5cff
     | undelta.lisp        | 100644 | ae0a070133d1a14d6e940a0f790f40b37e885b22 |
b2b47089
     | util.lisp           | 100644 | 02cf7436032dd6adec92d42d3ed9b7f6307860f7 |
821ddf96
 
1869d7ea
 *** 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=
 
87bdd68d
     #+BEGIN_SRC lisp :exports both :results table :hlines yes :post proc(data=*this*)
bdf26afb
       (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)))
29e36f3a
           (flet ((component (component)
                    (lambda (it)
bdf26afb
                      (co.fwoar.git:component component it))))
29e36f3a
             (list* '("Name" "Mode" "Hash")
                    'hline
                    (mapcar (data-lens:juxt (component :name)
                                            (component :mode)
                                            (component :hash))
                            tree-entries)))))
1869d7ea
     #+END_SRC
 
     #+RESULTS:
     | Name       |   Mode | Hash                                     |
     |------------+--------+------------------------------------------|
b2b47089
     | delta.lisp | 100644 | 1e6be7f65fa732646316d72a9a725c0145a84758 |
8a984d6e
     | graph.lisp | 100644 | 513606d9eb9eb9a5a3891d7307cb071034d84b59 |
     | model.lisp | 100644 | f305b81a1781579c5570d5bc5209048a0e3fe9dc |
     | tree.lisp  | 100644 | c798b0c4d0b5f552548bac98f44b5b5c19334e66 |
b2b47089
     | types.lisp | 100644 | 3f53e0f33ee260a962b97ef26de1d66b32a12a15 |
     | util.lisp  | 100644 | 02cf7436032dd6adec92d42d3ed9b7f6307860f7 |
1869d7ea
 
b7df27f1
 ** Partially Implemented:
 
29e36f3a
 *** Delta refs
b7df27f1
     Git uses a [[https://git-scm.com/docs/pack-format#_deltified_representation][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 [[file:delta.lisp::(defclass delta () ((%repository :initarg :repository :reader repository) (%base :initarg :base :reader base) (%commands :initarg :commands :reader commands)))][delta object]]. When
     this works adequately, I'll write an interpreter to do the actual
     merge.
ea6099ea
 
     A workaround for the moment is to manually unpack the pack files:
 
87bdd68d
     #+BEGIN_SRC sh :noeval
ea6099ea
       mkdir tmp
       mv .git/objects/pack/* tmp
fb9deed0
       for pack in tmp/*.pack; do
         git unpack-objects < "$pack";
       done
ea6099ea
     #+END_SRC
 
     Or, you can undeltify the packs by, first unpacking the packfile as above and then doing:
 
87bdd68d
     #+BEGIN_SRC sh :noeval
ea6099ea
       git repack --window=0
     #+END_SRC
aa622e50
 
 
6309be05
 *** git:git porcelain
     I have some thoughts abound a =(git:git ...)= form that can be
     used as a [[https://github.com/shinmera/lquery.git][lQuery-like]] DSL for manipulating git repositories, and
     this is partially implemented in [[file+emacs:./porcelain.lisp][porcelain.lisp]], but the details
     need more thought before it is ready.
 
 
 ** TODOs
 *** TODO start implementing Pharo-like git integration (read-only first, commits later)
bdf26afb
 
 #+name: proc
87bdd68d
 #+begin_src emacs-lisp :var data=()
bdf26afb
   (mapcar (lambda (it)
             (if (equal it 'HLINE)
                 'hline
               it))
87bdd68d
           data)
bdf26afb
 #+end_src
87bdd68d
 
 #+RESULTS: proc