# mq-push-reordered.sh
# ------------------------------------------------------------------------------
#
# Supplementary shell script; it implements the prerequisite checks, and
# patch series reordering logic to support "qpush --move" operations.
#
# ------------------------------------------------------------------------------
#
# $Id$
#
# Written by Keith Marshall <keith@users.osdn.me>
# Copyright (C) 2019, Keith Marshall
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ------------------------------------------------------------------------------
#
# To "move" a patch, within the series, requires rewriting of the series
# file, placing the moved patch reference as the first unguarded patch to
# follow the reference for the current topmost applied patch, (if there is
# any).  Rather than rewriting the series file in place, we will capture
# the change in a temporary file, with which we will then replace the
# series file when done.
#
  mq_require mq-tmpfile
  mq_tmpfile mq_series_file_tmp '`mktemp --tmpdir="$mq_patchdir"` ||
    $fatal "cannot create series file update cache"'

# The following awk script rewrites the series file content, taking care
# to emulate the behaviour of Mercurial's "hg qpush --move"; in particular:
#
#   - it will decline to move any patch reference for which the state is
#     recorded as "guarded";
#
#   - it will decline to move any patch reference from an earlier to a
#     later position in the series, even if its state is now recorded as
#     "unapplied", (possibly because its guard state has changed since
#     later patches were applied); (note that there does not seem to be
#     any compelling reason for this restriction, other than preserving
#     strict Mercurial compatibility);
#
#   - if any guarded patches appear, immediately following the topmost
#     "applied" patch, then the relocated reference will be placed such
#     that it immediately follows any such sequence of guarded patches,
#     provided that such relocation represents a movement to an earlier
#     position within the patch series; (once again, we do it this way
#     to maintain strict compatibility with Mercurial's behaviour).
#
  mq_require mq-why-guarded
  awk "$mq_guards $mq_series $mq_status
    $mq_error_handler $mq_function_why_guarded"'
    END { $0 = "'"$1"'";'"$mq_series_index_lookup"'
      if( (state[$1] != "U") || (applied >= entry[$1]) )
      { errout( "error", "patch \47" $1 "\47 cannot be applied;", "no-exit" );
	switch( state[$1] )
	{ case "A": errout( "error", "it has been applied already." );
	  case "G": $0 = series[entry[$1]];
	    errout( "error", why_guarded( "it is guarded by" ) "." );
	  default: errout( "error",
	    "it precedes the topmost applied patch in the series." );
	}
      } mark = entry[$1]; cache_file = "'"$mq_series_file_tmp"'";
      do { ++applied; $0 = series[applied]; } while( state[$1] == "G" );
      for( idx = 0; entries > idx; idx++ )
      { if( idx == applied ) print series[mark] > cache_file;
	if( idx != mark ) print series[idx] > cache_file;
      }
    }' "$mq_guards_file" "$mq_series_file" "$mq_status_file" &&
    mq_update mq_series_file || exit 1

# When the foregoing rewrite of the series file was successful, then
# the one patch which is to be applied will have been positioned such
# that it becomes the default for a "qpush" with no arguments; delete
# the residual argument, and allow the operation to continue on that
# default basis.
#
  set --
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
