├── .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:
15 | #+html:
16 | #+html:
17 | #+html:
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 |
--------------------------------------------------------------------------------