# git-mq-write-patch.sh
# ------------------------------------------------------------------------------
#
# Supplementary shell script fragment; invoked via "mq_require", it commits
# a changeset reflecting the state of the index, and writes a corresponding
# Git-MQ patch file.
#
# ------------------------------------------------------------------------------
#
# $Id$
#
# Written by Keith Marshall <keith@users.osdn.me>
# Copyright (C) 2019, 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/>.
#
# ------------------------------------------------------------------------------
#
# If refreshing an existing patch, then before proceeding with the
# update, ensure that any fixed date, or user assignments, which are
# already specified within its header, unless overridden for this
# invocation, are preserved.
#
  test -f "$mq_patchfile" && eval `awk '$1 != "#" { exit 0; }
    function option(name){ return "--" name "=\47" trim($0) "\47"; }
    function assign(var, txt){ print var "=${" var "-\42" txt "\42}";}
    function trim(txt){ sub(/^ */,"",txt); sub(/ *$/,"",txt); return txt; }
    $2 == "User" { $1 = $2 = ""; assign( "mq_commit_user", option("author") ); }
    $2 == "Date" { $1 = $2 = ""; assign( "mq_commit_date", option("date") ); }
  ' "$mq_patchfile"`

# If the preceding check, or any given command option, has resulted
# in an assignment for the patch date or author, then these must be
# propagated to the commit which will refresh the patch.
#
  eval ${mq_commit_date+'mq_collect mq_commit_opts "$mq_commit_date"'}
  eval ${mq_commit_user+'mq_collect mq_commit_opts "$mq_commit_user"'}

# Conversely, when performing a "git qfold", or a "git qrefresh", if
# the "mq_commit_date" has not be pre-assigned, we must set the date
# for the amended commit, to reflect the current date and time.
#
  case "$mq_facility" in "git qfold" | "git qrefresh")
    test -n "$mq_commit_date" ||
      mq_collect mq_commit_opts "--date='`date +'%s %z'`'"
    ;;
  esac

# We are now ready to create, or amend, the commit, whence the patch
# file itself will be generated; note that the handling of file name
# arguments differs between "git qnew", in which case "mq_args" will
# be defined, and other callers of this patch writing module.
#
  mq_argv=${mq_argv+'${1+"$@"}'}
  eval git commit --quiet --no-verify "$mq_commit_opts" $mq_argv || exit $?

# Following the commit, if the associated log message is anything
# other than the fall-back "[Git-MQ]: patchname" text, then we must
# ensure that it will be preserved within the patch header.
#
  local mq_logmsg="`git show --pretty='format:%B' --no-patch`"
  test "$mq_logmsg" = "[Git-MQ]: $mq_patchname" || mq_msgopt=true

# When amending a commit, to incorporate refreshed or folded patch
# content, reassign the "qtip" tag, and its associated patch ID tag,
# so that they point to the amended patch commit, then clean up the
# abandoned garbage, which will have been left over from the former
# commit of this patch.  Additionally, if we made any preparatory
# adjustments to git's index, we must now restore as much of the
# original index state as remains viable, after the commit.
#
  case "$mq_facility" in "git qfold" | "git qrefresh")
    test $# -gt 0 && git add "$@"
    for mq_tag in `git tag --points-at qtip`
      do git tag --force $mq_tag > /dev/null 2>&1; done
    git reflog expire --expire-unreachable=all --rewrite --all
    git prune --expire=now ;;
  esac

# Write, or rewrite the patch file, capturing user ID, date, and
# parent hash records within the header, as appropriate.
#
  mq_msgopt=${mq_msgopt+"%+B"}
  mq_commit_user=${mq_commit_user+"# User %aN <%aE>%n"}
  mq_commit_date=${mq_commit_date+"# Date %at `date +%z`%n"}

  mq_parent_hash=`git rev-parse --quiet --verify qtip~1` ||
    mq_parent_hash=`printf %040d 0`

  mq_patch_header="# Git-MQ patch%n$mq_commit_date$mq_commit_user"
  mq_patch_header="$mq_patch_header# Parent $mq_parent_hash$mq_msgopt"

  git show --pretty=format:"$mq_patch_header" > "$mq_patchfile_tmp" && {
    mq_update mq_patchfile
  }
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
