1
0
Fork 0
mirror of synced 2024-12-21 22:21:08 -05:00

Updates for yadm 2.0.0

This commit is contained in:
Tim Byrne 2019-10-20 15:07:13 -05:00
parent eec6d49f98
commit 392a66829a
No known key found for this signature in database
GPG key ID: 14DB4FC2465A4B12
14 changed files with 319 additions and 114 deletions

View file

@ -31,10 +31,16 @@ docs:
url: /docs/bootstrap url: /docs/bootstrap
- title: "Alternate Files" - title: "Alternate Files"
url: /docs/alternates url: /docs/alternates
- title: "Templates"
url: /docs/templates
- title: "Encryption" - title: "Encryption"
url: /docs/encryption url: /docs/encryption
- title: "Hooks"
url: /docs/hooks
- title: More Help - title: More Help
children: children:
- title: "Upgrading from Version 1"
url: /docs/upgrade_from_1
- title: "FAQ" - title: "FAQ"
url: /docs/faq url: /docs/faq
- title: "Example Dotfiles" - title: "Example Dotfiles"

View file

@ -45,11 +45,11 @@ current directory or below.
Read about [alternate files](alternates) for more details. Read about [alternate files](alternates) for more details.
<i class="fa fa-fw fa-asterisk" aria-hidden="true"></i> `yadm encrypt` <i class="fa fa-fw fa-asterisk" aria-hidden="true"></i> `yadm encrypt`
: Encrypt all files matching the patterns found in `$HOME/.yadm/encrypt`. Read : Encrypt all files matching the patterns found in `$HOME/.config/yadm/encrypt`. Read
about [encryption](encryption) for more details. about [encryption](encryption) for more details.
<i class="fa fa-fw fa-asterisk" aria-hidden="true"></i> `yadm decrypt`, `yadm decrypt -l` <i class="fa fa-fw fa-asterisk" aria-hidden="true"></i> `yadm decrypt`, `yadm decrypt -l`
: Decrypt files stored in `$HOME/.yadm/files.gpg`. Using the `-l` option will : Decrypt files stored in `$HOME/.config/yadm/files.gpg`. Using the `-l` option will
only list the files (without decrypting them). Read about only list the files (without decrypting them). Read about
[encryption](encryption) for more details. [encryption](encryption) for more details.

View file

@ -13,14 +13,14 @@ perform, yadm has a standard command for executing them.
yadm bootstrap yadm bootstrap
This command will execute the program named `$HOME/.yadm/bootstrap`. You must This command will execute the program named `$HOME/.config/yadm/bootstrap`. You must
provide this program yourself, and it must be made executable. But those are the provide this program yourself, and it must be made executable. But those are the
only constraints. only constraints.
After yadm successfully clones a repository, if there is a bootstrap program After yadm successfully clones a repository, if there is a bootstrap program
available, it will offer to run it for you. available, it will offer to run it for you.
Found .yadm/bootstrap Found .config/yadm/bootstrap
It appears that a bootstrap program exists. It appears that a bootstrap program exists.
Would you like to execute it now? (y/n) Would you like to execute it now? (y/n)

View file

@ -10,130 +10,107 @@ features and strategies for dealing with those occasions.
## Symlink alternates ## Symlink alternates
It can be useful to have an automated way of choosing an alternate version of a It can be useful to have an automated way of choosing an alternate version of a
file for a different operating system, host, or user. yadm implements a file for a different operating system, host, user, etc.
feature which will automatically create a symbolic link to the appropriate
version of a file, as long as you follow a specific naming convention. yadm can
detect files with names ending in:
| `##` | Default file linked | yadm will automatically create a symbolic link to the appropriate version of a
| `##CLASS` | Matching Class | file, when a valid suffix is appended to the filename. The suffix contains the
| `##CLASS.OS` | Matching Class & OS | conditions that must be met for that file to be used.
| `##CLASS.OS.HOSTNAME` | Matching Class, OS & Hostname |
| `##CLASS.OS.HOSTNAME.USER` | Matching Class, OS, Hostname, & User |
| `##OS` | Matching OS |
| `##OS.HOSTNAME` | Matching OS & Hostname |
| `##OS.HOSTNAME.USER` | Matching OS, Hostname, & User |
If there are any files managed by yadm's repository, or listed in The suffix begins with `##`, followed by any number of conditions separated by
`$HOME/.yadm/encrypt`, which match this naming convention, symbolic links will commas.
be created for the most appropriate version. This may best be demonstrated by
example. Assume the following files are managed by yadm's repository:
$HOME/path/example.txt## ##<condition>[,<condition>,…]
$HOME/path/example.txt##Work
$HOME/path/example.txt##Darwin
$HOME/path/example.txt##Darwin.host1
$HOME/path/example.txt##Darwin.host2
$HOME/path/example.txt##Linux
$HOME/path/example.txt##Linux.host1
$HOME/path/example.txt##Linux.host2
If running on a Macbook named `host2`, yadm will create a symbolic link which Each condition is an attribute/value pair, separated by a period. Some
looks like this: conditions do not require a "value", and in that case, the period and value can
be omitted. Most attributes can be abbreviated as a single letter.
`$HOME/path/example.txt``$HOME/path/example.txt##Darwin.host2` | Attribute | Meaning |
| - | - |
| `template`, `t` | Valid when the value matches a supported template processor. See the [Templates](/docs/templates) section for more details.|
| `user`, `u` | Valid if the value matches the current user. Current user is calculated by running <code>id&nbsp;&#8209;u&nbsp;&#8209;n</code>. |
| `distro`, `d` | Valid if the value matches the distro. Distro is calculated by running <code>lsb_release&nbsp;&#8209;si</code>. |
| `os`, `o` | Valid if the value matches the OS. OS is calculated by running <code>uname&nbsp;&#8209;s</code>. |
| `class`, `c` | Valid if the value matches the local.class configuration. Class must be manually set using <code>yadm&nbsp;config&nbsp;local.class&nbsp;&lt;class&gt;</code>. |
|`hostname`, `h`|Valid if the value matches the short hostname. Hostname is calculated by running `hostname`, and trimming off any domain.|
|`default`|Valid when no other alternate is valid.|
However, on another Macbook named `host3`, yadm will create a symbolic link You may use any number of conditions, in any order. An alternate will only be
which looks like this: 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.
`$HOME/path/example.txt``$HOME/path/example.txt##Darwin` The "most appropriate" version is determined by calculating a score for each
version of a file. A [template](/docs/templates) is always scored higher than
any symlink condition. The number of conditions is the next largest factor in
scoring. Files with more conditions will always be favored. Any invalid
condition will disqualify that file completely.
Since the host name doesn't match any of the managed files, the more generic If you don't care to have all versions of alternates stored in the same
version is chosen. directory as the generated symlink, you can place them in the
`$HOME/.config/yadm/alt` directory. The generated symlink or processed template
will be created using the same relative path.
If running on a Linux server named `host4`, the link will be: Alternate linking may best be demonstrated by example. Assume the following
files are managed by yadm's repository:
`$HOME/path/example.txt``$HOME/path/example.txt##Linux` $HOME/path/example.txt##default
$HOME/path/example.txt##class.Work
$HOME/path/example.txt##os.Darwin
$HOME/path/example.txt##os.Darwin,hostname.host1
$HOME/path/example.txt##os.Darwin,hostname.host2
$HOME/path/example.txt##os.Linux
$HOME/path/example.txt##os.Linux,hostname.host1
$HOME/path/example.txt##os.Linux,hostname.host2
If running on a Solaris server, the link use the default `##` version: If running on a Macbook named `host2`, yadm will create a symbolic link which looks like this:
`$HOME/path/example.txt``$HOME/path/example.txt##` `$HOME/path/example.txt``$HOME/path/example.txt##os.Darwin,hostname.host2`
If running on a system, with `CLASS` set to "Work" ([see below](alternates#class-and-overrides)), the link will be: However, on another Mackbook named `host3`, yadm will create a symbolic link which looks like this:
`$HOME/path/example.txt``$HOME/path/example.txt##Work` `$HOME/path/example.txt``$HOME/path/example.txt##os.Darwin`
If no `##` version exists and no files match the current CLASS/OS/HOSTNAME/USER, Since the hostname doesn't match any of the managed files, the more generic
then no link will be created. version is chosen. If running on a Linux server named `host4`, the link will be:
| **CLASS** must be manually set using `yadm config local.class <class>`. `$HOME/path/example.txt``$HOME/path/example.txt##os.Linux`
| **OS** is determined by running `uname -s`.
| **HOSTNAME** by running `hostname` and removing any domain.
| **USER** by running `id -u -n`.
yadm will automatically create these links by default. This can be disabled using the `yadm.auto-alt` configuration. Even if disabled, links can be manually created by running yadm alt. If running on a Solaris server, the link will use the default version:
## Wildcards `$HOME/path/example.txt``$HOME/path/example.txt##default`
It is possible to use `%` as a "wildcard" in place of `CLASS`, `OS`, `HOSTNAME`, If running on a system, with class set to `Work`, the link will be:
or `USER`. For example, The following file could be linked for *any host* when the
user is "harvey".
``` `$HOME/path/example.txt``$HOME/path/example.txt##class.Work`
$HOME/path/example.txt##%.%.harvey
``` If no `##default` version exists and no files have valid conditions, then no
link will be created.
Links are also created for directories named this way, as long as they have at
least one yadm managed file within them.
yadm will automatically create these links by default. This can be disabled
using the `yadm.auto-alt` configuration. Even if disabled, links can be manually
created by running `yadm alt`.
## Class and Overrides ## Class and Overrides
Class is a special value which is stored locally on each host (inside the local 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 repository). To use alternate symlinks using `##class.<CLASS>`, you must set the
class using the configuration `local.class`. This is set like any other yadm value of class using the configuration `local.class`. This is set like any other
configuration—with the `yadm config` command. The following sets the `CLASS` to yadm configuration—with the `yadm config` command. The following sets the
be "Work". `local.class` to be "Work".
yadm config local.class Work yadm config local.class Work
Similarly, the values of `OS`, `HOSTNAME`, and `USER` can be manually Similarly, the values of `os`, `hostname`, and `user` can be manually overridden
overridden using the configuration options `local.os`, `local.hostname`, and using the configuration options `local.os`, `local.hostname`, and `local.user`.
`local.user`.
## Jinja templates ## Templates
If the `envtpl` command is available, Jinja templates will also be processed to Templates are another powerful tool for creating alternate content on each host.
create or overwrite real files. yadm will treat files ending in `##yadm.j2` See the [Templates](/docs/templates) documentation for full details.
as Jinja templates. During processing, the following variables are set according
to the rules explained in the [Alternates section](alternates#symlink-alternates):
* `YADM_CLASS`
* `YADM_OS`
* `YADM_HOSTNAME`
* `YADM_USER`
In addition `YADM_DISTRO` is exposed as the value of `lsb_release -si` if
lsb_release is locally available.
For example, a file named `whatever##yadm.j2` with the following content
{% raw %}
{% if YADM_USER == 'harvey' -%}
config={{YADM_CLASS}}-{{ YADM_OS }}
{% else -%}
config=dev-whatever
{% endif -%}
{% endraw %}
would write a file named `whatever` with the following content if the user is
"harvey":
config=work-Linux
and the following otherwise:
config=dev-whatever
See [andreasjansson/envtpl](https://github.com/andreasjansson/envtpl) for more information about
`envtpl`, and see [jinja.pocoo.org](http://jinja.pocoo.org/) for an overview of
Jinja.
## Strategies for alternate files on different systems ## Strategies for alternate files on different systems

102
_docs/045_templates.md Normal file
View file

@ -0,0 +1,102 @@
---
title: "Templates"
permalink: /docs/templates
---
Templates are a special kind of [alternate](/docs/alternates) file. The template
content and host specific data are combined as input to a template processor
which produces a new file as its output.
This can be very useful if you need to vary a small part of a file, but it
doesn't support any kind of include directive.
## Template suffixes
To create a template, append an alternate suffix to the file name.
The suffix has the format:
##template.<template processor>
<sub>
"template" can also be shortened to "t".
</sub>
The supported template processors are:
| Processor | Suffixes | Dependencies |
| - | - | - |
| default | `##template`, `##template.default` | `awk` must be installed. (This should be installed on all *nix systems) |
| j2cli | `##template.j2`, `##template.j2cli` | `j2cli` must be installed. |
| envtpl | `##template.j2`, `##template.envtpl` | `envtpl` must be installed. |
<sub>
The processor can be omitted for "default".
Also, `j2` will be processed by either j2cli or envtpl, whichever is found.
</sub>
## Exposed data
When template processors run, they will be provided the following set of data.
| Default (built-in) | Jinja | Description | Source |
| - | - | - | - |
| `yadm.class` | `YADM_CLASS` | Locally defined yadm class | <code>yadm&nbsp;config&nbsp;local.class</code> |
| `yadm.distro` | `YADM_DISTRO` | Distribution | <code>lsb_release&nbsp;&#8209;si</code> |
| `yadm.hostname` | `YADM_HOSTNAME` | Hostname | `hostname` (without domain) |
| `yadm.os` | `YADM_OS` | Operating system | <code>uname&nbsp;&#8209;s</code> |
| `yadm.user` | `YADM_USER` | Current user | <code>id&nbsp;&#8209;u&nbsp;&#8209;n</code> |
| `yadm.source` | `YADM_SOURCE` | Template filename | (fully qualified path) |
## Supported template processors
default
: This built-in processor requires no additional software (assuming your distro
contains `awk`). This processor has a syntax _similar_ to the Jinja processors
below, however it only supports a small set of directives. Those directives are
detailed in the section below.
j2cli
: [j2cli][j2cli] (or `j2`) is a Python-based Jinja2 template processor. This
fully supports all directives of the [Jinja2 library][jinja]. When your template is
processed, the YADM_* values are provided to j2cli as environment variables.
envtpl
: [envtpl][envtpl] is another Python-based Jinja2 template processor. Online
comments suggest this software might not be maintained anymore.
## Built-in directives
yadm's "default" (built-in) template processor supports the following directives.
{% raw %}
variables
: Variables should be surrounded by `{{ }}`. It is fine for there to be
whitespace between the variable name and the double braces. The `{{` and
`}}` must be on the same line. For example:
```jinja
# WARNING: Do not edit this file.
# It was generated by processing {{ yadm.source }}
```
if-else-endif
: Entire blocks of content can be included or excluded based on the value of a
variable. Only equality can be tested. These blocks must start with
`{% if yadm.variable == "value" %}` and end with `{% endif %}`. An alternative
block can also be specified using the directive `{% else %}`. These directives
must appear on lines by themselves. They may not appear on the same line. The
"if" directive only supports testing a single variable, and there is no "elif"
directive as there is in Jinja. Here is an example.
```jinja
{% if yadm.os == "Darwin" %}
This block is included for MacOS
{% else %}
This block is included for for any other OS
{% endif %}
```
{% endraw %}
[envtpl]: https://github.com/andreasjansson/envtpl
[j2cli]: https://github.com/kolypto/j2cli
[jinja]: https://jinja.palletsprojects.com

View file

@ -12,18 +12,18 @@ _It is recommended that you use a private repository when keeping confidential
files, even though they are encrypted._ files, even though they are encrypted._
To use this feature, a list of patterns must be created and saved as To use this feature, a list of patterns must be created and saved as
`$HOME/.yadm/encrypt`. For example: `$HOME/.config/yadm/encrypt`. For example:
.ssh/*.key .ssh/*.key
The `yadm encrypt` command will find all files matching the patterns, and The `yadm encrypt` command will find all files matching the patterns, and
prompt for a password. Once a password has confirmed, the matching files will be prompt for a password. Once a password has confirmed, the matching files will be
encrypted and saved as `$HOME/.yadm/files.gpg`. The patterns and files.gpg encrypted and saved as `$HOME/.config/yadm/files.gpg`. The patterns and files.gpg
should be added to the yadm repository so they are available across multiple should be added to the yadm repository so they are available across multiple
systems. systems.
yadm add .yadm/encrypt yadm add .config/yadm/encrypt
yadm add .yadm/files.gpg yadm add .config/yadm/files.gpg
To decrypt these files later, or on another system run `yadm decrypt` and To decrypt these files later, or on another system run `yadm decrypt` and
provide the correct password. provide the correct password.

35
_docs/055_hooks.md Normal file
View file

@ -0,0 +1,35 @@
---
title: "Hooks"
permalink: /docs/hooks
---
For every command yadm supports, a program can be provided to run before 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 after
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-circuit" any
operation using a `pre_` hook.
Hooks have the following environment variables available to them at runtime:
YADM_HOOK_COMMAND
: The command which triggered the hook
YADM_HOOK_EXIT
: The exit status of the yadm command
YADM_HOOK_FULL_COMMAND
: The yadm command with all command line arguments
YADM_HOOK_REPO
: The path to the yadm repository
YADM_HOOK_WORK
: The path to the work-tree

61
_docs/059_upgrade.md Normal file
View file

@ -0,0 +1,61 @@
---
title: "Upgrading from Version 1"
permalink: /docs/upgrade_from_1
---
Beginning with version 2.0.0, yadm introduced a few major changes which may
require you to adjust your configurations.
If you want to retain yadm's old behavior until you transition your
configurations, you can set an environment variable `YADM_COMPATIBILITY=1`.
Doing so will automatically use the old yadm directory, and process alternates the same as version 1.
This compatibility mode is deprecated, and will be removed in future versions.
This mode exists solely for transitioning to the new paths and naming of alternates.
## New yadm directory location
yadm now uses the [XDG Base Directory Specification][xdg-spec] to find its configurations.
For the majority of users, this means configurations will now be in
`$HOME/.config/yadm` instead of the old location of `$HOME/.yadm`.
You can customize the base directory by specifying an environment variable
named `XDG_CONFIG_HOME`.
If you previously had configurations in `$HOME/.yadm`, the easiest way
to migrate is to use the new `yadm upgrade` command. This command will move your
existing repo and configurations to the new directory, and rename any yadm
configurations that are tracked by your repo.
## New alternate file naming convention
The naming conventions for alternate files have been changed.
Read full details about the new naming convention [here](/docs/alternates).
This table of examples should help you understand how to translate old filenames
to new ones.
| Conditions | Old suffix | New suffix |
| - | - | - |
| Default file | `##` | `##default` |
| MacOS host | `##Darwin` | `##o.Darwin` |
| yadm.class = "work" | `##work` | `##c.work` |
| Linux host named "dromio" | `##Linux.dromio` | `##o.Linux,h.dromio` |
| Linux host named "dromio" with user named "antipholus" | `##Linux.dromio.antipholus` | `##o.Linux,h.dromio,u.antipholus` |
| Host named "luciana" | `##%.luciana` | `##h.luciana` |
| Any Linux host with user named "egeon" | `##Linux.%.egeon` | `##o.Linux,u.egeon` |
| User named "balthazar" | `##%.%.balthazar` | `##u.balthazar` |
| A Jinja template | `##yadm.j2` | `##template.j2` |
## Built-in template processing
Older versions supported Jinja templates if envtpl was installed. New versions
support _multiple_ template processors, including a built-in processor. The
built-in processor has a limited feature set, but should be sufficient for most
users needs (without having to install additional software). Read full details
[here](/docs/templates).
## Option `yadm.cygwin-copy` changed to `yadm.alt-copy`
Older versions supported a `yadm.cygwin-copy` option, because some software
doesn't work well with CYGWIN symlinks. Now that option has been renamed to
`yadm.alt-copy`, and can be used on any system, not just CYGWIN. So if you have
a system which doesn't fully support symlinks, you can have alternates created
as files instead.
[xdg-spec]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

View file

@ -85,7 +85,7 @@ protocol. You can start by cloning the repository using the `https` protocol
(and providing a password), and then change the repository's URL after you've (and providing a password), and then change the repository's URL after you've
decrypted your ssh keys. decrypted your ssh keys.
### I've customized yadm configurations (stored in `~/.yadm/config`). Should I add that to my repository? ### I've customized yadm configurations (stored in `~/.config/yadm/config`). Should I add that to my repository?
Certainly. That is a good way to carry your yadm configurations around (just Certainly. That is a good way to carry your yadm configurations around (just
like the rest of your dotfiles). like the rest of your dotfiles).
@ -114,7 +114,7 @@ Of course. You only need `gpg` installed if you plan on using the
encrypt/decrypt features. yadm will tell you if it is missing a dependency encrypt/decrypt features. yadm will tell you if it is missing a dependency
for any command. for any command.
### Should I `yadm add` my `.yadm/encrypt` file? ### Should I `yadm add` my `.config/yadm/encrypt` file?
Yes! This way your configuration for what files should be encrypted will follow Yes! This way your configuration for what files should be encrypted will follow
you when you clone your repository. you when you clone your repository.
@ -122,18 +122,18 @@ you when you clone your repository.
### Should I `yadm add` encrypted files to repository? ### Should I `yadm add` encrypted files to repository?
No, you should not. Files you want encrypted should be added to the file No, you should not. Files you want encrypted should be added to the file
`.yadm/files.gpg` using the `yadm encrypt` command. Then `.yadm/files.gpg` `.config/yadm/files.gpg` using the `yadm encrypt` command. Then
should be added to the yadm repository. This way, only an encrypted `.config/yadm/files.gpg` should be added to the yadm repository. This way, only
collection of those files are put into the repository. After cloning or updating an encrypted collection of those files are put into the repository. After
your repository, you can use `yadm decrypt` to extract those files from cloning or updating your repository, you can use `yadm decrypt` to extract those
`.yadm/files.gpg`. See the files from `.config/yadm/files.gpg`. See the
[encryption help](encryption) for more details. [encryption help](encryption) for more details.
### I modified an encrypted file, but yadm doesn't show any modifications. Why? ### I modified an encrypted file, but yadm doesn't show any modifications. Why?
If you changed files which are matched by `.yadm/encrypt`, you must re-run `yadm If you changed files which are matched by `.config/yadm/encrypt`, you must
encrypt` to generate a new version of `.yadm/files.gpg`. Then `.yadm/files.gpg` re-run `yadm encrypt` to generate a new version of `.config/yadm/files.gpg`.
can be added to a new commit. Then `.config/yadm/files.gpg` can be added to a new commit.
### Why do I get the error `Inappropriate ioctl for device` when encrypting. ### Why do I get the error `Inappropriate ioctl for device` when encrypting.

View file

@ -32,7 +32,7 @@ feature_row:
alt: Overview alt: Overview
btn_class: btn--inverse btn_class: btn--inverse
btn_label: Discover yadm btn_label: Discover yadm
image_path: /images/cogs-padding.png image_path: /images/picture-padding.png
url: /docs/overview url: /docs/overview
excerpt: ' excerpt: '
@ -53,6 +53,7 @@ feature_row:
Sometimes you need different configurations on different systems. Sometimes you need different configurations on different systems.
yadm makes it possible to use alternate versions of files based on yadm makes it possible to use alternate versions of files based on
the OS or hostname of the system. the OS or hostname of the system.
Templates allow you to use alternate sections within files.
' '
- title: Encryption - title: Encryption
@ -81,6 +82,17 @@ feature_row:
If provided, yadm can execute your custom program immediately If provided, yadm can execute your custom program immediately
following a successful clone. following a successful clone.
'
- title: Hooks
alt: Hooks
btn_class: btn--inverse
btn_label: Get started
image_path: /images/cogs-padding.png
url: /docs/hooks
excerpt: '
Perform custom operations before or after any yadm command.
' '
- title: FAQ - title: FAQ
alt: FAQ alt: FAQ
@ -114,6 +126,18 @@ feature_row:
Need some inspiration? Here are some example dotfiles repository. Need some inspiration? Here are some example dotfiles repository.
'
- title: Contribute
alt: Contribute
btn_class: btn--inverse
btn_label: Read guidlines
image_path: /images/hands-padding.png
url: https://github.com/TheLocehiliosan/yadm/blob/master/.github/CONTRIBUTING.md
excerpt: '
Improve yadm by reporting bugs, coding changes, documentation and
packaging yadm installations.
' '
--- ---

BIN
images/hands-padding.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/hands.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
images/picture-padding.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
images/picture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB