From 33361ddea694503b4ade4f34ac599e5b47522de0 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Sat, 1 Sep 2018 17:28:02 +0200 Subject: [PATCH] add ability to add auto-generated dotdrop header in dotfiles --- README.md | 30 ++++++++++++-- dotdrop/templategen.py | 5 +++ dotdrop/utils.py | 10 +++++ tests-ng/header.sh | 94 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 3 deletions(-) create mode 100755 tests-ng/header.sh diff --git a/README.md b/README.md index 9e52a4b..d223eb2 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ why dotdrop rocks. * [Store sensitive dotfiles](#store-sensitive-dotfiles) * [Config](#config) -* [Template](#template) +* [Templating](#templating) * [Example](#example) * [User tricks](#user-tricks) * [People using dotdrop](#people-using-dotdrop) @@ -555,7 +555,7 @@ profiles: ``` Here profile *host1* contains all the dotfiles defined for *host2* plus `f_xinitrc`. -# Template +# Templating Dotdrop leverage the power of [jinja2](http://jinja.pocoo.org/) to handle the templating of dotfiles. See [jinja2 template doc](http://jinja.pocoo.org/docs/2.9/templates/) @@ -574,7 +574,31 @@ Note that dotdrop uses different delimiters than ## Available variables * `{{@@ profile @@}}` contains the profile provided to dotdrop. -* `{{@@ env['MY_VAR'] @@}}` contains environment variables (see [Environment variables](#environment-variables)) +* `{{@@ env['MY_VAR'] @@}}` contains environment variables (see [Environment variables](#environment-variables)). +* `{{@@ header @@}}` insert dotdrop header (see [Dotdrop header](#dotdrop-header)). + +## Dotdrop header + +Dotdrop is able to insert a header in the generated dotfiles. This allows +to remind anyone opening the file for editing that this file is managed by dotdrop. +The header provides additional information like the last update date/time and +dotdrop's version used. + +Here's an example of such an header: +``` +This dotfile is managed using dotdrop v0.19.2 / last updated 2018-09-01 00:01 +``` + +Such a header can be automatically added using jinja2 directive: +``` +{{@@ header @@}} +``` + +Properly commenting the header is the responsability of the user as jinja2 has no way of +knowning what is the proper char(s) used for comments. + +Either prepend the directive with the commenting char(s) used in the dotfile (for example `# {{@@ header @@}}`) +or provide it as an argument `{{@@ header('# ') @@}}`. The result is equivalent. ## Environment variables diff --git a/dotdrop/templategen.py b/dotdrop/templategen.py index 6e5dcb3..62618d2 100644 --- a/dotdrop/templategen.py +++ b/dotdrop/templategen.py @@ -35,6 +35,7 @@ class Templategen: variable_end_string=VAR_END, comment_start_string=COMMENT_START, comment_end_string=COMMENT_END) + self.env.globals['header'] = self._header self.log = Logger() def generate(self, src, profile): @@ -42,6 +43,10 @@ class Templategen: return '' return self._handle_file(src, profile) + def _header(self, prepend=''): + """add a comment usually in the header of a dotfile""" + return '{}{}'.format(prepend, utils.header()) + def _handle_file(self, src, profile): """generate the file content from template""" filetype = utils.run(['file', '-b', src], raw=False, debug=self.debug) diff --git a/dotdrop/utils.py b/dotdrop/utils.py index 807d8ef..7207ef0 100644 --- a/dotdrop/utils.py +++ b/dotdrop/utils.py @@ -9,10 +9,12 @@ import subprocess import tempfile import os import shlex +import datetime from shutil import rmtree # local import from dotdrop.logger import Logger +from dotdrop.version import __version__ as VERSION LOG = Logger() @@ -65,3 +67,11 @@ def samefile(path1, path2): if not os.path.exists(path2): return False return os.path.samefile(path1, path2) + + +def header(): + header = 'This dotfile is managed using dotdrop' + header += ' v{}'.format(VERSION) + now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") + header += ' / last updated {}'.format(now) + return header diff --git a/tests-ng/header.sh b/tests-ng/header.sh new file mode 100755 index 0000000..efeb1d3 --- /dev/null +++ b/tests-ng/header.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2017, deadc0de6 +# +# test header +# returns 1 in case of error +# + +# exit on first error +set -e + +# all this crap to get current path +rl="readlink -f" +if ! ${rl} "${0}" >/dev/null 2>&1; then + rl="realpath" + + if ! hash ${rl}; then + echo "\"${rl}\" not found !" && exit 1 + fi +fi +cur=$(dirname "$(${rl} "${0}")") + +#hash dotdrop >/dev/null 2>&1 +#[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 + +#echo "called with ${1}" + +# dotdrop path can be pass as argument +ddpath="${cur}/../" +[ "${1}" != "" ] && ddpath="${1}" +[ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 + +export PYTHONPATH="${ddpath}:${PYTHONPATH}" +bin="python3 -m dotdrop.dotdrop" + +echo "dotdrop path: ${ddpath}" +echo "pythonpath: ${PYTHONPATH}" + +# get the helpers +source ${cur}/helpers + +echo "RUNNING $(basename $BASH_SOURCE)" + +################################################################ +# this is the test +################################################################ + +# the dotfile source +tmps=`mktemp -d` +mkdir -p ${tmps}/dotfiles +#echo "dotfile source: ${tmps}" +# the dotfile destination +tmpd=`mktemp -d` +#echo "dotfile destination: ${tmpd}" + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: + f_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p1: + dotfiles: + - f_abc +_EOF +cat ${cfg} + +# create the dotfile +echo "{{@@ header() @@}}" > ${tmps}/dotfiles/abc +echo "{{@@ header('# ') @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ header('// ') @@}}" >> ${tmps}/dotfiles/abc +echo "test" >> ${tmps}/dotfiles/abc + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 + +grep '^This dotfile is managed using dotdrop' ${tmpd}/abc >/dev/null +grep '^# This dotfile is managed using dotdrop' ${tmpd}/abc >/dev/null +grep '^// This dotfile is managed using dotdrop' ${tmpd}/abc >/dev/null + +#cat ${tmpd}/abc + +## CLEANING +rm -rf ${tmps} ${tmpd} + +echo "OK" +exit 0