1
0
mirror of synced 2026-01-12 00:42:56 +00:00
Interlisp.medley/scripts/restore-versions.sh

139 lines
3.6 KiB
Bash
Executable File

#!/bin/sh
# restore old versions from git repo
# For use after a rm-versions or in a newly cloned repo
# not guaranteed to return the SAME version as before
# but it tries when it can.
# version numbers follow git history
# LC_ALL is needed for tr to keep it from getting confused
export LC_ALL=C
file="$1"
# If given a directory, restore all versions from that directory
# There's a suble difference, bcause glob expansion won't try
# to reversion .git .github at top level.
if [ -d "$file" ]; then
for dir in "$file/"*[a-zA-Z0-9]
do echo restoring versions "$dir" && \
find "$dir" -type f -iname "*[a-z0-9]" -exec "$0" {} \;
done
exit 0
fi
if [ ! -f "$file" ]; then
echo no such file "$file"
exit 1
fi
# file already has versions?
for vfn in "$file".~[1-9]*~
do if [ -f "$vfn" ]; then
echo "Already has versions: " $vfn && \
exit 1
fi
done
#stash file and remember status
#The $stash remembers if it did something or not
stash=`git stash push -- $file 2>&1`
# max is the maximum version checked in as as separate
max=0
# find commits with explicit old versions
# In most cases there will be only one commit
# these versions are restored, and n is set to 1+max of them
# this is specific to our situation where we checked in some
# ~nn~ versions and then .gitignore *~ was set
for commit in `git log --remove-empty --reverse --format="%h" -- "$file.~[1-9]*~"`
do git checkout -q $commit "$file.~[1-9]*~" 2>/dev/null && \
for version in "$file".~[1-9]*~
do vn=`echo $version | sed 's/^.*\.~\([1-9][0-9]*\)~$/\1/'`
if [ ! -z $vn ]; then
vn=`expr $vn + 1`
if [ $max -lt $vn ]; then
max=$vn
fi
fi
done
done
# if file and max version are the same, link them
# this obsoletes medley-fix-links
if cmp -q $file $file.~$max~ >/dev/null 2>&1
then
rm $file.~$max~
ln $file $file.~$max~
fi
# $base is used to look for mentions of DSK versions
base=`basename "$file" .LCOM`
base=`basename "$base" .DFASL`
pattern='{DSK}.*'"$base"'\.\?;[1-9][0-9]*'
# Restore versions from git history. This process starts with
# the max from the previous calculation and would go up by 1, but it
# also prefers to restore files to their FILECREATED version
# number. It does this by looking for {DSK}...root.~nn~ and using nn
# as the version number if it isn't too small. It then makes a hard
# link (each time for each commit) since the checkout will break any
# old links
n=`expr $max + 1`
####
# !!!! if you don't want these post-github versions
# skip until end
# If you want things before the last delete, remove the '--remove empty'
####
for commit in `git log --remove-empty --reverse --format="%h" -- "$file"`
do git checkout -q $commit "$file" && \
fcv=`tr '\r' '\n' <"$file" | head -n 6 | grep -ai --max-count=1 --only-matching "$pattern"`
fcv=`echo $fcv | sed 's/^.*;\([1-9][0-9]*\)$/\1/'`
if [ ! -z $fcv ]; then
if [ $fcv -gt $n ]; then
n=$fcv
fi
fi
ln "$file" "$file.~"$n"~" && \
date=`git log $commit -1 --date=format-local:%Y%m%d%H%M.%S --pretty="format:%cd"` && \
echo $commit $file $n $date && \
touch -t $date "$file" "$file.~"$n"~" && \
n=`expr $n + 1`
done
### END SKIP
# if the 'stash' at the beginning did something, restore the stashed file
case $stash in
"error*" | "No local changes*")
;;
"*")
git stash pop -- "$file" && \
ln $file "$file.~"$n"~" && n=`expr $n + 1`
;;
esac
# if the result is only one version ;1 remove it
# Otherwise, make sure no versions are staged
if [ $n -eq 2 ]; then
rm -f "$file".~1~
else
git restore --staged "$file.~[1-9]*~" 2>/dev/null
fi