# git-qpop-backend.sh
# ------------------------------------------------------------------------------
#
# Script to handle the "git qpop" operation, either when invoked directly,
# or on behalf of any other command which must pop patches from the stack.
#
# ------------------------------------------------------------------------------
#
# $Id$
#
# Written by Keith Marshall <keith@users.osdn.me>
# Copyright (C) 2019, Keith Marshall
#
#
# This file is part of the Git-MQ program suite.
#
# The Git-MQ program suite is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public Licence
# as published by the Free Software Foundation, either version 3 of
# the Licence, or (at your option) any later version.
#
# The Git-MQ program suite is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public Licence for more details.
#
# You should have received a copy of the GNU General Public Licence
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# ------------------------------------------------------------------------------
#
# On successful removal of patches, from the applied stack, we will need to
# rewrite the status file; initialize a temporary file, in which to capture
# the rewritten content.
#
  mq_require mq-tmpfile
  mq_tmpfile mq_status_file_tmp '`mktemp --tmpdir="$mq_patchdir"` ||
    $fatal "cannot establish status file update cache"'

# The actual "git qpop" operation is implemented by means of this dynamically
# generated awk script, operating on the guards, series, and status files, in
# conjunction with the git repository and associated patch files.
#
  awk "$mq_guards $mq_series $mq_status $mq_error_handler"'
    END { if( applied < 0 )
      errout( "error", "nothing to pop: no patches have been applied." );
    entry["qparent"] = -1; state["qparent"] = "A";
    $0 = "'"${1-${mq_push_pop_all+qparent}}"'";
    if( NF == 0 )
    { if( prev >= 0 ) $0 = series[prev]; else $0 = "qparent";
    }'"$mq_series_index_lookup"'
    if( (entry[$1] >= applied) || (state[$1] != "A") )
    { if( entry[$1] == applied )
	errout( "error", "\47" $1 "\47 is already the topmost applied patch." );
      else errout( "error", "patch \47" $1 "\47 has not been applied." );
    }'"
    $mq_assert"'facility = "'"$mq_facility"'"; idx0 = entry[$1];
    for( idx = applied; idx > idx0; idx-- )
    { $0 = series[idx]; if( state[$1] == "A" )
      { system( "git tag --delete > /dev/null 2>&1 " $1 );
	print facility ": popping patch \47" $1 "\47";
      }
    }
    do { $0 = series[idx];
	 if( state[$1] == "A" )
	 { system( "git tag --force qtip > /dev/null 2>&1 " $1 );
	   print facility ": \47" $1 "\47 is now the topmost applied patch.";
	   system( "git reset --hard qtip > /dev/null 2>&1" );
	 }
       } while( (state[$1] != "A") && (--idx >= idx0 ) );
    if( idx < 0 )
    { print facility ": no applied patches remain.";
      system( "git tag --delete qbase > /dev/null 2>&1" );
      system( "git tag --delete qtip > /dev/null 2>&1" );
      if( system( "git rev-parse --quiet --verify qparent -- > /dev/null" ) == 0 )
      { system( "git reset --hard qparent > /dev/null 2>&1" );
	system( "git tag --delete qparent > /dev/null 2>&1" );
      }
      else
      { while( (("git branch" | getline) > 0) && ($1 != "*") );
	if( $1 == "*" )
	{ system( "git checkout --quiet --orphan git-mq.tmp" );
	  system( "git branch --quiet -D " $2 );
	  system( "git checkout --quiet --orphan " $2 );
	  system( "git reset --quiet --hard" );
	}
      }
    }
    else while( idx >= 0 )
    { $0 = series[idx--]; if( state[$1] == "A" )
      { getline < "'"$mq_status_file"'"; print > "'"$mq_status_file_tmp"'"; }
    }
    system( "git reflog expire --expire-unreachable=all --rewrite --all" );
    system( "git prune --expire=now" );
  }' "$mq_guards_file" "$mq_series_file" "$mq_status_file" \
  && mq_update mq_status_file || rm -f "$mq_status_file_tmp"

# Avoid a profligate accumulation of worthless "reset: moving to qtip",
# or "reset: moving to qparent" entries in git's reference log.
#
  git reflog 2> /dev/null | sed 1q | awk '/HEAD@\{0\}: reset: moving to q/ {
    if( (NF == 6) && ($NF == "qtip") || ($NF == "qparent") )
    { sub( ":$", "", $2 ); system( "git reflog delete --rewrite " $2 ); }
  }'
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
