aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Bernoulli <jonas@bernoul.li>2018-10-29 14:52:27 +0100
committerJonas Bernoulli <jonas@bernoul.li>2019-04-19 17:39:44 +0200
commit287ba1136d43a7aeeabc4e185dc2fef0a836b004 (patch)
tree450a3ce4c27ee35dac9f46316f3bfcd9d803bd17
parentf9d8e5c51b2296e9b5c96d053ce6b8e74711f7b6 (diff)
Use libgit if available and desired
-rw-r--r--.travis.yml1
-rw-r--r--Makefile10
-rw-r--r--default.mk20
-rw-r--r--lisp/Makefile5
-rw-r--r--lisp/magit-core.el8
-rw-r--r--lisp/magit-git.el32
-rw-r--r--lisp/magit-libgit.el66
-rw-r--r--lisp/magit-mode.el3
-rw-r--r--lisp/magit-utils.el3
9 files changed, 145 insertions, 3 deletions
diff --git a/.travis.yml b/.travis.yml
index f0698d0..64cdcb3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@ env:
global:
- CURL="curl -fsSkL --retry 9 --retry-delay 9"
- GHRAW="https://raw.githubusercontent.com"
+ - BUILD_MAGIT_LIBGIT="false"
matrix:
- EMACS_VERSION=25.1
# 25.2 is identical to 25.3 except for a critical security bug in
diff --git a/Makefile b/Makefile
index 830ee63..d4f339d 100644
--- a/Makefile
+++ b/Makefile
@@ -197,6 +197,14 @@ define set_package_requires
`((emacs ,emacs-version) ;`
(dash ,dash-version)
(with-editor ,with-editor-version)))))
+(with-temp-file "lisp/magit-libgit.el"
+ (insert-file-contents "lisp/magit-libgit.el")
+ (re-search-forward "^;; Package-Requires: ")
+ (delete-region (point) (line-end-position))
+ (insert (format "%S"
+`((emacs "$(LIBGIT_EMACS_VERSION)") ;`
+ (magit "$(LIBGIT_MAGIT_VERSION)")
+ (libgit ,libgit-version)))))
(with-temp-file "lisp/magit-pkg.el"
(insert (pp-to-string
`(define-package "magit" "$(VERSION)" ;`
@@ -222,6 +230,7 @@ bump-versions-1:
(async-version \"$(ASYNC_VERSION)\")\
(dash-version \"$(DASH_VERSION)\")\
(git-commit-version \"$(GIT_COMMIT_VERSION)\")\
+ (libgit-version \"$(LIBGIT_VERSION)\")\
(transient-version \"$(TRANSIENT_VERSION)\")\
(with-editor-version \"$(WITH_EDITOR_VERSION)\"))\
$$set_package_requires)"
@@ -232,6 +241,7 @@ bump-snapshots:
(async-version \"$(ASYNC_MELPA_SNAPSHOT)\")\
(dash-version \"$(DASH_MELPA_SNAPSHOT)\")\
(git-commit-version \"$(GIT_COMMIT_MELPA_SNAPSHOT)\")\
+ (libgit-version \"$(LIBGIT_MELPA_SNAPSHOT)\")\
(transient-version \"$(TRANSIENT_MELPA_SNAPSHOT)\")\
(with-editor-version \"$(WITH_EDITOR_MELPA_SNAPSHOT)\"))\
$$set_package_requires)"
diff --git a/default.mk b/default.mk
index b968db0..2ebb1c1 100644
--- a/default.mk
+++ b/default.mk
@@ -33,6 +33,8 @@ INSTALL_INFO ?= $(shell command -v ginstall-info || printf install-info)
MAKEINFO ?= makeinfo
MANUAL_HTML_ARGS ?= --css-ref /assets/page.css
+BUILD_MAGIT_LIBGIT ?= true
+
## Files #############################################################
PKG = magit
@@ -49,7 +51,9 @@ ELS = git-commit.el
ELS += magit-transient.el
ELS += magit-utils.el
ELS += magit-section.el
-ELS += magit-git.el
+ifeq "$(BUILD_MAGIT_LIBGIT)" "true"
+ELS += magit-libgit.el
+endif
ELS += magit-mode.el
ELS += magit-margin.el
ELS += magit-process.el
@@ -102,17 +106,22 @@ VERSION ?= $(shell test -e $(TOP).git && git describe --tags --abbrev=0 | cut -c
ASYNC_VERSION = 1.9.3
DASH_VERSION = 2.14.1
GIT_COMMIT_VERSION = 2.91.0
+LIBGIT_VERSION = 0
TRANSIENT_VERSION = 0
WITH_EDITOR_VERSION = 2.8.0
ASYNC_MELPA_SNAPSHOT = 20180527
DASH_MELPA_SNAPSHOT = 20180910
GIT_COMMIT_MELPA_SNAPSHOT = 20181104
+LIBGIT_MELPA_SNAPSHOT = 0
TRANSIENT_MELPA_SNAPSHOT = 0
WITH_EDITOR_MELPA_SNAPSHOT = 20181103
EMACS_VERSION = 25.1
+LIBGIT_EMACS_VERSION = 26.1
+LIBGIT_MAGIT_VERSION = 0
+
EMACSOLD := $(shell $(BATCH) --eval \
"(and (version< emacs-version \"$(EMACS_VERSION)\") (princ \"true\"))")
ifeq "$(EMACSOLD)" "true"
@@ -132,6 +141,13 @@ ifeq "$(DASH_DIR)" ""
DASH_DIR = $(TOP)../dash
endif
+LIBGIT_DIR ?= $(shell \
+ find -L $(ELPA_DIR) -maxdepth 1 -regex '.*/libgit-[.0-9]*' 2> /dev/null | \
+ sort | tail -n 1)
+ifeq "$(LIBGIT_DIR)" ""
+ LIBGIT_DIR = $(TOP)../libgit
+endif
+
TRANSIENT_DIR ?= $(shell \
find -L $(ELPA_DIR) -maxdepth 1 -regex '.*/transient-[.0-9]*' 2> /dev/null | \
sort | tail -n 1)
@@ -160,10 +176,12 @@ LOAD_PATH = -L $(TOP)/lisp
ifdef CYGPATH
LOAD_PATH += -L $(shell cygpath --mixed $(DASH_DIR))
+ LOAD_PATH += -L $(shell cygpath --mixed $(LIBGIT_DIR))
LOAD_PATH += -L $(shell cygpath --mixed $(TRANSIENT_DIR))
LOAD_PATH += -L $(shell cygpath --mixed $(WITH_EDITOR_DIR))
else
LOAD_PATH += -L $(DASH_DIR)
+ LOAD_PATH += -L $(LIBGIT_DIR)
LOAD_PATH += -L $(TRANSIENT_DIR)
LOAD_PATH += -L $(WITH_EDITOR_DIR)
endif
diff --git a/lisp/Makefile b/lisp/Makefile
index 7577e46..95d6414 100644
--- a/lisp/Makefile
+++ b/lisp/Makefile
@@ -12,7 +12,12 @@ all: lisp
git-commit.elc:
magit-utils.elc:
magit-section.elc: magit-utils.elc
+ifeq "$(BUILD_MAGIT_LIBGIT)" "true"
+magit-libgit.elc:
+magit-git.elc: magit-utils.elc magit-section.elc magit-libgit.elc
+else
magit-git.elc: magit-utils.elc magit-section.elc
+endif
magit-mode.elc: magit-section.elc magit-git.elc
magit-margin.elc: magit-section.elc magit-mode.elc
magit-process.elc: magit-utils.elc magit-section.elc \
diff --git a/lisp/magit-core.el b/lisp/magit-core.el
index 127b9b5..ccb48bf 100644
--- a/lisp/magit-core.el
+++ b/lisp/magit-core.el
@@ -39,6 +39,14 @@
(require 'magit-transient)
(require 'magit-autorevert)
+(when (magit--libgit-available-p)
+ (condition-case err
+ (require 'magit-libgit)
+ (error
+ (setq magit-inhibit-libgit 'error)
+ (message "Error while loading `magit-libgit': %S" err)
+ (message "That is not fatal. The `libegit2' module just won't be used."))))
+
(defgroup magit nil
"Controlling Git from Emacs."
:link '(url-link "https://magit.vc")
diff --git a/lisp/magit-git.el b/lisp/magit-git.el
index eaaf443..a27dc56 100644
--- a/lisp/magit-git.el
+++ b/lisp/magit-git.el
@@ -66,6 +66,38 @@
;; From later in `magit-git'.
(defvar magit-tramp-process-environment nil)
+;;; Git implementations
+
+(defvar magit-inhibit-libgit nil
+ "Whether to inhibit the use of libgit.")
+
+(defvar magit--libgit-available-p eieio-unbound
+ "Whether libgit is available.
+Use the function by the same name instead of this variable.")
+
+(defun magit--libgit-available-p ()
+ (if (eq magit--libgit-available-p eieio-unbound)
+ (setq magit--libgit-available-p
+ (and module-file-suffix
+ (let ((libgit (locate-library "libgit")))
+ (and libgit
+ (or (locate-library "libegit2")
+ (let ((load-path
+ (cons (expand-file-name
+ (convert-standard-filename "build")
+ (file-name-directory libgit))
+ load-path)))
+ (locate-library "libegit2")))))))
+ magit--libgit-available-p))
+
+(defun magit-gitimpl ()
+ "Return the Git implementation used in this repository."
+ (if (and (not magit-inhibit-libgit)
+ (not (file-remote-p default-directory))
+ (magit--libgit-available-p))
+ 'libgit
+ 'git))
+
;;; Options
;; For now this is shared between `magit-process' and `magit-git'.
diff --git a/lisp/magit-libgit.el b/lisp/magit-libgit.el
new file mode 100644
index 0000000..515892a
--- /dev/null
+++ b/lisp/magit-libgit.el
@@ -0,0 +1,66 @@
+;;; magit-libgit.el --- Libgit functionality -*- lexical-binding: t -*-
+
+;; Copyright (C) 2010-2019 The Magit Project Contributors
+;;
+;; You should have received a copy of the AUTHORS.md file which
+;; lists all contributors. If not, see http://magit.vc/authors.
+
+;; Author: Jonas Bernoulli <jonas@bernoul.li>
+;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
+
+;; Package-Requires: ((emacs "26.1") (magit "0") (libgit "0"))
+;; Keywords: git tools vc
+;; Homepage: https://github.com/magit/magit
+
+;; Magit is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; Magit is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Magit. If not, see http://www.gnu.org/licenses.
+
+;;; Commentary:
+
+;; This package teaches Magit to use functions provided by the
+;; `libegit2' module to perform certain tasks. That module used the
+;; Libgit2 implementation of the Git core methods and is implemented
+;; in the `libgit' package.
+
+;; The hope is that using a C module instead of calling out to `git'
+;; all the time increases performance; especially on Windows where
+;; starting a process is unreasonably slow.
+
+;; This package is still experimental and not many functions have been
+;; reimplemented to use `libgit' yet.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'subr-x)
+
+(require 'magit-git)
+(require 'libgit)
+
+;;; Utilities
+
+(defun magit-libgit-repo (&optional directory)
+ "Return an object for the repository in DIRECTORY.
+If optional DIRECTORY is nil, then use `default-directory'."
+ (when-let ((default-directory
+ (let ((magit-inhibit-libgit t))
+ (magit-gitdir directory))))
+ (magit--with-refresh-cache
+ (cons default-directory 'magit-libgit-repo)
+ (libgit-repository-open default-directory))))
+
+;;; Methods
+
+;;; _
+(provide 'magit-libgit)
+;;; magit-libgit.el ends here
diff --git a/lisp/magit-mode.el b/lisp/magit-mode.el
index 948a045..527ed4f 100644
--- a/lisp/magit-mode.el
+++ b/lisp/magit-mode.el
@@ -1489,7 +1489,8 @@ repository's Magit buffers."
:key #'car :test #'equal)))
(dolist (buffer (magit-mode-get-buffers))
(with-current-buffer buffer
- (setq magit-section-visibility-cache nil))))
+ (setq magit-section-visibility-cache nil)))
+ (setq magit--libgit-available-p eieio-unbound))
;;; Utilities
diff --git a/lisp/magit-utils.el b/lisp/magit-utils.el
index 4a98c3c..bbcf0c9 100644
--- a/lisp/magit-utils.el
+++ b/lisp/magit-utils.el
@@ -738,10 +738,11 @@ See info node `(magit)Debugging Tools' for more information."
(cond
(path
(list (file-name-directory path)))
- (t
+ ((not (equal lib "libgit"))
(error "Cannot find mandatory dependency %s" lib)))))
'(;; Like `LOAD_PATH' in `default.mk'.
"dash"
+ "libgit"
"transient"
"with-editor"
;; Obviously `magit' itself is needed too.