Software by Jeff Bourdier

Plunge

Plunge is a command-line utility for Windows and Linux that is used to synchronize sets of files. (Don't just sync; Plunge!) It is a native application (written in C), and its only dependency is the C standard library. It is free, open-source software (FOSS), distributed under the MIT License. (In a nutshell, you can do whatever you want with it, so long as it retains the copyright notice.)

Plunge may be thought of as an extremely lightweight, portable version of Rsync. The typical use case is as follows: You have two sets of files that you wish to keep synchronized. One (the source) is the "master" set that you edit regularly and is generally up to date. The other (the destination) is a redundant set (e.g., a backup). From time to time, you'd like to run a command that compares each file in the one set to its counterpart in the other set, detects changes in size and timestamp, and copies each file from the source to the destination as necessary to bring the two sets in sync.

Usage

plunge [OPTION]... SOURCE DEST

SOURCE and DEST are the full pathnames of the source and destination directories (respectively). Each pathname may or may not end with a path separator (\ or /). Plunge then reads standard input (stdin) for a list of file pathnames relative to the source and destination directories. When end-of-file (EOF) is reached, each file in SOURCE is compared with its counterpart in DEST. If the SOURCE file is newer than the DEST file, or if the DEST file does not exist, the DEST file is overwritten with the SOURCE file; otherwise, no action is taken.

Options

-h, --help
Output a help message and exit.
-n, --dry-run
Do not actually copy files; just output the messages. This may be useful for examining the proposed actions and making sure there are no surprises.
-p, --purge
Report files in the destination directory that may need to be purged (i.e., because there are no corresponding files in the source directory).
-v, --verbose
Output messages for all files, whether copied or skipped. (By default, a message is output only when a file is copied, not when it is skipped.)

Example

Let's say you're developing a QGIS plugin (such as the PipelineML GeoPackager). You might have the following set of files for the GitHub repository:

C:\Users\Jeff\Documents\GitHub\pml-geopackager\__init__.py
C:\Users\Jeff\Documents\GitHub\pml-geopackager\algorithm.py
C:\Users\Jeff\Documents\GitHub\pml-geopackager\metadata.txt
C:\Users\Jeff\Documents\GitHub\pml-geopackager\plugin.py
C:\Users\Jeff\Documents\GitHub\pml-geopackager\provider.py
C:\Users\Jeff\Documents\GitHub\pml-geopackager\img\icon.svg
C:\Users\Jeff\Documents\GitHub\pml-geopackager\img\pml.svg

In order to test the plugin, you need a copy of each of these files in your QGIS plugin path:

C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\__init__.py
C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\algorithm.py
C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\metadata.txt
C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\plugin.py
C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\provider.py
C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\img\icon.svg
C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager\img\pml.svg

After making changes to these files, you might run:

plunge -v C:\Users\Jeff\Documents\GitHub\pml-geopackager C:\Users\Jeff\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\pml_geopackager < plunge.txt

The contents of plunge.txt would be:

__init__.py
algorithm.py
metadata.txt
plugin.py
provider.py
img/icon.svg
img/pml.svg

Typical output might be:

                     Pathname                             Status        Action
--------------------------------------------------  ------------------  ------
__init__.py . . . . . . . . . . . . . . . . . . . . Same age . . . . . . Skip
algorithm.py. . . . . . . . . . . . . . . . . . . . Src newer & larger . Copy
metadata.txt. . . . . . . . . . . . . . . . . . . . Src newer. . . . . . Copy
plugin.py . . . . . . . . . . . . . . . . . . . . . Same age . . . . . . Skip
provider.py . . . . . . . . . . . . . . . . . . . . Src newer. . . . . . Copy
img\icon.svg. . . . . . . . . . . . . . . . . . . . Dst not found. . . . Copy
img\pml.svg . . . . . . . . . . . . . . . . . . . . Dst not found. . . . Copy

Without the verbose (-v) option, output would be:

                         Pathname                                 Status
----------------------------------------------------------  ------------------
algorithm.py. . . . . . . . . . . . . . . . . . . . . . . . Newer and larger
metadata.txt. . . . . . . . . . . . . . . . . . . . . . . . Newer (not larger)
provider.py . . . . . . . . . . . . . . . . . . . . . . . . Newer (not larger)
img\icon.svg. . . . . . . . . . . . . . . . . . . . . . . . New
img\pml.svg . . . . . . . . . . . . . . . . . . . . . . . . New

Download

Plunge can be downloaded from its GitHub repository, where there are instructions on how to build it from source code.