#!/usr/bin/env bash
#
# Undo a commit or a series of commits.
# Copyright (c) Matt Porter, 2005
# Copyright (c) Petr Baudis, 2005
#
# Takes a commit ID which is the earliest commit to be removed from
# the repository. If no parameter is passed, it uncommits the latest
# commit ('HEAD'). Read the CAVEATS section before using it for the
# first time.
#
# OPTIONS
# -------
# -t::
#	This optional parameter makes `cg-admin-uncommit` to roll back
#	the tree as well to the previous commit. Without this option
#	(by default) 'Cogito' keeps the tree in its current state,
#	therefore generating tree with local changes against the target
#	commit, consisting of the changes in the rolled back commits.
#
# CAVEATS
# -------
# This command can be dangerous! It is safe to do as long as you do not
# push the commit out in the meantime, but you should 'NEVER' uncommit an
# already pushed out commit. Things will break for the fetchers since you
# just broke the fast-forward merging mechanism (the new commit is not
# descendant of the previous one), and the push command will refuse to
# push again after you uncommitted a pushed out commit, too. At the moment
# you pushed the commit out it's etched to the history, live with that.

USAGE="cg-admin-uncommit [-t] [COMMIT_ID]"
_git_requires_root=1

. ${COGITO_LIB}cg-Xlib || exit 1

[ -s $_git/blocked ] && die "uncommitting blocked: $(cat $_git/blocked)"

rollback_tree=
while optparse; do
	if optparse -t; then
		rollback_tree=1
	else
		optfail
	fi
done


base=$(cg-object-id -c) || exit 1

commit=$(cg-object-id -c "${ARGS[0]}") || exit 1
[ "$(git-rev-list ^$commit $base)" ] && \
	die "$commit: not an ancestor of HEAD"

parent=$(cg-object-id -p "$commit" | head -n 1) || exit 1
[ "$parent" ] || die "cannot rewind behind the initial commit"


echo "Rewinding $base (HEAD) -> $parent" >&2

tree_timewarp "backwards" "$rollback_tree" $base $parent
exit 0
