Fileset is a mini-DSL to ease creation, manipulation and inspection of
filesystem hierarchies, including content of files. It can express arbitrary
strings both as filenames and file content, with only very simple escaping for
newlines. It can be easily generated using a templating/macro language.

Fileset language consists of statements. Each line that starts with non-tab
character is start of new statement. Lines that start with tab character are
continuation lines from previous statement, where the newline is semantically
retained but the tab character is ignored where processing. This means that you
can embed literal "\n" by replacing each occurence with "\n\t", which is still
conveniently readable in plain text, unlike most other escaping schemes.

Each statement with single command character. The command may either take fixed
number of tab-separated argument or operate on whole rest of statement.
When the command does not consume whole statement, next command is taken from the
first character after a tab delimiting the last argument.
Two special commands ("/" and "P") do nothing by themselves, they only set the
path (filename) for subsequent commands to operate on.

Commands that take one argument:

/<path>
	set the path (filename) to operate on (may not contain tab, see P)

u<mode>
	set the umask for creating new files

o<owner>
	change owner (and group) of the filename, argument is directly passed to chown

m<mode>
	change file mode (permissions), argument is directly passed to chmod

r<flags>
	remove filename, for flags see below

f<flags>
	create plain file

d<flags>
	create a directory

p<flags>
	(not implemented) create FIFO / named pipe

Commands that take two arguments:

l<flags><tab><destination>
	create symbolic link pointing to destination (destination may not contain tab, see L)

h<flags><tab><destination>
	(not implemented) create a hard link pointing to destination (ditto, see H)

c<flags><tab><content>
	create plain file with specified content (content may not contain tab, see C)
	a final newline is appended if the content does not end in newline,
	unless following flags are given:
	"n" - always append a newline
	"N" - never append a newline

b<flags><tab><content>
	base64, TODO description

s<flags><tab><content>
	checksum, TODO description

D<flags><tab><device-type>:<major>:<minor>
	TODO

Commands that take whole statement:

P<tab><path>
	set the path (filename) to operate on

L<flags><tab><destination>
	create symbolic link pointing to destination

H<flags><tab><destination>
	(not implemented) create a hard link pointing to destination

C<flags><tab><content>
	create regular file with specified content, additional flags as with "c"

B<flags><tab><content>
	create regular file with content specified as base64,
	additional flags as with "b"

X<flags><tab><content>
	create regular file with content specified as hexdump as produced by xxd

!<flags><tab><command>
	run shell command on file, depending on the flags:
	"i" - redirect stdin from the file for the command
	"o" - redirect stdout to the file for the command, rewriting it
	"a" - redirect stdout to the file for the command, appending to it
	"f" - use command as a filter, redirecting the file to stdin and stdout to
	      temporary file, overwriting the original if change was detected
	      also takes additional flags as for "f" command
	"c" - with "f" create empty file first if it doesn't exist yet

Flags taken by the rfdlhcLHC commands:
	"!" - remove existing file if already present and of different type (eg.
	      symlink instead of directory)
	      files of same type are always replaced even without this flag
	"r" - when removing existing file (directory), do it recursively (rm -r)
	"f" - when removing existing file, do it forcibly (rm -f)
	"p" - create parent directories if they don't exist (mkdir -p)

?<flags><tab><command>
	Modifies following ! command. The command specified as argument will be run
	to determine the following ! command should be run
	(if ? command exits nonzero) and if so it's used once again after
	to check that ! command performed required action (when ? command exits zero).
	flags:
	"i" - redirect stdin from the file for the command

Commandline utilities:

fileset [file [file ...]]
	Convert fileset language into executable shell script. Read stdin if no
	files are passed.

fsapply [-x] root [file [file ...]]
	Convert fileset language to shell script and execute it, relative to root
	directory. The shell executed is determined by FILESET_SHELL environment
	variable, defaulting to "sh". The -x option is passed to the shell, so
	tracing can be turned on.

fslist [file [file ...]]
	Print out attributes and content of given files in fileset format. If
	directories are given, they are processed recursively. When nothing is
	given, current working directory is used.