├── .github ├── workflows │ ├── compile.yml │ ├── manual.yml │ └── stats.yml └── PULL_REQUEST_TEMPLATE ├── .gitignore ├── .dir-locals.el ├── default.mk ├── README.org ├── docs ├── .orgconfig ├── Makefile ├── borg.org └── borg.texi ├── Makefile ├── borg-elpa.el ├── borg.mk ├── borg.sh ├── CHANGELOG └── LICENSE /.github/workflows/compile.yml: -------------------------------------------------------------------------------- 1 | name: Compile 2 | on: [push, pull_request] 3 | jobs: 4 | compile: 5 | name: Compile 6 | uses: emacscollective/workflows/.github/workflows/compile.yml@main 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /config.mk 2 | /docs/*.html 3 | /docs/*.info 4 | /docs/*.pdf 5 | /docs/*.texi 6 | /docs/.revdesc 7 | /docs/dir 8 | /docs/stats/ 9 | 10 | /*-autoloads.el 11 | /*.elc 12 | /docs/borg/ 13 | -------------------------------------------------------------------------------- /.github/workflows/manual.yml: -------------------------------------------------------------------------------- 1 | name: Manual 2 | on: 3 | push: 4 | branches: main 5 | tags: "v[0-9]+.[0-9]+.[0-9]+" 6 | jobs: 7 | manual: 8 | name: Manual 9 | uses: emacscollective/workflows/.github/workflows/manual.yml@main 10 | secrets: 11 | rclone_config: ${{ secrets.RCLONE_CONFIG }} 12 | -------------------------------------------------------------------------------- /.github/workflows/stats.yml: -------------------------------------------------------------------------------- 1 | name: Statistics 2 | on: 3 | push: 4 | branches: main 5 | schedule: 6 | - cron: '3 13 * * 1' 7 | jobs: 8 | stats: 9 | name: Statistics 10 | uses: emacscollective/workflows/.github/workflows/stats.yml@main 11 | secrets: 12 | rclone_config: ${{ secrets.RCLONE_CONFIG }} 13 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((nil 2 | (indent-tabs-mode . nil)) 3 | (makefile-mode 4 | (indent-tabs-mode . t) 5 | (outline-regexp . "#\\(#+\\)") 6 | (mode . outline-minor)) 7 | (git-commit-mode 8 | (git-commit-major-mode . git-commit-elisp-text-mode)) 9 | (".github/PULL_REQUEST_TEMPLATE" 10 | (nil (truncate-lines . nil))) 11 | ("CHANGELOG" 12 | (nil (fill-column . 70) 13 | (mode . display-fill-column-indicator)))) 14 | -------------------------------------------------------------------------------- /default.mk: -------------------------------------------------------------------------------- 1 | TOP := $(dir $(lastword $(MAKEFILE_LIST))) 2 | 3 | DOMAIN ?= emacsmirror.org 4 | 5 | PKG = borg 6 | 7 | ELS = $(PKG).el 8 | ELS += $(PKG)-elpa.el 9 | ELCS = $(ELS:.el=.elc) 10 | 11 | # Optional: 12 | DEPS = cond-let 13 | DEPS += epkg/lisp 14 | DEPS += magit/lisp 15 | 16 | LOAD_PATH ?= $(addprefix -L ../,$(DEPS)) 17 | LOAD_PATH += -L . 18 | ORG_LOAD_PATH ?= -L ../../org/lisp 19 | 20 | VERSION ?= $(shell test -e $(TOP).git && git describe --tags --abbrev=0 | cut -c2-) 21 | REVDESC := $(shell test -e $(TOP).git && git describe --tags) 22 | 23 | EMACS ?= emacs 24 | EMACS_ARGS ?= --eval "(progn \ 25 | (put 'if-let 'byte-obsolete-info nil) \ 26 | (put 'when-let 'byte-obsolete-info nil))" 27 | EMACS_Q_ARG ?= -Q 28 | EMACS_BATCH ?= $(EMACS) $(EMACS_Q_ARG) --batch $(EMACS_ARGS) $(LOAD_PATH) 29 | EMACS_ORG ?= $(EMACS) $(EMACS_Q_ARG) --batch $(EMACS_ARGS) $(ORG_LOAD_PATH) 30 | 31 | INSTALL_INFO ?= $(shell command -v ginstall-info || printf install-info) 32 | MAKEINFO ?= makeinfo 33 | MANUAL_HTML_ARGS ?= --css-ref https://$(DOMAIN)/assets/page.css 34 | 35 | GITSTATS ?= gitstats 36 | GITSTATS_DIR ?= $(TOP)docs/stats 37 | GITSTATS_ARGS ?= -c style=https://$(DOMAIN)/assets/stats.css -c max_authors=999 38 | 39 | RCLONE ?= rclone 40 | RCLONE_ARGS ?= -v 41 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * Assimilate Emacs packages as Git submodules 2 | 3 | Borg is a bare-bones package manager for Emacs packages. It provides 4 | only a few essential features and should be combined with other tools 5 | such as [[https://github.com/magit/magit][Magit]], [[https://github.com/emacscollective/epkg][epkg]], [[https://github.com/jwiegley/use-package][use-package]], and [[https://github.com/tarsius/auto-compile][auto-compile]]. 6 | 7 | Borg assimilates packages into the =~/.config/emacs= repository as Git 8 | submodules. An assimilated package is called a drone and a borg-based 9 | =~/.config/emacs= repository is called a collective. 10 | 11 | /For more information see the [[https://emacsair.me/2016/05/17/assimilate-emacs-packages-as-git-submodules][announcement]] and the [[https://emacsmirror.net/manual/borg][manual]]./ 12 | 13 | #+html:

14 | #+html: Compile 15 | #+html: Manual 16 | #+html: MELPA Stable 17 | #+html: MELPA 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | Use a dedicated feature branch 3 | ================================================================= 4 | 5 | Please use a dedicated feature branch for your feature request, instead of asking us to merge "your-fork/master" into "origin/master". The use of dedicated branches makes it much more convenient to deal with pull-requests, especially when using Magit to do so. 6 | 7 | If you were about to open a pull-request asking us to merge your version of "master", then see [1] for instructions on how to quickly fix that and some information on why we ask you to do so. 8 | 9 | Additionally we ask you to allow us to push to the branch you want us to merge. We might want to push additional commits and/or make minor changes. Please make sure the box next to "Allow edits from maintainers" is checked before creating the pull-request. 10 | 11 | [1]: https://github.com/magit/magit/wiki/Dedicated-pull-request-branches 12 | 13 | ================================================================= 14 | What you should write here 15 | ================================================================= 16 | 17 | Please summarize the changes made in the commits. Explain why you are making these changes, not just what changes you are making. This also applies to the commit messages. 18 | 19 | ================================================================= 20 | How to update the manual 21 | ================================================================= 22 | 23 | Edit only "borg.org". To update "borg.texi" run "make texi". 24 | -------------------------------------------------------------------------------- /docs/.orgconfig: -------------------------------------------------------------------------------- 1 | # -*- mode:org -*- 2 | # Copyright (C) 2021-2025 Jonas Bernoulli 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # URL: https://github.com/emacscollective/org-macros 5 | # Visit that to see these macros in a human-readable format. 6 | 7 | #+language: en 8 | 9 | #+options: H:4 num:3 toc:2 compact-itemx:t 10 | #+property: header-args :eval never 11 | 12 | #+macro: year (eval (format-time-string "%Y")) 13 | #+macro: version (eval (if-let ((tag (ignore-errors (car (process-lines "git" "describe" "--exact-match"))))) (concat "version " (substring tag 1)) (or (ignore-errors (car (process-lines "git" "describe"))) (concat "version " (or $1 ""))))) 14 | #+macro: kbd (eval (format "@@texinfo:@kbd{@@%s@@texinfo:}@@" (let (case-fold-search) (replace-regexp-in-string (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL" "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN") 'words) "@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t)))) 15 | #+macro: kbdvar (eval (format "@@texinfo:@kbd{@@%s@@texinfo:}@@" (let (case-fold-search) (replace-regexp-in-string "<\\([a-zA-Z-]+\\)>" "@@texinfo:@var{@@\\1@@texinfo:}@@" (replace-regexp-in-string (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL" "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN") 'words) "@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t) t)))) 16 | #+macro: codevar (eval (format "@@texinfo:@code{@@%s@@texinfo:}@@" (let (case-fold-search) (replace-regexp-in-string "\\([A-Z][A-Z-]+\\)" "@@texinfo:@var{@@\\&@@texinfo:}@@" $1 t)))) 17 | #+macro: var @@texinfo:@var{@@$1@@texinfo:}@@ 18 | #+macro: dfn @@texinfo:@dfn{@@$1@@texinfo:}@@ 19 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | -include ../config.mk 2 | include ../default.mk 3 | 4 | .PHONY: stats 5 | 6 | docs: texi info html html-dir pdf 7 | 8 | texi: $(PKG).texi 9 | info: $(PKG).info dir 10 | html: $(PKG).html 11 | html-dir: $(PKG)/index.html 12 | pdf: $(PKG).pdf 13 | 14 | ORG_EVAL += --eval "(setq indent-tabs-mode nil)" 15 | ORG_EVAL += --eval "(setq org-src-preserve-indentation nil)" 16 | ORG_EVAL += --eval "\ 17 | (defun org-texinfo--sanitize-content (text)\ 18 | (replace-regexp-in-string \"[@@{}]\" \"@@\\&\" text))" 19 | ORG_EVAL += --funcall org-texinfo-export-to-texinfo 20 | 21 | redo-docs: 22 | @touch $(PKG).org 23 | @make docs 24 | 25 | .revdesc: ; 26 | _ := $(shell test "$(REVDESC)" = "$$(cat .revdesc 2> /dev/null)" ||\ 27 | echo "$(REVDESC)" > .revdesc) 28 | 29 | %.texi: %.org .orgconfig .revdesc 30 | @printf "Generating $@\n" 31 | @$(EMACS_ORG) $< $(ORG_EVAL) 32 | 33 | %.info: %.texi 34 | @printf "Generating $@\n" 35 | @$(MAKEINFO) --no-split $< -o $@ 36 | 37 | dir: $(PKG).info 38 | @printf "Generating $@\n" 39 | @printf "%s" $^ | xargs -n 1 $(INSTALL_INFO) --dir=$@ 40 | 41 | %.html: %.texi 42 | @printf "Generating $@\n" 43 | @$(MAKEINFO) --html --no-split $(MANUAL_HTML_ARGS) $< 44 | 45 | %/index.html: %.texi 46 | @printf "Generating $(PKG)/*.html\n" 47 | @rm -rf $(PKG) 48 | @$(MAKEINFO) --html -o $(PKG)/ $(MANUAL_HTML_ARGS) $< 49 | 50 | %.pdf: %.texi 51 | @printf "Generating $@\n" 52 | @texi2pdf --clean $< > /dev/null 53 | 54 | DOCS_DOMAIN = docs.$(DOMAIN) 55 | STAT_DOMAIN = stats.$(DOMAIN) 56 | SNAP_TARGET = $(subst .,_,$(DOCS_DOMAIN)):devel/$(PKG)/ 57 | DOCS_TARGET = $(subst .,_,$(DOCS_DOMAIN)):$(PKG)/ 58 | STAT_TARGET = $(subst .,_,$(STAT_DOMAIN)):$(PKG)/ 59 | 60 | publish: redo-docs 61 | @printf "Publishing snapshot manual...\n" 62 | @cp $(PKG).pdf $(PKG)/$(PKG).pdf 63 | @$(RCLONE) sync $(RCLONE_ARGS) $(PKG) $(SNAP_TARGET) 64 | 65 | release: redo-docs 66 | @printf "Publishing release manual...\n" 67 | @cp $(PKG).pdf $(PKG)/$(PKG).pdf 68 | @$(RCLONE) sync $(RCLONE_ARGS) $(PKG) $(DOCS_TARGET) 69 | 70 | stats: 71 | @printf "Generating statistics...\n" 72 | @$(GITSTATS) $(GITSTATS_ARGS) $(TOP) $(GITSTATS_DIR) 73 | 74 | stats-upload: 75 | @printf "Uploading statistics...\n" 76 | @$(RCLONE) sync $(RCLONE_ARGS) stats $(STAT_TARGET) 77 | 78 | CLEAN = $(PKG).info dir $(PKG) $(PKG).html $(PKG).pdf 79 | 80 | clean: 81 | @printf " Cleaning docs/*...\n" 82 | @rm -rf $(CLEAN) 83 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | -include config.mk 2 | include default.mk 3 | 4 | .PHONY: lisp docs 5 | 6 | all: lisp docs 7 | 8 | help: 9 | $(info make all -- Generate lisp and manual) 10 | $(info make lisp -- Generate byte-code and autoloads) 11 | $(info make redo -- Re-generate byte-code and autoloads) 12 | $(info make docs -- Generate all manual formats) 13 | $(info make redo-docs -- Re-generate all manual formats) 14 | $(info make texi -- Generate texi manual) 15 | $(info make info -- Generate info manual) 16 | $(info make html -- Generate html manual file) 17 | $(info make html-dir -- Generate html manual directory) 18 | $(info make pdf -- Generate pdf manual) 19 | $(info make publish -- Publish snapshot manuals) 20 | $(info make release -- Publish release manuals) 21 | $(info make stats -- Generate statistics) 22 | $(info make stats-upload -- Publish statistics) 23 | $(info make clean -- Remove most generated files) 24 | @printf "\n" 25 | 26 | lisp: $(ELCS) autoloads check-declare 27 | redo: clean-lisp lisp 28 | 29 | docs: 30 | @$(MAKE) -C docs docs 31 | redo-docs: 32 | @$(MAKE) -C docs redo-docs 33 | texi: 34 | @$(MAKE) -C docs texi 35 | info: 36 | @$(MAKE) -C docs info 37 | html: 38 | @$(MAKE) -C docs html 39 | html-dir: 40 | @$(MAKE) -C docs html-dir 41 | pdf: 42 | @$(MAKE) -C docs pdf 43 | 44 | publish: 45 | @$(MAKE) -C docs publish 46 | release: 47 | @$(MAKE) -C docs release 48 | 49 | stats: 50 | @$(MAKE) -C docs stats 51 | stats-upload: 52 | @$(MAKE) -C docs stats-upload 53 | 54 | clean: clean-lisp clean-docs 55 | clean-lisp: 56 | @printf " Cleaning *...\n" 57 | @rm -rf $(ELCS) $(PKG)-autoloads.el 58 | clean-docs: 59 | @$(MAKE) -C docs clean 60 | 61 | autoloads: $(PKG)-autoloads.el 62 | 63 | %.elc: %.el 64 | @printf "Compiling $<\n" 65 | @$(EMACS_BATCH) --funcall batch-byte-compile $< 66 | 67 | check-declare: 68 | @printf " Checking function declarations\n" 69 | @$(EMACS_BATCH) --eval "(check-declare-directory default-directory)" 70 | 71 | $(PKG)-autoloads.el: $(ELS) 72 | @printf " Creating $@\n" 73 | @$(EMACS_BATCH) --load autoload --eval "\ 74 | (let* ((file (expand-file-name \"$@\"))\ 75 | (generated-autoload-file file)\ 76 | (coding-system-for-write 'utf-8-emacs-unix)\ 77 | (backup-inhibited t)\ 78 | (version-control 'never)\ 79 | (inhibit-message t))\ 80 | (write-region (autoload-rubric file \"package\" t) nil file)\ 81 | (update-directory-autoloads default-directory))" \ 82 | 2>&1 | sed "/^Package autoload is deprecated$$/d" 83 | -------------------------------------------------------------------------------- /borg-elpa.el: -------------------------------------------------------------------------------- 1 | ;;; borg-elpa.el --- Use Borg alongside Package.el -*- lexical-binding:t -*- 2 | 3 | ;; Copyright (C) 2018-2025 Jonas Bernoulli 4 | 5 | ;; Author: Jonas Bernoulli 6 | ;; Homepage: https://github.com/emacscollective/borg 7 | ;; Keywords: tools 8 | 9 | ;; SPDX-License-Identifier: GPL-3.0-or-later 10 | 11 | ;; This file is free software: you can redistribute it and/or modify 12 | ;; it under the terms of the GNU General Public License as published 13 | ;; by the Free Software Foundation, either version 3 of the License, 14 | ;; or (at your option) any later version. 15 | ;; 16 | ;; This file is distributed in the hope that it will be useful, 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | ;; GNU General Public License for more details. 20 | ;; 21 | ;; You should have received a copy of the GNU General Public License 22 | ;; along with this file. If not, see . 23 | 24 | ;; This file contains code taken from GNU Emacs, which is 25 | ;; Copyright (C) 1976-2023 Free Software Foundation, Inc. 26 | 27 | ;;; Commentary: 28 | 29 | ;; Use Borg alongside `package.el'. 30 | 31 | ;; Borg can be used by itself or alongside `package.el'. Installing 32 | ;; Borg from Melpa is still experimental. For instructions and help 33 | ;; see https://github.com/emacscollective/borg/issues/46. The manual 34 | ;; does not yet cover this topic. 35 | 36 | ;;; Code: 37 | 38 | (require 'cl-lib) 39 | (require 'eieio) 40 | (require 'seq) 41 | (require 'subr-x) 42 | 43 | (with-suppressed-warnings ((obsolete autoload)) 44 | (require 'borg)) 45 | (require 'package) 46 | 47 | ;; Do not require `epkg' to avoid forcing all `borg' users 48 | ;; to install that and all of its numerous dependencies. 49 | (declare-function epkg "epkg" (name)) 50 | (eval-when-compile 51 | (cl-pushnew 'summary eieio--known-slot-names)) 52 | 53 | (defun borg-elpa-initialize () 54 | "Initialize Borg and Elpa in the correct order." 55 | (add-to-list 'package-directory-list 56 | (directory-file-name borg-drones-directory)) 57 | (unless (featurep 'epkg) 58 | (let ((load-path 59 | (nconc (mapcan 60 | (lambda (name) 61 | (let ((dir (expand-file-name name borg-drones-directory))) 62 | (if (file-directory-p dir) 63 | (list dir) 64 | nil))) ; Just hope that it is installed using elpa. 65 | '("emacsql" "closql" "epkg")) 66 | load-path))) 67 | (require (quote epkg) nil t))) 68 | (borg-initialize) 69 | (package-initialize)) 70 | 71 | (define-advice package-activate-1 (:around (fn pkg-desc &optional reload deps) 72 | borg-handle-activation) 73 | "For a Borg-installed package, let Borg handle the activation." 74 | (or (package--borg-clone-p (package-desc-dir pkg-desc)) 75 | (funcall fn pkg-desc reload deps))) 76 | 77 | (define-advice package-load-descriptor (:around (fn pkg-dir) borg-use-database) 78 | "For a Borg-installed package, use information from the Epkgs database." 79 | (if-let ((dir (package--borg-clone-p pkg-dir))) 80 | (let* ((name (file-name-nondirectory (directory-file-name dir))) 81 | (epkg (and (fboundp 'epkg) (epkg name))) 82 | (desc (package-process-define-package 83 | (list 'define-package 84 | name 85 | (borg--package-version name) 86 | (if epkg 87 | (or (oref epkg summary) 88 | "[No summary]") 89 | (format "[Installed using Borg, but %s]" 90 | (if (featurep 'epkg) 91 | "not in Epkgs database" 92 | "Epkg database not available"))) 93 | ())))) 94 | (setf (package-desc-dir desc) pkg-dir) 95 | desc) 96 | (funcall fn pkg-dir))) 97 | 98 | (defun package--borg-clone-p (pkg-dir) 99 | ;; Currently `pkg-dir' is a `directory-file-name', but that might change. 100 | (setq pkg-dir (file-name-as-directory pkg-dir)) 101 | (and (equal (file-name-directory (directory-file-name pkg-dir)) 102 | borg-drones-directory) 103 | pkg-dir)) 104 | 105 | (defvar borg--version-tag-glob "*[0-9]*") 106 | 107 | (defun borg--package-version (clone) 108 | (or (let ((version 109 | (let ((default-directory (borg-worktree clone))) 110 | (ignore-errors 111 | (car (process-lines "git" "describe" "--tags" "--match" 112 | borg--version-tag-glob)))))) 113 | (and version 114 | (string-match 115 | "\\`\\(?:[^0-9]+\\)?\\([.0-9]+\\)\\(?:-\\([0-9]+-g\\)\\)?" 116 | version) 117 | (let ((version (version-to-list (match-string 1 version))) 118 | (commits (match-string 2 version))) 119 | (when commits 120 | (setq commits (string-to-number commits)) 121 | (setq version (seq-take version 3)) 122 | (when (< (length version) 3) 123 | (setq version 124 | (nconc version (make-list (- 3 (length version)) 0)))) 125 | (setq version 126 | (nconc version (list commits)))) 127 | (mapconcat #'number-to-string version ".")))) 128 | "9999")) 129 | 130 | ;;; _ 131 | (provide 'borg-elpa) 132 | ;; Local Variables: 133 | ;; indent-tabs-mode: nil 134 | ;; End: 135 | ;;; borg-elpa.el ends here 136 | -------------------------------------------------------------------------------- /borg.mk: -------------------------------------------------------------------------------- 1 | ## Copyright (C) 2016-2025 Jonas Bernoulli 2 | # 3 | # Author: Jonas Bernoulli 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | 6 | ## Settings 7 | 8 | BORG_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 9 | 10 | BORG_CLEAN_ELN := true 11 | 12 | -include etc/borg/config.mk 13 | 14 | ifeq "$(BORG_SECONDARY_P)" "true" 15 | DRONES_DIR ?= $(shell git config "borg.drones-directory" || echo "elpa") 16 | BORG_ARGS = -L $(BORG_DIR) --load borg-elpa \ 17 | --funcall borg-elpa-initialize $(SILENCIO) 18 | else 19 | DRONES_DIR ?= $(shell git config "borg.drones-directory" || echo "lib") 20 | BORG_ARGS = -L $(BORG_DIR) --load borg \ 21 | --funcall borg-initialize $(SILENCIO) 22 | endif 23 | 24 | EMACS ?= emacs 25 | EMACS_ARGS ?= --eval "(setq load-prefer-newer t)" 26 | EMACS_EXTRA ?= 27 | EMACS_Q_ARG ?= -Q 28 | EMACS_BATCH ?= $(EMACS) $(EMACS_Q_ARG) --batch $(EMACS_ARGS) $(EMACS_EXTRA) 29 | 30 | # Initial revisions of these kludges: 31 | # - be368ce85e6 byte-obsolete-generalized-variable 32 | # - a013a0eee79 registering 33 | # - f6e9cb62ea0 succeeded 34 | # - 38e9e01efb1 scraping 35 | SILENCIO += --eval "(progn\ 36 | (with-eval-after-load 'gv\ 37 | (put 'buffer-substring 'byte-obsolete-generalized-variable nil))\ 38 | (define-advice message (:around (fn format &rest args) silencio)\ 39 | (unless (or (member format\ 40 | '(\"Not registering prefix \\\"%s\\\" from %s. Affects: %S\"\ 41 | \"(Shell command succeeded with %s)\"))\ 42 | (and (stringp (car args))\ 43 | (string-match-p \"Scraping files for\" (car args))))\ 44 | (apply fn format args))))" 45 | 46 | .FORCE: 47 | .PHONY: help helpall clean build native quick-clean quick-build quick \ 48 | init-clean init-build bootstrap-borg bootstrap \ 49 | clone-modules checkout-modules 50 | 51 | ifeq ($(V),1) 52 | Q= 53 | else 54 | Q=@ 55 | endif 56 | 57 | ## Help 58 | 59 | help helpall:: 60 | $(info ) 61 | $(info Getting help) 62 | $(info ------------) 63 | $(info make help = show brief help) 64 | $(info make helpall = show extended help) 65 | $(info ) 66 | $(info Batch targets) 67 | $(info -------------) 68 | $(info make clean = remove all byte-code and native files) 69 | helpall:: 70 | $(info make clean-force = remove all byte-code files using find) 71 | help helpall:: 72 | $(info make build = byte-compile all drones and init files) 73 | $(info make native = byte+native-compile drones and byte-compile init files) 74 | helpall:: 75 | $(info make quick-clean = clean most drones and init files) 76 | $(info make quick-build = byte-compile most drones and init files) 77 | help helpall:: 78 | $(info make quick = clean and byte-compile most drones and init files) 79 | $(info make redo = clean and byte-compile all drones and init files) 80 | $(info ) 81 | $(info Drone targets) 82 | $(info -------------) 83 | $(info make build/DRONE = byte-compile DRONE) 84 | $(info make native/DRONE = byte+native-compile DRONE) 85 | helpall:: 86 | $(info ) 87 | $(info Init file targets) 88 | $(info -----------------) 89 | $(info make init-clean = remove byte-code init files) 90 | $(info make init-tangle = recreate init.el from init.org) 91 | $(info make init-build = byte-compile init files) 92 | help helpall:: 93 | $(info ) 94 | $(info Bootstrapping) 95 | $(info -------------) 96 | $(info make bootstrap = bootstrap collective or new drones) 97 | @printf "\n" 98 | 99 | ## Batch 100 | 101 | clean: 102 | ifeq "$(BORG_CLEAN_ELN)" "true" 103 | @printf "Cleaning...\n" 104 | $(Q)rm -f init.elc $(INIT_FILES:.el=.elc) 105 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) \ 106 | --funcall borg--batch-clean 2>&1 107 | @printf "\n" 108 | else 109 | $(Q)find . -name '*.elc' -printf 'removed %p\n' -delete 110 | $(Q)find . -name '*-autoloads.el' -printf 'removed %p\n' -delete 111 | endif 112 | 113 | clean-force: 114 | $(Q)find . -name '*.elc' -printf 'removed %p\n' -delete 115 | $(Q)find . -name '*-autoloads.el' -printf 'removed %p\n' -delete 116 | 117 | build: init-clean 118 | @printf "Building...\n" 119 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) \ 120 | --funcall borg-batch-rebuild $(INIT_FILES) 2>&1 121 | 122 | native: init-clean 123 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) \ 124 | --eval "(borg-batch-rebuild nil t)" $(INIT_FILES) 2>&1 125 | 126 | ## Batch Quick 127 | 128 | quick-clean: init-clean 129 | @printf "Cleaning...\n" 130 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) \ 131 | --eval '(borg--batch-clean t)' 2>&1 132 | @printf "\n" 133 | 134 | quick-build: 135 | @printf "Building...\n" 136 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) \ 137 | --eval '(borg-batch-rebuild t)' $(INIT_FILES) 2>&1 138 | 139 | quick: quick-clean quick-build 140 | 141 | redo: clean build 142 | 143 | ## Per-Clone 144 | 145 | clean/%: .FORCE 146 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) --eval '(borg-clean "$*")' 2>&1 147 | 148 | # Make tries to rebuild included files. Since the next rule 149 | # would be used in this case, we need a no-op rule to prevent that. 150 | # https://github.com/magit/magit/issues/3318#issuecomment-357548808 151 | $(DRONES_DIR)/borg/borg.mk: ; 152 | 153 | $(DRONES_DIR)/% : .FORCE 154 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) --eval '(borg-build "$*")' 2>&1 155 | 156 | # Define the "aliases" separately to avoid warnings about "peer 157 | # targets" not being updated. 158 | build/%: .FORCE 159 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) --eval '(borg-build "$*")' 2>&1 160 | 161 | 162 | native/%: .FORCE 163 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) --eval '(borg-build "$*" nil t)' 2>&1 164 | 165 | ## Init Files 166 | 167 | init-clean: 168 | $(Q)rm -f init.elc $(INIT_FILES:.el=.elc) 169 | 170 | init-tangle: init.org 171 | @printf "%s\n" "--- [init.org] ---" 172 | $(Q)$(EMACS_BATCH) --load org \ 173 | --eval '(org-babel-tangle-file "init.org")' 2>&1 174 | 175 | init-build: init-clean 176 | $(Q)$(EMACS_BATCH) $(BORG_ARGS) \ 177 | --funcall borg-batch-rebuild-init $(INIT_FILES) 2>&1 178 | 179 | ifeq ($(wildcard init.org), init.org) 180 | init-build: init-tangle 181 | endif 182 | 183 | ## Bootstrap 184 | 185 | bootstrap: 186 | $(Q)printf "\n=== Running 'git submodule init' ===\n\n" 187 | $(Q)git submodule init 188 | $(Q)printf "\n=== Running 'make clone-modules' ===\n" 189 | $(Q)$(MAKE) clone-modules 190 | $(Q)printf "\n=== Running 'make checkout-modules' ===\n" 191 | $(Q)$(MAKE) checkout-modules 192 | $(Q)printf "\n=== Running 'make build' ===\n\n" 193 | $(Q)$(MAKE) build 194 | $(Q)printf "\n=== Bootstrapping finished ===\n\n" 195 | $(Q)git submodule status 196 | 197 | clone-modules: 198 | $(Q)$(BORG_DIR)borg.sh clone 199 | 200 | checkout-modules: 201 | $(Q)$(BORG_DIR)borg.sh checkout 202 | -------------------------------------------------------------------------------- /borg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (C) 2016-2025 Jonas Bernoulli 4 | # 5 | # Author: Jonas Bernoulli 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | 8 | script=$(basename $0) 9 | USAGE="$script clone [...] 10 | or: $script checkout [...]" 11 | OPTIONS_SPEC= 12 | SUBDIRECTORY_OK=Yes 13 | . "$(git --exec-path)/git-sh-setup" 14 | require_work_tree 15 | wt_prefix=$(git rev-parse --show-prefix) 16 | cd_to_toplevel 17 | 18 | GIT_PROTOCOL_FROM_USER=0 19 | export GIT_PROTOCOL_FROM_USER 20 | 21 | set -eu 22 | 23 | usage() { die "usage: $USAGE"; } 24 | 25 | super=$(pwd) 26 | command= 27 | path= 28 | 29 | module_name () { 30 | git config -f .gitmodules --list | 31 | sed -n "s|^submodule.\([^.]*\).path=$1\$|\1|p" 32 | } 33 | 34 | module_hash () { 35 | git submodule foreach 'echo $path $sha1' | 36 | sed -n "s|^$1 \([^.]*\)|\1|p" 37 | } 38 | 39 | clone () { 40 | path="$1" 41 | modsdir="$2/modules" 42 | shift 2 43 | echo "--- [$path] ---" 44 | 45 | cd "$super" 46 | 47 | name=$(module_name "$path") 48 | push_remote=$(git config --includes -f .gitmodules remote.pushDefault || true) 49 | push_match=$(git config --includes -f .gitmodules --get-all remote.pushMatch || true) 50 | 51 | # Unlike is_tree_submodule_active, ignore value of submodule.active. 52 | if [ "$(git config --get --type=bool --default=true submodule.$name.active)" \ 53 | = false -o -z "$(git config --get submodule.$name.url)" ] 54 | then 55 | echo "Skipping $path (not activated)" 56 | else 57 | if [ ! -e "$path"/.git ] 58 | then 59 | url=$(git config submodule.$name.url) 60 | args= 61 | rename= 62 | echo "Cloning $path from origin ($url)" 63 | case "$name,$url" in 64 | elpa-admin,*git.savannah.gnu.org*/git/emacs/elpa.git) 65 | args="--no-tags --single-branch --branch $name" 66 | rename=$name 67 | ;; 68 | *,*git.savannah.gnu.org*/git/emacs/elpa.git) 69 | args="--no-tags --single-branch --branch externals/$name" 70 | rename=externals/$name 71 | ;; 72 | *,*git.savannah.gnu.org*/git/emacs/nongnu.git) 73 | args="--no-tags --single-branch --branch elpa/$name" 74 | rename=elpa/$name 75 | ;; 76 | esac 77 | 78 | mkdir -p "$modsdir" 79 | git clone "$url" "$path" $args \ 80 | --separate-git-dir "$modsdir/$name" || 81 | echo "Cloning failed" 82 | 83 | if [ -n "$rename" ] 84 | then 85 | cd "$path" 86 | echo "Renaming branch $rename to main" 87 | git branch -m $rename main 88 | fi 89 | fi 90 | 91 | git config --includes -f .gitmodules --get-all submodule.$name.remote | 92 | while read -r remote url refspec 93 | do 94 | cd "$super" 95 | 96 | if [ ! -e "$path"/.git ] 97 | then 98 | echo "Cloning $path from $remote ($url)" 99 | 100 | mkdir -p "$modsdir" 101 | if git clone "$url" "$path" \ 102 | --separate-git-dir "$modsdir/$name" 103 | then 104 | git remote rename origin "$remote" 105 | else 106 | echo "Cloning failed" 107 | fi 108 | else 109 | cd "$path" 110 | 111 | if ! git remote | grep -q "^$remote\$" 112 | then 113 | echo "Augmenting $path with remote $remote ($url)" 114 | args= 115 | case "$url" in 116 | *git.savannah.gnu.org*/git/emacs/elpa.git) 117 | args="--no-tags -t externals/$name" ;; 118 | *git.savannah.gnu.org*/git/emacs/nongnu.git) 119 | args="--no-tags -t elpa/$name" ;; 120 | esac 121 | git remote add "$remote" "$url" $args 122 | git fetch "$remote" || echo "fetch failed" 123 | fi 124 | fi 125 | 126 | if [ -e "$super/$path/.git" ] 127 | then 128 | cd "$super/$path" 129 | 130 | if ! git config remote.pushDefault > /dev/null && 131 | [ "$remote" = "$push_remote" ] 132 | then 133 | echo "Setting remote.pushDefault for $path to $remote" 134 | git config remote.pushDefault "$remote" 135 | fi 136 | fi 137 | done 138 | 139 | if [ -e "$super/$path/.git" ] 140 | then 141 | cd "$super/$path" 142 | 143 | if [ -z "$(git config remote.pushDefault)" ] 144 | then 145 | url=$(git config remote.origin.url) 146 | for p in $push_match 147 | do 148 | case $url in 149 | *$p*) 150 | echo "Setting remote.pushDefault for $path to origin" 151 | git config remote.pushDefault origin ;; 152 | esac 153 | done 154 | fi 155 | fi 156 | fi 157 | echo 158 | } 159 | 160 | checkout () { 161 | path="$1" 162 | shift 163 | echo "--- [$path] ---" 164 | 165 | cd "$super" 166 | 167 | name=$(module_name "$path") 168 | hash=$(module_hash "$path") 169 | 170 | if [ ! -e "$path"/.git ] 171 | then 172 | echo "Skipping $path (not populated)" 173 | else 174 | cd "$path" 175 | 176 | head=$(git rev-parse HEAD) 177 | branch=$(git symbolic-ref --short HEAD 2> /dev/null || true) 178 | upstream=$(git rev-parse --verify --abbrev-ref $branch@{u} 2> /dev/null || true) 179 | if [ "$hash" = "$head" ] 180 | then 181 | echo "ok" 182 | elif [ "$name" = "borg" ] 183 | then 184 | echo "Skipping $path (always using latest/checked out borg)" 185 | echo " HEAD: $head" 186 | echo "expected: $hash" 187 | elif [ -n "$(git status --porcelain=v1 --ignored)" ] 188 | then 189 | echo "Skipping $path (uncommitted changes)" 190 | echo " HEAD: $head" 191 | echo "expected: $hash" 192 | elif ! git diff --quiet "$head" "$upstream" 193 | then 194 | echo "Skipping $path (tip no longer matches upstream)" 195 | echo " HEAD: $head" 196 | echo "expected: $hash" 197 | else 198 | echo "Checkout $path ($hash)" 199 | echo "HEAD was $(git log --no-walk --format='%h %s' HEAD)" 200 | if ! git reset --hard "$hash" 201 | then 202 | echo "Checkout of '$hash' into submodule path '$path' failed" 203 | fi 204 | fi 205 | fi 206 | echo 207 | } 208 | 209 | cmd_clone () { 210 | gitdir="$(realpath "$(git rev-parse --git-dir)")" 211 | 212 | if [ $# -gt 0 ] 213 | then 214 | for path in "$@"; do clone $path $gitdir; done 215 | else 216 | git ls-files -s | grep ^160000 | cut -f2 | 217 | while read path; do clone $path $gitdir; done 218 | fi 219 | } 220 | 221 | cmd_checkout () { 222 | if [ $# -gt 0 ] 223 | then 224 | for path in "$@"; do checkout $path; done 225 | else 226 | git ls-files -s | grep ^160000 | cut -f2 | 227 | while read path; do checkout $path; done 228 | fi 229 | } 230 | 231 | command=${1-} 232 | 233 | case "$command" in 234 | clone|checkout) shift; "cmd_$command" "$@" ;; 235 | *) usage ;; 236 | esac 237 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | # -*- mode: org -*- 2 | * v4.4.0 UNRELEASED 3 | 4 | - Dropped support for Emacs 27. 64f67e5 5 | 6 | - For Emacs 28 autoloads were not re-generated from scratch. f2316c1 7 | 8 | * v4.3.0 2025-11-01 9 | 10 | - ~borg-batch-rebuild~ now skips empty drones, which are created when 11 | cloning fails. This command would end up creating an autoloads 12 | file, which in turn would prevent later cloning attempts to fail. 13 | b8fee39 14 | 15 | - For Emacs 28 and earlier we generated autoloads files that did not 16 | contain a ~provide~ form. 9166c2b 17 | 18 | * v4.2.2 2025-10-06 19 | 20 | - Autoload files are now always recreated from scratch because merely 21 | updating them, as implemented in ~loaddefs-generate,~ is unreliable. 22 | #174 23 | 24 | * v4.2.1 2025-09-01 25 | 26 | Thoughts and whitespace. 27 | 28 | * v4.2.0 2025-06-01 29 | 30 | - Made it safer to rerun ~make bootstrap~ or parts thereof. cd95c7c 31 | 32 | - Added make targets ~checkout-module~ and ~clone-modules~, making it 33 | more convenient to rerun just parts of the bootstrapping process. 34 | 746d6cc 35 | 36 | * v4.1.5 2025-04-28 37 | 38 | - Fixed bug in bootstrapping script. #171 39 | 40 | * v4.1.4 2025-04-01 41 | 42 | Thoughts and whitespace. 43 | 44 | * v4.1.3 2025-03-02 45 | 46 | Thoughts and whitespace. 47 | 48 | * v4.1.2 2024-12-01 49 | 50 | - Stopped using a ~realpath~ gnu-ism. #167 51 | 52 | * v4.1.1 2024-11-02 53 | 54 | - Org export errors are now being demoted instead of being ignored 55 | entirely. 13caf51 56 | 57 | - Makefile and documentation improvements. 58 | 59 | * v4.1.0 2024-09-01 60 | 61 | - The robustness of the code used to set ~borg-drones-directory~, 62 | ~borg-user-emacs-directory~ and ~borg-top-level-directory~ has been 63 | increased. As a result ~borg-drones-directory~ no longer has to 64 | be a direct subdirectory of ~borg-user-emacs-directory~. #144 65 | 66 | - The Emacs configuration repository can now itself be a submodule. 67 | #154 68 | 69 | - Updated tooling. 70 | 71 | * v4.0.0 2024-08-08 72 | 73 | - Dropped support for Emacs 26. fd9d044 74 | 75 | - The bootstrapping process has been improved. e27463e 76 | 77 | - Added support for including other files in 78 | ~~/.config/emacs/.gitmodules~ and use that to separate essential 79 | module configuration (still in ~.gitmodules~), additional remotes 80 | (now in ~.gitremotes~) and build configuration (now in ~.borgconfig~). 81 | f9a9140 82 | 83 | - ~borg-read-package~ used to suggest the Emacsmirror URL for packages 84 | from many forges, when it should have suggested the upstream URL 85 | instead. d8aecb0 86 | 87 | - When building an individual drone, it is now cleaned first, just 88 | like it was always done when building all drones at once. b8f7561 89 | 90 | - While a build step is running, the new ~borg-clone~ variable is bound 91 | to the package currently being build. c0ad642 92 | 93 | - Added new variable ~borg.extra-build-step~ which allows specifying 94 | additional build steps to be used when building any drone. 2f41ec4 95 | 96 | - The value of a ~submodule.DRONE.disabled~ variable can now be a lisp 97 | expression. 15a8905 98 | 99 | - Added new variable ~borg-minimal-emacs-alist~, used to disable drones 100 | that require a more recent Emacs release than what is currently 101 | being used. 00132c1 102 | 103 | - Added support for exporting Org files to Texinfo. #121 104 | 105 | - When building only most drones using the ~quick~ make target, drones 106 | that aren't going to be re-build are no longer cleaned. 5647cd7 107 | 108 | - Stopped using ~git submodule--helper~ subcommands, which were removed 109 | in Git v2.38.0. 78a1c87 8d00bb8 etc. 110 | 111 | - Renamed many ~make~ targets. Made ~help~ the default target. Removed 112 | the ~all~ target (since there is no one-fits-all). Added ~clean-force~ 113 | target. 675d97a 41d8ba4 d843820 3dc7068 d873be8 etc. 114 | 115 | - Improved support for native compilation. c166368 40b0664 2520ae9 116 | 21acd89 etc. 117 | 118 | - Use ~loaddefs-generate~ in Emacs 29 and later. 14c140d 119 | 120 | - The format of the raw output of ~borg-drones~ changed. 47122b6 121 | 122 | - Disabled drones are now highlighted in Magit's tabulated module lists. 123 | d3cdc17 124 | 125 | - ~make clean~ and ~make force-clean~ now also remove autoload files. 126 | 1172842, 52234b0 127 | 128 | - Values added to ~SILENCIO~ in ~borg.mk~ are no longer discarded. This 129 | variable can be used to suppress warnings when compiling drones. 130 | 72000eb 131 | 132 | - 7baf949 borg-makeinfo: Do not regenerate tracked but missing file 133 | - 04df5ca borg-build: Remove trailing slash from clone name 134 | - 1f87dfc borg--build-interactive: Use pop-to-buffer-same-window 135 | - 9e59c64 Handle autoloads and load-path more robustly 136 | - 7ef6a70 make: No longer hardcode drone directory in target names 137 | - cb198c7 borg.sh: Improve safety outside initial "make bootstrap" 138 | - 3cd6b4f make: Explicitly specify output directory for makeinfo --html 139 | - c83238b borg-elpa: Don't assume epkg is available 140 | - a337603 Ensure activation happens only after building is done 141 | - e29d983 borg-drones: Append slash to borg-drones-directory if necessary 142 | - 8a5a718 Display build buffer after setting major-mode 143 | - 1b4efad #157 borg-build: let-bind borg-compile-function 144 | - 94b9be7 borg-update-autoloads: Add to load-path again 145 | 146 | * v3.3.1 2022-02-16 147 | 148 | - ~borg-user-emacs-directory~ wasn't used in all places where it 149 | should be used. 150 | 151 | - Added new function ~borg-dronep~. 152 | 153 | - Added new macro ~borg-do-drones~, which is mostly like ~dolist~ but 154 | caches variables that are set in ".gitmodules". 155 | 156 | - Added new make target ~build-native~. 157 | 158 | - Like manual in the top directory, those in the ~doc/~ and ~docs/~ 159 | directories are now also automatically build and added to 160 | ~Info-directory-list~. 161 | 162 | - Added an additional make variable ~EMACS_ARGUMENTS~ that is reserved 163 | for use by users. 164 | 165 | * v3.3.0 2022-01-01 166 | 167 | - When setting ~borg-top-level-directory~ do not assume we are inside 168 | a Git repository, which makes it possible to use Borg to build a 169 | static configuration to be deployed outside the repository used 170 | to build it. #110 171 | 172 | - Fixed path to ~etc/borg/config.mk~, which is now also loaded when 173 | building not-interactively. 174 | 175 | - Added new variable ~borg-compile-function~, which can be set to 176 | ~native-compile~ to enable upfront native compilation. This should 177 | be done in ~~/.emacs.d/etc/borg/config.el~ like so: 178 | 179 | #+begin_src emacs-lisp 180 | (when (native-comp-available-p) 181 | (setq borg-compile-function #'native-compile)) 182 | #+end_src 183 | 184 | Renamed ~borg-byte-compile-recursively~ to ~borg-compile-recursively~ 185 | and ~borg-byte-compile~ to ~borg-compile~ accordingly. #116 186 | 187 | - ~borg-drones~ learned to ignore non-drone submodules. #117 188 | 189 | - The ~variable~ argument of ~borg-get~ can now be a symbol. 190 | 191 | - If a variable has multiple values ~borg-get~ failed to return the 192 | last value when using the cache, as it already did when not using 193 | the cache. 194 | 195 | * v3.2.0 2021-05-30 196 | 197 | - Taught ~borg-load-path~ to use the ~elisp/~ directory automatically 198 | like it already uses the ~lisp/~ directory or the top-level. The 199 | ~elisp/~ directory takes precedence over the other two directories. 200 | a8bce40 201 | 202 | - Users can now specify the init files that should be compiled by 203 | setting the ~INIT_FILES~ variable in the top-level ~Makefile~. If 204 | that is not specified, then the same files as before are compiled 205 | (~init.el~ and ~.el~). 35b63df 206 | 207 | - Each init file is now loaded before it is compiled. Previously 208 | this was only done for ~init.el~. f6a2e0c 209 | 210 | - The ~default-directory~ used during compilation and when presenting 211 | the results did not always match, leading to broken links. 41b4494 212 | 213 | - When initializing and rebuilding packages, then missing and disabled 214 | packages are skipped now. bde5d4c, 93f40f9, 640169d 215 | 216 | - It is now possible to place the drones in a directory that is named 217 | something other than ~lib~ using the ~borg.drones-directory~ variable. 218 | The default is still ~lib~, except when using Borg alongside Package; 219 | then the new default is ~borg~. 83f96dd, fd31cff 220 | 221 | - The ~borg-user-emacs-directory~ no longer has to be the top-level 222 | directory of the containing repository. bbea37f 223 | 224 | - The variable ~borg-drones-directory~ was previously known as 225 | ~borg-drone-directory~. dd0c142 226 | 227 | - When Borg is used as secondary package manager, then ~borg.mk~ is now 228 | usable as well. 5d87d34 229 | 230 | - Added documentation on how to recover from missing commits and 231 | missing repositories. ecb2f9f 232 | 233 | - Symlinks are resolved now when setting path variables. 444b9d7 234 | 235 | * v3.1.2 2019-12-05 236 | 237 | - The new option ~borg-rewrite-urls-alist~ allows rewriting certain urls 238 | when a package repository is cloned. This is mostly intended to 239 | replace Github and Gitlab ssh URLs with https urls. 240 | 241 | * v3.1.1 2019-05-05 242 | 243 | - Cosmetics and improvements to maintenance tools. 244 | 245 | * v3.1.0 2019-01-28 246 | 247 | - The new user configuration file ~~/.emacs.d/etc/borg/init.el~ is 248 | loaded by ~borg-initialize~ if Emacs is running without an interactive 249 | terminal. 250 | 251 | * v3.0.0 2018-10-31 252 | 253 | - Borg can now be used as a secondary package manager alongside 254 | ~package.el~. When used like this, then Borg itself should be 255 | installed from Melpa. This is still experimental. For instructions 256 | and help see https://github.com/emacscollective/borg/issues/46. The 257 | manual does not yet cover this topic. 258 | 259 | - The commands ~borg-assimilate~ and ~borg-clone~ now require the user to 260 | confirm before acting on a package that is known to be (potentially) 261 | unsafe. Note that this does not imply that other packages are safe, 262 | and also that the ~epkg~ package has to be available for this to kick 263 | in for the most dangerous packages — those from the Emacswiki, into 264 | which anyone could trivially inject malicious code. 265 | 266 | - The new files ~borg.mk~ and ~borg.sh~ were added, replacing files that 267 | were previously located directly in the super-repository. 268 | 269 | The super-repository still contains a ~Makefile~, which users who do 270 | not use the Emacs.g collective have to update manually, but failure 271 | to do so should be less problematic now, because this file only 272 | defines a single target needed to make ~borg.mk~ and ~borg.sh~ 273 | accessible during bootstrap, while using these files for everything 274 | it previously did itself. 275 | 276 | This makes it easier and safer to improve the respective 277 | functionality iteratively and to create configurations that are not 278 | based on the Emacs.d collective. 279 | 280 | - The new user configuration files ~~/.emacs.d/etc/borg/config.el~ and 281 | ~~/.emacs.d/etc/borg/config.mk~ are loaded by ~borg-build~ and ~make~ if 282 | they exist. These files are primarily intended to set the variables 283 | ~borg-emacs-argument~ (which see) and ~EMACS_ARGUMENTS~. The latter can 284 | also be used to set ~EMACS~ and/or to define new make targets. 285 | 286 | - The new command ~borg-insert-update-message~ inserts information 287 | about drones that are updated in the index. The inserted text is 288 | formatted according to the commit message conventions documented 289 | in the manual. In ~git-commit-mode-map~ ~C-c C-b~ is bound to this 290 | command. 291 | 292 | - A new make target ~tangle-init~ was added which recreates ~init.el~ from 293 | ~init.org~. 294 | 295 | - Added new variables ~submodule.DRONE.recursive-byte-compile~ and 296 | ~borg-byte-compile-recursively~. 297 | 298 | - The user is asked to save relevant buffers before compiling. 299 | 300 | - The values of ~submodule.DRONE.no-byte-compile~ are now treated as 301 | relative to the top-level. The documentation already claimed that 302 | was the case before. 303 | 304 | - All build output is appended to the same buffer now. Previously each 305 | build created a new, unspecialized buffer that never got cleaned up. 306 | The buffer is automatically shown on every build but can easily be 307 | buried using ~C-q~. 308 | 309 | - The command ~borg-insert-update-message~ now also handles assimilations 310 | and removals. 311 | 312 | * v2.0.0 2017-09-19 313 | 314 | - Added new command ~borg-clone~ to make it easier to review a package 315 | before assimilating it. Assimilating a package gives that package 316 | a change to run arbitrary code, so the review should happen first. 317 | 318 | Packages that have been cloned are now being referred to as clones. 319 | If they have additionally been assimilated, then they are referred 320 | to as drones, as before. Note that drones are also clones. 321 | 322 | When a package has not even been cloned yet, then it is referred 323 | to as just a package. 324 | 325 | - Added new command ~borg-remove~ to replace ~borg-uninstall~. The new 326 | name is more appropriate because this command is also suitable for 327 | removing a package that has previously been cloned, without also 328 | being assimilated. This command moves the working tree to the 329 | trash, but does not remove the gitdir. It also refuses to do 330 | anything if the working tree isn't clean. 331 | 332 | - Command ~borg-assimilate~ now assimilates an already cloned package 333 | without the user having to use a prefix argument, while separating 334 | the gitdir from the working tree, if that isn't already the case. 335 | The latter is useful after the user initialized a new repository, 336 | or cloned a package using something other than ~borg-clone~. 337 | 338 | When assimilating a package, that has been cloned or assimilated 339 | before but was then removed again, then the user is now given the 340 | choice between reusing the existing gitdir or starting over. 341 | 342 | - Command ~borg-build~ now also activates the clone or drone using the 343 | new command ~borg-activate~, which was extracted from ~borg-assimilate~. 344 | 345 | - Command ~borg-build~ now always uses a non-interactive Emacs instance 346 | to avoid polluting the new byte-code with old versions of the same 347 | code that is already loaded. 348 | 349 | - The functions ~borg-update-autoloads~, ~borg-byte-compile~, and 350 | ~borg-makeinfo~ can now be used as explicit build steps without 351 | having to specify their argument(s). 352 | 353 | - Added new variable ~borg-build-shell-command~ to give users complete 354 | control over how shell command build steps are executed. 355 | 356 | - Added new utility function ~borg-gitdir~ and, in order to avoid 357 | confusion and match Git terminology, renamed ~borg-repository~ to 358 | ~borg-worktree~. 359 | 360 | - Added new utility functions ~borg-read-package~, ~borg-read-clone~, 361 | and ~borg-clones~. 362 | 363 | - Fixed a type error in ~borg-initialized~ when drones are being 364 | skipped. 365 | 366 | * v1.0.0 2016-12-31 367 | 368 | - Repository moved to https://github.com/emacscollective/borg. 369 | 370 | - The ~~/.emacs.d/bin/borg-bootstrap~ script can now add additional 371 | remotes. That script is part of the repository of the ~emacs.g~ 372 | collective. It cannot be part of the ~borg~ repository, because it 373 | is has to be available before the ~borg~ repository and all the other 374 | drone/submodule repositories are cloned. But the documentation 375 | about this script can be found in the ~borg~ manual. 376 | 377 | - ~borg-initialize~ now uses a cache to avoid calling ~git config~ 378 | excessively. On Windows this significantly improves performance. 379 | 380 | - ~borg-drones~ learned to optionally return drone variables instead 381 | of just the drone names. 382 | 383 | - ~borg-byte-compile~ and ~borg-update-autoloads~ now don't require the 384 | PATH argument. 385 | 386 | - ~borg-uninstall~ was broken. 387 | 388 | - The manual was updated heavily. 389 | 390 | - Cosmetic and other minor improvements. 391 | 392 | - Minor bug fixes and typo fixes. 393 | 394 | * v0.2.0 2016-11-05 395 | 396 | - Repository moved to https://gitlab.com/emacscollective/borg. 397 | 398 | - Updated manual and made source compatible with Org v9.0. 399 | 400 | - Improved and extended ~make~ targets. 401 | 402 | * v0.1.6 2016-10-08 403 | 404 | - Updated homepage link. 405 | 406 | * v0.1.5 2016-09-27 407 | 408 | - Typo fixes. 409 | 410 | * v0.1.4 2016-09-27 411 | 412 | - When invoked as a command ~borg-build~ failed. 413 | 414 | * v0.1.3 2016-09-01 415 | 416 | - Added new function ~borg-batch-rebuild-init~ to allow compiling 417 | just the init files without also compiling all drones. 418 | 419 | * v0.1.2 2016-08-27 420 | 421 | - ~borg-batch-rebuild~ now also compiles the secondary init file 422 | ~.el~ if present. 423 | 424 | - ~borg-batch-rebuild~ now compiles ~org~ before all other packages. 425 | 426 | * v0.1.1 2016-05-18 427 | 428 | - ~borg-build~ did not respect ~submodule..build-step~. 429 | 430 | * v0.1.0 2016-05-17 431 | 432 | - First release. 433 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /docs/borg.org: -------------------------------------------------------------------------------- 1 | #+title: Borg User Manual 2 | :PREAMBLE: 3 | #+author: Jonas Bernoulli 4 | #+email: emacs.borg@jonas.bernoulli.dev 5 | #+date: 2018-{{{year}}} 6 | 7 | #+texinfo_dir_category: Emacs 8 | #+texinfo_dir_title: Borg: (borg). 9 | #+texinfo_dir_desc: Assimilate Emacs packages as Git submodules 10 | #+subtitle: for version 4.3.0 11 | 12 | #+setupfile: .orgconfig 13 | #+texinfo: @paragraphindent none 14 | 15 | The Borg assimilate Emacs packages as Git submodules. Borg is a 16 | bare-bones package manager for Emacs packages. 17 | 18 | This manual is for Borg version 4.3.0. 19 | 20 | #+texinfo: @insertcopying 21 | :END: 22 | * Introduction 23 | 24 | The Borg assimilate Emacs packages as Git submodules. 25 | 26 | Borg is a bare-bones package manager for Emacs packages. It provides 27 | only a few essential features and should be combined with other tools 28 | such as Magit, ~epkg~, ~use-package~, and ~auto-compile~. 29 | 30 | Borg assimilates packages into the ~~/.config/emacs~ [fn:1] repository 31 | as Git submodules. An assimilated package is called a drone and a 32 | borg-based ~~/.config/emacs~ repository is called a collective. 33 | 34 | It is possible to clone a package repository without assimilating it. 35 | A cloned package is called a clone. 36 | 37 | To learn more about this project, also read the blog post [fn:2] in 38 | which it was announced. 39 | 40 | [fn:1] Or ~~/.emacs.d~ of course, if you prefer that or have to use the 41 | old location because you still have to support older Emacs releases. 42 | [fn:2] https://emacsair.me/2016/05/17/assimilate-emacs-packages-as-git-submodules. 43 | 44 | * Installation 45 | 46 | Borg can be used by itself, in which case it has to be bootstrapped. 47 | This is how Borg originally was intended to be used exclusively, but 48 | nowadays you may also choose to use it merely as a secondary package 49 | manager, in which case Borg itself is installed using Package. 50 | 51 | ** Use as secondary package manager 52 | 53 | To use Borg as a secondary package manager alongside Package, begin by 54 | installing the former using the latter. Borg is only available from 55 | Melpa, so you have to add that first. 56 | 57 | #+begin_src emacs-lisp 58 | (add-to-list 'package-archives 59 | (cons "melpa" "https://melpa.org/packages/") 60 | t) 61 | #+end_src 62 | 63 | Then you have to ~M-x package-refresh-contents RET~ before you can ~M-x 64 | package-install RET borg RET~. Doing that should add a verbose variant 65 | of this to your init file: 66 | 67 | #+begin_src emacs-lisp 68 | (custom-set-variables 69 | '(package-selected-packages '(borg))) 70 | #+end_src 71 | 72 | Then you have to make the two package managers aware of each other by 73 | replacing the call to ~package-initialize~ in your init file with this: 74 | 75 | #+begin_src emacs-lisp 76 | (if (require 'borg-elpa nil t) 77 | (borg-elpa-initialize) 78 | (package-initialize)) 79 | #+end_src 80 | 81 | Just like Package (aka Elpa) defaults to installing packages in ~elpa/~, 82 | Borg defaults to installing them in ~borg/~. (When using both package 83 | managers, that is. If used by itself, then Borg defaults to using 84 | ~lib/~.) If you want to use another directory, then you can do so by 85 | setting the Git variable ~borg.drones-directory~. 86 | 87 | You should also add a ~Makefile~ containing: 88 | 89 | #+begin_src makefile 90 | BORG_SECONDARY_P = true 91 | include $(shell find -L elpa -maxdepth 1 -regex '.*/borg-[.0-9]*' |\ 92 | sort | tail -n 1)/borg.mk 93 | #+end_src 94 | 95 | Despite its title, many things mentioned in the next section are 96 | relevant even when Borg was installed the way we just did. Just 97 | saying. 98 | 99 | ** Bootstrapping 100 | 101 | (As mentioned in the next section you can use a location other than 102 | ~~/.config/emacs~ (or ~~/.emacs.d~). Nevertheless most of the subsequent 103 | examples just talk about ~~/.config/emacs~ and if you use something 104 | else, then obviously have to substitute that. The same applies to the 105 | string ~lib~ and the variables ~user-init-file~ and ~user-emacs-directory~, 106 | which also might not be appropriate depending on your choices.) 107 | 108 | *** Bootstrapping using a seed 109 | 110 | To get started clone the repository of the ~emacs.g~ collective. A 111 | "collective" is a starter-kit and/or configuration seed that relies on 112 | Borg as the package manager. Most users end up using ~emacs.g~ merely 113 | as a bootstrapping seed and do not merge upstream changes after that. 114 | 115 | This collective already assimilates a few drones in addition to ~borg~ 116 | itself, namely ~magit~, ~epkg~, ~use-package~, ~auto-compile~, ~git-modes~ and 117 | ~diff-hl~, as well as their dependencies. These drones are not required 118 | by ~borg~ but their use is highly recommended. 119 | 120 | Clone the ~emacs.g~ repository to either ~~/.config/emacs~, or for testing 121 | purposes to any other location. This repository contains a ~Makefile~ 122 | that imports ~lib/borg/borg.mk~ and defines an additional target whose 123 | purpose is to make that file and ~lib/borg/borg.sh~ available. Run ~make 124 | bootstrap-borg~ to clone the ~borg~ repository. That does not completely 125 | setup ~borg~ but it makes the latest version of the mentioned files 126 | available. 127 | 128 | Now that these files are available you can run ~make bootstrap~ to get 129 | and configure all submodules (including the ~borg~ submodule) and to 130 | build all drones. 131 | 132 | #+begin_src sh 133 | git clone git@github.com:emacscollective/emacs.g.git ~/.config/emacs 134 | cd ~/.config/emacs 135 | make bootstrap-borg 136 | make bootstrap 137 | #+end_src 138 | 139 | If you have assimilated many packages, you might want to use ~make 140 | bootstrap | tee bootstrap.log~. 141 | 142 | The last command run during bootstrap is ~git submodule status~, which 143 | prints one line per module. If a line is prefixed with =+=, that means 144 | that it was not possible to checkout the recorded commit, and ~-~ means 145 | that the module could not be cloned. Even if some module could not be 146 | cloned, that usually does not render a configuration unusable, so just 147 | run ~emacs~ now, and then investigate any issues from the comfort of 148 | Magit. 149 | 150 | If you cloned to somewhere other than ~~/.config/emacs~, then you can 151 | use that configuration using ~emacs --init-directory /path/to/emacs.g/~, 152 | provided you are using Emacs 29 or later. Otherwise you have to 153 | resort to ~emacs -Q -l /path/to/emacs.g/early-init.el -l 154 | /path/to/emacs.g/init.el~. 155 | 156 | For drones whose upstream repositories are located on Github or Gitlab 157 | the ~emacs.g~ collective uses the ~ssh~ protocol by default, which is a 158 | problem if you don't have accounts there and have not properly setup 159 | your keys. See [[*Using https URLs]]. 160 | 161 | During package compilation you may notice the submodules relating to 162 | those packages become dirty due to the compilation outputs not being 163 | ignored in those submodules. For this reason it is useful to ignore 164 | these outputs globally, for example in your ~~/.config/git/ignore~ 165 | file: 166 | 167 | #+begin_src undefined 168 | *.elc 169 | *-autoloads.el 170 | dir 171 | #+end_src 172 | 173 | You may discover more things that you'll want to ignore this way as 174 | you use ~borg~. 175 | 176 | *** Bootstrapping from scratch 177 | 178 | If you don't want to base your configuration on the ~emacs.g~ 179 | starter-kit described in the previous section, then you have 180 | to do a few things manually. 181 | 182 | #+begin_src sh 183 | git init ~/.config/emacs 184 | cd ~/.config/emacs 185 | #+end_src 186 | 187 | By default Borg installs packages inside the ~lib/~ subdirectory, but 188 | since you are starting from scratch, you may choose something else 189 | by setting the Git variable ~borg.drones-directory~ locally for this 190 | repository. 191 | 192 | Then you should add a ~Makefile~ containing at least: 193 | 194 | #+begin_src makefile 195 | DRONES_DIR = $(shell git config "borg.drones-directory" || echo "lib") 196 | 197 | -include $(DRONES_DIR)/borg/borg.mk 198 | 199 | bootstrap-borg: 200 | @git submodule--helper clone --name borg --path $(DRONES_DIR)/borg \ 201 | --url git@github.com:emacscollective/borg.git 202 | @cd $(DRONES_DIR)/borg; git symbolic-ref HEAD refs/heads/main 203 | @cd $(DRONES_DIR)/borg; git reset --hard HEAD 204 | #+end_src 205 | 206 | Now you are probably tempted to run ~make bootstrap-borg~, but that is 207 | for bootstrapping /from a seed/, and what we are doing right now is to 208 | bootstrap /from scratch/. In the process we are creating a seed but we 209 | are not there yet. Instead run this: 210 | 211 | #+begin_src sh 212 | git submodule add --name borg git@github.com:emacscollective/borg.git lib/borg 213 | #+end_src 214 | 215 | Now that ~borg~ is available we can build all the assimilated packages (currently 216 | just ~borg~ itself) using ~make bootstrap~. 217 | 218 | Now it is time to tell Emacs to initialize Borg instead of Package by 219 | adding a simple ~early-init.el~ file containing: 220 | 221 | #+begin_src emacs-lisp 222 | ;; -*- lexical-binding:t; no-byte-compile:t -*- 223 | 224 | (setq load-prefer-newer t) 225 | 226 | (add-to-list 'load-path (expand-file-name "lib/borg" user-emacs-directory)) 227 | (require 'borg) 228 | (borg-initialize) 229 | 230 | (setq package-enable-at-startup nil) 231 | #+end_src 232 | 233 | Changing the values of ~load-prefer-newer~ and ~package-enable-at-startup~ 234 | as shown here is optional but strongly recommended. ~load-prefer-newer~ 235 | should be enabled before loading ~borg~. 236 | 237 | Now you could create the initial commit but you could also delay that. 238 | 239 | #+begin_src sh 240 | git commit -m "Assimilate borg" 241 | #+end_src 242 | 243 | Now it is time to assimilate some other essential packages. You could 244 | do so using ~M-x borg-assimilate~, but you would quickly notice that 245 | doing so without the help of the ~epkg~ package is quite cumbersome, 246 | so lets manually install that and its dependency first: 247 | 248 | #+begin_src sh 249 | git submodule add --name closql git@github.com:emacscollective/closql.git lib/closql 250 | git submodule add --name emacsql git@github.com:magit/emacsql.git lib/emacsql 251 | git submodule add --name compat git@github.com:emacs-compat/compat.git lib/compat 252 | git submodule add --name llama https://git.sr.ht/~tarsius/llama lib/llama 253 | git submodule add --name epkg git@github.com:emacscollective/epkg.git lib/epkg 254 | git config -f .gitmodules submodule.emacsql.no-byte-compile emacsql-pg.el 255 | echo /epkgs/ >> .gitignore 256 | git add .gitignore .gitmodules 257 | make build 258 | git commit -m "Assimilate epkg and dependencies" 259 | #+end_src 260 | 261 | Once you have done that and have restarted Emacs, you can install 262 | Magit using Borg, as described in [[*Assimilation]]. You should also 263 | configure Magit status buffers to display submodules: 264 | 265 | #+begin_src emacs-lisp 266 | (with-eval-after-load 'magit 267 | (magit-add-section-hook 'magit-status-sections-hook 268 | 'magit-insert-modules 269 | 'magit-insert-stashes 270 | 'append)) 271 | #+end_src 272 | 273 | Finally (look, nobody forced you to do this from scratch ;-) I 274 | strongly suggest that you make yourself familiar with my ~auto-compile~ 275 | package. 276 | 277 | *** Migrating a legacy configuration 278 | 279 | If you are currently using Package and want to gently ease into using 280 | Borg alongside that, then you can proceed as described in [[*Use as 281 | secondary package manager]]. 282 | 283 | If on the other hand you are already manually using Git modules, 284 | then you should proceed as described in [[*Bootstrapping from scratch]]. 285 | Obviously "from scratch" does not apply this time around, so just skip 286 | steps like ~git init~. 287 | 288 | *** Using your configuration on another machine 289 | 290 | Getting started using your existing configuration on another machine 291 | works the same way as described in [[*Bootstrapping using a seed]]. The 292 | only difference is that instead of starting by cloning someone else's 293 | repository you start by cloning your own repository. 294 | 295 | *** Using https URLs 296 | 297 | For drones whose upstream repositories are located on Github or Gitlab 298 | the ~emacs.g~ collective uses the ~ssh~ protocol by default, which is a 299 | problem if you don't have accounts there and have not properly setup 300 | your keys. 301 | 302 | Luckily this can easily be fixed using the following global rules. 303 | 304 | #+begin_src emacs-lisp 305 | git config --global url.https://github.com/.insteadOf git@github.com: 306 | git config --global url.https://gitlab.com/.insteadOf git@gitlab.com: 307 | #+end_src 308 | 309 | If you don't want to configure this globally, then you can also configure 310 | Borg itself to prefer the ~https~ URLS. 311 | 312 | #+begin_src emacs-lisp 313 | (setq borg-rewrite-urls-alist 314 | '(("git@github.com:" . "https://github.com/") 315 | ("git@gitlab.com:" . "https://gitlab.com/"))) 316 | #+end_src 317 | 318 | This does not affect packages that have already been assimilated. 319 | During bootstrapping you have to change the URLs for packages that 320 | are assimilated by default. 321 | 322 | #+begin_src sh 323 | cd ~/.config/emacs 324 | sed -i "s|git@github.com:|https://github.com/|g" .gitmodules 325 | sed -i "s|git@gitlab.com:|https://gitlab.com/|g" .gitmodules 326 | git commit -m "Use https URLs for Github and Gitlab" 327 | #+end_src 328 | 329 | If you have already run ~make bootstrap~, then you also have to edit 330 | ~.git/config~. 331 | 332 | #+begin_src sh 333 | cd ~/.config/emacs 334 | sed -i "s|git@github.com:|https://github.com/|g" .git/config 335 | sed -i "s|git@gitlab.com:|https://gitlab.com/|g" .git/config 336 | #+end_src 337 | 338 | * Startup 339 | 340 | The early init file, ~early-init.el~ (see [[info:emacs#Early Init File]]), 341 | should contain a call to ~borg-initialize~. 342 | 343 | Changing the values of ~load-prefer-newer~ and ~package-enable-at-startup~ 344 | as shown here is optional but strongly recommended. ~load-prefer-newer~ 345 | should be enabled before loading ~borg~. 346 | 347 | #+begin_src emacs-lisp 348 | ;; -*- lexical-binding:t; no-byte-compile:t -*- 349 | 350 | (setq load-prefer-newer t) 351 | 352 | (add-to-list 'load-path (expand-file-name "lib/borg" user-emacs-directory)) 353 | (require 'borg) 354 | (borg-initialize) 355 | 356 | (setq package-enable-at-startup nil) 357 | #+end_src 358 | 359 | - Function: borg-initialize :: 360 | 361 | This function initializes assimilated drones using ~borg-activate~. 362 | 363 | To skip the activation of the drone named DRONE, temporarily disable 364 | it by setting the value of the Git variable ~submodule.DRONE.disabled~ 365 | to true in ~~/.config/emacs/.gitmodules~. 366 | 367 | Borg automatically reports how long it takes to load ~borg.el~ itself, 368 | ~early-init.el,~ and other config files that it loads directly. It 369 | cannot do the same for ~init.el~, so you should explicitly call the 370 | following function from that file, and possibly from other home-made 371 | config files. 372 | 373 | - Function: borg-report-load-duration &optional file format-string :: 374 | 375 | This function reports how long it takes to load the file currently 376 | being loaded. It should be called very early in the file, ideally 377 | before doing anything else. This prints two messages; one right 378 | when the function is called and another once the file has been 379 | loaded. 380 | 381 | If optional FILE is non-~nil~, this function instead reports how long 382 | it takes to load that file (this assumes that it is currently being 383 | loaded). Optional FORMAT-STRING, if non-~nil~, is passed to ~message~. 384 | It should should end with "..." and contain zero or one ~%s~, which 385 | stands for the file name. 386 | 387 | - Function: borg-report-init-duration :: 388 | 389 | This function adds functions to ~after-init-hook~, which, once that 390 | hook is nearly done running, will report how long it took to run 391 | that hook and also how long Emacs initialization took. Calling 392 | this function does nothing if the hook already ran. 393 | 394 | * Assimilation 395 | 396 | A third-party package is assimilated by adding it as a submodule and, 397 | if necessary, by configuring it in ~~/.config/emacs/init.el~. Built-in 398 | packages are assimilated merely by configuring them. 399 | 400 | To begin the assimilation of a third-party package use the command 401 | ~borg-assimilate~, which adds the package's repository as a submodule 402 | and attempts to build the drone. 403 | 404 | A safer alternative is to first clone the package without assimilating 405 | it, using ~borg-clone~. This gives you an opportunity to inspect the 406 | cloned package for broken or malicious code, before it gets a chance 407 | to run arbitrary code. Later you can proceed with the assimilation 408 | using ~borg-assimilate~, or remove the clone using ~borg-remove~. 409 | 410 | Building the drone can fail, for example due to missing dependencies. 411 | Failure to build a drone is not considered as a failure to assimilate. 412 | If a build fails, then a buffer containing information about the 413 | issue pops up. If the failure is due to unsatisfied dependencies, 414 | then assimilate those too, and then build any drone, which previously 415 | couldn't be built, by using the Emacs command ~borg-build~ or ~make 416 | lib/DRONE~. Alternatively you can just rebuild everything using ~make 417 | build~. 418 | 419 | If you wish to avoid such complications, you should use the command 420 | ~epkg-describe-package~ before assimilating a package. Among other 421 | useful information, it also provides a dependency tree. 422 | 423 | Once the packages have been added as a submodules and the drones have 424 | been built, the assimilation is completed by creating an assimilation 425 | commit. 426 | 427 | If you assimilate a single package, then it is recommended that you 428 | use a message similar to this: 429 | 430 | #+begin_src undefined 431 | Assimilate foo v1.0.0 432 | #+end_src 433 | 434 | Or if one or more dependencies had to be assimilated, something like: 435 | 436 | #+begin_src undefined 437 | Assimilate foo and dependencies 438 | 439 | Assimilate foo v1.0.0 440 | Assimilate bar v1.1.0 441 | Assimilate baz v0.1.0 442 | #+end_src 443 | 444 | It's usually a good idea not to assimilate unrelated packages in the 445 | same commit, but doing it for related packages, which do not strictly 446 | depend on one another, it might make sense: 447 | 448 | #+begin_src undefined 449 | Assimilate ido and extensions 450 | 451 | Assimilate flx v0.6.1-3-gae0981b 452 | Assimilate ido-at-point v1.0.0 453 | Assimilate ido-ubiquitous v3.12-2-g7354d98 454 | Assimilate ido-vertical-mode v0.1.6-33-gb42e422 455 | Assimilate smex 3.0-13-g55aaebe 456 | #+end_src 457 | 458 | The command ~borg-insert-update-message~ can be used to generate such 459 | commit messages. 460 | 461 | - Key: C-c C-b [in git-commit-mode buffer] (borg-insert-update-message) :: 462 | 463 | This command insert information about drones that are changed in the 464 | index. Formatting is according to the commit message conventions 465 | described above. 466 | 467 | - Command: borg-assimilate package url &optional partially :: 468 | 469 | This command assimilates the package named PACKAGE from URL. 470 | 471 | If ~epkg~ is available, then only the name of the package is read in 472 | the minibuffer and the url stored in the Epkg database is used. If 473 | ~epkg~ is unavailable, the package is not in the database, or if a 474 | prefix argument is used, then the url too is read in the minibuffer. 475 | 476 | If a negative prefix argument is used, then the submodule is added 477 | but the build and activation steps are skipped. This is useful when 478 | assimilating a package that requires special build steps. After 479 | configuring the build steps use ~borg-build~ to complete the 480 | assimilation. 481 | 482 | - Command: borg-clone package url :: 483 | 484 | This command clones the package named PACKAGE from URL, without 485 | assimilating it. This is useful when you want to inspect the 486 | package before potentially executing malicious or broken code. 487 | 488 | Interactively, when the ~epkg~ package is available, then the name 489 | is read in the minibuffer and the url stored in the Epkg database 490 | is used. If ~epkg~ is unavailable, the package is unknown, or when 491 | a prefix argument is used, then the url is also read in the 492 | minibuffer. 493 | 494 | - Command: borg-activate clone :: 495 | 496 | This command activates the clone named CLONE by adding the 497 | appropriate directories to the ~load-path~ and to ~Info-directory-list~, 498 | and by loading the autoloads file, if it exists. 499 | 500 | Unlike ~borg-initialize~, this function ignores the Git variable 501 | ~submodule.DRONE.disabled~ and can be used to activate clones that 502 | have not been assimilated. 503 | 504 | - Command: borg-remove clone :: 505 | 506 | This command removes the cloned or assimilated package named CLONE, 507 | by removing the working tree from ~borg-drones-directory~, regardless 508 | of whether that repository belongs to an assimilated package or a 509 | package that has only been cloned for review using ~borg-clone~. The 510 | Git directory is not removed. 511 | 512 | - Command: borg-build clone &optional activate :: 513 | 514 | This command builds the clone named CLONE. Interactively, or when 515 | optional ACTIVATE is non-~nil~, then also activate the drone using 516 | ~borg-activate~. 517 | 518 | - Function: borg-update-autoloads clone &optional path :: 519 | 520 | This function updates the autoload file for the libraries belonging 521 | to the clone named CLONE in the directories in PATH. PATH can be 522 | omitted or contain file-names that are relative to the top-level of 523 | CLONE's repository. 524 | 525 | - Function: borg-compile clone &optional path :: 526 | 527 | This function compiles the libraries for the clone named CLONE in 528 | the directories in PATH. PATH can be omitted or contain file-names 529 | that are relative to the top-level of CLONE's repository. 530 | 531 | - Function: borg-maketexi clone &optional files :: 532 | 533 | This function generates Texinfo files from certain Org files for the 534 | clone named CLONE. Org files that are located on ~borg-info-path~ are 535 | exported if their names match ~borg-maketexi-filename-regexp~ and the 536 | ~TEXINFO_DIR_HEADER~ export keyword is set in their content. 537 | 538 | - Function: borg-makeinfo clone :: 539 | 540 | This function generates the Info manuals and the Info index for the 541 | clone named CLONE. 542 | 543 | - Function: borg-batch-rebuild &optional quick :: 544 | 545 | This function rebuilds all assimilated drones in alphabetic order, 546 | except for Org which is rebuilt first. After that it also builds 547 | the user init files using ~borg-batch-rebuild-init~. 548 | 549 | This function is not intended for interactive use; instead it is 550 | used by the Make target ~build~ described in the following section. 551 | 552 | When optional QUICK is non-~nil~, then this function does not build 553 | drones for which ~submodule.DRONE.build-step~ is set, assuming that 554 | those are the drones that take longer to be built. 555 | 556 | - Function: borg-batch-rebuild-init :: 557 | 558 | This function builds the init files specified by the Make variable 559 | ~INIT_FILES~, or if that is unspecified ~init.el~ and ~LOGIN.el~, where 560 | ~LOGIN~ is the value of the variable ~user-real-login-name~. If a file 561 | does not exist, then it is silently ignored. 562 | 563 | This function is not intended for interactive use; instead it is 564 | used by the Make targets ~build-init~ and (indirectly) ~build~, which 565 | are described in [[*Make targets]]. 566 | 567 | * Updating drones 568 | 569 | Borg does not provide an update command. By not doing so, it empowers 570 | you to update to exactly the commit you wish to update to, instead of 571 | to "the" new version. 572 | 573 | To determine the drones that you /might/ want to update, visit the Magit 574 | status buffer of the ~~/.config/emacs~ repository and press ~f m~ to fetch 575 | inside all submodules. After you have done so, and provided there 576 | actually are any modules with new upstream commits, a section titled 577 | "Modules unpulled from @{upstream}" appears. 578 | 579 | Each subsection of that section represents a submodule with new 580 | upstream commits. Expanding such a subsection lists the new upstream 581 | commits. These commits can be visited by pressing ~RET~, and the status 582 | buffer of a submodule can be visited by pressing ~RET~ while point is 583 | inside the heading of the respective submodule section. To return to 584 | the status buffer of ~~/.config/emacs~ press ~q~. 585 | 586 | Inside the status buffer of a submodule, you can pull the upstream 587 | changes as usual, using ~F u~. If you wish you can inspect the changes 588 | before doing so. And you can also choose to check out another commit 589 | instead of the upstream ~HEAD~. 590 | 591 | Once you have "updated" to a new commit, you should also rebuild the 592 | drone using the command ~borg-build~. This may fail, e.g., due to new 593 | dependencies. 594 | 595 | Once you have resolved all issues, you should create an "update 596 | commit". You can either create one commit per updated drone or you 597 | can create a single commit for all updated drones, which ever you find 598 | more appropriate. However it is recommended that you use a message 599 | similar to: 600 | 601 | #+begin_src undefined 602 | Update foo to v1.1.0 603 | #+end_src 604 | 605 | Or for multiple packages: 606 | 607 | #+begin_src undefined 608 | Update 2 drones 609 | 610 | Update foo to v1.1.0 611 | Update bar to v1.2.1 612 | #+end_src 613 | 614 | The command ~borg-insert-update-message~ can be used to generate such 615 | commit messages. 616 | 617 | To update the Epkg package database use the command ~epkg-update~. 618 | 619 | * Patching drones 620 | 621 | By using Borg you can not only make changes to assimilated packages, 622 | you can also keep track of those patches and share them with others. 623 | 624 | If you created some commits in a drone repository and are the 625 | maintainer of the respective package, then you can just push your 626 | changes to the "origin" remote. 627 | 628 | You don't have to do this every time you created some commits, but at 629 | important checkpoints, such as after creating a release, you should 630 | record the changes in the ~~/.config/emacs~ repository. To do so 631 | proceed as described in [[*Updating drones]]. 632 | 633 | But for most packages you are not the maintainer and if you create 634 | commits for such drones, then you have to create a fork and push there 635 | instead. You should configure that remote as the push-remote using 636 | ~git config remote.pushDefault FORK~, or by pressing ~b C M-p~ in Magit. 637 | After you have done that, you can continue to pull from the upstream 638 | using ~F u~ in Magit and you can also push to your fork using ~P p~. 639 | 640 | Of course you should also occasionally record the changes in the 641 | ~~/.config/emacs~ repository. Additionally, and ideally when you first 642 | fork a drone, you should also record information about your personal 643 | remote in the super-repository by setting ~submodule.DRONE.remote~ in 644 | ~~/.config/emacs/.gitmodules~. 645 | 646 | - Variable: submodule.DRONE.remote "NAME URL" :: 647 | 648 | This variable specifies an additional remote named NAME that is 649 | fetched from URL. This variable can be specified multiple times. 650 | Note that "NAME URL" is a single value and that the two parts of 651 | that value are separated by a single space. 652 | 653 | ~make bootstrap~ automatically adds all remotes that are specified 654 | like this to the DRONE repository by setting ~remote.NAME.url~ to 655 | URL and using the standard value for ~remote.NAME.fetch~. 656 | 657 | - Variable: borg.pushDefault FORK :: 658 | 659 | This variable specifies a name used for push-remotes. Because this 660 | variable can only have one value it is recommended that you use the 661 | same name, FORK, for your personal remote in all drone repositories 662 | in which you have created patches that haven't been merged into the 663 | upstream repository (yet). A good value may be your username. 664 | 665 | For all DRONES for which one value of ~submodule.DRONE.remote~ 666 | specifies a remote whose NAME matches FORK, ~make bootstrap~ 667 | automatically configures FORK to be used as the push-remote by 668 | setting ~remote.pushDefault~ to FORK. 669 | 670 | * Make targets 671 | 672 | The following ~make~ targets are available by default. To use them you 673 | have to be in ~~/.config/emacs~ in a shell. They are implemented in 674 | ~borg.mk~, which is part of the ~borg~ package. 675 | 676 | To show the commands that are run, use ~V=1 make ...~. Otherwise only 677 | their output is shown. 678 | 679 | ** Help targets 680 | :PROPERTIES: 681 | :UNNUMBERED: notoc 682 | :END: 683 | 684 | - Command: help :: 685 | 686 | This target prints information about most of the following targets. 687 | 688 | This is the default target, unless the user sets ~.DEFAULT_GOAL~. 689 | 690 | - Command: helpall :: 691 | 692 | This target prints information about all of the following targets. 693 | 694 | ** Batch targets 695 | :PROPERTIES: 696 | :UNNUMBERED: notoc 697 | :END: 698 | 699 | - Command: clean :: 700 | 701 | This target removes all byte-code and native files of all drones and 702 | config files. 703 | 704 | To ensure a clean build, this target should always be run before 705 | ~build~, so you might want to add a default target that does just 706 | that. To do so, add this to ~~/.config/emacs/etc/borg/config.mk~: 707 | 708 | #+begin_src makefile-gmake 709 | .DEFAULT_GOAL := all 710 | all: clean build 711 | #+end_src 712 | 713 | - Command: clean-force :: 714 | 715 | This target removes all byte-code files using ~find~. The ~clean~ 716 | target on the other hand uses the lisp function ~borg--batch-clean~. 717 | Byte-code isn't always compatible between Emacs releases and this 718 | target makes it possible to recover from such an incompatibility. 719 | 720 | - Command: build :: 721 | 722 | This target byte-compiles Borg and Compat first, followed by all 723 | other drones in alphabetic order. After that it also byte-compiles 724 | the user init files, like ~init-build~ does. 725 | 726 | - Command: native :: 727 | 728 | This target byte-compiles and natively compiles Borg and Compat 729 | first, followed by all other drones in alphabetic order. After that 730 | it also byte-compiles the user init files, like ~init-build~ does. 731 | 732 | ** Quick batch targets 733 | :PROPERTIES: 734 | :UNNUMBERED: notoc 735 | :END: 736 | 737 | These targets act on most drones but exclude those for which the Git 738 | variable ~submodule.DRONE.build-step~ is set. The assumption is that 739 | those are the drones that take longer to build. 740 | 741 | - Command: quick :: 742 | 743 | This target cleans and builds most drones. 744 | 745 | It also cleans and builds the init files as described for ~build~. 746 | 747 | - Command: quick-clean :: 748 | 749 | This target removes all byte-code and native files of most drones 750 | It also remove the byte-code files of the config files. 751 | 752 | - Command: quick-build :: 753 | 754 | This target builds /most/ drones and the config files 755 | 756 | It also builds the init files as described for ~build~. 757 | 758 | ** Drone targets 759 | :PROPERTIES: 760 | :UNNUMBERED: notoc 761 | :END: 762 | 763 | - Command: clean/DRONE :: 764 | 765 | This target removes all byte-code and native files belonging to the 766 | drone named DRONE. 767 | 768 | - Command: build/DRONE :: 769 | 770 | This target byte-compiles the drone named DRONE. 771 | 772 | ~lib/DRONE~ is an alias for this target; or rather ~DIR/DRONE~, where 773 | ~DIR~ is directory containing the drone submodules. 774 | 775 | - Command: native/DRONE :: 776 | 777 | This target byte-compiles and natively-compiles the drone named 778 | DRONE. 779 | 780 | ** Init file targets 781 | :PROPERTIES: 782 | :UNNUMBERED: notoc 783 | :END: 784 | 785 | - Command: init-clean :: 786 | 787 | This target removes byte-code files for init files. 788 | 789 | - Command: init-tangle :: 790 | 791 | This target tangles (creates) ~init.el~ from ~init.org~. You obviously 792 | don't have to use such a file, if you don't want to. 793 | 794 | - Command: init-build :: 795 | 796 | This target byte-compiles the init files specified by the make 797 | variable ~INIT_FILES~; or if that is unspecified ~init.el~ and ~LOGIN.el~ 798 | (where ~LOGIN~ is the value of the variable ~user-real-login-name~). 799 | If an init file does not exist, then that is silently ignored. 800 | 801 | If you publish your ~~/.config/emacs~ repository but would like to 802 | keep some settings private, then you can do so by putting them in a 803 | file ~~/.config/emacs/LOGIN.el~. The downside of this approach is 804 | that you will have to somehow synchronize that file between your 805 | machines without checking it into Git. 806 | 807 | ** Bootstrap targets 808 | :PROPERTIES: 809 | :UNNUMBERED: notoc 810 | :END: 811 | 812 | - Command: bootstrap-borg :: 813 | 814 | This target bootstraps ~borg~ itself. 815 | 816 | - Command: bootstrap :: 817 | 818 | This target attempts to bootstrap all drones. To do so it runs ~git 819 | submodule init~, ~make clone-modules~, ~make checkout-modules~ and ~make 820 | build~. 821 | 822 | If an error occurs during one of these steps, then you can just run 823 | the target that failed (and the subsequent targets) again to process 824 | the remaining drones. Doing so does not discard any local changes, 825 | such as uncommitted changes, new commits, or the effect of manually 826 | checking out some other commit. 827 | 828 | If a drone cannot be cloned from any of the known remotes, then you 829 | can temporarily ignore it using ~git submodule deinit lib/DRONE~. 830 | 831 | If you have run ~make clone-modules~ and/or ~make checkout-modules~ 832 | manually, then make sure to finish by running ~make build~ again too. 833 | 834 | - Command: clone-modules :: 835 | 836 | This target attempts to clone all modules that were initialized by 837 | ~git submodule init~ and which the user did not explicitly deactivate 838 | afterwards, either by de-initializing it again (~git submodule deinit 839 | lib/DRONE~) or by setting ~submodule.DRONE.active~ to ~false~. 840 | 841 | This may fail, for example, if the URL of the remote repository has 842 | changed. If that happens, you can update the URL, and then run this 843 | command again. Already cloned modules are skipped on reruns. 844 | 845 | Alternatively drones can be cloned individually, using 846 | ~lib/borg/borg.sh clone DRONE~. 847 | 848 | - Command: checkout-modules :: 849 | 850 | This target attempts to checkout commits recorded for all modules, 851 | which were successfully cloned by ~make clone-modules~, while also 852 | trying to check out the recorded commit. 853 | 854 | It is safe to rerun this target. Doing so does not discard any 855 | local changes, such as uncommitted changes, new commits, or the 856 | effect of manually checking out some other commit. 857 | 858 | Alternatively drones can be checked out individually, using 859 | ~lib/borg/borg.sh checkout DRONE~. 860 | 861 | * Variables 862 | 863 | - Variable: borg.drones-directory DIRECTORY :: 864 | 865 | This Git variable can be used to override the name of the directory 866 | that contains the drone submodules. If specified, the value has to 867 | be relative to the top-level directory of the repository. 868 | 869 | Note that if you change the value of this variable, then you might 870 | have to additionally edit ~~/.config/emacs/Makefile~. 871 | 872 | The values of the following variables are set at startup and should 873 | not be changed by the user. 874 | 875 | - Variable: borg-drones-directory :: 876 | 877 | The value of this constant is the directory beneath which drone 878 | submodules are placed. The value is set based on the location of 879 | the ~borg~ library and the Git variable ~borg.drones-directory~ if set, 880 | and should not be changed. 881 | 882 | - Variable: borg-user-emacs-directory :: 883 | 884 | The value of this constant is the directory beneath which additional 885 | per-user Emacs-specific files are placed. The value is set based on 886 | the location of the ~borg~ library and should not be changed. The 887 | value is usually the same as that of ~user-emacs-directory~, except 888 | when Emacs is started with ~emacs -q -l /path/to/init.el~. 889 | 890 | - Variable: borg-gitmodules-file :: 891 | 892 | The value of this constant is the ~.gitmodules~ file of the 893 | super-repository. 894 | 895 | If you want to change the value of the following variable, you have to 896 | do so before requiring ~borg~, else it does not have the desired effect. 897 | 898 | - Variable: borg-debug-user-init-files :: 899 | 900 | This variable controls whether the effect of the command-line 901 | argument ~--debug-init~ extends to user init files. If non-~nil~ and 902 | ~--debug-init~ is used, then ~debug-on-error~ is automatically enable 903 | and ~use-package-verbose~ is set to ~debug~. Finally these variables 904 | are reset to their default values using ~after-init-hook~. 905 | 906 | The value of this Make variable has to be set in 907 | ~~/.config/emacs/Makefile~. 908 | 909 | - Variable: INIT​_FILES :: 910 | 911 | A list of init files to be build by the Make targets ~build~ and 912 | ~build-init~. See [[*Make targets]]. 913 | 914 | The values of these borg-specific Git variables have to be set in the 915 | file ~~/.config/emacs/.gitmodules~. The variables ~borg.pushDefault~ and 916 | ~submodule.DRONE.remote~ are described in [[*Patching drones]]. 917 | 918 | Because most repositories used to maintain Emacs packages follow some 919 | common-sense conventions, Borg usually does not have to be told how to 920 | build a given drone. Building is done using ~borg-build~, which in turn 921 | usually does its work using ~borg-update-autoloads~, ~borg-compile~, 922 | ~borg-maketexi~, and ~borg-makeinfo~. 923 | 924 | However some packages don't follow the conventions either because they 925 | are too complex to do so, or for the sake of doing it differently. 926 | But in either case resistance is futile; by using the following 927 | variables you can tell Borg how to build such packages. 928 | 929 | - Variable: submodule.DRONE.build-step COMMAND :: 930 | 931 | By default drones are built using the lisp functions 932 | ~borg-update-autoloads~, ~borg-compile~, ~borg-maketexi~, and 933 | ~borg-makeinfo~, but if this variable has one or more values, then 934 | DRONE is built using these COMMANDs *instead*. 935 | 936 | Each COMMAND can be one of the default steps, an S-expression, or 937 | a shell command. The COMMANDs are executed in the specified order. 938 | 939 | If a COMMAND matches one of default steps, then it is evaluated with 940 | the appropriate arguments. 941 | 942 | If a COMMAND begins with a parenthesis, then it is evaluated as 943 | a lisp expression. In that case the variable ~borg-clone~ holds 944 | the name of the package that is being build. To make a function 945 | available in this context, you usually have to define or load it 946 | in =etc/borg/config.el=, relative to ~borg-user-emacs-directory~. 947 | 948 | Otherwise COMMAND is assumed to be a shell command and is executed 949 | with ~shell-command~. 950 | 951 | #+BEGIN_SRC undefined 952 | [submodule "mu4e"] 953 | path = lib/mu4e 954 | url = git@github.com:djcb/mu.git 955 | build-step = test -e ./configure || autoreconf -i 956 | build-step = ./configure 957 | build-step = make -C mu4e > /dev/null 958 | build-step = borg-update-autoloads 959 | load-path = mu4e 960 | #+END_SRC 961 | 962 | To skip generating "autoloads" (e.g., using ~use-package~ to create 963 | "autoloads" on the fly), just provide the required build steps to 964 | build the package, omitting ~borg-update-autoloads~. Borg silently 965 | ignores a missing "autoloads" file during initialization 966 | (~borg-initialize~). 967 | 968 | #+BEGIN_SRC undefined 969 | [submodule "multiple-cursors"] 970 | path = lib/multiple-cursors 971 | url = git@github.com:magnars/multiple-cursors.el.git 972 | build-step = borg-compile 973 | #+END_SRC 974 | 975 | Note that just because a package provides a ~Makefile~, you do not 976 | necessarily have to use it. 977 | 978 | Even if ~make~ generates the Info file, you might still have to add 979 | ~borg-makeinfo~ as an additional build-step because the former might 980 | not generate an Info index file (named ~dir~), which Borg relies on. 981 | 982 | Also see ~borg.extra-build-step~ below. 983 | 984 | - Variable: borg-build-shell-command :: 985 | 986 | This variable can be used to change how shell commands specified 987 | by ~submodule.DRONE.build-step~ are run. The default value is ~nil~, 988 | meaning that each build step is run unchanged using ~shell-command~. 989 | 990 | If the value is a string, then that is combined with each build step 991 | in turn and the results are run using ~shell-command~. This string 992 | must contain either %s, which is replaced with the unchanged build 993 | step, or %S, which is replaced with the result of quoting the build 994 | step using ~shell-quote-argument~. 995 | 996 | If the value is a function, then that is called once with the drone 997 | as argument and must return either a string or a function. If the 998 | returned value is a string, then that is used as described above. 999 | 1000 | If the value returned by the first function is another function, then 1001 | this second function is called for each build step with the drone and 1002 | the build step as arguments. It must return a string or ~nil~. If the 1003 | returned value is a string, then that is used as described above. 1004 | 1005 | Finally the second function may execute the build step at its own 1006 | discretion and return ~nil~ to indicate that it has done so. 1007 | 1008 | Notice that if the value of this variable is a function, this 1009 | function must a) be defined in a drone; and b) be registered as an 1010 | autoload. This is because build happens in a separate Emacs process 1011 | started with ~-Q --batch~, which only receives the name of the function. 1012 | 1013 | - Variable: submodule.DRONE.load-path PATH :: 1014 | 1015 | This variable instructs ~borg-activate~ to add PATH to the ~load-path~ 1016 | instead of the directory it would otherwise have added. Likewise it 1017 | instructs ~borg-compile~ to compile the libraries in that directory. 1018 | PATH has to be relative to the top-level of the repository of the 1019 | drone named DRONE. This variable can be specified multiple times. 1020 | 1021 | Normally Borg uses ~elisp/~ as the drone's ~load-path~, if that exists; 1022 | otherwise ~lisp/~, if that exists; or else the top-level directory. 1023 | If this variable is set, then it /overrides/ the default location. 1024 | Therefore, to /add/ an additional directory, you also have to 1025 | explicitly specify the default location. 1026 | 1027 | #+BEGIN_SRC undefined 1028 | [submodule "org"] 1029 | path = lib/org 1030 | url = git://orgmode.org/org-mode.git 1031 | build-step = make 1032 | load-path = lisp 1033 | load-path = contrib/lisp 1034 | info-path = doc 1035 | #+END_SRC 1036 | 1037 | - Variable: submodule.DRONE.no-byte-compile PATH :: 1038 | 1039 | This variable instructs ~borg-compile~ to not compile the library at 1040 | PATH. PATH has to be relative to the top-level of the repository of 1041 | the drone named DRONE. This variable can be specified multiple 1042 | times. 1043 | 1044 | Sometimes a drone comes with an optional library which adds support 1045 | for some other third-party package, which you don't want to use. 1046 | For example ~emacsql~ comes with a PostgreSQL back-end, which is 1047 | implemented in the library ~emacsql-pg.el~, which requires the ~pg~ 1048 | package. The standard Borg collective ~emacs.g~ assimilates ~emacsql~, 1049 | for the sake of the ~epkg~ drone, which only requires the SQLite 1050 | back-end. To avoid an error about ~pg~ not being available, ~emacs.g~ 1051 | instructs Borg to not compile ~emacsql-pg.el~. (Of course if you want 1052 | to use the PostgreSQL back-end and assimilate ~pg~, then you should 1053 | undo that.) 1054 | 1055 | - Variable: submodule.DRONE.recursive-byte-compile BOOLEAN :: 1056 | 1057 | Setting this variable to ~true~ instructs ~borg-compile~ to compile 1058 | DRONE's directories recursively. This isn't done by default because 1059 | there are more repositories in which doing so would cause issues 1060 | than there are repositories that would benefit from doing so. 1061 | 1062 | Unfortunately many packages put problematic test files or (usually 1063 | outdated) copies of third-party libraries into subdirectories. The 1064 | latter is a highly questionable thing to do, but the former would be 1065 | perfectly fine, if only the non-library lisp files did not provide 1066 | a feature (which effectively turns them into libraries) and/or if a 1067 | file named ~.nosearch~ existed in the subdirectory. That file tells 1068 | functions such as ~normal-top-level-add-subdirs-to-load-path~ and 1069 | ~borg-compile~ to ignore the containing directory. 1070 | 1071 | - Variable: borg-compile-function :: 1072 | 1073 | The function used to compile each individual library. 1074 | One of ~byte-compile-file~, ~borg-byte+native-compile~ or 1075 | ~borg-byte+native-compile-async~. 1076 | 1077 | To enable native compilation when running ~make~, use one of the 1078 | respective make targets, as described in [[*Make targets]]. 1079 | 1080 | - Variable: borg-compile-recursively :: 1081 | 1082 | Setting this variable to a non-~nil~ value instructs ~borg-compile~ 1083 | to compile all drones recursively. Doing so is discouraged. 1084 | 1085 | - Variable: borg-native-compile-deny-list :: 1086 | 1087 | This variable lists the names of files to be excluded from native 1088 | compilation. 1089 | 1090 | - Variable: borg.extra-build-step COMMAND :: 1091 | 1092 | This variable instructs Borg to execute COMMAND after the default 1093 | build-steps for each DRONE (or after ~submodule.DRONE.build-step,~ if 1094 | that specified). It has to be set in ~borg-gitmodules-file~ and can 1095 | have multiple values. 1096 | 1097 | If a COMMAND begins with a parenthesis, then it is evaluated as 1098 | a lisp expression. In that case the variable ~borg-clone~ holds 1099 | the name of the package that is being build. To make a function 1100 | available in this context, you usually have to define or load it 1101 | in =etc/borg/config.el=, relative to ~borg-user-emacs-directory~. 1102 | 1103 | Otherwise COMMAND is assumed to be a shell command and is executed 1104 | with ~shell-command~. 1105 | 1106 | - Variable: submodule.DRONE.info-path PATH :: 1107 | 1108 | This variable instructs ~borg-initialize~ to add PATH to 1109 | ~Info-directory-list~. PATH has to be relative to the top-level of 1110 | the repository of the drone named DRONE. 1111 | 1112 | - Variable: submodule.DRONE.no-maketexi PATH :: 1113 | 1114 | This variable instructs ~borg-maketexi~ to not create a Texinfo file 1115 | for the Org file at PATH. PATH has to be relative to the top-level 1116 | of the repository of the drone named DRONE. This variable can be 1117 | specified multiple times. 1118 | 1119 | - Variable: submodule.DRONE.no-makeinfo PATH :: 1120 | 1121 | This variable instructs ~borg-makeinfo~ to not create an Info file for 1122 | the Texinfo file at PATH. PATH has to be relative to the top-level 1123 | of the repository of the drone named DRONE. This variable can be 1124 | specified multiple times. 1125 | 1126 | - Variable: submodule.DRONE.disabled true|false :: 1127 | 1128 | If the value of this variable is ~true~, then it is skipped by 1129 | ~borg-initialize~. 1130 | 1131 | - Variable: borg-rewrite-urls-alist :: 1132 | 1133 | An alist that can optionally be used to rewrite certain URLs. Each 1134 | element has the form ~(ORIG . BASE)~. Each URL that starts with ORIG 1135 | is rewritten to start with BASE instead. See [[*Using https URLs]]. 1136 | 1137 | - Variable: borg-maketexi-filename-regexp :: 1138 | 1139 | A regexp matching Org files that may be exported to Texinfo by 1140 | ~borg-maketexi~. The name of the clone is substituted for ~%s~. 1141 | Setting this to ~nil~ disables the export of any Org files. 1142 | 1143 | * Low-level functions 1144 | 1145 | You normally should not have to use the following low-level functions 1146 | directly. That being said, you might want to do so anyway if you 1147 | build your own tools on top of Borg. 1148 | 1149 | - Function: borg-worktree clone :: 1150 | 1151 | This function returns the top-level of the working tree of the 1152 | clone named CLONE. 1153 | 1154 | - Function: borg-gitdir clone :: 1155 | 1156 | This function returns the Git directory of the clone named CLONE. 1157 | 1158 | It always returns ~BORG-USER-EMACS-DIRECTORY/.git/modules/CLONE~, even 1159 | when CLONE's Git directory is actually located inside the working 1160 | tree. 1161 | 1162 | - Macro: borg-do-drones (var [result]) body...) :: 1163 | 1164 | This macro loop over drones. BODY is evaluated with VAR bound to 1165 | each drone, in turn. Inside BODY variables set in ~.gitmodules~ are 1166 | cached. Then RESULT is evaluated to get the return value, 1167 | defaulting to ~nil~. 1168 | 1169 | - Function: borg-get clone variable &optional all :: 1170 | 1171 | This function returns the value of the Git variable 1172 | ~submodule.CLONE.VARIABLE~ defined in ~~/.config/emacs/.gitmodules~. 1173 | If optional ALL is non-~nil~, then it returns all values as a list. 1174 | 1175 | - Function: borg-get-all clone variable :: 1176 | 1177 | This function returns all values of the Git variable 1178 | ~submodule.CLONE.VARIABLE~ defined in ~~/.config/emacs/.gitmodules~ as a 1179 | list. 1180 | 1181 | - Function: borg-load-path clone :: 1182 | 1183 | This function returns the ~load-path~ for the clone named CLONE. 1184 | 1185 | - Function: borg-info-path clone &optional setup :: 1186 | 1187 | This function returns the ~Info-directory-list~ for the clone named 1188 | CLONE. 1189 | 1190 | If optional SETUP is non-~nil~, then it returns a list of directories 1191 | containing ~texi~ and/or ~info~ files. Otherwise it returns a list of 1192 | directories containing a file named ~dir~. 1193 | 1194 | - Function: borg-dronep name :: 1195 | 1196 | This function returns non-~nil~ if a drone named NAME exists. 1197 | 1198 | If that is set in ~.gitmodules~, then it returns the value of 1199 | ~submodule.NAME.path~, ~nil~ otherwise. 1200 | 1201 | - Function: borg-drones &optional include-variables :: 1202 | 1203 | This function returns a list of all assimilated drones. 1204 | 1205 | The returned value is a list of the names of the assimilated 1206 | drones, unless optional INCLUDE-VARIABLES is non-~nil~, in which 1207 | case elements of the returned list have the form ~(NAME . ALIST)~. 1208 | 1209 | ALIST is an association list. Property names are symbols 1210 | and correspond to a VARIABLE defined in the Borg repository's 1211 | ~.gitmodules~ file as ~submodule.NAME.VARIABLE~. 1212 | 1213 | Each property value is either a string or a list of strings. If 1214 | INCLUDE-VARIABLES is ~raw~ then all values are lists. Otherwise a 1215 | property value is only a list if the corresponding property name is 1216 | a member of ~borg--multi-value-variables~. If a property name isn't 1217 | a member of ~borg--multi-value-variables~ but it does have multiple 1218 | values anyway, then it is undefined with value is included in the 1219 | returned value. 1220 | 1221 | - Function: borg-clones :: 1222 | 1223 | This function returns a list of all cloned packages. 1224 | 1225 | The returned value includes the names of all drones, as well as the 1226 | names of all other repositories that are located directly inside 1227 | ~borg-drones-directory~ but aren't tracked as submodules. 1228 | 1229 | - Function: borg-read-package prompt &optional edit-url :: 1230 | 1231 | This function reads a package name and the url of its upstream 1232 | repository from the user, and returns them as a list. 1233 | 1234 | When the ~epkg~ package is available, then the user is only prompted 1235 | for the name of the package, and the upstream url is retrieved from 1236 | the Epkg database. If the package isn't in the database then the 1237 | url has to be provided by the user. If optional EDIT-URL is 1238 | non-~nil~, then the url from the database, if any, is provided as 1239 | initial input for the user to edit. 1240 | 1241 | PROMPT is used when prompting for the package name. 1242 | 1243 | - Function: borg-read-clone prompt :: 1244 | 1245 | This function reads the name of a cloned package from the user. 1246 | 1247 | There exist a few more functions, but those are considered to be 1248 | internal and might therefore change in incompatible ways without that 1249 | being noted in the change log. 1250 | 1251 | - Function: borg--maybe-absorb-gitdir pkg :: 1252 | - Function: borg--maybe-reuse-gitdir pkg :: 1253 | - Function: borg--restore-worktree pkg :: 1254 | - Function: borg--call-git pkg &rest args :: 1255 | - Function: borg--expand-load-path drone path :: 1256 | - Function: borg--sort-submodule-sections :: 1257 | 1258 | * Function and Command Index 1259 | :PROPERTIES: 1260 | :APPENDIX: t 1261 | :INDEX: fn 1262 | :END: 1263 | * Variable Index 1264 | :PROPERTIES: 1265 | :APPENDIX: t 1266 | :INDEX: vr 1267 | :END: 1268 | * Copying 1269 | :PROPERTIES: 1270 | :COPYING: t 1271 | :END: 1272 | 1273 | #+begin_quote 1274 | Copyright (C) 2016-{{{year}}} Jonas Bernoulli 1275 | 1276 | You can redistribute this document and/or modify it under the terms 1277 | of the GNU General Public License as published by the Free Software 1278 | Foundation, either version 3 of the License, or (at your option) any 1279 | later version. 1280 | 1281 | This document is distributed in the hope that it will be useful, 1282 | but WITHOUT ANY WARRANTY; without even the implied warranty of 1283 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1284 | General Public License for more details. 1285 | #+end_quote 1286 | 1287 | # LocalWords: CLONE's COMMANDs DRONE's Elpa Epkg Github Gitlab 1288 | # LocalWords: LocalWords MERCHANTABILITY Magit Makefile Melpa 1289 | # LocalWords: PLIST Texinfo alist args autoload autoloads borg 1290 | # LocalWords: else's emacs eval featurep gitdir gitmodules https 1291 | # LocalWords: init makeinfo minibuffer plist pushDefault src 1292 | # LocalWords: subdirectories subdirectory submodule submodules 1293 | # LocalWords: texinfo unpulled url urls worktree 1294 | 1295 | # IMPORTANT: Also update ORG_ARGS and ORG_EVAL in the Makefile. 1296 | # Local Variables: 1297 | # indent-tabs-mode: nil 1298 | # org-src-preserve-indentation: nil 1299 | # End: 1300 | -------------------------------------------------------------------------------- /docs/borg.texi: -------------------------------------------------------------------------------- 1 | \input texinfo @c -*- texinfo -*- 2 | @c %**start of header 3 | @setfilename borg.info 4 | @settitle Borg User Manual 5 | @documentencoding UTF-8 6 | @documentlanguage en 7 | @c %**end of header 8 | 9 | @copying 10 | @quotation 11 | Copyright (C) 2016-2025 Jonas Bernoulli 12 | 13 | You can redistribute this document and/or modify it under the terms 14 | of the GNU General Public License as published by the Free Software 15 | Foundation, either version 3 of the License, or (at your option) any 16 | later version. 17 | 18 | This document is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE@. See the GNU 21 | General Public License for more details. 22 | 23 | @end quotation 24 | @end copying 25 | 26 | @dircategory Emacs 27 | @direntry 28 | * Borg: (borg). Assimilate Emacs packages as Git submodules. 29 | @end direntry 30 | 31 | @finalout 32 | @titlepage 33 | @title Borg User Manual 34 | @subtitle for version 4.3.0 35 | @author Jonas Bernoulli 36 | @page 37 | @vskip 0pt plus 1filll 38 | @insertcopying 39 | @end titlepage 40 | 41 | @contents 42 | 43 | @ifnottex 44 | @node Top 45 | @top Borg User Manual 46 | 47 | @paragraphindent none 48 | 49 | The Borg assimilate Emacs packages as Git submodules. Borg is a 50 | bare-bones package manager for Emacs packages. 51 | 52 | This manual is for Borg version 4.3.0. 53 | 54 | @insertcopying 55 | @end ifnottex 56 | 57 | @menu 58 | * Introduction:: 59 | * Installation:: 60 | * Startup:: 61 | * Assimilation:: 62 | * Updating drones:: 63 | * Patching drones:: 64 | * Make targets:: 65 | * Variables:: 66 | * Low-level functions:: 67 | * Function and Command Index:: 68 | * Variable Index:: 69 | 70 | @detailmenu 71 | --- The Detailed Node Listing --- 72 | 73 | Installation 74 | 75 | * Use as secondary package manager:: 76 | * Bootstrapping:: 77 | 78 | @end detailmenu 79 | @end menu 80 | 81 | @node Introduction 82 | @chapter Introduction 83 | 84 | The Borg assimilate Emacs packages as Git submodules. 85 | 86 | Borg is a bare-bones package manager for Emacs packages. It provides 87 | only a few essential features and should be combined with other tools 88 | such as Magit, @code{epkg}, @code{use-package}, and @code{auto-compile}. 89 | 90 | Borg assimilates packages into the @code{~/.config/emacs} @footnote{Or @code{~/.emacs.d} of course, if you prefer that or have to use the 91 | old location because you still have to support older Emacs releases.} repository 92 | as Git submodules. An assimilated package is called a drone and a 93 | borg-based @code{~/.config/emacs} repository is called a collective. 94 | 95 | It is possible to clone a package repository without assimilating it. 96 | A cloned package is called a clone. 97 | 98 | To learn more about this project, also read the blog post @footnote{@uref{https://emacsair.me/2016/05/17/assimilate-emacs-packages-as-git-submodules}.} in 99 | which it was announced. 100 | 101 | @node Installation 102 | @chapter Installation 103 | 104 | Borg can be used by itself, in which case it has to be bootstrapped. 105 | This is how Borg originally was intended to be used exclusively, but 106 | nowadays you may also choose to use it merely as a secondary package 107 | manager, in which case Borg itself is installed using Package. 108 | 109 | @menu 110 | * Use as secondary package manager:: 111 | * Bootstrapping:: 112 | @end menu 113 | 114 | @node Use as secondary package manager 115 | @section Use as secondary package manager 116 | 117 | To use Borg as a secondary package manager alongside Package, begin by 118 | installing the former using the latter. Borg is only available from 119 | Melpa, so you have to add that first. 120 | 121 | @lisp 122 | (add-to-list 'package-archives 123 | (cons "melpa" "https://melpa.org/packages/") 124 | t) 125 | @end lisp 126 | 127 | Then you have to @code{M-x package-refresh-contents RET} before you can @code{M-x 128 | package-install RET borg RET}. Doing that should add a verbose variant 129 | of this to your init file: 130 | 131 | @lisp 132 | (custom-set-variables 133 | '(package-selected-packages '(borg))) 134 | @end lisp 135 | 136 | Then you have to make the two package managers aware of each other by 137 | replacing the call to @code{package-initialize} in your init file with this: 138 | 139 | @lisp 140 | (if (require 'borg-elpa nil t) 141 | (borg-elpa-initialize) 142 | (package-initialize)) 143 | @end lisp 144 | 145 | Just like Package (aka Elpa) defaults to installing packages in @code{elpa/}, 146 | Borg defaults to installing them in @code{borg/}. (When using both package 147 | managers, that is. If used by itself, then Borg defaults to using 148 | @code{lib/}.) If you want to use another directory, then you can do so by 149 | setting the Git variable @code{borg.drones-directory}. 150 | 151 | You should also add a @code{Makefile} containing: 152 | 153 | @example 154 | BORG_SECONDARY_P = true 155 | include $(shell find -L elpa -maxdepth 1 -regex '.*/borg-[.0-9]*' |\ 156 | sort | tail -n 1)/borg.mk 157 | @end example 158 | 159 | Despite its title, many things mentioned in the next section are 160 | relevant even when Borg was installed the way we just did. Just 161 | saying. 162 | 163 | @node Bootstrapping 164 | @section Bootstrapping 165 | 166 | (As mentioned in the next section you can use a location other than 167 | @code{~/.config/emacs} (or @code{~/.emacs.d}). Nevertheless most of the subsequent 168 | examples just talk about @code{~/.config/emacs} and if you use something 169 | else, then obviously have to substitute that. The same applies to the 170 | string @code{lib} and the variables @code{user-init-file} and @code{user-emacs-directory}, 171 | which also might not be appropriate depending on your choices.) 172 | 173 | @anchor{Bootstrapping using a seed} 174 | @subsection Bootstrapping using a seed 175 | 176 | To get started clone the repository of the @code{emacs.g} collective. A 177 | "collective" is a starter-kit and/or configuration seed that relies on 178 | Borg as the package manager. Most users end up using @code{emacs.g} merely 179 | as a bootstrapping seed and do not merge upstream changes after that. 180 | 181 | This collective already assimilates a few drones in addition to @code{borg} 182 | itself, namely @code{magit}, @code{epkg}, @code{use-package}, @code{auto-compile}, @code{git-modes} and 183 | @code{diff-hl}, as well as their dependencies. These drones are not required 184 | by @code{borg} but their use is highly recommended. 185 | 186 | Clone the @code{emacs.g} repository to either @code{~/.config/emacs}, or for testing 187 | purposes to any other location. This repository contains a @code{Makefile} 188 | that imports @code{lib/borg/borg.mk} and defines an additional target whose 189 | purpose is to make that file and @code{lib/borg/borg.sh} available. Run @code{make 190 | bootstrap-borg} to clone the @code{borg} repository. That does not completely 191 | setup @code{borg} but it makes the latest version of the mentioned files 192 | available. 193 | 194 | Now that these files are available you can run @code{make bootstrap} to get 195 | and configure all submodules (including the @code{borg} submodule) and to 196 | build all drones. 197 | 198 | @example 199 | git clone git@@github.com:emacscollective/emacs.g.git ~/.config/emacs 200 | cd ~/.config/emacs 201 | make bootstrap-borg 202 | make bootstrap 203 | @end example 204 | 205 | If you have assimilated many packages, you might want to use @code{make 206 | bootstrap | tee bootstrap.log}. 207 | 208 | The last command run during bootstrap is @code{git submodule status}, which 209 | prints one line per module. If a line is prefixed with @samp{+}, that means 210 | that it was not possible to checkout the recorded commit, and @code{-} means 211 | that the module could not be cloned. Even if some module could not be 212 | cloned, that usually does not render a configuration unusable, so just 213 | run @code{emacs} now, and then investigate any issues from the comfort of 214 | Magit. 215 | 216 | If you cloned to somewhere other than @code{~/.config/emacs}, then you can 217 | use that configuration using @code{emacs --init-directory /path/to/emacs.g/}, 218 | provided you are using Emacs 29 or later. Otherwise you have to 219 | resort to @code{emacs -Q -l /path/to/emacs.g/early-init.el -l 220 | /path/to/emacs.g/init.el}. 221 | 222 | For drones whose upstream repositories are located on Github or Gitlab 223 | the @code{emacs.g} collective uses the @code{ssh} protocol by default, which is a 224 | problem if you don't have accounts there and have not properly setup 225 | your keys. See @ref{Using https URLs}. 226 | 227 | During package compilation you may notice the submodules relating to 228 | those packages become dirty due to the compilation outputs not being 229 | ignored in those submodules. For this reason it is useful to ignore 230 | these outputs globally, for example in your @code{~/.config/git/ignore} 231 | file: 232 | 233 | @example 234 | *.elc 235 | *-autoloads.el 236 | dir 237 | @end example 238 | 239 | You may discover more things that you'll want to ignore this way as 240 | you use @code{borg}. 241 | 242 | @anchor{Bootstrapping from scratch} 243 | @subsection Bootstrapping from scratch 244 | 245 | If you don't want to base your configuration on the @code{emacs.g} 246 | starter-kit described in the previous section, then you have 247 | to do a few things manually. 248 | 249 | @example 250 | git init ~/.config/emacs 251 | cd ~/.config/emacs 252 | @end example 253 | 254 | By default Borg installs packages inside the @code{lib/} subdirectory, but 255 | since you are starting from scratch, you may choose something else 256 | by setting the Git variable @code{borg.drones-directory} locally for this 257 | repository. 258 | 259 | Then you should add a @code{Makefile} containing at least: 260 | 261 | @example 262 | DRONES_DIR = $(shell git config "borg.drones-directory" || echo "lib") 263 | 264 | -include $(DRONES_DIR)/borg/borg.mk 265 | 266 | bootstrap-borg: 267 | @@git submodule--helper clone --name borg --path $(DRONES_DIR)/borg \ 268 | --url git@@github.com:emacscollective/borg.git 269 | @@cd $(DRONES_DIR)/borg; git symbolic-ref HEAD refs/heads/main 270 | @@cd $(DRONES_DIR)/borg; git reset --hard HEAD 271 | @end example 272 | 273 | Now you are probably tempted to run @code{make bootstrap-borg}, but that is 274 | for bootstrapping @emph{from a seed}, and what we are doing right now is to 275 | bootstrap @emph{from scratch}. In the process we are creating a seed but we 276 | are not there yet. Instead run this: 277 | 278 | @example 279 | git submodule add --name borg git@@github.com:emacscollective/borg.git lib/borg 280 | @end example 281 | 282 | Now that @code{borg} is available we can build all the assimilated packages (currently 283 | just @code{borg} itself) using @code{make bootstrap}. 284 | 285 | Now it is time to tell Emacs to initialize Borg instead of Package by 286 | adding a simple @code{early-init.el} file containing: 287 | 288 | @lisp 289 | ;; -*- lexical-binding:t; no-byte-compile:t -*- 290 | 291 | (setq load-prefer-newer t) 292 | 293 | (add-to-list 'load-path (expand-file-name "lib/borg" user-emacs-directory)) 294 | (require 'borg) 295 | (borg-initialize) 296 | 297 | (setq package-enable-at-startup nil) 298 | @end lisp 299 | 300 | Changing the values of @code{load-prefer-newer} and @code{package-enable-at-startup} 301 | as shown here is optional but strongly recommended. @code{load-prefer-newer} 302 | should be enabled before loading @code{borg}. 303 | 304 | Now you could create the initial commit but you could also delay that. 305 | 306 | @example 307 | git commit -m "Assimilate borg" 308 | @end example 309 | 310 | Now it is time to assimilate some other essential packages. You could 311 | do so using @code{M-x borg-assimilate}, but you would quickly notice that 312 | doing so without the help of the @code{epkg} package is quite cumbersome, 313 | so lets manually install that and its dependency first: 314 | 315 | @example 316 | git submodule add --name closql git@@github.com:emacscollective/closql.git lib/closql 317 | git submodule add --name emacsql git@@github.com:magit/emacsql.git lib/emacsql 318 | git submodule add --name compat git@@github.com:emacs-compat/compat.git lib/compat 319 | git submodule add --name llama https://git.sr.ht/~tarsius/llama lib/llama 320 | git submodule add --name epkg git@@github.com:emacscollective/epkg.git lib/epkg 321 | git config -f .gitmodules submodule.emacsql.no-byte-compile emacsql-pg.el 322 | echo /epkgs/ >> .gitignore 323 | git add .gitignore .gitmodules 324 | make build 325 | git commit -m "Assimilate epkg and dependencies" 326 | @end example 327 | 328 | Once you have done that and have restarted Emacs, you can install 329 | Magit using Borg, as described in @ref{Assimilation}. You should also 330 | configure Magit status buffers to display submodules: 331 | 332 | @lisp 333 | (with-eval-after-load 'magit 334 | (magit-add-section-hook 'magit-status-sections-hook 335 | 'magit-insert-modules 336 | 'magit-insert-stashes 337 | 'append)) 338 | @end lisp 339 | 340 | Finally (look, nobody forced you to do this from scratch ;-) I 341 | strongly suggest that you make yourself familiar with my @code{auto-compile} 342 | package. 343 | 344 | @anchor{Migrating a legacy configuration} 345 | @subsection Migrating a legacy configuration 346 | 347 | If you are currently using Package and want to gently ease into using 348 | Borg alongside that, then you can proceed as described in @ref{Use as secondary package manager}. 349 | 350 | If on the other hand you are already manually using Git modules, 351 | then you should proceed as described in @ref{Bootstrapping from scratch}. 352 | Obviously "from scratch" does not apply this time around, so just skip 353 | steps like @code{git init}. 354 | 355 | @anchor{Using your configuration on another machine} 356 | @subsection Using your configuration on another machine 357 | 358 | Getting started using your existing configuration on another machine 359 | works the same way as described in @ref{Bootstrapping using a seed}. The 360 | only difference is that instead of starting by cloning someone else's 361 | repository you start by cloning your own repository. 362 | 363 | @anchor{Using https URLs} 364 | @subsection Using https URLs 365 | 366 | For drones whose upstream repositories are located on Github or Gitlab 367 | the @code{emacs.g} collective uses the @code{ssh} protocol by default, which is a 368 | problem if you don't have accounts there and have not properly setup 369 | your keys. 370 | 371 | Luckily this can easily be fixed using the following global rules. 372 | 373 | @lisp 374 | git config --global url.https://github.com/.insteadOf git@@github.com: 375 | git config --global url.https://gitlab.com/.insteadOf git@@gitlab.com: 376 | @end lisp 377 | 378 | If you don't want to configure this globally, then you can also configure 379 | Borg itself to prefer the @code{https} URLS@. 380 | 381 | @lisp 382 | (setq borg-rewrite-urls-alist 383 | '(("git@@github.com:" . "https://github.com/") 384 | ("git@@gitlab.com:" . "https://gitlab.com/"))) 385 | @end lisp 386 | 387 | This does not affect packages that have already been assimilated. 388 | During bootstrapping you have to change the URLs for packages that 389 | are assimilated by default. 390 | 391 | @example 392 | cd ~/.config/emacs 393 | sed -i "s|git@@github.com:|https://github.com/|g" .gitmodules 394 | sed -i "s|git@@gitlab.com:|https://gitlab.com/|g" .gitmodules 395 | git commit -m "Use https URLs for Github and Gitlab" 396 | @end example 397 | 398 | If you have already run @code{make bootstrap}, then you also have to edit 399 | @code{.git/config}. 400 | 401 | @example 402 | cd ~/.config/emacs 403 | sed -i "s|git@@github.com:|https://github.com/|g" .git/config 404 | sed -i "s|git@@gitlab.com:|https://gitlab.com/|g" .git/config 405 | @end example 406 | 407 | @node Startup 408 | @chapter Startup 409 | 410 | The early init file, @code{early-init.el} (see @ref{Early Init File,,,emacs,}), 411 | should contain a call to @code{borg-initialize}. 412 | 413 | Changing the values of @code{load-prefer-newer} and @code{package-enable-at-startup} 414 | as shown here is optional but strongly recommended. @code{load-prefer-newer} 415 | should be enabled before loading @code{borg}. 416 | 417 | @lisp 418 | ;; -*- lexical-binding:t; no-byte-compile:t -*- 419 | 420 | (setq load-prefer-newer t) 421 | 422 | (add-to-list 'load-path (expand-file-name "lib/borg" user-emacs-directory)) 423 | (require 'borg) 424 | (borg-initialize) 425 | 426 | (setq package-enable-at-startup nil) 427 | @end lisp 428 | 429 | @defun borg-initialize 430 | This function initializes assimilated drones using @code{borg-activate}. 431 | 432 | To skip the activation of the drone named DRONE, temporarily disable 433 | it by setting the value of the Git variable @code{submodule.DRONE.disabled} 434 | to true in @code{~/.config/emacs/.gitmodules}. 435 | @end defun 436 | 437 | Borg automatically reports how long it takes to load @code{borg.el} itself, 438 | @code{early-init.el,} and other config files that it loads directly. It 439 | cannot do the same for @code{init.el}, so you should explicitly call the 440 | following function from that file, and possibly from other home-made 441 | config files. 442 | 443 | @defun borg-report-load-duration &optional file format-string 444 | This function reports how long it takes to load the file currently 445 | being loaded. It should be called very early in the file, ideally 446 | before doing anything else. This prints two messages; one right 447 | when the function is called and another once the file has been 448 | loaded. 449 | 450 | If optional FILE is non-@code{nil}, this function instead reports how long 451 | it takes to load that file (this assumes that it is currently being 452 | loaded). Optional FORMAT-STRING, if non-@code{nil}, is passed to @code{message}. 453 | It should should end with "@dots{}" and contain zero or one @code{%s}, which 454 | stands for the file name. 455 | @end defun 456 | 457 | @defun borg-report-init-duration 458 | This function adds functions to @code{after-init-hook}, which, once that 459 | hook is nearly done running, will report how long it took to run 460 | that hook and also how long Emacs initialization took. Calling 461 | this function does nothing if the hook already ran. 462 | @end defun 463 | 464 | @node Assimilation 465 | @chapter Assimilation 466 | 467 | A third-party package is assimilated by adding it as a submodule and, 468 | if necessary, by configuring it in @code{~/.config/emacs/init.el}. Built-in 469 | packages are assimilated merely by configuring them. 470 | 471 | To begin the assimilation of a third-party package use the command 472 | @code{borg-assimilate}, which adds the package's repository as a submodule 473 | and attempts to build the drone. 474 | 475 | A safer alternative is to first clone the package without assimilating 476 | it, using @code{borg-clone}. This gives you an opportunity to inspect the 477 | cloned package for broken or malicious code, before it gets a chance 478 | to run arbitrary code. Later you can proceed with the assimilation 479 | using @code{borg-assimilate}, or remove the clone using @code{borg-remove}. 480 | 481 | Building the drone can fail, for example due to missing dependencies. 482 | Failure to build a drone is not considered as a failure to assimilate. 483 | If a build fails, then a buffer containing information about the 484 | issue pops up. If the failure is due to unsatisfied dependencies, 485 | then assimilate those too, and then build any drone, which previously 486 | couldn't be built, by using the Emacs command @code{borg-build} or @code{make 487 | lib/DRONE}. Alternatively you can just rebuild everything using @code{make 488 | build}. 489 | 490 | If you wish to avoid such complications, you should use the command 491 | @code{epkg-describe-package} before assimilating a package. Among other 492 | useful information, it also provides a dependency tree. 493 | 494 | Once the packages have been added as a submodules and the drones have 495 | been built, the assimilation is completed by creating an assimilation 496 | commit. 497 | 498 | If you assimilate a single package, then it is recommended that you 499 | use a message similar to this: 500 | 501 | @example 502 | Assimilate foo v1.0.0 503 | @end example 504 | 505 | Or if one or more dependencies had to be assimilated, something like: 506 | 507 | @example 508 | Assimilate foo and dependencies 509 | 510 | Assimilate foo v1.0.0 511 | Assimilate bar v1.1.0 512 | Assimilate baz v0.1.0 513 | @end example 514 | 515 | It's usually a good idea not to assimilate unrelated packages in the 516 | same commit, but doing it for related packages, which do not strictly 517 | depend on one another, it might make sense: 518 | 519 | @example 520 | Assimilate ido and extensions 521 | 522 | Assimilate flx v0.6.1-3-gae0981b 523 | Assimilate ido-at-point v1.0.0 524 | Assimilate ido-ubiquitous v3.12-2-g7354d98 525 | Assimilate ido-vertical-mode v0.1.6-33-gb42e422 526 | Assimilate smex 3.0-13-g55aaebe 527 | @end example 528 | 529 | The command @code{borg-insert-update-message} can be used to generate such 530 | commit messages. 531 | 532 | @table @asis 533 | @item @kbd{C-c C-b [in git-commit-mode buffer]} (@code{borg-insert-update-message}) 534 | @kindex C-c C-b [in git-commit-mode buffer] 535 | @findex borg-insert-update-message 536 | This command insert information about drones that are changed in the 537 | index. Formatting is according to the commit message conventions 538 | described above. 539 | @end table 540 | 541 | @deffn Command borg-assimilate package url &optional partially 542 | This command assimilates the package named PACKAGE from URL@. 543 | 544 | If @code{epkg} is available, then only the name of the package is read in 545 | the minibuffer and the url stored in the Epkg database is used. If 546 | @code{epkg} is unavailable, the package is not in the database, or if a 547 | prefix argument is used, then the url too is read in the minibuffer. 548 | 549 | If a negative prefix argument is used, then the submodule is added 550 | but the build and activation steps are skipped. This is useful when 551 | assimilating a package that requires special build steps. After 552 | configuring the build steps use @code{borg-build} to complete the 553 | assimilation. 554 | @end deffn 555 | 556 | @deffn Command borg-clone package url 557 | This command clones the package named PACKAGE from URL, without 558 | assimilating it. This is useful when you want to inspect the 559 | package before potentially executing malicious or broken code. 560 | 561 | Interactively, when the @code{epkg} package is available, then the name 562 | is read in the minibuffer and the url stored in the Epkg database 563 | is used. If @code{epkg} is unavailable, the package is unknown, or when 564 | a prefix argument is used, then the url is also read in the 565 | minibuffer. 566 | @end deffn 567 | 568 | @deffn Command borg-activate clone 569 | This command activates the clone named CLONE by adding the 570 | appropriate directories to the @code{load-path} and to @code{Info-directory-list}, 571 | and by loading the autoloads file, if it exists. 572 | 573 | Unlike @code{borg-initialize}, this function ignores the Git variable 574 | @code{submodule.DRONE.disabled} and can be used to activate clones that 575 | have not been assimilated. 576 | @end deffn 577 | 578 | @deffn Command borg-remove clone 579 | This command removes the cloned or assimilated package named CLONE, 580 | by removing the working tree from @code{borg-drones-directory}, regardless 581 | of whether that repository belongs to an assimilated package or a 582 | package that has only been cloned for review using @code{borg-clone}. The 583 | Git directory is not removed. 584 | @end deffn 585 | 586 | @deffn Command borg-build clone &optional activate 587 | This command builds the clone named CLONE@. Interactively, or when 588 | optional ACTIVATE is non-@code{nil}, then also activate the drone using 589 | @code{borg-activate}. 590 | @end deffn 591 | 592 | @defun borg-update-autoloads clone &optional path 593 | This function updates the autoload file for the libraries belonging 594 | to the clone named CLONE in the directories in PATH@. PATH can be 595 | omitted or contain file-names that are relative to the top-level of 596 | CLONE's repository. 597 | @end defun 598 | 599 | @defun borg-compile clone &optional path 600 | This function compiles the libraries for the clone named CLONE in 601 | the directories in PATH@. PATH can be omitted or contain file-names 602 | that are relative to the top-level of CLONE's repository. 603 | @end defun 604 | 605 | @defun borg-maketexi clone &optional files 606 | This function generates Texinfo files from certain Org files for the 607 | clone named CLONE@. Org files that are located on @code{borg-info-path} are 608 | exported if their names match @code{borg-maketexi-filename-regexp} and the 609 | @code{TEXINFO_DIR_HEADER} export keyword is set in their content. 610 | @end defun 611 | 612 | @defun borg-makeinfo clone 613 | This function generates the Info manuals and the Info index for the 614 | clone named CLONE@. 615 | @end defun 616 | 617 | @defun borg-batch-rebuild &optional quick 618 | This function rebuilds all assimilated drones in alphabetic order, 619 | except for Org which is rebuilt first. After that it also builds 620 | the user init files using @code{borg-batch-rebuild-init}. 621 | 622 | This function is not intended for interactive use; instead it is 623 | used by the Make target @code{build} described in the following section. 624 | 625 | When optional QUICK is non-@code{nil}, then this function does not build 626 | drones for which @code{submodule.DRONE.build-step} is set, assuming that 627 | those are the drones that take longer to be built. 628 | @end defun 629 | 630 | @defun borg-batch-rebuild-init 631 | This function builds the init files specified by the Make variable 632 | @code{INIT_FILES}, or if that is unspecified @code{init.el} and @code{LOGIN.el}, where 633 | @code{LOGIN} is the value of the variable @code{user-real-login-name}. If a file 634 | does not exist, then it is silently ignored. 635 | 636 | This function is not intended for interactive use; instead it is 637 | used by the Make targets @code{build-init} and (indirectly) @code{build}, which 638 | are described in @ref{Make targets}. 639 | @end defun 640 | 641 | @node Updating drones 642 | @chapter Updating drones 643 | 644 | Borg does not provide an update command. By not doing so, it empowers 645 | you to update to exactly the commit you wish to update to, instead of 646 | to "the" new version. 647 | 648 | To determine the drones that you @emph{might} want to update, visit the Magit 649 | status buffer of the @code{~/.config/emacs} repository and press @code{f m} to fetch 650 | inside all submodules. After you have done so, and provided there 651 | actually are any modules with new upstream commits, a section titled 652 | "Modules unpulled from @@@{upstream@}" appears. 653 | 654 | Each subsection of that section represents a submodule with new 655 | upstream commits. Expanding such a subsection lists the new upstream 656 | commits. These commits can be visited by pressing @code{RET}, and the status 657 | buffer of a submodule can be visited by pressing @code{RET} while point is 658 | inside the heading of the respective submodule section. To return to 659 | the status buffer of @code{~/.config/emacs} press @code{q}. 660 | 661 | Inside the status buffer of a submodule, you can pull the upstream 662 | changes as usual, using @code{F u}. If you wish you can inspect the changes 663 | before doing so. And you can also choose to check out another commit 664 | instead of the upstream @code{HEAD}. 665 | 666 | Once you have "updated" to a new commit, you should also rebuild the 667 | drone using the command @code{borg-build}. This may fail, e.g., due to new 668 | dependencies. 669 | 670 | Once you have resolved all issues, you should create an "update 671 | commit". You can either create one commit per updated drone or you 672 | can create a single commit for all updated drones, which ever you find 673 | more appropriate. However it is recommended that you use a message 674 | similar to: 675 | 676 | @example 677 | Update foo to v1.1.0 678 | @end example 679 | 680 | Or for multiple packages: 681 | 682 | @example 683 | Update 2 drones 684 | 685 | Update foo to v1.1.0 686 | Update bar to v1.2.1 687 | @end example 688 | 689 | The command @code{borg-insert-update-message} can be used to generate such 690 | commit messages. 691 | 692 | To update the Epkg package database use the command @code{epkg-update}. 693 | 694 | @node Patching drones 695 | @chapter Patching drones 696 | 697 | By using Borg you can not only make changes to assimilated packages, 698 | you can also keep track of those patches and share them with others. 699 | 700 | If you created some commits in a drone repository and are the 701 | maintainer of the respective package, then you can just push your 702 | changes to the "origin" remote. 703 | 704 | You don't have to do this every time you created some commits, but at 705 | important checkpoints, such as after creating a release, you should 706 | record the changes in the @code{~/.config/emacs} repository. To do so 707 | proceed as described in @ref{Updating drones}. 708 | 709 | But for most packages you are not the maintainer and if you create 710 | commits for such drones, then you have to create a fork and push there 711 | instead. You should configure that remote as the push-remote using 712 | @code{git config remote.pushDefault FORK}, or by pressing @code{b C M-p} in Magit. 713 | After you have done that, you can continue to pull from the upstream 714 | using @code{F u} in Magit and you can also push to your fork using @code{P p}. 715 | 716 | Of course you should also occasionally record the changes in the 717 | @code{~/.config/emacs} repository. Additionally, and ideally when you first 718 | fork a drone, you should also record information about your personal 719 | remote in the super-repository by setting @code{submodule.DRONE.remote} in 720 | @code{~/.config/emacs/.gitmodules}. 721 | 722 | @defvar submodule.DRONE.remote "NAME URL" 723 | This variable specifies an additional remote named NAME that is 724 | fetched from URL@. This variable can be specified multiple times. 725 | Note that "NAME URL" is a single value and that the two parts of 726 | that value are separated by a single space. 727 | 728 | @code{make bootstrap} automatically adds all remotes that are specified 729 | like this to the DRONE repository by setting @code{remote.NAME.url} to 730 | URL and using the standard value for @code{remote.NAME.fetch}. 731 | @end defvar 732 | 733 | @defvar borg.pushDefault FORK 734 | This variable specifies a name used for push-remotes. Because this 735 | variable can only have one value it is recommended that you use the 736 | same name, FORK, for your personal remote in all drone repositories 737 | in which you have created patches that haven't been merged into the 738 | upstream repository (yet). A good value may be your username. 739 | 740 | For all DRONES for which one value of @code{submodule.DRONE.remote} 741 | specifies a remote whose NAME matches FORK, @code{make bootstrap} 742 | automatically configures FORK to be used as the push-remote by 743 | setting @code{remote.pushDefault} to FORK@. 744 | @end defvar 745 | 746 | @node Make targets 747 | @chapter Make targets 748 | 749 | The following @code{make} targets are available by default. To use them you 750 | have to be in @code{~/.config/emacs} in a shell. They are implemented in 751 | @code{borg.mk}, which is part of the @code{borg} package. 752 | 753 | To show the commands that are run, use @code{V=1 make ...}. Otherwise only 754 | their output is shown. 755 | 756 | @anchor{Help targets} 757 | @heading Help targets 758 | 759 | @deffn Command help 760 | This target prints information about most of the following targets. 761 | 762 | This is the default target, unless the user sets @code{.DEFAULT_GOAL}. 763 | @end deffn 764 | 765 | @deffn Command helpall 766 | This target prints information about all of the following targets. 767 | @end deffn 768 | 769 | @anchor{Batch targets} 770 | @heading Batch targets 771 | 772 | @deffn Command clean 773 | This target removes all byte-code and native files of all drones and 774 | config files. 775 | 776 | To ensure a clean build, this target should always be run before 777 | @code{build}, so you might want to add a default target that does just 778 | that. To do so, add this to @code{~/.config/emacs/etc/borg/config.mk}: 779 | 780 | @example 781 | .DEFAULT_GOAL := all 782 | all: clean build 783 | @end example 784 | @end deffn 785 | 786 | @deffn Command clean-force 787 | This target removes all byte-code files using @code{find}. The @code{clean} 788 | target on the other hand uses the lisp function @code{borg--batch-clean}. 789 | Byte-code isn't always compatible between Emacs releases and this 790 | target makes it possible to recover from such an incompatibility. 791 | @end deffn 792 | 793 | @deffn Command build 794 | This target byte-compiles Borg and Compat first, followed by all 795 | other drones in alphabetic order. After that it also byte-compiles 796 | the user init files, like @code{init-build} does. 797 | @end deffn 798 | 799 | @deffn Command native 800 | This target byte-compiles and natively compiles Borg and Compat 801 | first, followed by all other drones in alphabetic order. After that 802 | it also byte-compiles the user init files, like @code{init-build} does. 803 | @end deffn 804 | 805 | @anchor{Quick batch targets} 806 | @heading Quick batch targets 807 | 808 | These targets act on most drones but exclude those for which the Git 809 | variable @code{submodule.DRONE.build-step} is set. The assumption is that 810 | those are the drones that take longer to build. 811 | 812 | @deffn Command quick 813 | This target cleans and builds most drones. 814 | 815 | It also cleans and builds the init files as described for @code{build}. 816 | @end deffn 817 | 818 | @deffn Command quick-clean 819 | This target removes all byte-code and native files of most drones 820 | It also remove the byte-code files of the config files. 821 | @end deffn 822 | 823 | @deffn Command quick-build 824 | This target builds @emph{most} drones and the config files 825 | 826 | It also builds the init files as described for @code{build}. 827 | @end deffn 828 | 829 | @anchor{Drone targets} 830 | @heading Drone targets 831 | 832 | @deffn Command clean/DRONE 833 | This target removes all byte-code and native files belonging to the 834 | drone named DRONE@. 835 | @end deffn 836 | 837 | @deffn Command build/DRONE 838 | This target byte-compiles the drone named DRONE@. 839 | 840 | @code{lib/DRONE} is an alias for this target; or rather @code{DIR/DRONE}, where 841 | @code{DIR} is directory containing the drone submodules. 842 | @end deffn 843 | 844 | @deffn Command native/DRONE 845 | This target byte-compiles and natively-compiles the drone named 846 | DRONE@. 847 | @end deffn 848 | 849 | @anchor{Init file targets} 850 | @heading Init file targets 851 | 852 | @deffn Command init-clean 853 | This target removes byte-code files for init files. 854 | @end deffn 855 | 856 | @deffn Command init-tangle 857 | This target tangles (creates) @code{init.el} from @code{init.org}. You obviously 858 | don't have to use such a file, if you don't want to. 859 | @end deffn 860 | 861 | @deffn Command init-build 862 | This target byte-compiles the init files specified by the make 863 | variable @code{INIT_FILES}; or if that is unspecified @code{init.el} and @code{LOGIN.el} 864 | (where @code{LOGIN} is the value of the variable @code{user-real-login-name}). 865 | If an init file does not exist, then that is silently ignored. 866 | 867 | If you publish your @code{~/.config/emacs} repository but would like to 868 | keep some settings private, then you can do so by putting them in a 869 | file @code{~/.config/emacs/LOGIN.el}. The downside of this approach is 870 | that you will have to somehow synchronize that file between your 871 | machines without checking it into Git. 872 | @end deffn 873 | 874 | @anchor{Bootstrap targets} 875 | @heading Bootstrap targets 876 | 877 | @deffn Command bootstrap-borg 878 | This target bootstraps @code{borg} itself. 879 | @end deffn 880 | 881 | @deffn Command bootstrap 882 | This target attempts to bootstrap all drones. To do so it runs @code{git 883 | submodule init}, @code{make clone-modules}, @code{make checkout-modules} and @code{make 884 | build}. 885 | 886 | If an error occurs during one of these steps, then you can just run 887 | the target that failed (and the subsequent targets) again to process 888 | the remaining drones. Doing so does not discard any local changes, 889 | such as uncommitted changes, new commits, or the effect of manually 890 | checking out some other commit. 891 | 892 | If a drone cannot be cloned from any of the known remotes, then you 893 | can temporarily ignore it using @code{git submodule deinit lib/DRONE}. 894 | 895 | If you have run @code{make clone-modules} and/or @code{make checkout-modules} 896 | manually, then make sure to finish by running @code{make build} again too. 897 | @end deffn 898 | 899 | @deffn Command clone-modules 900 | This target attempts to clone all modules that were initialized by 901 | @code{git submodule init} and which the user did not explicitly deactivate 902 | afterwards, either by de-initializing it again (@code{git submodule deinit 903 | lib/DRONE}) or by setting @code{submodule.DRONE.active} to @code{false}. 904 | 905 | This may fail, for example, if the URL of the remote repository has 906 | changed. If that happens, you can update the URL, and then run this 907 | command again. Already cloned modules are skipped on reruns. 908 | 909 | Alternatively drones can be cloned individually, using 910 | @code{lib/borg/borg.sh clone DRONE}. 911 | @end deffn 912 | 913 | @deffn Command checkout-modules 914 | This target attempts to checkout commits recorded for all modules, 915 | which were successfully cloned by @code{make clone-modules}, while also 916 | trying to check out the recorded commit. 917 | 918 | It is safe to rerun this target. Doing so does not discard any 919 | local changes, such as uncommitted changes, new commits, or the 920 | effect of manually checking out some other commit. 921 | 922 | Alternatively drones can be checked out individually, using 923 | @code{lib/borg/borg.sh checkout DRONE}. 924 | @end deffn 925 | 926 | @node Variables 927 | @chapter Variables 928 | 929 | @defvar borg.drones-directory DIRECTORY 930 | This Git variable can be used to override the name of the directory 931 | that contains the drone submodules. If specified, the value has to 932 | be relative to the top-level directory of the repository. 933 | 934 | Note that if you change the value of this variable, then you might 935 | have to additionally edit @code{~/.config/emacs/Makefile}. 936 | @end defvar 937 | 938 | The values of the following variables are set at startup and should 939 | not be changed by the user. 940 | 941 | @defvar borg-drones-directory 942 | The value of this constant is the directory beneath which drone 943 | submodules are placed. The value is set based on the location of 944 | the @code{borg} library and the Git variable @code{borg.drones-directory} if set, 945 | and should not be changed. 946 | @end defvar 947 | 948 | @defvar borg-user-emacs-directory 949 | The value of this constant is the directory beneath which additional 950 | per-user Emacs-specific files are placed. The value is set based on 951 | the location of the @code{borg} library and should not be changed. The 952 | value is usually the same as that of @code{user-emacs-directory}, except 953 | when Emacs is started with @code{emacs -q -l /path/to/init.el}. 954 | @end defvar 955 | 956 | @defvar borg-gitmodules-file 957 | The value of this constant is the @code{.gitmodules} file of the 958 | super-repository. 959 | @end defvar 960 | 961 | If you want to change the value of the following variable, you have to 962 | do so before requiring @code{borg}, else it does not have the desired effect. 963 | 964 | @defvar borg-debug-user-init-files 965 | This variable controls whether the effect of the command-line 966 | argument @code{--debug-init} extends to user init files. If non-@code{nil} and 967 | @code{--debug-init} is used, then @code{debug-on-error} is automatically enable 968 | and @code{use-package-verbose} is set to @code{debug}. Finally these variables 969 | are reset to their default values using @code{after-init-hook}. 970 | @end defvar 971 | 972 | The value of this Make variable has to be set in 973 | @code{~/.config/emacs/Makefile}. 974 | 975 | @defvar INIT​_FILES 976 | A list of init files to be build by the Make targets @code{build} and 977 | @code{build-init}. See @ref{Make targets}. 978 | @end defvar 979 | 980 | The values of these borg-specific Git variables have to be set in the 981 | file @code{~/.config/emacs/.gitmodules}. The variables @code{borg.pushDefault} and 982 | @code{submodule.DRONE.remote} are described in @ref{Patching drones}. 983 | 984 | Because most repositories used to maintain Emacs packages follow some 985 | common-sense conventions, Borg usually does not have to be told how to 986 | build a given drone. Building is done using @code{borg-build}, which in turn 987 | usually does its work using @code{borg-update-autoloads}, @code{borg-compile}, 988 | @code{borg-maketexi}, and @code{borg-makeinfo}. 989 | 990 | However some packages don't follow the conventions either because they 991 | are too complex to do so, or for the sake of doing it differently. 992 | But in either case resistance is futile; by using the following 993 | variables you can tell Borg how to build such packages. 994 | 995 | @defvar submodule.DRONE.build-step COMMAND 996 | By default drones are built using the lisp functions 997 | @code{borg-update-autoloads}, @code{borg-compile}, @code{borg-maketexi}, and 998 | @code{borg-makeinfo}, but if this variable has one or more values, then 999 | DRONE is built using these COMMANDs @strong{instead}. 1000 | 1001 | Each COMMAND can be one of the default steps, an S-expression, or 1002 | a shell command. The COMMANDs are executed in the specified order. 1003 | 1004 | If a COMMAND matches one of default steps, then it is evaluated with 1005 | the appropriate arguments. 1006 | 1007 | If a COMMAND begins with a parenthesis, then it is evaluated as 1008 | a lisp expression. In that case the variable @code{borg-clone} holds 1009 | the name of the package that is being build. To make a function 1010 | available in this context, you usually have to define or load it 1011 | in @samp{etc/borg/config.el}, relative to @code{borg-user-emacs-directory}. 1012 | 1013 | Otherwise COMMAND is assumed to be a shell command and is executed 1014 | with @code{shell-command}. 1015 | 1016 | @example 1017 | [submodule "mu4e"] 1018 | path = lib/mu4e 1019 | url = git@@github.com:djcb/mu.git 1020 | build-step = test -e ./configure || autoreconf -i 1021 | build-step = ./configure 1022 | build-step = make -C mu4e > /dev/null 1023 | build-step = borg-update-autoloads 1024 | load-path = mu4e 1025 | @end example 1026 | 1027 | To skip generating "autoloads" (e.g., using @code{use-package} to create 1028 | "autoloads" on the fly), just provide the required build steps to 1029 | build the package, omitting @code{borg-update-autoloads}. Borg silently 1030 | ignores a missing "autoloads" file during initialization 1031 | (@code{borg-initialize}). 1032 | 1033 | @example 1034 | [submodule "multiple-cursors"] 1035 | path = lib/multiple-cursors 1036 | url = git@@github.com:magnars/multiple-cursors.el.git 1037 | build-step = borg-compile 1038 | @end example 1039 | 1040 | Note that just because a package provides a @code{Makefile}, you do not 1041 | necessarily have to use it. 1042 | 1043 | Even if @code{make} generates the Info file, you might still have to add 1044 | @code{borg-makeinfo} as an additional build-step because the former might 1045 | not generate an Info index file (named @code{dir}), which Borg relies on. 1046 | 1047 | Also see @code{borg.extra-build-step} below. 1048 | @end defvar 1049 | 1050 | @defvar borg-build-shell-command 1051 | This variable can be used to change how shell commands specified 1052 | by @code{submodule.DRONE.build-step} are run. The default value is @code{nil}, 1053 | meaning that each build step is run unchanged using @code{shell-command}. 1054 | 1055 | If the value is a string, then that is combined with each build step 1056 | in turn and the results are run using @code{shell-command}. This string 1057 | must contain either %s, which is replaced with the unchanged build 1058 | step, or %S, which is replaced with the result of quoting the build 1059 | step using @code{shell-quote-argument}. 1060 | 1061 | If the value is a function, then that is called once with the drone 1062 | as argument and must return either a string or a function. If the 1063 | returned value is a string, then that is used as described above. 1064 | 1065 | If the value returned by the first function is another function, then 1066 | this second function is called for each build step with the drone and 1067 | the build step as arguments. It must return a string or @code{nil}. If the 1068 | returned value is a string, then that is used as described above. 1069 | 1070 | Finally the second function may execute the build step at its own 1071 | discretion and return @code{nil} to indicate that it has done so. 1072 | 1073 | Notice that if the value of this variable is a function, this 1074 | function must a) be defined in a drone; and b) be registered as an 1075 | autoload. This is because build happens in a separate Emacs process 1076 | started with @code{-Q --batch}, which only receives the name of the function. 1077 | @end defvar 1078 | 1079 | @defvar submodule.DRONE.load-path PATH 1080 | This variable instructs @code{borg-activate} to add PATH to the @code{load-path} 1081 | instead of the directory it would otherwise have added. Likewise it 1082 | instructs @code{borg-compile} to compile the libraries in that directory. 1083 | PATH has to be relative to the top-level of the repository of the 1084 | drone named DRONE@. This variable can be specified multiple times. 1085 | 1086 | Normally Borg uses @code{elisp/} as the drone's @code{load-path}, if that exists; 1087 | otherwise @code{lisp/}, if that exists; or else the top-level directory. 1088 | If this variable is set, then it @emph{overrides} the default location. 1089 | Therefore, to @emph{add} an additional directory, you also have to 1090 | explicitly specify the default location. 1091 | 1092 | @example 1093 | [submodule "org"] 1094 | path = lib/org 1095 | url = git://orgmode.org/org-mode.git 1096 | build-step = make 1097 | load-path = lisp 1098 | load-path = contrib/lisp 1099 | info-path = doc 1100 | @end example 1101 | @end defvar 1102 | 1103 | @defvar submodule.DRONE.no-byte-compile PATH 1104 | This variable instructs @code{borg-compile} to not compile the library at 1105 | PATH@. PATH has to be relative to the top-level of the repository of 1106 | the drone named DRONE@. This variable can be specified multiple 1107 | times. 1108 | 1109 | Sometimes a drone comes with an optional library which adds support 1110 | for some other third-party package, which you don't want to use. 1111 | For example @code{emacsql} comes with a PostgreSQL back-end, which is 1112 | implemented in the library @code{emacsql-pg.el}, which requires the @code{pg} 1113 | package. The standard Borg collective @code{emacs.g} assimilates @code{emacsql}, 1114 | for the sake of the @code{epkg} drone, which only requires the SQLite 1115 | back-end. To avoid an error about @code{pg} not being available, @code{emacs.g} 1116 | instructs Borg to not compile @code{emacsql-pg.el}. (Of course if you want 1117 | to use the PostgreSQL back-end and assimilate @code{pg}, then you should 1118 | undo that.) 1119 | @end defvar 1120 | 1121 | @defvar submodule.DRONE.recursive-byte-compile BOOLEAN 1122 | Setting this variable to @code{true} instructs @code{borg-compile} to compile 1123 | DRONE's directories recursively. This isn't done by default because 1124 | there are more repositories in which doing so would cause issues 1125 | than there are repositories that would benefit from doing so. 1126 | 1127 | Unfortunately many packages put problematic test files or (usually 1128 | outdated) copies of third-party libraries into subdirectories. The 1129 | latter is a highly questionable thing to do, but the former would be 1130 | perfectly fine, if only the non-library lisp files did not provide 1131 | a feature (which effectively turns them into libraries) and/or if a 1132 | file named @code{.nosearch} existed in the subdirectory. That file tells 1133 | functions such as @code{normal-top-level-add-subdirs-to-load-path} and 1134 | @code{borg-compile} to ignore the containing directory. 1135 | @end defvar 1136 | 1137 | @defvar borg-compile-function 1138 | The function used to compile each individual library. 1139 | One of @code{byte-compile-file}, @code{borg-byte+native-compile} or 1140 | @code{borg-byte+native-compile-async}. 1141 | 1142 | To enable native compilation when running @code{make}, use one of the 1143 | respective make targets, as described in @ref{Make targets}. 1144 | @end defvar 1145 | 1146 | @defvar borg-compile-recursively 1147 | Setting this variable to a non-@code{nil} value instructs @code{borg-compile} 1148 | to compile all drones recursively. Doing so is discouraged. 1149 | @end defvar 1150 | 1151 | @defvar borg-native-compile-deny-list 1152 | This variable lists the names of files to be excluded from native 1153 | compilation. 1154 | @end defvar 1155 | 1156 | @defvar borg.extra-build-step COMMAND 1157 | This variable instructs Borg to execute COMMAND after the default 1158 | build-steps for each DRONE (or after @code{submodule.DRONE.build-step,} if 1159 | that specified). It has to be set in @code{borg-gitmodules-file} and can 1160 | have multiple values. 1161 | 1162 | If a COMMAND begins with a parenthesis, then it is evaluated as 1163 | a lisp expression. In that case the variable @code{borg-clone} holds 1164 | the name of the package that is being build. To make a function 1165 | available in this context, you usually have to define or load it 1166 | in @samp{etc/borg/config.el}, relative to @code{borg-user-emacs-directory}. 1167 | 1168 | Otherwise COMMAND is assumed to be a shell command and is executed 1169 | with @code{shell-command}. 1170 | @end defvar 1171 | 1172 | @defvar submodule.DRONE.info-path PATH 1173 | This variable instructs @code{borg-initialize} to add PATH to 1174 | @code{Info-directory-list}. PATH has to be relative to the top-level of 1175 | the repository of the drone named DRONE@. 1176 | @end defvar 1177 | 1178 | @defvar submodule.DRONE.no-maketexi PATH 1179 | This variable instructs @code{borg-maketexi} to not create a Texinfo file 1180 | for the Org file at PATH@. PATH has to be relative to the top-level 1181 | of the repository of the drone named DRONE@. This variable can be 1182 | specified multiple times. 1183 | @end defvar 1184 | 1185 | @defvar submodule.DRONE.no-makeinfo PATH 1186 | This variable instructs @code{borg-makeinfo} to not create an Info file for 1187 | the Texinfo file at PATH@. PATH has to be relative to the top-level 1188 | of the repository of the drone named DRONE@. This variable can be 1189 | specified multiple times. 1190 | @end defvar 1191 | 1192 | @defvar submodule.DRONE.disabled true|false 1193 | If the value of this variable is @code{true}, then it is skipped by 1194 | @code{borg-initialize}. 1195 | @end defvar 1196 | 1197 | @defvar borg-rewrite-urls-alist 1198 | An alist that can optionally be used to rewrite certain URLs. Each 1199 | element has the form @code{(ORIG . BASE)}. Each URL that starts with ORIG 1200 | is rewritten to start with BASE instead. See @ref{Using https URLs}. 1201 | @end defvar 1202 | 1203 | @defvar borg-maketexi-filename-regexp 1204 | A regexp matching Org files that may be exported to Texinfo by 1205 | @code{borg-maketexi}. The name of the clone is substituted for @code{%s}. 1206 | Setting this to @code{nil} disables the export of any Org files. 1207 | @end defvar 1208 | 1209 | @node Low-level functions 1210 | @chapter Low-level functions 1211 | 1212 | You normally should not have to use the following low-level functions 1213 | directly. That being said, you might want to do so anyway if you 1214 | build your own tools on top of Borg. 1215 | 1216 | @defun borg-worktree clone 1217 | This function returns the top-level of the working tree of the 1218 | clone named CLONE@. 1219 | @end defun 1220 | 1221 | @defun borg-gitdir clone 1222 | This function returns the Git directory of the clone named CLONE@. 1223 | 1224 | It always returns @code{BORG-USER-EMACS-DIRECTORY/.git/modules/CLONE}, even 1225 | when CLONE's Git directory is actually located inside the working 1226 | tree. 1227 | @end defun 1228 | 1229 | @defmac borg-do-drones (var [result]) body@dots{}) 1230 | This macro loop over drones. BODY is evaluated with VAR bound to 1231 | each drone, in turn. Inside BODY variables set in @code{.gitmodules} are 1232 | cached. Then RESULT is evaluated to get the return value, 1233 | defaulting to @code{nil}. 1234 | @end defmac 1235 | 1236 | @defun borg-get clone variable &optional all 1237 | This function returns the value of the Git variable 1238 | @code{submodule.CLONE.VARIABLE} defined in @code{~/.config/emacs/.gitmodules}. 1239 | If optional ALL is non-@code{nil}, then it returns all values as a list. 1240 | @end defun 1241 | 1242 | @defun borg-get-all clone variable 1243 | This function returns all values of the Git variable 1244 | @code{submodule.CLONE.VARIABLE} defined in @code{~/.config/emacs/.gitmodules} as a 1245 | list. 1246 | @end defun 1247 | 1248 | @defun borg-load-path clone 1249 | This function returns the @code{load-path} for the clone named CLONE@. 1250 | @end defun 1251 | 1252 | @defun borg-info-path clone &optional setup 1253 | This function returns the @code{Info-directory-list} for the clone named 1254 | CLONE@. 1255 | 1256 | If optional SETUP is non-@code{nil}, then it returns a list of directories 1257 | containing @code{texi} and/or @code{info} files. Otherwise it returns a list of 1258 | directories containing a file named @code{dir}. 1259 | @end defun 1260 | 1261 | @defun borg-dronep name 1262 | This function returns non-@code{nil} if a drone named NAME exists. 1263 | 1264 | If that is set in @code{.gitmodules}, then it returns the value of 1265 | @code{submodule.NAME.path}, @code{nil} otherwise. 1266 | @end defun 1267 | 1268 | @defun borg-drones &optional include-variables 1269 | This function returns a list of all assimilated drones. 1270 | 1271 | The returned value is a list of the names of the assimilated 1272 | drones, unless optional INCLUDE-VARIABLES is non-@code{nil}, in which 1273 | case elements of the returned list have the form @code{(NAME . ALIST)}. 1274 | 1275 | ALIST is an association list. Property names are symbols 1276 | and correspond to a VARIABLE defined in the Borg repository's 1277 | @code{.gitmodules} file as @code{submodule.NAME.VARIABLE}. 1278 | 1279 | Each property value is either a string or a list of strings. If 1280 | INCLUDE-VARIABLES is @code{raw} then all values are lists. Otherwise a 1281 | property value is only a list if the corresponding property name is 1282 | a member of @code{borg--multi-value-variables}. If a property name isn't 1283 | a member of @code{borg--multi-value-variables} but it does have multiple 1284 | values anyway, then it is undefined with value is included in the 1285 | returned value. 1286 | @end defun 1287 | 1288 | @defun borg-clones 1289 | This function returns a list of all cloned packages. 1290 | 1291 | The returned value includes the names of all drones, as well as the 1292 | names of all other repositories that are located directly inside 1293 | @code{borg-drones-directory} but aren't tracked as submodules. 1294 | @end defun 1295 | 1296 | @defun borg-read-package prompt &optional edit-url 1297 | This function reads a package name and the url of its upstream 1298 | repository from the user, and returns them as a list. 1299 | 1300 | When the @code{epkg} package is available, then the user is only prompted 1301 | for the name of the package, and the upstream url is retrieved from 1302 | the Epkg database. If the package isn't in the database then the 1303 | url has to be provided by the user. If optional EDIT-URL is 1304 | non-@code{nil}, then the url from the database, if any, is provided as 1305 | initial input for the user to edit. 1306 | 1307 | PROMPT is used when prompting for the package name. 1308 | @end defun 1309 | 1310 | @defun borg-read-clone prompt 1311 | This function reads the name of a cloned package from the user. 1312 | @end defun 1313 | 1314 | There exist a few more functions, but those are considered to be 1315 | internal and might therefore change in incompatible ways without that 1316 | being noted in the change log. 1317 | 1318 | @defun borg--maybe-absorb-gitdir pkg 1319 | @end defun 1320 | @defun borg--maybe-reuse-gitdir pkg 1321 | @end defun 1322 | @defun borg--restore-worktree pkg 1323 | @end defun 1324 | @defun borg--call-git pkg &rest args 1325 | @end defun 1326 | @defun borg--expand-load-path drone path 1327 | @end defun 1328 | @defun borg--sort-submodule-sections 1329 | @end defun 1330 | 1331 | @node Function and Command Index 1332 | @appendix Function and Command Index 1333 | 1334 | @printindex fn 1335 | 1336 | @node Variable Index 1337 | @appendix Variable Index 1338 | 1339 | @printindex vr 1340 | 1341 | @bye 1342 | --------------------------------------------------------------------------------