#!/bin/sh
# ------------------------------------------------------------------------------
#
# git-qdiff.sh: Implement the Git-MQ "git qdiff" extension command.
#
# Display a diff representing the content of the current topmost patch,
# augmented by any working directory changes made since the last refresh
# of that patch; effectively, this represents what the content of this
# patch will become following execution of "git qrefresh".
#
# $Id$
#
# ------------------------------------------------------------------------------
#
# I'd have liked to call this a "SYNOPSIS", (which is what it is), but git's
# git-sh-setup script requires the much less appropriate name "OPTIONS_SPEC",
# (which describes only a small subset of its actual content).
#
OPTIONS_SPEC="\
git qdiff [<option> ...] [<path> ...]

Display a diff representing the changes introduced by the current
topmost patch, and any additional changes within the working tree;
this is effectively the set of changes which will be incorporated
within the topmost patch, following \"git qrefresh\".
--
a,text!                 assume all files are text
U,unified!?             number of context lines to include
B,ignore-blank-lines!*  ignore changes comprising only blank lines
b,ignore-space-change!  ignore changes in amount of white space
w,ignore-all-space!     ignore white space when comparing lines

ignore-blank-lines!     ignore changes comprising only blank lines
ignore-space-at-eol!    ignore white space changes at end-of-line
stat!                   display a diffstat summary of changes"
#
# ------------------------------------------------------------------------------
#
# $Id$
#
# Written by Keith Marshall <keith@users.osdn.me>
# Copyright (C) 2018-2020, 2022, 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/>.
#
# ------------------------------------------------------------------------------
#
# Although they may not always have any effect, all Git-MQ commands, like
# their hg counterparts, are expected to accept the global verbosity, and
# colour control options; ensure that they are declared:
#
OPTIONS_SPEC="$OPTIONS_SPEC
colour?*     generic output colour control -- may have no effect"
${OPTION_VERBOSE_DEFINED-false} || OPTIONS_SPEC="$OPTIONS_SPEC
v,verbose!*  generic verbosity selector -- may have no effect"

# For Git-MQ options, such as "--colour", we prefer a spelling convention
# which conforms to "World English" standards; however, git itself adopts
# "US English" convention.  Thus, we must also accommodate users who will
# specify "--color" instead of "--colour", without creating any ambiguity
# in the possible abbreviations; to achieve this, we check for "--color",
# among the command-line arguments, replacing it with "--colour", BEFORE
# we allow git to parse them.
#
for mq_argv
do case "$mq_argv" in
     --color*) mq_argv=`echo $mq_argv | sed 's/^--colo/&u/'` ;;
     --no-color) mq_argv="--no-colour" ;;
   esac
   ${mq_argv_init-true} && { set -- "$mq_argv"; mq_argv_init=false
   } || set -- "$@" "$mq_argv"
done

# Now, we may let git parse the command line, and set up its shell script
# processing environment, for use within a git working directory tree.
#
SUBDIRECTORY_OK=true . "`git --exec-path`/git-sh-setup" && require_work_tree

libexecdir=`dirname "$0"`
test `basename "$libexecdir"` = bin && libexecdir=`dirname "$libexecdir"`
libexecdir="$libexecdir/libexec/git-mq/${VERSION=1.0}"

mq_require(){ test -f "$1" || die "fatal: '$1' not found."; . "$1"; }
mq_require "$libexecdir/git-mq-setup.sh"

# Collect any options, which have been specified on the command line,
# into the "mq_diff_opts" shell variable, so that we may pass them on
# to the "git diff" command; in any case, we implicitly assume that
# the "--ignore-submodules" option is present.
#
mq_diff_opts="--ignore-submodules"; while git_mq_getopt "$@"
do case $1 in
     -U*) # Note that we need special handling when the "-U" (a.k.a.
	  # "--unified") option is specified, because parsing by (at
	  # least some versions of) "git rev-parse" incorrectly detach
	  # any optional argument, which may follow it; we recognize
	  # that any valid optional argument should not exhibit an
	  # initial hyphen, and any following argument which does
	  # must indicate absence of the optional argument, so any
	  # such argument must be left for option matching, while
	  # any which does not must be reattached.
	  #
	  case $2 in -*) mq_collect mq_diff_opts $1 ;;
	    *) mq_collect mq_diff_opts $1$2; shift ;;
	  esac ;;

      # All other options are simply collected verbatim...
      #
     -a | -b | -w | --ignore* | --stat) mq_collect mq_diff_opts $1 ;;

      # ...except that the "-B" option, as understood by "hg qdiff",
      # has a different meaning to "git diff", so we collect it in its
      # long form, which is interpreted similarly in both cases.
      #
     -B) mq_collect mq_diff_opts --ignore-blank-lines ;;
   esac; shift
done

# The "--color" option also requires special handling.  It is handled
# internally, by "git_mq_getopt", but we also need to collect it into
# the "mq_diff_opts" shell variable.
#
test "${mq_colour+set}" = "set" && mq_collect mq_diff_opts --color=$mq_colour

# Before proceeding any further, we must verify the integrity of the
# patch queue; if any patches have been applied, then the "qtip" tag
# MUST refer to the HEAD commit.
#
mq_facility="git qdiff"
mq_require git-mq-integrity-check fatal qtip HEAD
mq_fatal="mq_abort 2 fatal:"

# In addition to the preceding integrity check, we also require that
# at least one patch, from within the queue, has been applied.
#
mq_top=`git qtop` || $mq_fatal "no Git-MQ managed patches have been applied"

# The required "git qdiff" patch is simply the difference in state
# between the immediate parent commit of the topmost patch, when any
# such parent commit exists, or an empty tree object if not.
#
mq_immediate_parent_ref=`git rev-parse --quiet --verify $mq_top~1` ||
  mq_immediate_parent_ref=`git hash-object -t tree /dev/null`

git diff $mq_diff_opts $mq_immediate_parent_ref ${1+"--"} "$@"
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
