On 2023-09-08 19:08:05 +0200, Ludovic Courtès wrote: > Hello! > > Josselin Poiret <[email protected]> skribis: > > > Right, although I wouldn't necessarily say that the former doesn't have > > a proper API, but rather that it has a Unix-oriented API. That leads to > > performance issues on e.g. Windows but on Linux I'm not sure there's > > much of a difference. > > [...] > > > We could consider replacing the guile-git dependency with another > > library built directly on top of git-minimal, and have this be a > > dependency of Guix. Not ideal though, and not really scalable either: > > we can't just add every VCS as direct dependencies. > > I cannot imagine a viable implementation of things like ‘commit-closure’ > and ‘commit-relation’ from (guix git) done by shelling out to ‘git’.
I am sure I must be missing some part of the contract of the function, but at
least the commit-relation seems fairly straightforward:
(define (shelling-commit-relation old new)
(let ((h-old (oid->string (commit-id old)))
(h-new (oid->string (commit-id new))))
(cond ((eq? old new)
'self)
((zero? (git-C %repo "merge-base" "--is-ancestor" h-old h-new))
'ancestor)
((zero? (git-C %repo "merge-base" "--is-ancestor" h-new h-old))
'descendant)
(else
'unrelated))))
I would argue it is even somewhat more readable than the current implementation.
> I’m quite confident this would be slow
My version is ~2000x faster compared to (guix git):
Guix: 1048.620992ms
Git: 0.532143ms
Again, I am sure I must have miss something, either in the implementation or in
the measurements, because it is pretty hard to believe there is so much room for
improvement.
The full script I used is attached to this email.
> and brittle.
In general git plumbing command are design to have stable CLI interface in order
to be usable in scripting. So I am not sure where the brittleness would come
from.
>
> It looks like there’s no option other than carrying the two
> implementations.
Assuming I made no mistake (hard to believe), it is probably worth exploring the
feasibility of just shelling out to the git binary some more.
>
> ~~~
>
> Years ago, Andy Wingo sketched a plan for GNU hackers to implement Git
> in pure Scheme. That was on April 1st though, so people mistakenly
> assumed it was a joke and the project was never carried out.
>
> I digress, but I wonder: is there not even a viable Haskell or OCaml
> implementation of Git?
>
> Thanks,
> Ludo’.
>
W.
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
#!/bin/sh
# -*-scheme-*-
exec guile -s "$0" "$@"
!#
(use-modules (git)
(guix git))
(define %repo "/tmp/guix-fork")
(define h1 "72745172d155e489936f694d6b9013cb76272370")
(define h2 "6d60d7ccba5a8e06c17d55a1772fa7f4529b5eff")
(define h3 "c3db650680f995f0556d3ddce567cdc1c33e4603")
;;; r has to still be defined when the commit-relation is called. There is *no*
;;; error, but it always returns 'unrelated. Quite a footgun.
(define r (repository-open %repo))
(define c1 (commit-lookup r (string->oid h1)))
(define c2 (commit-lookup r (string->oid h2)))
(define c3 (commit-lookup r (string->oid h3)))
(define (git-C dir . args)
(apply system* "git" "-C" dir args))
(define (shelling-commit-relation old new)
(let ((h-old (oid->string (commit-id old)))
(h-new (oid->string (commit-id new))))
(cond ((eq? old new)
'self)
;; In real code, git-C should probably return #t (for 0), #f (for 1)
;; or raise (for anything else).
((zero? (git-C %repo "merge-base" "--is-ancestor" h-old h-new))
'ancestor)
((zero? (git-C %repo "merge-base" "--is-ancestor" h-new h-old))
'descendant)
(else
'unrelated))))
;;; Make sure it actually works.
(let ((tests `((,c1 . ,c1)
(,c1 . ,c2)
(,c2 . ,c1)
(,c1 . ,c3))))
(for-each (λ (c)
(format #t "Guix: ~a\nGit: ~a\n\n"
(commit-relation (car c) (cdr c))
(shelling-commit-relation (car c) (cdr c))))
tests))
(define (time proc)
(let* ((start (get-internal-run-time))
(_ (proc))
(end (get-internal-run-time)))
(exact->inexact (* 1000 (/ (- end start) internal-time-units-per-second)))))
(format #t "Guix: ~ams\nGit: ~ams\n"
(time (λ () (commit-relation c1 c2)))
(time (λ () (shelling-commit-relation c1 c2))))
signature.asc
Description: PGP signature
