Files listed in @config are installed in /var/db/etc/ using the name dir1::dir2::dir3:: for /dir1/dir2/dir3/filename The files are recorded in /var/db/etc/etcmerge-FILENAMES (using etcmerge-FILENAMES.lock as a lockfile) when a new package is registered. Each line in this has the following format: * To make this file simple to work with during port installs, the ports can add lines to the file, and only the last line will matter. etcmerge will clean this up during a run. For example, if you have /usr/local/etc/todorc and this was previously named /usr/local/share/todo/rc and before that /usr/local/share/todorc, and you have not run etcmerge in the meantime, the file will contain /usr/local/share/todorc /usr/local/share/todo/rc /usr/local/share/todorc /usr/local/etc/todorc /usr/local/share/todo/rc /usr/local/share/todorc When etcmerge is run, this would be resolved to only /usr/local/etc/todorc /usr/local/share/todo/rc /usr/local/share/todorc When a new package is installed, the following happens (pseudocode) for line in [configlines]; do line=$(echo $line | sed -e 's/^@config //') # Get first filename on the line filename=$(echo $line | sed -e 's/ .*//') # Copy in dist file as configuration if no configuration # exists if [ ! -e $filename ]; then cp ${filename}-dist $filename cp ${filename}-dist /var/db/etc/$(echo $filename | sed 's|/|::|g') fi lock /var/db/etc/etcmerge-FILENAMES.lock echo $line >> /var/db/etc/etcmerge-FILENAMES done When a package is de-installed, the following happens (pseudocode) for line in [configlines]; do filename=$(echo $line | sed -e 's/^@config //' -e 's/ .*//') if cmp -s ${filename} ${filename}-dist; then rm -f ${filename} fi done When merging: The last line for the config file in question is gone through in order; the first of the matches is used as a reference file for a 3-way merge. The output of the 3-way merge is stored in a "new etc", under a standard resolved dir, but with all files resolved using :: "path separators". The change to using ::-separation makes all config files available directly under /var/db/etc, thus avoiding massive directory trees when introducing handling of ports[1]. If there is no reference file, etcmerge will record any conflict between the reference file and the installed file in the standard directory for this (etc-conflicts in the work directory.)[2] etcmerge install will then install all merged files. [1] The introduction of ::-separation also makes it necessary to introduce 'etcmerge diff', as the previous technique of using 'diff -ur /etc etc-merged' no longer works. [2] etcmerge needs to grow a way to resolve 2-way conflicts, like mergemaster does. Previously, this has not been necessary, as we'd be able to assume a decent set of reference files, but if etcmerge is to work on previously installed files, we also need to support 2-way merges.