• R/O
  • HTTP
  • SSH
  • HTTPS

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Mercurial Queues Emulation for Git


File Info

修訂. 1a53f0d998b3fb0ed2b9ba877996ad57a22b9783
大小 11,215 bytes
時間 2022-03-31 22:05:16
作者 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
* All files (v1.0-final): Tag assigned; excepting copyright
assignment corrections, none are changed from v1.0-rc-3.

Content

# git-qnew.shar
# ------------------------------------------------------------------------------
# Shell archive to deliver the implementation for the "git qnew" command.
# ------------------------------------------------------------------------------
#
# $Id$
#
# Written by Keith Marshall <keith@users.osdn.me>
# Copyright (C) 2018, 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-qnew.sh: Implement the Git-MQ "git qnew" extension command.
#
# Create a new patch, and push it on to the patch series stack.  Essentially,
# this emulates Mercurial's "hg qnew" command; however, it provides additional
# capabilities to accommodate complexity arising from Git's index.
#
# $Id$
#
# ------------------------------------------------------------------------------
#
mq_facility="git qnew"
#
# 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 qnew [-e] [[[-m <text>] ...] | [-F <file>]] <patch> [<file> ...]

Create a new patch, and push it on to the top of the patch series stack.
--
e,edit!         edit commit message
F,file!=        read commit message from nominated file
l,logfile!=*    hg compatible alias for --file option
m,message!=     specify text for commit message
D,currentdate!  record current date within patch, as commit date
d,date!=        record specified date as patch commit date
U,currentuser!  record current user as patch author
u,user!=        record specified user as patch author
a,all!          include all modified tracked files"
ETX

# Incorporate the universal set-up code, which is common to all of the
# Git-MQ command implementations.
#
. ./git-mq-setup.shar

cat <<\ETX
# Regardless of any options specified by the user, we must be prepared
# to commit an empty patch.
#
mq_commit_opts="--allow-empty"

# 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

# Process any options which the user may have specified on the command
# line; shift them out of the way, leaving only non-option arguments.
#
while git_mq_getopt "$@"
  do case $1 in
       -e) mq_collect mq_commit_opts "--edit" ;;
       -a) mq_commit_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 ;;
       -d) mq_commit_date="--date='$2'"; shift ;;
       -D) mq_commit_date="--date='`date '+%s %z'`'" ;;
       -u) mq_commit_user="--author='$2'"; shift ;;
       -U) mq_commit_user="" ;;
     esac; shift
  done

# After processing any command line options, there must be at least
# one argument remaining, representing the patch name...
#
test $# -gt 0 || $fatal "no patch name specified
`usage | sed 1q`"

# ...and no patch, with that name, may yet exist in the currently
# active patch queue directory.
#
mq_patchname="$1" mq_patchfile="$mq_patchdir/$1"
test -f "$mq_patchfile" && $fatal "patch '$1' already exists."

# Furthermore, no entry for the named patch may exist within the
# series file; (any such entry would represent an inconsistency in
# the patch series meta-data).
#
test -f "$mq_patchdir/series" && {
  awk '$1 == "'"$1"'" {exit 1}' "$mq_patchdir/series" ||
    $fatal "entry for patch '$1' exists in series file."
}

# When any patches have been applied already...
#
if git qtop > /dev/null 2>&1
then
# ...we should already have a 'qbase' tag, representing the commit for
# the first applied patch, and similarly, a 'qtip' tag representing the
# current topmost patch, on top of which we will now push this new one.
#
  git_mq_require_tag() {
    eval mq_$1'_hash=`git rev-parse --quiet --verify '$1'`' ||
      eval "$fatal \"cannot resolve '$1' reference for '`eval $2`'\""
  }
  git_mq_require_tag qbase 'git qapplied | sed 1q'
  git_mq_require_tag qtip 'git qtop'

else
# Conversely, when no patches have been applied, neither the preceding
# tags, nor any 'qparent' tag, should have been defined...
#
  for mq_tag in qparent qbase qtip
  do git rev-parse --quiet --verify $mq_tag > /dev/null &&
     $fatal "tag '$mq_tag' exists, but no patches applied."
  done

# ...but any existing 'HEAD' reference will become the effective 'qtip',
# on top of which the new patch will be pushed, and to which the 'qparent'
# tag will then point; (if no such 'HEAD' reference exists, then the patch
# will become the first commit on its unborn branch, and no 'qparent' tag
# will be assigned).
#
  mq_qtip_hash=`git rev-parse --quiet --verify HEAD` &&
    mq_qparent_hash=$mq_qtip_hash || mq_qtip_hash=`printf %040d 0`
fi

# Before actually changing anything, within the git repository, ensure
# that we can create an intermediate file, in the appropriate directory,
# in which to store the associated patch content.
#
mq_require mq-tmpfile
test -d "$mq_patchdir" || mkdir -p "$mq_patchdir" || exit 2
mq_tmpfile mq_patchfile_tmp '`mktemp --tmpdir="$mq_patchdir"` ||
  $fatal "cannot create intermediate patch file"'

# Also, ensure that we can create a temporary file, in which to cache
# updates to the patch queue series file.
#
mq_tmpfile mq_series_file_tmp '`mktemp --tmpdir="$mq_patchdir"` ||
  $fatal "cannot establish series file update cache"'

# If any further arguments are specified, following the patch name,
# they must be interpreted as a list of files to be included in the
# patch; drop the patch name argument itself, and any "--" separator
# which may have been included to conform to git convention, leaving
# just the list of files, which becomes the basis for patch content.
#
# Note: this is not compatible with use of the "--all" option; when
# allowed, all specified files must be accessible under "$GIT_ROOT",
# and must already be tracked by git.  We may use "git ls-files" to
# detect exceptions to the former requirement, but, by default, it
# will silently ignore exceptions to the latter; thus, in addition
# to the "ls-files" check, we loop over the argument list to check
# for accessibility of all specified files.  Having performed these
# checks, we then run "git ls-files" again, to silently filter out
# any files which are not tracked.
#
shift
while test "x${1}x" = "x--x"; do shift; done
test $# -gt 0 && {
  ${mq_commit_all-false} && {
    mq_abort 2 "error: named files not allowed with '--all' option"
  }
  mq_status=`git ls-files "$@" 2>&1 > /dev/null | awk '{ print $1, $3 }'`
  test "$mq_status" && mq_abort 2 "$mq_status is not under '$GIT_ROOT'"
  for mq_arg
    do test -r "$mq_arg" || $fatal "'$mq_arg' is not accessible"
    done
  eval set -- `git ls-files "$@" | awk '{ print "\47" $0 "\47" }'`

# After checking accessibility of specified files, under "$GIT_ROOT",
# and reducing the list to include only tracked files, there may now
# be none left.  This requires special handling, since it implies a
# request to create an empty patch: to achieve this, we must back up
# and clear any already staged changes, from git's index, allowing
# us to commit the empty patch content, and subsequently restore
# the index state when we have finished.
#
  test $# -gt 0 || {
    git update-index -q --ignore-submodules --refresh
    git diff --quiet --cached --ignore-submodules || {
      mq_cache_backup=`mktemp` || $fatal "cannot create index backup cache"
      git diff --cached --ignore-submodules > "$mq_cache_backup"
      git reset --quiet -- `git diff --cached --name-only --ignore-submodules`
      mq_require mq-atexit "mq_cache_restore '$mq_cache_backup'"
      mq_cache_restore() { git apply --cached "$1"; rm "$1"; }
    }
  }
}

# Fold any user specified log message options into the primary
# commit options set; if no log message specified, substitute a
# suitable default.
#
test ${mq_msgopt+set} && mq_collect mq_commit_opts "$mq_msgopt" ||
  mq_collect mq_commit_opts "--message '[Git-MQ]: $mq_patchname'"

# Delegate the commit, and subsequent patch generation, to the patch
# writing module, advising that any passed arguments are to be used in
# the commit command invocation.
#
mq_argv=commit mq_require git-mq-write-patch ${1+"$@"}

# Assign tags to facilitate tracking of applied patches; (note that each
# patch is individually tagged with its own name, and also the "qtip" tag,
# which will always move to the patch at the top of the series stack; the
# "qbase" tag is also assigned, if it doesn't yet exist, on the basis of
# an inference that the current patch is the first to be applied, and in
# this case, the "qparent" tag is also assigned to the preceding "HEAD",
# if any such commit exists).
#
git tag "$mq_patchname"
test "x$mq_qparent_hash" = x || git tag qparent $mq_qparent_hash
git rev-parse --quiet --verify qbase > /dev/null || git tag qbase
git tag --force qtip > /dev/null

# Update the series file, inserting an entry for the new patch; (notice
# that we had previously verified that no such entry existed beforehand).
# We capture the update in the previously created temporary cache file,
# then, regardless of where we have mapped the location of the original,
# we store the update to $mq_patchdir/series, overwriting any existing
# file with this name.
#
mq_map_control_file_refs "$mq_patchdir" series status
awk "$mq_series $mq_status"' END {
  if( entries > 0 )
  { if( applied < 0 )
      print "'"$mq_patchname"'" > "'"$mq_series_file_tmp"'";
    for( idx = 0; entries > idx; idx++ )
    { print series[idx] > "'"$mq_series_file_tmp"'";
      if( idx == applied )
	print "'"$mq_patchname"'" > "'"$mq_series_file_tmp"'";
    }
  }
  else print "'"$mq_patchname"'" > "'"$mq_series_file_tmp"'";
}' "$mq_series_file" "$mq_status_file"
mq_series_file="$mq_patchdir/series" mq_update mq_series_file

# Finally, update the status file, in place, to reflect that the new
# patch has been applied, and is at the top of the patch queue stack.
#
git show --no-patch --format="%H:$mq_patchname" >> "$mq_patchdir/status"
#
# ------------------------------------------------------------------------------
# $RCSfile$: end of file
ETX