Merge pull request #352 from Interlisp/restore-versions
Add small util for restoring versions from git history
This commit is contained in:
commit
4fac4e3e96
134
scripts/restore-versions.sh
Executable file
134
scripts/restore-versions.sh
Executable file
@ -0,0 +1,134 @@
|
||||
#!/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"~" && 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user