aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bachelier <laurent@bachelier.name>2013-03-04 01:21:30 +0100
committerLaurent Bachelier <laurent@bachelier.name>2013-03-04 01:21:30 +0100
commit29b9a4124a1fdc1e36484bff741d2a13ef054aef (patch)
treebf8c1233cdd56e627887d8875f37fe76d937687a
parentTypo (diff)
downloadconfman-29b9a4124a1fdc1e36484bff741d2a13ef054aef.tar.xz
Add a real README
-rw-r--r--README168
1 files changed, 166 insertions, 2 deletions
diff --git a/README b/README
index 573a517..ad07cb8 100644
--- a/README
+++ b/README
@@ -1,4 +1,168 @@
-Synchronize config files between machines, lazily, without root permissions, and still be able to create powerful rules when needed.
+=======
+confman
+=======
+Description
+-----------
+
+Synchronize configuration files between machines, lazily, without root permissions,
+and still be able to create powerful rules when needed.
+
+While it is mainly targeted at managing personal configuration files (dotfiles),
+it can be used to deploy files to pretty much anything.
+
+It is designed to have almost no dependencies, and is contained in one small file.
+
+By default, it will create symbolic links in the destination directory to the files
+in the source directory.
+However, some filenames can indicate special actions instead (see below).
+
+
+Requirements
+------------
+
+Python 2.5 or later.
+No installation needed, though you can install it.
+
+
+Usage
+-----
The project is usable, but has no CLI interface for now.
-Examples are available in example.py and in the public-dotfiles repository.
+Examples are available in ``example.py`` and in the public-dotfiles repository.
+
+A simple example:
+
+::
+
+ from confman import ConfigSource
+ c = ConfigSource("~/dotfiles", "~")
+ c.sync()
+
+
+Special actions
+---------------
+
+* Files with names starting with ``_`` will be ignored.
+ This is useful to provide data for programmable actions.
+* File with names ending with ``.copy`` will be a copy.
+ It will update the destination file every time.
+* File with names ending with ``.copyonce`` will be a copy.
+ It will not update the destination file if either file is modified.
+* Files with names ending with ``.empty`` will be an empty file.
+ It will not update the destination file if either file is modified.
+* Files with names ending with ``.p.py`` are programmable actions.
+ They contain Python code, and are provided with some special methods.
+
+All the matching parts of the special actions are removed; ``myfile.empty`` will create
+an empty file named ``myfile``.
+
+Programmable actions
+--------------------
+
+Programmable actions can do everything special actions can do, and more.
+They have to raise a "Forwarder", however for most uses helpers are provided to
+keep the code short.
+
+* ``empty()`` raises an empty action.
+* ``ignore()`` raises an ignore action.
+* ``redirect(filename)`` will create a symbolic link to the provided filename with a ``_`` added.
+ ``redirect('myfile')`` will create a symbolic link to ``_myfile``.
+
+
+Text / Templates
+~~~~~~~~~~~~~~~~
+
+Both ``text()`` and ``template()`` use ``string.Template`` templates.
+
+* ``text(data)`` will put the text from the data variable in the destination file.
+* ``template(filename)`` acts like ``text()`` but takes the data from a file.
+
+They have to be used in two steps:
+
+::
+
+ text('hello $name').render(hello='laurentb')
+
+A ``warning`` variable is provided, to help prevent users from modifying
+automatically generated files.
+
+::
+
+ text('''# $warning
+ aaa=$var''').render(var='123')
+
+Will output:
+
+::
+
+ # WARNING: Do not edit this file, edit the template instead.
+ aaa=123
+
+Since it is Python, you can use external libraries if you want,
+including advanced template libraries like ``mako``.
+
+
+Options variable
+~~~~~~~~~~~~~~~~
+
+You can provide an ``options`` variable to ``confman``, which will be provided
+to the programmable actions.
+
+::
+
+ from confman import ConfigSource
+ c = ConfigSource("~/dotfiles", "~", options={'hostname': 'myhostname'})
+ c.sync()
+
+A programmable action could use it like this:
+
+::
+
+ if options['hostname'] == 'myhostname':
+ redirect('myfile')
+ else:
+ ignore()
+
+
+The ``options`` variable does not have to be a ``dict``, it can be anything you want.
+
+
+Advanced use
+------------
+
+To debug what is happening (and why), you can do:
+
+::
+
+ from confman import ConfigSource
+ c.sync()
+ print repr(c)
+
+
+Changing the default behavior
+-----------------------------
+
+All special actions are optional, and can be configured or subclassed.
+For example, you could change the matching of "copy" actions:
+
+::
+
+ import confman, re
+ # use .COPY instead of .copy
+ confman.CopyAction.MATCHED = re.compile(r"\.COPY$")
+ # use hg instead of git
+ confman.IgnoreAction.MATCHED = re.compile(r"_|\.hg|\.hgignore")
+
+You can also change what classes are used.
+By default, it is ``confman.ConfigSource.DEFAULT_CLASSES``.
+
+::
+
+ import confman
+ confman.ConfigSource("~/dotfiles", "~", classes=[MyClass, confman.SymlinkAction])
+
+
+Development
+-----------
+
+Contributions can be sent in the form of git patches, to laurent@bachelier.name.