Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

convert old/ directory to git history

So one of my old ways, that I still use, of simple configuration management/history of a file is to bup (short for backup) it to an old/ directory right where the file is. That is, /etc/httpd/httpd.conf goes to /etc/httpd/old/httpd.conf.2024-05-09.01 for example.

You can find my bup script in the source of my bgscripts package.

Anyway, so now that I have years and years worth of changes to compare, of say my Devuan preseed file, but only stored in this old/ directory method, I wanted to be able to visualize some of the changes.

So I whipped up this script, and then threw the results into my cgit for myself.

files/2024/listings/convert-bup-to-git.sh (Source)

#/bin/sh
# File: convert-bup-to-git.sh
# Location: blog exclusive
# Author: bgstack15
# SPDX-License-Identifier: GPL-3.0-only
# Startdate: 2024-04-15-2 10:03
# Title: Convert Bup directory to git history
# Purpose: turn an old/ directory full of FILE.YYYY-MM-DD.[0-]{1,2} files into a git history so I can visualize with cgit
# History:
# Usage:
#    INDIR=/path/to/scripts/old
#    Optional:
#       WORKDIR if not set, will use ${INDIR}/to-git/
#       VERBOSE
#       INFILE if not set, will find most-used filename prefix in INDIR.
# Reference: https://bgstack15.ddns.net/blog/posts/2024/05/09/convert-old-directory-to-git-history
# Improve:
# Documentation:
#    This only works against one file exactly.
# Dependencies: git, find
test -z "${INDIR}" && test -n "${1}" && INDIR="${1}"
test -z "${INDIR}" && { echo "Fatal! Need INDIR or \$1 provided. Aborted." ; exit 1 ; }
# find the intended file if not provided
if test -z "${INFILE}" ;
then
   if test -n "${2}" ;
   then
      INFILE="${2}"
   else
      # find the intended file by counting the most common filename prefix
      # this YYYY-MM-DD format in the sed expression is from bup and thankfully exactly what I want to search for and I do not need a more general solution.
      # use an awk trick to count unique occurrences, and then sort, and then print the filename of the first one. If there is a comma in the filename that could be a problem but thankfully I avoid those in general, and particuarly for source code files such as what I would want to convert to an scm history.
      INFILE="$( find "${INDIR}" -maxdepth 1 -mindepth 1 ! -type d -printf '%f\n' | sed -r -e "s/\.[0-9]{4}(-[0-9]{2}){2}\.[0-9]{2}//" | awk 'BEGIN{OFS=","} !x[$0]++{} END{for(i in x)print x[i],i}' | sort -r -n -k1 | awk -F',' 'NR==1{print $NF}' )"
   fi
fi
# prepare the workdir
if test -z "${WORKDIR}" ;
then
   if test -n "${3}" ;
   then
      WORKDIR="${3}"
   else
      WORKDIR="${INDIR}/to-git"
   fi
fi
export WORKDIR
test -n "${VERBOSE}" && {
   echo "Using INDIR=${INDIR}, INFILE=${INFILE}, WORKDIR=${WORKDIR}" 1>&2
}
# main
# loop through all files that match
mkdir -p "${WORKDIR}" ; cd "${WORKDIR}" ; git init .
find "${INDIR}" -maxdepth 1 -mindepth 1 ! -type d -iname "${INFILE}*" -printf "%T@ %f\n" | sort -k1 -n | while read a b ;
do
   cp -pf "${INDIR}/${b}" "${INFILE}"
   git add "${INFILE}"
   GIT_AUTHOR_DATE="@${a}" GIT_COMMITTER_DATE="@${a}" git commit -m "changes for day"
done

It's not perfect, and I should bother to find a way to easily rewrite the whole history after adding useful commit comments, but today is not that day.

Comments