git-annex-configure is a git-annex addon command that enables declarative
configuration of git-annex repositories using Guile Scheme. With a few
limitations, you can apply settings for all of your repositories with a config
file and a single execution of git-annex-configure
.
git-annex-configure is likely not available in your package manager’s repositories at the moment, but feel free to open an issue if this statement becomes inaccurate.
If you have GNU Guix, this repository comes with a package definition in
guix.scm that you can use for installation. After cloning this repository, the
following can be run in the directory where guix.scm
is located to install it
to your default profile:
guix package --install-from-file=guix.scm
To apply a configuration, simply run something like this:
git-annex configure /path/to/config/file
The configuration file should be located inside a git-annex repository, otherwise git-annex-configure will not know what repository it should operate on.
Most settings can be set from a single repository and then propagated via syncing to other repositories, which is what git-annex-configure takes advantage of. However, some settings are not propagated (i.e. can only be done when on the same machine), and thus have to be applied on a repository-by-repository basis:
- Remotes (including git-annex special remotes).
- Git config (not including git-annex config).
- Hooks.
git-annex-configure will only apply configurations of this nature for the repository that it is executed on, if any such configurations exist.
Here is a fairly basic setup with two client repositories:
(use-modules
(git-annex-configure git remote))
(configuration
(annex-config `(("annex.largefiles"
. ,(string-join
(list "exclude=.annex.scm"
"exclude=.gitignore"
"exclude=*/.gitignore")
" and "))
("annex.dotfiles"
. "true")))
(repositories
(list
(repository-configuration
(uuid "repository-1-uuid")
(description "repository 1!")
(groups
(list "client"))
(wanted "standard")
(remotes
(list (remote "repository-2" "/path/to/repository-2"))))
(repository-configuration
(uuid "repository-2-uuid")
(description "repository 2!")
(groups
(list "client"))
(wanted "standard")
(remotes
(list (remote "repository-1" "/path/to/repository-1")))))))
For comparison, the above configuration would be equivalent to the following script:
git-annex config --set annex.largefiles \
"exclude=.annex.scm and exclude=.gitignore and exclude=*/.gitignore"
git-annex config --set annex.dotfiles true
git-annex describe "repository-1-uuid" "repository 1!"
git-annex group "repository-1-uuid" client
git-annex wanted "repository-1-uuid" standard
git-annex describe "repository-2-uuid" "repository 2!"
git-annex group "repository-2-uuid" client
git-annex wanted "repository-2-uuid" standard
if [ $(git config annex.uuid) = repository-1-uuid ]; then
git remote add repository-2 /path/to/repository-2
elif [ $(git config annex.uuid) = repository-2-uuid ]; then
git remote add repository-1 /path/to/repository-1
fi
In addition to the above examples, this section gives one more example with comments describing the full configuration specification at a high level for easy reference of what settings exist and how to apply them. If you would like a lower-level reference, you might find it useful to start by examining spec.scm, which is where the configuration record definitions are located.
With the exception of repository UUIDs (if any repository-configuration is specified) - which are not modified, but used as identifiers - all settings are optional and may be omitted.
Omitted settings will not be touched, so existing settings may coexist with settings specified for git-annex-configure. Otherwise, expect that any specified setting will have its corresponding setting in the repository be modified or overwritten.
;; use-modules may be needed for certain procedures to be available.
(use-modules
;; included for use of `remote' constructor.
(git-annex-configure git remote)
;; included for use of `borg-remote' constructor.
(git-annex-configure git annex remotes))
;; This is the configuration record where all settings will be specified.
;; git-annex-configure expects the configuration file to evaluate to some
;; value constructed from `configuration'.
(configuration
;; git-annex config settings. Value should be an alist of setting names to
;; setting values.
(annex-config '(("config-key" . "config-value")
("other-config-key" . "other-config-value")))
;; git-annex groupwanted setting. Value should be an alist of group names to
;; matchexpressions.
(groupwanted '(("group1" . "group1 wanted matchexpression")
("group2" . "group2 wanted matchexpression")))
;; repository configurations. Value should be a list of repository
;; configurations, each made via `repository-configuration'.
(repositories
(list
(repository-configuration
;; git-annex repository UUID string. Obtained via `git config
;; annex.uuid'. Required to correctly identify repositories that will be
;; configured.
(uuid "repository-uuid")
;; Boolean telling git-annex-configure whether this repository
;; configuration is to be ignored when applying configurations.
(disabled? #t)
;; git-annex description string.
(description "example description")
;; git-annex wanted matchexpression string.
(wanted "wanted matchexpression")
;; git-annex required matchexpression string.
(required "required matchexpression")
;; git-annex groups. Value should be a list of groups.
(groups
(list "group1"
"group2"))
;; The rest of the configurations that can be specified with
;; repository-configuration (described below) can only apply if
;; git-annex-configure is executed on this repository with the same UUID
;; due to limitations mentioned in this README.
;; git remotes and git-annex special remotes. Value should be a list of
;; remotes. All possible remote types are listed below.
(remotes
(list
;; Normal git remote. Made using the `(remote name url)' procedure,
;; where name is a string specifying the remote name, and url is a
;; string specifying the remote url.
(remote "remote2-name" "remote2-url")
;; Borg special remote. Made with the procedure
;; `(borg-remote name #:borgrepo borgrepo #:subdir subdir
;; #:appendonly? appendonly)', where name is the borg remote name and
;; the rest are key arguments corresponding to the options in the borg
;; special remote documentation:
;; https://git-annex.branchable.com/special_remotes/borg/
(borg-remote "borg-remote-name"
#:borgrepo "borg repository url"
#:subdir "borg repo subdir"
#:appendonly? #t)))
;; git config. Value should be an alist of config keys to config values,
;; where keys and values must be strings.
(config '(("config1-key" . "config1-value")
("config2-key" . "config2-value")))
;; git hooks. Value should be an alist of hook script name strings to
;; quoted Guile expressions. A hook file script will be created with the
;; corresponding Guile expression inserted, which will then be executed
;; whenever the hook is called. Note that git-annex-configure does not
;; prevent you from overwriting other hook files, so be aware of what
;; hooks might already be used by git-annex.
(hooks '(("hook1-name"
. (begin
(display "the (begin ...) is required if...\n")
(display "...you want more than one expression")))
("hook2-name"
. (begin
(display "do stuff")))))))))
This project’s infrastructure and development is managed primarily using Guix.
In the project root directory, run the following to enter an environment with all the necessary dependencies:
guix shell
When you want to test your changes, you can run the following to build git-annex-configure and enter an environment with it included:
guix shell -f guix.scm
If you already have git-annex-configure installed, you should run the following instead to avoid using modules from the currently installed version:
guix shell --container -f guix.scm
Tests exist in ./tests
, however they are fairly basic at the moment and lack
instructions for ease of use due to a recent re-organization of the project
structure.