Mercurial Queues Emulation for Git
Rev. | 1a53f0d998b3fb0ed2b9ba877996ad57a22b9783 |
---|---|
Size | 8,513 bytes |
Time | 2022-03-31 22:05:16 |
Author | Keith Marshall |
Log Message | Promote git-mq-1.0-rc-3 to final release status,
* configure.ac (AC_INIT): Set version number to 1.0
|
# git-qrefresh.shar
# ------------------------------------------------------------------------------
# Shell archive to deliver the implementation for the "git qrefresh" command.
# ------------------------------------------------------------------------------
#
# $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/>.
#
# ------------------------------------------------------------------------------
#
cat <<\ETX
#!/bin/sh
# ------------------------------------------------------------------------------
#
# git-qrefresh.sh: Implement the Git-MQ "git qrefresh" extension command.
#
# Update the current Git-MQ patch, to capture any changes within the working
# directory tree, and/or staged in git's index.
#
# $Id$
#
# ------------------------------------------------------------------------------
#
mq_facility="git qrefresh"
#
# 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 qrefresh [-e] [[[-m <text>] ...] | [-F <file>]] [-s] [-a | <path> ...]
Update the current topmost patch, to incorporate staged changes, and
optionally unstaged working tree changes, to tracked and/or specified
files.
--
a,all! add changes in unstaged tracked files
e,edit edit the commit message for the patch
F,file!= read replacement commit message from <file>
l,logfile!=* hg compatible alias for --file option
m,message!= replacement text for the commit message
s,short! short-list files already named in the patch
D,currentdate! record current date as effective patch date
d,date!= record specified date as effective patch date
u,user!= attribute patch to specified user
U,currentuser! attribute patch to current user"
ETX
# Incorporate the universal set-up code, which is common to all of the
# Git-MQ command implementations.
#
. ./git-mq-setup.shar
cat <<\ETX
# If this command proceeds to successful completion, it will perform
# a "git commit ...", for which the "--amend" option must be specified,
# so initialize the "mq_commit_opts" shell variable accordingly.
#
mq_commit_opts="--amend"
# The commit message definition options, "--message", "--logfile", or
# "--file", require a special validating interpreter, to ensure that no
# invalid combination is specified; this collects any valid sequence of
# such options into the "mq_msgopt" shell variable.
#
mq_require mq-message-opts
# Collect any other options, which have been specified on the command
# line, into the "mq_commit_opts" shell variable, so that we may pass
# them on to the "git commit" command.
#
while git_mq_getopt "$@"
do case $1 in
-e) mq_collect mq_commit_opts --edit ;;
-a) mq_refresh_all=true; mq_collect mq_commit_opts --all ;;
-F) mq_collect_valid_msgopt --file "$2"; shift ;;
-l) mq_collect_valid_msgopt --logfile "$2"; shift ;;
-m) mq_collect_valid_msgopt --message "$2"; shift ;;
-U) mq_commit_user="--reset-author" ;;
-u) mq_commit_user="--author='$2'"; shift ;;
-D) mq_commit_date="--date='`date '+%s %z'`'" ;;
-d) mq_commit_date="--date='$2'"; shift ;;
-s) mq_shortlist=true ;;
esac; shift
done
# 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_require git-mq-integrity-check fatal qtip HEAD
# In addition to the preceding integrity check, we also require that
# at least one patch, from within the queue, has been applied.
#
mq_patchname=`git qtop` || $fatal "no git-mq patches have been applied"
mq_patchfile="$mq_patchdir/$mq_patchname"
# We must also ensure that a log message is provided for the commit;
# if none was given via a command line option, then arrange to reuse
# whatever message was provided for the original patch.
#
test ${mq_msgopt+set} && mq_collect mq_commit_opts "$mq_msgopt" ||
mq_collect mq_commit_opts "-C qtip"
# We prefer to capture the updated patch into a temporary file,
# before finally updating the actual patch.
#
mq_require mq-tmpfile
mq_tmpfile mq_patchfile_tmp '`mktemp --tmpdir="$mq_patchdir"` ||
$fatal "cannot reserve temporary patch file storage"'
# Having rewritten the patch file, it is almost certain that its
# commit hash will have changed; thus we will also need to update
# the status file, via a further temporary file, to reflect this.
#
mq_tmpfile mq_status_file_tmp '`mktemp --tmpdir="$mq_patchdir"` ||
$fatal "cannot establish status file update cache"'
# In the simplest, and most common case, when no files have been
# either short-listed or specified, we may simply amend the topmost
# commit; however, when any files HAVE been specified, or have been
# short-listed, we first need to adjust git's index.
#
mq_adjust_index() { local mq_cached_files_list
mq_cached_files_list=`mq_cached_file_names "$2"`
test x"$mq_cached_files_list" = x || {
eval git reset --quiet "$2" -- $mq_cached_files_list
eval $1='"$mq_cached_files_list"'
}
}
mq_cached_file_names() {
git diff-index --name-only "$1" | awk '{print "\42"$0"\42"}'
}
# To perform any such adjustment, we require either a valid commit
# reference for the immediate parent of the topmost patch, which may
# be passed to the "git diff-index" command; failing this, we may
# substitute a dummy reference to an empty tree object.
#
{ test $# -gt 0 || ${mq_shortlist-false}; } && {
mq_parent_ref=`git rev-parse --quiet --verify qtip~1` || {
mq_parent_ref=`git hash-object -t tree /dev/null`
}
}
# When an explicit list of files is specified, and noting that this
# is not compatible with use of the "--all" option, we perform a two
# step adjustment, first resetting the index back to its state when
# the current patch was applied, and then separately, and provided
# the set of changes included within this patch is not implicitly
# specified, back to the state before the same patch was applied,
# before staging changes in the specified files.
#
if test $# -gt 0
then ${mq_refresh_all-false} && {
mq_abort 2 "error: named files not allowed with '--all' option"
}
mq_adjust_index mq_cached_files qtip
${mq_shortlist-false} && {
mq_shortlist_files=`mq_cached_file_names $mq_parent_ref`
eval git add $mq_shortlist_files
} || mq_adjust_index mq_shortlist_files $mq_parent_ref
git add "$@"
# Alternatively, when no files are explicitly specified, but those
# included within the current patch are implied, (by the "--short"
# option), it is sufficient to adjust back only to the index state
# as it was after this patch was applied; (again, noting that this
# is incompatible with use of the "--all" option).
#
elif ${mq_shortlist-false}
then ${mq_refresh_all-false} && {
mq_abort 2 "error: '--short' and '--all' options are incompatible"
}
mq_adjust_index mq_cached_files qtip
mq_shortlist_files=`mq_cached_file_names $mq_parent_ref`
eval git add $mq_shortlist_files
fi
# Hand off the actual commit, and subsequent patch generation, to the
# shared patch writing support module.
#
eval mq_require git-mq-write-patch $mq_shortlist_files $mq_cached_files
# Finally, since the commit hash for the refreshed patch will normally
# have changed, we must update the status file accordingly.
#
mq_map_control_file_refs "$mq_patchdir" status
awk -F: -v id=`git rev-parse --quiet --verify qtip` '
NR > 1 { print hold; } { hold = $0; } END { OFS = FS; $1 = id; print; }
' $mq_status_file > $mq_status_file_tmp
mq_update mq_status_file
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
ETX