MyNixOS website logo
Description

Backstop a target directory by source directories.

The backstop command is a UNIX, Linux, and *BSD tool. Intuitively, backstop fills in the missing objects or holes that exist in the target directory relative to the source directories thereby creating a merged view of the target and source directories. De-backstop undoes this. See "backstop -m" for a manual page or the homepage for more information.

The backstop command

The backstop command is a UNIX, Linux, and *BSD tool. Intuitively, backstop fills in the missing objects or holes that exist in the target directory relative to the source directories thereby creating a merged view of the target and source directories. De-backstop undoes this. See "backstop -m" for a manual page or the homepage for more information.

The command backstop was created over twenty years ago to manage development environement toolchains in which part of the project was under source control and part of the project was not, e.g. binaries. It was inspired by lndir, graft, and "Source Control to Project Control: Applying RCS and SCCS" by Don Bolinger and Tan Bronson. Techniques have changed with time, but backstop is a robust tool with an extensive test suite that runs around 2700 tests, a combination of HUnit, QuickCheck, and black box tests.

In the author's obviously biased veiw, backstop has pedagogical value. The module Backstop uses a ReaderT monad transformer to manage an Environment passed to it via the command line, a StateT monad transformer to keep track of a set of counters and to keep track of the status of direcotry content while backstopping or de-backstopping. The last two are Monoids. With this structure, the handling of a dry-run for backstop or de-backstop is rather powerful even it is a bit subtle (obscure) to understand.

On a personal note, the author truly began to appreciate Haskell after creating the Backstop module and its test suite and has not stopped appreciating Haskell since.

The backstop manual page


NAME
   backstop - Backstop a target directory by source directories

SYNOPSIS
   backstop [-nprt] [-a|-d] trgdir srcdir [srcdir ...]
   backstop -h
   backstop -l
   backstop -m
   backstop -v
   backstop -y

AVAILABILITY
   Marcus D. Gabriel (c)1999-2019.  All rights reserved.

   [email protected]

   License terms: GNU GPL version 3 or later (backstop -l)

DESCRIPTION
   Backstop a target directory by source directories thereby
   creating a backing chain using relative symbolic links by default
   or absolute symbolic links by option.  If more than one source
   directory is given, backstop the target directory with each
   source directory in turn starting from left to right on the
   command line.

   Intuitively, backstop fills in the missing objects or holes that
   exist in the target directory relative to the source directories
   thereby creating a merged view of the target and source
   directories.

   De-backstop a target directory by its source directories.  In
   this case, the source directories no longer need to exist.  If
   more than one source directory is given, de-backstop the target
   directory by the source directories.

   Symbolic links are never followed.  However, the target and
   source directories are canonicalized (realpath(3)) internally by
   the command backstop before backstopping and de-backstoppoing.

   By default no output is displayed except possibly to STDERR.

ALGORITHM
   There must be at least two arguments or operands.  The first
   operand is the target directory, and the second operand and
   beyond are source directories.  The target and source directory
   must be parallel directories, that is, neither canonicalized
   (realpath(3)) directory path may be a sub-directory of the other.
   If the above is not true, a usage error occurs.

   Nevertheless, pathnames are internally in reduced form such that
   symbolic link names are treated literally when finding directory
   names.  See "cd -L" of ksh(1).  In other words, components in the
   pathname that are not directories but symbolic links to
   directories are not resolved to their corresponding directories.

   A list of objects or names is collected under the root of the
   source directory excluding the directory dot (.) and the
   directory double-dot (..).  If the list is empty, the algorithm
   is done, otherwise the objects divide into two classes, objects
   that are not directories and objects that are directories.  There
   are five possibilities:

   1. The object is either dot (.) or double-dot (..) whereupon no
      action is taken.

   2. If an object of the same name as the name of the object under
      the root of the source directory does not exists under the
      root of the target directory, then a symbolic link, relative
      or absolute as required, is created under the root of the
      target directory to the object under the root of the source
      directory.  If populating (-p) and the object under the root
      of the source directory is a directory, then a sub-directory
      is created instead.

   3. If an object of the same name as the name of the object under
      the root of the source directory does exists under the root of
      the target directory and is a file, no action is taken,
      regardless of whether or not the object under the root of the
      source directory is a file or a directory.

   4. If an object of the same name as the name of the object under
      the root of the source directory does exists under the root of
      the target directory and is a directory, and if the object of
      the same name under the root of the source directory is a
      file, no action is taken.

   5. If an object of the same name as the name of the object under
      the root of the source directory does exists under the root of
      the target directory and is a directory, and if the object of
      the same name under the root of the source directory is also a
      directory, then recursion occurs with the objects of the same
      name under the roots of the target and source directories as
      new root target and source directories, respectively.

   When de-backstopping a target directory by source directories,
   the sources no longer need to exist.  Symbolic links under the
   target are removed if and only if they point to a pahtname under
   one of the source directories.  This can be determined even if
   the source directory no longer exists because symbolic links
   within directory pathnames are taken literally.  See "cd -L" of
   ksh(1).

   When de-populating while de-backstopping (-pd), a directory is
   removed if all objects within the directory are symbolic links
   that have been remove while de-backstopping.  An empty directory
   is removed if and only if there exists a corresponding directory
   path under one of the source directories as under the target
   directory.  This can only be determined if the source directory
   and correponding sub-directory still exist.  If not, then no
   action is taken.

OPTIONS
   The following options are supported:

   -a Create symbolic links which are absolute paths.

   -d De-backstop the target directory by its source directories.
      The -a option has no affect on the -d option.

   -h Display a short command summary.

   -l Display the backstop license terms.

   -m Display this internal manual page.

   -n Take no action but trace possible program execution.  The -n
      option implies the -t option.

   -p Populate the target by making equivalent sub-directories of
      the source sub-directories instead of symbolic links for these
      sub-directories that point back into the sources.  For
      example, if the target directory is empty, then for a set of
      source directories, from left to right on the command line,
      this creates a combined directory structure of the sources
      under the target directory in which all non-directories are
      symbolic links pointing back into the source directories.
      This is similar to the lndir(1) command of the X consortium.

      With the -d option, all sub-directories emptied of symbolic
      links under the target directory are removed, and all empty
      directories are removed if and only if the correspoding
      sub-directory under the source directory exists.

   -r Report the number of symbolic links and directories created,
      the number of calls and maximum depth of backstop, the
      maximum breadth observed by backstop, and the number of non-
      fatal errors encountered.  With the -d option, show the
      number of symbolic links and directories removed.

   -t Show the trace of program execution.  The output is a list
      of executable commands.

   -v The version of backstop.

   -y A synopsis of the internal manual page.

OPERANDS
   trgdir
      The directory that will be backed by other directories.  The
      target directory can be backed by multiple source directories
      where each source directory could be backed by yet another
      directory or multiple directories thereby creating an
      extensible backing chain.

   srcdir
      The directory which backs a target directory.  The source
      directory can be backed by multiple additional directories
      where each additional directory could be backed by yet another
      directory or multiple directories thereby creating an
      extensible backing chain.

USAGE NOTES
   Evolved with ghc 6.10, 6.12, 7.0, 7.4, 7.10, 8.0.2, and 8.4.1.
   Tested with 8.4.1.

EXAMPLES
   To display a summary of usage, use

      backstop -h

   To display a synopsis of this internal manual page, use

      backstop -y

   To display this internal manual page, use

      backstop -m

   To trace program execution, use

      backstop -t /export/install/sparc/devlopment/modules \
                  /export/install/sparc/modules

   To trace program execution taking no action, use

      backstop -n /export/install/sparc/devlopment/modules \
                  /export/install/sparc/modules

   To back /export/install/sparc/devlopment/modules with
   /export/install/sparc/modules using relative symbolic links, use

      backstop /export/install/sparc/devlopment/modules \
               /export/install/sparc/modules

   To back /export/install/sparc/devlopment/modules with
   /export/install/sparc/modules using absolute symbolic links, use

      backstop -a /export/install/sparc/devlopment/modules \
                  /export/install/sparc/modules

   To stop backing /export/install/sparc/devlopment/modules with
   /export/install/sparc/modules, use

      backstop -d /export/install/sparc/devlopment/modules \
                  /export/install/sparc/modules

ENVIRONMENT VARIABLES
   PAGER   Page the internal manual page or license terms
           using "${PAGER}", otherwise print it.

EXIT STATUS
   An exit status of 0 is returned if successful, otherwise non-zero
   is returned.  The following error exit codes are used by
   backstop:

       EXIT CODE    MEANING
          251       Less than two operands.
          252       Not a directory, that is, trgdir or one or more
                    of the srcdir are not a directory.
          253       Not parallel directories, that is, a srcdir is
                    a sub-directory of trgdir or vice versa, or one
                    of the srcdir is a sub-directory of another
                    srcdir.
          254       Not yet implemented.
          255       Non-fatal errors occurred.  Error messages are
                    sent to STDERR for each non-fatal error that
                    occurred with return code equal to the number of
                    non-falal errors if less than 251, otherwise the
                    return code is 255, that is, "infinity".

FILES
   N/A.

SEE ALSO
   ln(1), mkdir(1), rm(1), rmdir(1), ksh(1), lndir(1), realpath(3)

   "Source Control to Project Control: Applying RCS and SCCS" by Don
   Bolinger and Tan Bronson. ISBN 1-56592-117-8.

NOTES
   Please send bug reports to https://github.com/mdgabriel/backstop/issues.

BUGS
   No known bugs to date.
Metadata

Version

1.3.0.354

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows