1
0
Fork 0
mirror of synced 2024-12-04 14:45:36 -05:00

Compare commits

..

13 commits

Author SHA1 Message Date
Ross Smith II
c15a9daa68
Merge 7ff657c7a5 into 640b324401 2024-11-10 02:35:34 +00:00
Ross Smith II
7ff657c7a5
Merge branch 'develop' into rasa/improve-template-logic 2024-11-09 18:35:32 -08:00
Erik Flodin
640b324401
Prepare for version 3.3.0
* Support nested ifs in default template (#436)
 * Support include and ifs in default template includes (#406)
 * Support environment variables in ifs in default template (#488)
 * Support != in default template (#358, #477)
 * Fix multiple classes in default template on macOS (#437)
2024-11-08 20:23:23 +01:00
Erik Flodin
8e5d4b1578
Pass classes as separate arguments to template_default
To work around problem with passing newlines in variable with awk on
darwin. This fixes #437.
2024-11-08 19:54:14 +01:00
Erik Flodin
d74a41b1b4
Merge pull request #497 from erijo/template-default
Rewrite default template to handle nested ifs, != and env vars in if
2024-11-06 22:25:40 +01:00
Erik Flodin
144f35b82d
Update links under .github/ to point to new github org 2024-11-04 23:12:28 +01:00
Erik Flodin
8ba9823407
Rewrite default template to handle nested ifs, != and env vars in if
The awk script now performs all processing in the BEGIN block using an
implementation that is capable of handling if statements which contain nested
if statments (fixes #436). To make nested ifs look better, if, else and endif
lines can now have optional whitespace before {%.

Includes are now handled in the same way as the main file which means that
included files can both include other files and have if statements in addition
to variables (fixes #406). Include lines can now also have optional whitespace
before {%.

All variables are handled in the same way now so it's now possible to use env
variables in if statements (fixes #488).

Also add support for != in addition to == (fixes #358). Thus it's now
e.g. possible to check if a variable is set (#477) by doing:

{% if yadm.class != ""%}
Class is set to {{ yadm.class }}
{% endif %}

A non-existing yadm or env variable is now replaced with the empty string.
2024-11-04 22:30:23 +01:00
Tim Byrne
6d3b9dac71
Merge branch 'move' 2024-10-31 15:41:38 -05:00
Tim Byrne
e097d16d88
Update docker image used by scheduled test 2024-10-31 15:37:40 -05:00
Tim Byrne
3ecbe7ec27
Merge branch 'move' (Updating location) 2024-10-30 17:55:49 -05:00
Tim Byrne
38880abc68
Update repo location 2024-10-30 17:18:49 -05:00
Tim Byrne
0a5e7aa353
Merge pull request #470 from LFd3v/master 2023-11-12 07:33:09 -06:00
LFdev
040dd461bd
Update Arch Linux badge in README.md
community repo was merged with extra, please refer to:

https://archlinux.org/news/git-migration-announcement/
https://archlinux.org/news/git-migration-completed/
2023-11-08 23:02:14 +00:00
20 changed files with 353 additions and 255 deletions

View file

@ -1,7 +1,7 @@
# Introduction
Thank you for considering contributing to **yadm**. I develop this project in my
limited spare time, so help is very appreciated.
Thank you for considering contributing to **yadm**. We develop this project in
our limited spare time, so help is very appreciated.
All contributors must follow our [Code of Conduct][conduct]. Please make sure
you are welcoming and friendly during your interactions, and report any
@ -17,7 +17,8 @@ To contribute, you can:
* Star the yadm repo, the star count helps others discover yadm.
* Report [bugs](#reporting-a-bug)
* Request [features/enhancements](#suggesting-a-feature-or-enhancement)
* Contribute changes to [code, tests](#contributing-code), and [documentation](#improving-documentation)
* Contribute changes to [code, tests](#contributing-code), and
[documentation](#improving-documentation)
* Maintain installation [packages](#maintaining-packages)
* Help other users by [answering support questions](#answering-support-questions)
@ -70,14 +71,14 @@ Consider trying to reproduce the bug inside a docker container using the
[yadm/testbed][] docker image. Doing so will greatly increase the likelihood of
the problem being fixed.
The easiest way to start this container, is to clone the [TheLocehiliosan/yadm
The easiest way to start this container, is to clone the [yadm
repo][yadm-repo], and use the `scripthost` make target. _(You will need `make`
and `docker` installed.)_
For example:
```text
$ git clone https://github.com/TheLocehiliosan/yadm.git
$ git clone https://github.com/yadm-dev/yadm.git
$ cd yadm
$ make scripthost version=1.12.0
Starting scripthost version="1.12.0" (recording script)
@ -203,7 +204,7 @@ these principles when making changes.
3. Add the official repository (`upstream`) as a remote repository.
```text
$ git remote add upstream https://github.com/TheLocehiliosan/yadm.git
$ git remote add upstream https://github.com/yadm-dev/yadm.git
```
4. Verify you can run the test harness. _(This will require dependencies:
@ -361,25 +362,24 @@ see if you can help.
[attach-help]: https://help.github.com/en/articles/file-attachments-on-issues-and-pull-requests
[commit-style]: https://chris.beams.io/posts/git-commit/#seven-rules
[conduct]: CODE_OF_CONDUCT.md
[contrib-hooks]: https://github.com/TheLocehiliosan/yadm/tree/master/contrib/hooks
[contrib-hooks]: https://github.com/yadm-dev/yadm/tree/master/contrib/hooks
[flake8]: https://pypi.org/project/flake8/
[groff-man]: https://www.gnu.org/software/groff/manual/html_node/man.html
[hooks-help]: https://github.com/TheLocehiliosan/yadm/blob/master/yadm.md#hooks
[hooks-help]: https://github.com/yadm-dev/yadm/blob/master/yadm.md#hooks
[html-proofer]: https://github.com/gjtorikian/html-proofer
[jekyll]: https://jekyllrb.com
[new-bug]: https://github.com/TheLocehiliosan/yadm/issues/new?template=BUG_REPORT.md
[new-feature]: https://github.com/TheLocehiliosan/yadm/issues/new?template=FEATURE_REQUEST.md
[open-issues]: https://github.com/TheLocehiliosan/yadm/issues
[new-bug]: https://github.com/yadm-dev/yadm/issues/new?template=BUG_REPORT.md
[new-feature]: https://github.com/yadm-dev/yadm/issues/new?template=FEATURE_REQUEST.md
[open-issues]: https://github.com/yadm-dev/yadm/issues
[pr-help]: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork
[pylint]: https://pylint.org/
[pytest]: https://pytest.org/
[questions]: https://github.com/TheLocehiliosan/yadm/labels/question
[refactor]: https://github.com/TheLocehiliosan/yadm/issues/146
[questions]: https://github.com/yadm-dev/yadm/labels/question
[shellcheck]: https://www.shellcheck.net
[signing-commits]: https://help.github.com/en/articles/signing-commits
[tpope-style]: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[yadm-man]: https://github.com/TheLocehiliosan/yadm/blob/master/yadm.md
[yadm-repo]: https://github.com/TheLocehiliosan/yadm
[yadm-man]: https://github.com/yadm-dev/yadm/blob/master/yadm.md
[yadm-repo]: https://github.com/yadm-dev/yadm
[yadm/jekyll]: https://hub.docker.com/r/yadm/jekyll
[yadm/testbed]: https://hub.docker.com/r/yadm/testbed
[yamllint]: https://github.com/adrienverge/yamllint

View file

@ -1,6 +1,6 @@
<!--
Before submitting, please search open and closed issues at
https://github.com/TheLocehiliosan/yadm/issues to avoid duplication.
https://github.com/yadm-dev/yadm/issues to avoid duplication.
If you have found a security vulnerability, do NOT open an issue.
Email yadm@yadm.io instead.

View file

@ -8,7 +8,7 @@ assignees: ''
---
<!--
Before submitting, please search open and closed issues at
https://github.com/TheLocehiliosan/yadm/issues to avoid duplication.
https://github.com/yadm-dev/yadm/issues to avoid duplication.
If you have found a security vulnerability, do NOT open an issue.
Email yadm@yadm.io instead.
@ -25,10 +25,10 @@ Can this be reproduced with the yadm/testbed docker image: [Yes/No]
Consider trying to reproduce the bug inside a docker container using the
yadm/testbed docker image. https://hub.docker.com/r/yadm/testbed
The easiest way to start this container, is to clone the TheLocehiliosan/yadm
The easiest way to start this container, is to clone the yadm-dev/yadm
repo, and use the "scripthost" make target. For example:
$ git clone https://github.com/TheLocehiliosan/yadm.git
$ git clone https://github.com/yadm-dev/yadm.git
$ cd yadm
$ make scripthost version=1.11.0
Starting scripthost version="1.11.0" (recording script)

View file

@ -8,7 +8,7 @@ assignees: ''
---
<!--
Before submitting, please search open and closed issues at
https://github.com/TheLocehiliosan/yadm/issues to avoid duplication.
https://github.com/yadm-dev/yadm/issues to avoid duplication.
-->
### Is your feature request related to a problem? Please describe.

View file

@ -8,7 +8,7 @@ assignees: ''
---
<!--
Before submitting, please search open and closed issues at
https://github.com/TheLocehiliosan/yadm/issues to avoid duplication.
https://github.com/yadm-dev/yadm/issues to avoid duplication.
-->
### This issue is about

View file

@ -8,11 +8,11 @@ assignees: ''
---
<!--
Before submitting, please search open and closed issues at
https://github.com/TheLocehiliosan/yadm/issues to avoid duplication.
https://github.com/yadm-dev/yadm/issues to avoid duplication.
Please also consult:
* The FAQ: https://yadm.io/docs/faq
* The manual: https://github.com/TheLocehiliosan/yadm/blob/master/yadm.md
* The manual: https://github.com/yadm-dev/yadm/blob/master/yadm.md
-->
### This question is about

View file

@ -29,6 +29,6 @@ Be sure to preface the issue/PR numbers with a "#".
Please review [yadm's Contributing Guide][3] for best practices.
[1]: https://github.com/TheLocehiliosan/yadm/blob/master/.github/CONTRIBUTING.md#test-conventions
[1]: https://github.com/yadm-dev/yadm/blob/master/.github/CONTRIBUTING.md#test-conventions
[2]: https://help.github.com/en/articles/signing-commits
[3]: https://github.com/TheLocehiliosan/yadm/blob/master/.github/CONTRIBUTING.md
[3]: https://github.com/yadm-dev/yadm/blob/master/.github/CONTRIBUTING.md

View file

@ -14,7 +14,7 @@ jobs:
docker create -t
--name yadm-website
--entrypoint test/validate
yadm/jekyll:2019-10-17;
yadm/jekyll:2024-10-31;
docker cp ./ yadm-website:/srv/jekyll
- name: Test Site
run: docker start yadm-website -a

View file

@ -1,3 +1,10 @@
3.3.0
* Support nested ifs in default template (#436)
* Support include and ifs in default template includes (#406)
* Support environment variables in ifs in default template (#488)
* Support != in default template (#358, #477)
* Fix multiple classes in default template on macOS (#437)
3.2.2
* Support spaces in distro/distro-family (#432)
* Fix zsh hanging when tab completing add/checkout (#417)

View file

@ -25,9 +25,9 @@ Paulo Köch
Oren Zipori
Daniel Gray
Paraplegic Racehorse
japm48
Siôn Le Roux
Mateusz Piotrowski
japm48
Uroš Golja
Satoshi Ohki
Jonas
@ -35,18 +35,20 @@ Franciszek Madej
Daniel Wagenknecht
Stig Palmquist
Patrick Hof
con-f-use
Samisafool
LFdev
con-f-use
Bram Ceulemans
Travis A. Everett
Sheng Yang
Jared Smartt
Adam Jimerson
dessert1
addshore
Tim Condit
Thomas Luzat
Russ Allbery
Patrick Roddy
dessert1
Brayden Banks
Alexandre GV
addshore
Felipe S. S. Schneider

View file

@ -56,32 +56,31 @@ The star count helps others discover yadm.
[Git]: https://git-scm.com/
[GnuPG]: https://gnupg.org/
[OpenSSL]: https://www.openssl.org/
[arch-badge]: https://img.shields.io/archlinux/v/community/any/yadm
[arch-link]: https://archlinux.org/packages/community/any/yadm/
[dev-pages-badge]: https://img.shields.io/github/actions/workflow/status/TheLocehiliosan/yadm/test.yml?branch=dev-pages
[develop-badge]: https://img.shields.io/github/actions/workflow/status/TheLocehiliosan/yadm/test.yml?branch=develop
[develop-commits]: https://github.com/TheLocehiliosan/yadm/commits/develop
[develop-date]: https://img.shields.io/github/last-commit/TheLocehiliosan/yadm/develop.svg?label=develop
[arch-badge]: https://img.shields.io/archlinux/v/extra/any/yadm
[arch-link]: https://archlinux.org/packages/extra/any/yadm/
[dev-pages-badge]: https://img.shields.io/github/actions/workflow/status/yadm-dev/yadm/test.yml?branch=dev-pages
[develop-badge]: https://img.shields.io/github/actions/workflow/status/yadm-dev/yadm/test.yml?branch=develop
[develop-commits]: https://github.com/yadm-dev/yadm/commits/develop
[develop-date]: https://img.shields.io/github/last-commit/yadm-dev/yadm/develop.svg?label=develop
[dotfiles]: https://en.wikipedia.org/wiki/Hidden_file_and_hidden_directory
[gh-pages-badge]: https://img.shields.io/github/actions/workflow/status/TheLocehiliosan/yadm/test.yml?branch=gh-pages
[gh-pages-badge]: https://img.shields.io/github/actions/workflow/status/yadm-dev/yadm/test.yml?branch=gh-pages
[git-crypt]: https://github.com/AGWA/git-crypt
[homebrew-badge]: https://img.shields.io/homebrew/v/yadm.svg
[homebrew-link]: https://formulae.brew.sh/formula/yadm
[license-badge]: https://img.shields.io/github/license/TheLocehiliosan/yadm.svg
[license-link]: https://github.com/TheLocehiliosan/yadm/blob/master/LICENSE
[master-badge]: https://img.shields.io/github/actions/workflow/status/TheLocehiliosan/yadm/test.yml?branch=master
[master-commits]: https://github.com/TheLocehiliosan/yadm/commits/master
[master-date]: https://img.shields.io/github/last-commit/TheLocehiliosan/yadm/master.svg?label=master
[obs-badge]: https://img.shields.io/badge/OBS-v3.2.2-blue
[license-badge]: https://img.shields.io/github/license/yadm-dev/yadm.svg
[license-link]: https://github.com/yadm-dev/yadm/blob/master/LICENSE
[master-badge]: https://img.shields.io/github/actions/workflow/status/yadm-dev/yadm/test.yml?branch=master
[master-commits]: https://github.com/yadm-dev/yadm/commits/master
[master-date]: https://img.shields.io/github/last-commit/yadm-dev/yadm/master.svg?label=master
[obs-badge]: https://img.shields.io/badge/OBS-v3.3.0-blue
[obs-link]: https://software.opensuse.org//download.html?project=home%3ATheLocehiliosan%3Ayadm&package=yadm
[releases-badge]: https://img.shields.io/github/tag/TheLocehiliosan/yadm.svg?label=latest+release
[releases-link]: https://github.com/TheLocehiliosan/yadm/releases
[releases-badge]: https://img.shields.io/github/tag/yadm-dev/yadm.svg?label=latest+release
[releases-link]: https://github.com/yadm-dev/yadm/releases
[transcrypt]: https://github.com/elasticdog/transcrypt
[travis-ci]: https://travis-ci.com/TheLocehiliosan/yadm/branches
[website-commits]: https://github.com/TheLocehiliosan/yadm/commits/gh-pages
[website-date]: https://img.shields.io/github/last-commit/TheLocehiliosan/yadm/gh-pages.svg?label=website
[website-commits]: https://github.com/yadm-dev/yadm/commits/gh-pages
[website-date]: https://img.shields.io/github/last-commit/yadm-dev/yadm/gh-pages.svg?label=website
[website-link]: https://yadm.io/
[workflow-dev-pages]: https://github.com/thelocehiliosan/yadm/actions?query=workflow%3a%22test+site%22+branch%3adev-pages
[workflow-develop]: https://github.com/TheLocehiliosan/yadm/actions?query=workflow%3ATests+branch%3Adevelop
[workflow-gh-pages]: https://github.com/thelocehiliosan/yadm/actions?query=workflow%3a%22test+site%22+branch%3agh-pages
[workflow-master]: https://github.com/TheLocehiliosan/yadm/actions?query=workflow%3ATests+branch%3Amaster
[workflow-dev-pages]: https://github.com/yadm-dev/yadm/actions?query=workflow%3a%22test+site%22+branch%3adev-pages
[workflow-develop]: https://github.com/yadm-dev/yadm/actions?query=workflow%3ATests+branch%3Adevelop
[workflow-gh-pages]: https://github.com/yadm-dev/yadm/actions?query=workflow%3a%22test+site%22+branch%3agh-pages
[workflow-master]: https://github.com/yadm-dev/yadm/actions?query=workflow%3ATests+branch%3Amaster

View file

@ -29,7 +29,7 @@
# source <(curl -L bootstrap.yadm.io)
#
YADM_REPO="https://github.com/TheLocehiliosan/yadm"
YADM_REPO="https://github.com/yadm-dev/yadm"
YADM_RELEASE=${release:-master}
REPO_URL=""

View file

@ -39,7 +39,7 @@ Load `_yadm` as a plugin in your `.zshrc`:
```zsh
fpath=("$ZPLUG_HOME/bin" $fpath)
zplug "TheLocehiliosan/yadm", use:"completion/zsh/_yadm", as:command, defer:2
zplug "yadm-dev/yadm", use:"completion/zsh/_yadm", as:command, defer:2
```
## Fish (manual installation)

View file

@ -11,4 +11,4 @@ this is a place to share it.
I recommend *careful review* of any code from here before using it. No
guarantees of code quality is assumed.
[hooks-help]: https://github.com/TheLocehiliosan/yadm/blob/master/yadm.md#hooks
[hooks-help]: https://github.com/yadm-dev/yadm/blob/master/yadm.md#hooks

View file

@ -57,8 +57,8 @@ RUN mkdir /yadm \
&& echo "\t@false" >> /yadm/Makefile
# Include released versions of yadm to test upgrades
ADD https://raw.githubusercontent.com/TheLocehiliosan/yadm/1.12.0/yadm /usr/local/bin/yadm-1.12.0
ADD https://raw.githubusercontent.com/TheLocehiliosan/yadm/2.5.0/yadm /usr/local/bin/yadm-2.5.0
ADD https://raw.githubusercontent.com/yadm-dev/yadm/1.12.0/yadm /usr/local/bin/yadm-1.12.0
ADD https://raw.githubusercontent.com/yadm-dev/yadm/2.5.0/yadm /usr/local/bin/yadm-2.5.0
RUN chmod +x /usr/local/bin/yadm-*
# Configure git to make it easier to test yadm manually

View file

@ -1,4 +1,5 @@
"""Unit tests: template_default"""
import os
FILE_MODE = 0o754
@ -12,6 +13,7 @@ LOCAL_HOST = "default_Test+@-!^Host"
LOCAL_USER = "default_Test+@-!^User"
LOCAL_DISTRO = "default_Test+@-!^Distro"
LOCAL_DISTRO_FAMILY = "default_Test+@-!^Family"
ENV_VAR = "default_Test+@-!^Env"
TEMPLATE = f"""
start of template
default class = >{{{{yadm.class}}}}<
@ -30,6 +32,9 @@ Included section from else
{{% if yadm.class == "wrongclass1" %}}
wrong class 1
{{% endif %}}
{{% if yadm.class != "wronglcass" %}}
Included section from !=
{{% endif\t\t %}}
{{% if yadm.class == "{LOCAL_CLASS}" %}}
Included section for class = {{{{yadm.class}}}} ({{{{yadm.class}}}} repeated)
Multiple lines
@ -97,6 +102,13 @@ Included section for distro_family = \
{{% if yadm.distro_family == "wrongfamily2" %}}
wrong family 2
{{% endif %}}
{{% if env.VAR == "{ENV_VAR}" %}}
Included section for env.VAR = {{{{env.VAR}}}} ({{{{env.VAR}}}} again)
{{% endif %}}
{{% if env.VAR == "wrongenvvar" %}}
wrong env.VAR
{{% endif %}}
yadm.no_such_var="{{{{ yadm.no_such_var }}}}" and env.NO_SUCH_VAR="{{{{ env.NO_SUCH_VAR }}}}"
end of template
"""
EXPECTED = f"""
@ -111,6 +123,7 @@ default distro_family = >{LOCAL_DISTRO_FAMILY}<
classes = >{LOCAL_CLASS2}
{LOCAL_CLASS}<
Included section from else
Included section from !=
Included section for class = {LOCAL_CLASS} ({LOCAL_CLASS} repeated)
Multiple lines
Included section for second class
@ -121,6 +134,8 @@ Included section for user = {LOCAL_USER} ({LOCAL_USER} repeated)
Included section for distro = {LOCAL_DISTRO} ({LOCAL_DISTRO} again)
Included section for distro_family = \
{LOCAL_DISTRO_FAMILY} ({LOCAL_DISTRO_FAMILY} again)
Included section for env.VAR = {ENV_VAR} ({ENV_VAR} again)
yadm.no_such_var="" and env.NO_SUCH_VAR=""
end of template
"""
@ -138,7 +153,7 @@ The first line
An empty file removes the line above
{%include basic%}
{% include "./variables.{{ yadm.os }}" %}
{% include dir/nested %}
{% include dir/nested %}
Include basic again:
{% include basic %}
"""
@ -154,6 +169,42 @@ Include basic again:
basic
"""
TEMPLATE_NESTED_IFS = """\
{% if yadm.user == "me" %}
print1
{% if yadm.user == "me" %}
print2
{% else %}
no print1
{% endif %}
{% else %}
{% if yadm.user == "me" %}
no print2
{% else %}
no print3
{% endif %}
{% endif %}
{% if yadm.user != "me" %}
no print4
{% if yadm.user == "me" %}
no print5
{% else %}
no print6
{% endif %}
{% else %}
{% if yadm.user == "me" %}
print3
{% else %}
no print7
{% endif %}
{% endif %}
"""
EXPECTED_NESTED_IFS = """\
print1
print2
print3
"""
def test_template_default(runner, yadm, tmpdir):
"""Test template_default"""
@ -182,7 +233,7 @@ def test_template_default(runner, yadm, tmpdir):
local_distro_family="{LOCAL_DISTRO_FAMILY}"
template_default "{input_file}" "{output_file}"
"""
run = runner(command=["bash"], inp=script)
run = runner(command=["bash"], inp=script, env={"VAR": ENV_VAR})
assert run.success
assert run.err == ""
assert output_file.read() == EXPECTED
@ -243,12 +294,30 @@ def test_include(runner, yadm, tmpdir):
assert os.stat(output_file).st_mode == os.stat(input_file).st_mode
def test_nested_ifs(runner, yadm, tmpdir):
"""Test nested if statements"""
input_file = tmpdir.join("input")
input_file.write(TEMPLATE_NESTED_IFS, ensure=True)
output_file = tmpdir.join("output")
script = f"""
YADM_TEST=1 source {yadm}
set_awk
local_user="me"
template_default "{input_file}" "{output_file}"
"""
run = runner(command=["bash"], inp=script)
assert run.success
assert run.err == ""
assert output_file.read() == EXPECTED_NESTED_IFS
def test_env(runner, yadm, tmpdir):
"""Test env"""
input_file = tmpdir.join("input")
input_file.write("{{env.PWD}}", ensure=True)
input_file.chmod(FILE_MODE)
output_file = tmpdir.join("output")
script = f"""

183
yadm
View file

@ -1,6 +1,6 @@
#!/bin/sh
# yadm - Yet Another Dotfiles Manager
# Copyright (C) 2015-2023 Tim Byrne
# Copyright (C) 2015-2024 Tim Byrne
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -21,7 +21,7 @@ if [ -z "$BASH_VERSION" ]; then
[ "$YADM_TEST" != 1 ] && exec bash "$0" "$@"
fi
VERSION=3.2.2
VERSION=3.3.0
YADM_WORK="$HOME"
YADM_DIR=
@ -368,93 +368,119 @@ function template_default() {
# the explicit "space + tab" character class used below is used because not
# all versions of awk seem to support the POSIX character classes [[:blank:]]
read -r -d '' awk_pgm << "EOF"
# built-in default template processor
BEGIN {
blank = "[ ]"
c["class"] = class
c["classes"] = classes
c["arch"] = arch
c["os"] = os
c["hostname"] = host
c["user"] = user
c["distro"] = distro
c["distro_family"] = distro_family
c["source"] = source
ifs = "^{%" blank "*if"
els = "^{%" blank "*else" blank "*%}$"
end = "^{%" blank "*endif" blank "*%}$"
skp = "^{%" blank "*(if|else|endif)"
vld = conditions()
inc_start = "^{%" blank "*include" blank "+\"?"
inc_end = "\"?" blank "*%}$"
inc = inc_start ".+" inc_end
prt = 1
err = 0
}
END { exit err }
{ replace_vars() } # variable replacements
$0 ~ vld, $0 ~ end {
if ($0 ~ vld || $0 ~ end) prt=1;
if ($0 ~ els) prt=0;
if ($0 ~ skp) next;
}
($0 ~ ifs && $0 !~ vld), $0 ~ end {
if ($0 ~ ifs && $0 !~ vld) prt=0;
if ($0 ~ els || $0 ~ end) prt=1;
if ($0 ~ skp) next;
}
{ if (!prt) next }
$0 ~ inc {
file = $0
sub(inc_start, "", file)
sub(inc_end, "", file)
sub(/^[^\/].*$/, source_dir "/&", file)
classes = ARGV[2]
for (i = 3; i < ARGC; ++i) {
classes = classes "\n" ARGV[i]
}
yadm["class"] = class
yadm["classes"] = classes
yadm["arch"] = arch
yadm["os"] = os
yadm["hostname"] = host
yadm["user"] = user
yadm["distro"] = distro
yadm["distro_family"] = distro_family
yadm["source"] = source
while ((res = getline <file) > 0) {
replace_vars()
print
VARIABLE = "(env|yadm)\\.[a-zA-Z0-9_]+"
current = 0
filename[current] = ARGV[1]
line[current] = 0
level = 0
skip[level] = 0
for (; current >= 0; --current) {
while ((res = getline <filename[current]) > 0) {
++line[current]
if ($0 ~ "^[ \t]*\\{%[ \t]*if[ \t]+" VARIABLE "[ \t]*[!=]=[ \t]*\".*\"[ \t]*%\\}$") {
if (skip[level]) { skip[++level] = 1; continue }
match($0, VARIABLE)
lhs = substr($0, RSTART, RLENGTH)
match($0, /[!=]=/)
op = substr($0, RSTART, RLENGTH)
match($0, /".*"/)
rhs = replace_vars(substr($0, RSTART + 1, RLENGTH - 2))
if (lhs == "yadm.class") {
lhs = "not" rhs
split(classes, cls_array, "\n")
for (idx in cls_array) {
if (rhs == cls_array[idx]) { lhs = rhs; break }
}
}
else {
lhs = replace_vars("{{" lhs "}}")
}
if (op == "==") { skip[++level] = lhs != rhs }
else { skip[++level] = lhs == rhs }
}
else if (/^[ \t]*\{%[ \t]*else[ \t]*%\}$/) {
if (level == 0 || skip[level] < 0) { error("else without matching if") }
skip[level] = skip[level] ? skip[level - 1] : -1
}
else if (/^[ \t]*\{%[ \t]*endif[ \t]*%\}$/) {
if (--level < 0) { error("endif without matching if") }
}
else if (!skip[level]) {
$0 = replace_vars($0)
if (match($0, /^[ \t]*\{%[ \t]*include[ \t]+("[^"]+"|[^"]+)[ \t]*%\}$/)) {
include = $0
sub(/^[ \t]*\{%[ \t]*include[ \t]+"?/, "", include)
sub(/"?[ \t]*%\}$/, "", include)
if (index(include, "/") != 1) {
include = source_dir "/" include
}
filename[++current] = include
line[current] = 0
}
else { print }
}
}
if (res >= 0) { close(filename[current]) }
else if (current == 0) { error("could not read input file") }
else { --current; error("could not read include file '" filename[current + 1] "'") }
}
if (res < 0) {
printf "%s:%d: error: could not read '%s'\n", FILENAME, NR, file | "cat 1>&2"
err = 1
if (level > 0) {
current = 0
error("unterminated if")
}
close(file)
next
exit 0
}
{ print }
function replace_vars() {
for (label in c) {
gsub(("{{" blank "*yadm\\." label blank "*}}"), c[label])
}
for (label in ENVIRON) {
gsub(("{{" blank "*env\\." label blank "*}}"), ENVIRON[label])
}
function error(text) {
printf "%s:%d: error: %s\n",
filename[current], line[current], text > "/dev/stderr"
exit 1
}
function condition_helper(label, value) {
gsub(/[\\.^$(){}\[\]|*+?]/, "\\\\&", value)
return sprintf("yadm\\.%s" blank "*==" blank "*\"%s\"", label, value)
}
function conditions() {
pattern = ifs blank "+("
for (label in c) {
if (label != "class") {
value = c[label]
pattern = sprintf("%s%s|", pattern, condition_helper(label, value));
function replace_vars(input) {
output = ""
while (match(input, "\\{\\{[ \t]*" VARIABLE "[ \t]*\\}\\}")) {
if (RSTART > 1) {
output = output substr(input, 0, RSTART - 1)
}
data = substr(input, RSTART + 2, RLENGTH - 4)
input = substr(input, RSTART + RLENGTH)
gsub(/[ \t]+/, "", data)
split(data, fields, /\./)
if (fields[1] == "env") {
output = output ENVIRON[fields[2]]
}
else {
output = output yadm[fields[2]]
}
}
split(classes, cls_array, "\n")
for (idx in cls_array) {
value = cls_array[idx]
pattern = sprintf("%s%s|", pattern, condition_helper("class", value));
}
sub(/\|$/, ")" blank "*%}$", pattern)
return pattern
return output input
}
EOF
local source_dir yadm_classes content
local source_dir content
source_dir=$(dirname "$input")
yadm_classes=$(join_string $'\n' "${local_classes[@]}")
content=$("${AWK_PROGRAM[0]}" \
-v class="$local_class" \
-v arch="$local_arch" \
@ -465,9 +491,8 @@ EOF
-v distro_family="$local_distro_family" \
-v source="$input" \
-v source_dir="$source_dir" \
-v classes="$yadm_classes" \
"$awk_pgm" \
"$input")
"$input" "${local_classes[@]}")
move_file "$input" "$output" "$content"
}

4
yadm.1
View file

@ -1,5 +1,5 @@
.\" vim: set spell so=8:
.TH yadm 1 "23 January 2023" "3.2.2"
.TH yadm 1 "8 November 2024" "3.3.0"
.SH NAME
@ -989,7 +989,7 @@ Commit a new set of encrypted files
Report issues or create pull requests at GitHub:
https://github.com/TheLocehiliosan/yadm/issues
https://github.com/yadm-dev/yadm/issues
.SH AUTHOR

222
yadm.md
View file

@ -1,6 +1,4 @@
## NAME
yadm - Yet Another Dotfiles Manager
@ -56,17 +54,17 @@
aged repository. The working directory for Git commands will be
the configured work-tree (usually $HOME).
Dotfiles are managed by using standard git commands; add, com
Dotfiles are managed by using standard git commands; add, com
mit, push, pull, etc.
The config command is not passed directly through. Instead use
The config command is not passed directly through. Instead use
the gitconfig command (see below).
alt Create symbolic links and process templates for any managed
files matching the naming rules described in the ALTERNATES and
TEMPLATES sections. It is usually unnecessary to run this com
mand, as yadm automatically processes alternates by default.
This automatic behavior can be disabled by setting the configu
alt Create symbolic links and process templates for any managed
files matching the naming rules described in the ALTERNATES and
TEMPLATES sections. It is usually unnecessary to run this com
mand, as yadm automatically processes alternates by default.
This automatic behavior can be disabled by setting the configu
ration yadm.auto-alt to "false".
bootstrap
@ -82,12 +80,12 @@
The repository is stored in $HOME/.local/share/yadm/repo.git.
By default, $HOME will be used as the work-tree, but this can be
overridden with the -w option. yadm can be forced to overwrite
an existing repository by providing the -f option. If you want
to use a branch other than the remote HEAD branch you can spec
ify it using the -b option. By default yadm will ask the user
if the bootstrap program should be run (if it exists). The op
tions --bootstrap or --no-bootstrap will either force the boot
overridden with the -w option. yadm can be forced to overwrite
an existing repository by providing the -f option. If you want
to use a branch other than the remote HEAD branch you can spec
ify it using the -b option. By default yadm will ask the user
if the bootstrap program should be run (if it exists). The op
tions --bootstrap or --no-bootstrap will either force the boot
strap to be run, or prevent it from being run, without prompting
the user.
@ -96,8 +94,8 @@
section for more details.
decrypt
Decrypt all files stored in $HOME/.local/share/yadm/archive.
Files decrypted will be relative to the configured work-tree
Decrypt all files stored in $HOME/.local/share/yadm/archive.
Files decrypted will be relative to the configured work-tree
(usually $HOME). Using the -l option will list the files stored
without extracting them.
@ -135,28 +133,28 @@
use the yadm repository.
git-crypt enables transparent encryption and decryption of files
in a git repository. You can read https://github.com/AGWA/git-
in a git repository. You can read https://github.com/AGWA/git-
crypt for details.
gitconfig
Pass options to the git config command. Since yadm already uses
the config command to manage its own configurations, this com
Pass options to the git config command. Since yadm already uses
the config command to manage its own configurations, this com
mand is provided as a way to change configurations of the repos
itory managed by yadm. One useful case might be to configure
the repository so untracked files are shown in status commands.
yadm initially configures its repository so that untracked files
are not shown. If you wish use the default Git behavior (to
show untracked files and directories), you can remove this con
are not shown. If you wish use the default Git behavior (to
show untracked files and directories), you can remove this con
figuration.
yadm gitconfig --unset status.showUntrackedFiles
help Print a summary of yadm commands.
init Initialize a new, empty repository for tracking dotfiles. The
repository is stored in $HOME/.local/share/yadm/repo.git. By
default, $HOME will be used as the work-tree, but this can be
overridden with the -w option. yadm can be forced to overwrite
init Initialize a new, empty repository for tracking dotfiles. The
repository is stored in $HOME/.local/share/yadm/repo.git. By
default, $HOME will be used as the work-tree, but this can be
overridden with the -w option. yadm can be forced to overwrite
an existing repository by providing the -f option.
list Print a list of files managed by yadm. The -a option will cause
@ -168,14 +166,14 @@
configs, repo, and switches. The purpose of introspection is to
support command line completion.
perms Update permissions as described in the PERMISSIONS section. It
is usually unnecessary to run this command, as yadm automati
cally processes permissions by default. This automatic behavior
can be disabled by setting the configuration yadm.auto-perms to
perms Update permissions as described in the PERMISSIONS section. It
is usually unnecessary to run this command, as yadm automati
cally processes permissions by default. This automatic behavior
can be disabled by setting the configuration yadm.auto-perms to
"false".
transcrypt options
If transcrypt is installed, this command allows you to pass op
If transcrypt is installed, this command allows you to pass op
tions directly to transcrypt, with the environment configured to
use the yadm repository.
@ -187,16 +185,16 @@
Version 3 of yadm uses a different directory for storing data.
When you start to use version 3 for the first time, you may see
warnings about moving your data to this new directory. The eas
iest way to accomplish this is by running "yadm upgrade". This
command will start by moving your yadm repo to the new path.
Next it will move any archive data. If the archive is tracked
iest way to accomplish this is by running "yadm upgrade". This
command will start by moving your yadm repo to the new path.
Next it will move any archive data. If the archive is tracked
within your yadm repo, this command will "stage" the renaming of
that file in the repo's index.
Upgrading will attempt to de-initialize and re-initialize your
submodules. If your submodules cannot be de-initialized, the up
grade will fail. The most common reason submodules will fail to
de-initialize is because they have local modifications. If you
grade will fail. The most common reason submodules will fail to
de-initialize is because they have local modifications. If you
are willing to lose the local modifications to those submodules,
you can use the -f option with the "upgrade" command to force
the de-initialization.
@ -213,20 +211,20 @@
## OPTIONS
yadm supports a set of universal options that alter the paths it uses.
The default paths are documented in the FILES section. Any path speci
fied by these options must be fully qualified. If you always want to
override one or more of these paths, it may be useful to create an
alias for the yadm command. For example, the following alias could be
yadm supports a set of universal options that alter the paths it uses.
The default paths are documented in the FILES section. Any path speci
fied by these options must be fully qualified. If you always want to
override one or more of these paths, it may be useful to create an
alias for the yadm command. For example, the following alias could be
used to override the repository directory.
alias yadm='yadm --yadm-repo /alternate/path/to/repo'
The following is the full list of universal options. Each option
The following is the full list of universal options. Each option
should be followed by a path.
-Y,--yadm-dir
Override the yadm directory. yadm stores its configurations
Override the yadm directory. yadm stores its configurations
relative to this directory.
--yadm-data
@ -291,40 +289,40 @@
TION.
yadm.git-program
Specify an alternate program to use instead of "git". By de
Specify an alternate program to use instead of "git". By de
fault, the first "git" found in $PATH is used.
yadm.gpg-perms
Disable the permission changes to $HOME/.gnupg/*. This feature
Disable the permission changes to $HOME/.gnupg/*. This feature
is enabled by default.
yadm.gpg-program
Specify an alternate program to use instead of "gpg". By de
Specify an alternate program to use instead of "gpg". By de
fault, the first "gpg" found in $PATH is used.
yadm.gpg-recipient
Asymmetrically encrypt files with a gpg public/private key pair.
Provide a "key ID" to specify which public key to encrypt with.
The key must exist in your public keyrings. Multiple recipients
can be specified (separated by space). If left blank or not
provided, symmetric encryption is used instead. If set to
"ASK", gpg will interactively ask for recipients. See the EN
CRYPTION section for more details. This feature is disabled by
can be specified (separated by space). If left blank or not
provided, symmetric encryption is used instead. If set to
"ASK", gpg will interactively ask for recipients. See the EN
CRYPTION section for more details. This feature is disabled by
default.
yadm.openssl-ciphername
Specify which cipher should be used by openssl. "aes-256-cbc"
Specify which cipher should be used by openssl. "aes-256-cbc"
is used by default.
yadm.openssl-old
Newer versions of openssl support the pbkdf2 key derivation
function. This is used by default. If this configuration is set
to "true", openssl operations will use options compatible with
older versions of openssl. If you change this option, you will
Newer versions of openssl support the pbkdf2 key derivation
function. This is used by default. If this configuration is set
to "true", openssl operations will use options compatible with
older versions of openssl. If you change this option, you will
need to recreate your encrypted archive.
yadm.openssl-program
Specify an alternate program to use instead of "openssl". By
Specify an alternate program to use instead of "openssl". By
default, the first "openssl" found in $PATH is used.
yadm.ssh-perms
@ -343,11 +341,11 @@
yadm config --add local.class <additional-class>
local.arch
Override the architecture for the purpose of symlinking alter
Override the architecture for the purpose of symlinking alter
nate files.
local.hostname
Override the hostname for the purpose of symlinking alternate
Override the hostname for the purpose of symlinking alternate
files.
local.os
@ -362,9 +360,9 @@
to have an automated way of choosing an alternate version of a file for
a different operating system, host, user, etc.
yadm will automatically create a symbolic link to the appropriate ver
sion of a file, when a valid suffix is appended to the filename. The
suffix contains the conditions that must be met for that file to be
yadm will automatically create a symbolic link to the appropriate ver
sion of a file, when a valid suffix is appended to the filename. The
suffix contains the conditions that must be met for that file to be
used.
The suffix begins with "##", followed by any number of conditions sepa
@ -384,11 +382,11 @@
template, t
Valid when the value matches a supported template processor.
Valid when the value matches a supported template processor.
See the TEMPLATES section for more details.
user, u
Valid if the value matches the current user. Current user is
Valid if the value matches the current user. Current user is
calculated by running id -u -n.
hostname, h
@ -407,14 +405,14 @@
lease.
distro_family, f
Valid if the value matches the distro family. Distro family is
Valid if the value matches the distro family. Distro family is
calculated by inspecting the ID_LIKE line from /etc/os-release.
os, o Valid if the value matches the OS. OS is calculated by running
os, o Valid if the value matches the OS. OS is calculated by running
uname -s.
arch, a
Valid if the value matches the architecture. Architecture is
Valid if the value matches the architecture. Architecture is
calculated by running uname -m.
default
@ -423,16 +421,16 @@
extension, e
A special "condition" that doesn't affect the selection process.
Its purpose is instead to allow the alternate file to end with a
certain extension to e.g. make editors highlight the content
certain extension to e.g. make editors highlight the content
properly.
NOTE: The OS for "Windows Subsystem for Linux" is reported as "WSL",
NOTE: The OS for "Windows Subsystem for Linux" is reported as "WSL",
even though uname identifies as "Linux".
You may use any number of conditions, in any order. An alternate will
only be used if ALL conditions are valid. For all files managed by
yadm's repository or listed in $HOME/.config/yadm/encrypt, if they
match this naming convention, symbolic links will be created for the
You may use any number of conditions, in any order. An alternate will
only be used if ALL conditions are valid. For all files managed by
yadm's repository or listed in $HOME/.config/yadm/encrypt, if they
match this naming convention, symbolic links will be created for the
most appropriate version.
The "most appropriate" version is determined by calculating a score for
@ -491,12 +489,12 @@
have at least one yadm managed file within them (at the top level).
yadm will automatically create these links by default. This can be dis
abled using the yadm.auto-alt configuration. Even if disabled, links
abled using the yadm.auto-alt configuration. Even if disabled, links
can be manually created by running yadm alt.
Class is a special value which is stored locally on each host (inside
the local repository). To use alternate symlinks using class, you must
set the value of class using the configuration local.class. This is
Class is a special value which is stored locally on each host (inside
the local repository). To use alternate symlinks using class, you must
set the value of class using the configuration local.class. This is
set like any other yadm configuration with the yadm config command. The
following sets the class to be "Work".
@ -515,11 +513,11 @@
Supported template processors:
default
This is yadm's built-in template processor. This processor is
very basic, with a Jinja-like syntax. The advantage of this pro
cessor is that it only depends upon awk, which is available on
most *nix systems. To use this processor, specify the value of
"default" or just leave the value off (e.g. "##template").
This is yadm's built-in template processor. This processor is
very basic, with a Jinja-like syntax. The advantage of this
processor is that it only depends upon awk, which is available
on most *nix systems. To use this processor, specify the value
of "default" or just leave the value off (e.g. "##template").
ESH ESH is a template processor written in POSIX compliant shell. It
allows executing shell commands within templates. This can be
@ -610,8 +608,8 @@
It can be useful to manage confidential files, like SSH or GPG keys,
across multiple systems. However, doing so would put plain text data
into a Git repository, which often resides on a public system. yadm can
make it easy to encrypt and decrypt a set of files so the encrypted
version can be maintained in the Git repository. This feature will
make it easy to encrypt and decrypt a set of files so the encrypted
version can be maintained in the Git repository. This feature will
only work if a supported tool is available. Both gpg(1) and openssl(1)
are supported. gpg is used by default, but openssl can be configured
with the yadm.cipher configuration.
@ -624,7 +622,7 @@
.gnupg/*.gpg
Standard filename expansions (*, ?, [) are supported. If you have Bash
version 4, you may use "**" to match all subdirectories. Other shell
version 4, you may use "**" to match all subdirectories. Other shell
expansions like brace and tilde are not supported. Spaces in paths are
supported, and should not be quoted. If a directory is specified, its
contents will be included, but not recursively. Paths beginning with a
@ -637,13 +635,13 @@
tory so they are available across multiple systems.
To decrypt these files later, or on another system run yadm decrypt and
provide the correct password. After files are decrypted, permissions
provide the correct password. After files are decrypted, permissions
are automatically updated as described in the PERMISSIONS section.
Symmetric encryption is used by default, but asymmetric encryption may
Symmetric encryption is used by default, but asymmetric encryption may
be enabled using the yadm.gpg-recipient configuration.
NOTE: It is recommended that you use a private repository when keeping
NOTE: It is recommended that you use a private repository when keeping
confidential files, even though they are encrypted.
Patterns found in $HOME/.config/yadm/encrypt are automatically added to
@ -653,10 +651,10 @@
Using transcrypt or git-crypt
A completely separate option for encrypting data is to install and use
transcrypt or git-crypt. Once installed, you can use these tools by
running yadm transcrypt or yadm git-crypt. These tools enables trans
parent encryption and decryption of files in a git repository. See the
A completely separate option for encrypting data is to install and use
transcrypt or git-crypt. Once installed, you can use these tools by
running yadm transcrypt or yadm git-crypt. These tools enables trans
parent encryption and decryption of files in a git repository. See the
following web sites for more information:
- https://github.com/elasticdog/transcrypt
@ -664,9 +662,9 @@
- https://github.com/AGWA/git-crypt
## PERMISSIONS
When files are checked out of a Git repository, their initial permis
sions are dependent upon the user's umask. Because of this, yadm will
automatically update the permissions of some file paths. The "group"
When files are checked out of a Git repository, their initial permis
sions are dependent upon the user's umask. Because of this, yadm will
automatically update the permissions of some file paths. The "group"
and "others" permissions will be removed from the following files:
- $HOME/.local/share/yadm/archive
@ -696,21 +694,21 @@
## HOOKS
For every command yadm supports, a program can be provided to run be
fore or after that command. These are referred to as "hooks". yadm
looks for hooks in the directory $HOME/.config/yadm/hooks. Each hook
For every command yadm supports, a program can be provided to run be
fore or after that command. These are referred to as "hooks". yadm
looks for hooks in the directory $HOME/.config/yadm/hooks. Each hook
is named using a prefix of pre_ or post_, followed by the command which
should trigger the hook. For example, to create a hook which is run af
ter every yadm pull command, create a hook named post_pull. Hooks must
have the executable file permission set.
If a pre_ hook is defined, and the hook terminates with a non-zero exit
status, yadm will refuse to run the yadm command. For example, if a
pre_commit hook is defined, but that command ends with a non-zero exit
status, the yadm commit will never be run. This allows one to "short-
status, yadm will refuse to run the yadm command. For example, if a
pre_commit hook is defined, but that command ends with a non-zero exit
status, the yadm commit will never be run. This allows one to "short-
circuit" any operation using a pre_ hook.
Hooks have the following environment variables available to them at
Hooks have the following environment variables available to them at
runtime:
YADM_HOOK_COMMAND
@ -732,10 +730,10 @@
## FILES
All of yadm's configurations are relative to the "yadm directory".
yadm uses the "XDG Base Directory Specification" to determine this di
rectory. If the environment variable $XDG_CONFIG_HOME is defined as a
fully qualified path, this directory will be $XDG_CONFIG_HOME/yadm.
All of yadm's configurations are relative to the "yadm directory".
yadm uses the "XDG Base Directory Specification" to determine this di
rectory. If the environment variable $XDG_CONFIG_HOME is defined as a
fully qualified path, this directory will be $XDG_CONFIG_HOME/yadm.
Otherwise it will be $HOME/.config/yadm.
Similarly, yadm's data files are relative to the "yadm data directory".
@ -744,7 +742,7 @@
fully qualified path, this directory will be $XDG_DATA_HOME/yadm. Oth
erwise it will be $HOME/.local/share/yadm.
The following are the default paths yadm uses for its own data. Most
The following are the default paths yadm uses for its own data. Most
of these paths can be altered using universal options. See the OPTIONS
section for details.
@ -753,16 +751,16 @@
tive to this directory.
$HOME/.local/share/yadm
The yadm data directory. By default, all data yadm stores is
The yadm data directory. By default, all data yadm stores is
relative to this directory.
$YADM_DIR/config
Configuration file for yadm.
$YADM_DIR/alt
This is a directory to keep "alternate files" without having
them side-by-side with the resulting symlink or processed tem
plate. Alternate files placed in this directory will be created
This is a directory to keep "alternate files" without having
them side-by-side with the resulting symlink or processed tem
plate. Alternate files placed in this directory will be created
relative to $HOME instead.
$YADM_DATA/repo.git
@ -798,7 +796,7 @@
## REPORTING BUGS
Report issues or create pull requests at GitHub:
https://github.com/TheLocehiliosan/yadm/issues
https://github.com/yadm-dev/yadm/issues
## AUTHOR
@ -810,5 +808,3 @@
https://yadm.io/

View file

@ -1,7 +1,7 @@
%{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}-%{version}}
Name: yadm
Summary: Yet Another Dotfiles Manager
Version: 3.2.2
Version: 3.3.0
Group: Development/Tools
Release: 1%{?dist}
URL: https://yadm.io