# mq-setup.sh
# ------------------------------------------------------------------------------
#
# Initialization hook for the mingw-pkg mq plugin.  All components of the
# mingw-pkg mq plugin source this; additionally, it may be sourced by other
# free-standing mq emulation packages, (such as git-mq), typically sourced
# indirectly, via their own package-specific initialization hooks.
#
# ------------------------------------------------------------------------------
#
# $Id$
#
# Written by Keith Marshall <keith@users.osdn.me>
# Copyright (C) 2018, 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.
#
# ------------------------------------------------------------------------------
#
# If sourced by mingw-pkg's mq plugin, this will have been requested by
# mingw-pkg's "require plugin ..." command; map "mq_require" to preserve
# this loading strategy...
#
  if test "$1" = plugin
  then
    mq_require(){ require plugin "mq/$@"; }

# ...otherwise, we assume that the requesting package has specified its
# own $libexecdir path; map "mq_require" to load additional plugin files
# directly from the designated $libexecdir directory; (note that, in any
# "mq_require" call, any arguments which we wish to pass to the plugin
# will be prefaced by the plugin name; discard that here).
#
  else
    mq_require(){
      local required="$libexecdir/$1.sh"; shift
      test -f "$required" || die "fatal: '$required' not found."
      . "$required"
    }
  fi

# The following function provides a mechanism for mapping shell variables
# as references to the control files, (series, status, and guards files),
# within the preceding patch directory, (for which the path name must be
# passed as first argument, followed by a list of control file names).
#
  mq_map_control_file_refs(){
    local ref dir="$1"; shift; for ref
    do test -f "$dir/$ref" && eval mq_$ref'_file="'"$dir/$ref"'"' \
	|| eval mq_$ref'_file="/dev/null"'
    done
  }

# The following awk script fragments are provided, to standardize the
# interpretation of the content of the series, status, and guards control
# file contents, across all patch queue management functions.
#
  mq_guards='
    FILENAME ~ /guards$/ {
    # Construct a list of currently active guards, as specified
    # by the content of the "guards" file.
    #
      for( i = 1; NF >= i; i++ ) guard[$i] = 1;
    }'

  mq_series='
    BEGIN { entries = 0; }
    FILENAME ~ /series$/ {
    # Construct a serialized, indexed, and cross-referenced list of
    # registered patches, from the content of the "series" file.
    #
      entry[$1] = entries; series[entries++] = $0;
      state[$1] = guard_state( "U" );
    }
    function guard_state( value, idx ) {
    # Called for each "series" file entry, as it is read, test each
    # associated guard against the list of active guards, to determine
    # if a patch is to be excluded by any such guard; (requires that
    # the "guards" file is parsed before the "series" file).
    #
      for( idx = 2; NF >= idx && value == "U"; idx++ )
	switch( substr( $idx, 1, 2 ) )
	{ case "#+": if( ! guard[substr( $idx, 3 )] ) value = "G"; break;
	  case "#-": if( guard[substr( $idx, 3 )] ) value = "G"; break;
	}
      return value;
    }'

  mq_status='
    BEGIN { FS="[: ]"; applied = prev = -1; }
    FILENAME ~ /status$/ {
    # Update the state of each entry in the serialized list of
    # patches, from the content of the "status" file, to reflect
    # which patches have been applied, and record the indicies of
    # the most recently applied, and its predecessor; (requires
    # the "series" file to have been parsed before "status").
    #
      state[$2] = "A"; if( entry[$2] > applied ) {
	prev = applied; applied = entry[$2];
      }
    }'
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
