git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v5 0/8] detached-stash: regularise handling of stash arguments by git stash
@ 2010-08-18 13:09 Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 1/8] detached-stash: introduce parse_flags_and_revs function Jon Seymour
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jon Seymour @ 2010-08-18 13:09 UTC (permalink / raw)
  To: git; +Cc: gitster, j6t, Jon Seymour

This patch introduces a common flags and revision parsing function to the following git stash commands:
 * apply
 * branch
 * pop
 * drop
 * show

With these changes, git stash now:
 * allows non-stash log entry references to passed to 'stash branch' provided they are stash-like
 * relaxes the requirement that a stash log currently entry exists for 'stash show' or 'stash branch' 
 * does not attempt to drop the specified revision if it doesn't look like a stash log entry reference
 * fails 'stash pop' and 'stash drop' early if the specified revision is not a stash log entry reference
 * fails early if more than one stash-like commit is specified
 * fails early if the specified revision is of the form ref@{n} and ref exists, but ref@{n} does not exist
 * reports various error conditions that can occur across multiple commanbds with consistent error messages.

The implementation of several commands is simplified to a lesser or greater degree by taking
advantage of the new common parsing and validation function, parse_flags_and_rev(). 

This revision incorporates feedback and corrections from Johannes Sixt and Junio Hamano.

Jon Seymour (8):
  detached-stash: introduce parse_flags_and_revs function
  detached-stash: simplify stash_apply
  detached-stash: simplify stash_drop
  detached-stash: refactor git stash pop implementation
  detached-stash: simplify git stash branch
  detached-stash: simplify git stash show
  detached-stash: tests of git stash with stash-like arguments
  detached-stash: update Documentation

 Documentation/git-stash.txt |   16 ++-
 git-stash.sh                |  223 ++++++++++++++++++++++++++++---------------
 t/t3903-stash.sh            |  140 +++++++++++++++++++++++++++
 3 files changed, 296 insertions(+), 83 deletions(-)

-- 
1.7.2.1.95.g969a4.dirty

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v5 1/8] detached-stash: introduce parse_flags_and_revs function
  2010-08-18 13:09 [PATCH v5 0/8] detached-stash: regularise handling of stash arguments by git stash Jon Seymour
@ 2010-08-18 13:09 ` Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 2/8] detached-stash: simplify stash_apply Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 3/8] detached-stash: simplify stash_drop Jon Seymour
  2 siblings, 0 replies; 4+ messages in thread
From: Jon Seymour @ 2010-08-18 13:09 UTC (permalink / raw)
  To: git; +Cc: gitster, j6t, Jon Seymour

Introduce parse_flags_and_revs. This function requires that
there is at at most one stash-like revision parameter and
sero or more flags.

It knows how to parse -q,--quiet and --index flags, but leaves
other flags unparsed.

Specified revisions are checked to see that they are at least stash-like
(meaning: they look like something created by git stash save or git stash
create).

If this is so, then IS_STASH_LIKE is initialized to a non-empty value.

If the specified revision also looks like a stash log entry reference,
then IS_STASH_REF is initialized to a non-empty value.

References of the form ref@{spec} are required to precisely identify
an individual commit.

If no reference is specified, stash@{0} is assumed.

Once the specified reference is validated to be at least stash_like
a ensemble of derived variables, (w_commit, w_tree, b_commit, etc)
are initialized with a single call to git rev-parse.

Repeated calls to parse_flags_and_rev() avoid repeated calls
to git rev-parse if the specified arguments have already been
parsed.

An ensemble of supporting functions that make use of the state
established by parse_flags_and_rev(). These are describe below.
Subsequent patches in the series modify the existing
git stash subcommands to make use of these functions as appropriate.

The ancillary functions are:

is_stash_like(): which can be used to test
whether a specified commit looks like a commit created with
git stash save or git stash create.

assert_stash_like(): which can be used by
commands that misbehave unless their arguments stash-like.

is_stash_ref(): which checks whether an argument
is valid stash reference(e.g. is of the form
['refs/']stash['@{'something'}])

assert_stash_ref(): which can be used by commands
that misbehave unless their arguments are both stash-like and
refer to valid stash entries.

Signed-off-by: Jon Seymour <jon.seymour@gmail.com>
---
 git-stash.sh |  133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/git-stash.sh b/git-stash.sh
index 1d95447..42b0da2 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -225,6 +225,138 @@ show_stash () {
 	git diff $flags $b_commit $w_commit
 }
 
+#
+# Parses the remaining options looking for flags and
+# at most one revision defaulting to ${ref_stash}@{0}
+# if none found.
+#
+# Derives related tree and commit objects from the
+# revision, if one is found.
+#
+# stash records the work tree, and is a merge between the
+# base commit (first parent) and the index tree (second parent).
+#
+#   REV is set to the symbolic version of the specified stash-like commit
+#   IS_STASH_LIKE is non-blank if ${REV} looks like a stash
+#   IS_STASH_REF is non-blank if the ${REV} looks like a stash ref
+#   s is set to the SHA1 of the stash commit
+#   w_commit is set to the commit containing the working tree
+#   b_commit is set to the base commit
+#   i_commit is set to the commit containing the index tree
+#   w_tree is set to the working tree
+#   b_tree is set to the base tree
+#   i_tree is set to the index tree
+#
+#   GIT_QUIET is set to t if -q is specified
+#   INDEX_OPTION is set to --index if --index is specified.
+#   FLAGS is set to the remaining flags
+#
+# dies if:
+#   * too many revisions specified
+#   * no revision is specified and there is no stash stack
+#   * a revision is specified which cannot be resolve to a SHA1
+#   * a non-existent stash reference is specified
+#
+
+parse_flags_and_rev()
+{
+	test "$PARSE_CACHE" = "$*" && return 0 # optimisation
+	PARSE_CACHE="$*"
+
+	IS_STASH_LIKE=
+	IS_STASH_REF=
+	INDEX_OPTION=
+	s=
+	w_commit=
+	b_commit=
+	i_commit=
+	w_tree=
+	b_tree=
+	i_tree=
+
+	REV=$(git rev-parse --no-flags --symbolic "$@" 2>/dev/null)
+	FLAGS=$(git rev-parse --no-revs -- "$@" 2>/dev/null)
+
+	set -- $FLAGS
+
+	FLAGS=
+	while test $# -ne 0
+	do
+		case "$1" in
+			-q|--quiet)
+				GIT_QUIET=-t
+			;;
+			--index)
+				INDEX_OPTION=--index
+			;;
+			--)
+				:
+			;;
+			*)
+				FLAGS="${FLAGS}${FLAGS:+ }$1"
+			;;
+		esac
+		shift
+	done
+
+	set -- $REV
+
+	case $# in
+		0)
+			have_stash || die "No stash found."
+			set -- ${ref_stash}@{0}
+		;;
+		1)
+			:
+		;;
+		*)
+			die "Too many revisions specified: $REV"
+		;;
+	esac
+
+	REV=$(git rev-parse --quiet --symbolic --verify $1 2>/dev/null) || die "$1 is not valid reference"
+
+	i_commit=$(git rev-parse --quiet --verify $REV^2 2>/dev/null) &&
+	set -- $(git rev-parse $REV $REV^1 $REV: $REV^1: $REV^2: 2>/dev/null) &&
+	s=$1 &&
+	w_commit=$1 &&
+	b_commit=$2 &&
+	w_tree=$3 &&
+	b_tree=$4 &&
+	i_tree=$5 &&
+	IS_STASH_LIKE=t &&
+	test "$ref_stash" = "$(git rev-parse --symbolic-full-name "${REV%@*}")" &&
+	IS_STASH_REF=t
+
+	if test "${REV}" != "${REV%{*\}}"
+	then
+		# maintainers: it would be better if git rev-parse indicated
+		# this condition with a non-zero status code but as of 1.7.2.1 it
+		# it did not. So, we use non-empty stderr output as a proxy for the
+		# condition of interest.
+		test -z "$(git rev-parse "$REV" 2>&1 >/dev/null)" || die "$REV does not exist in the stash log"
+	fi
+
+}
+
+is_stash_like()
+{
+	parse_flags_and_rev "$@"
+	test -n "$IS_STASH_LIKE"
+}
+
+assert_stash_like() {
+	is_stash_like "$@" || die "'$*' is not a stash-like commit"
+}
+
+is_stash_ref() {
+	is_stash_like "$@" && test -n "$IS_STASH_REF"
+}
+
+assert_stash_ref() {
+	is_stash_ref "$@" || die "'$*' is not a stash reference"
+}
+
 apply_stash () {
 	applied_stash=
 	unstash_index=
@@ -375,6 +507,7 @@ apply_to_branch () {
 	drop_stash $stash
 }
 
+PARSE_CACHE='--not-parsed'
 # The default command is "save" if nothing but options are given
 seen_non_option=
 for opt
-- 
1.7.2.1.95.g4fabf

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 2/8] detached-stash: simplify stash_apply
  2010-08-18 13:09 [PATCH v5 0/8] detached-stash: regularise handling of stash arguments by git stash Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 1/8] detached-stash: introduce parse_flags_and_revs function Jon Seymour
@ 2010-08-18 13:09 ` Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 3/8] detached-stash: simplify stash_drop Jon Seymour
  2 siblings, 0 replies; 4+ messages in thread
From: Jon Seymour @ 2010-08-18 13:09 UTC (permalink / raw)
  To: git; +Cc: gitster, j6t, Jon Seymour

The implementation of stash_apply() is simplified to take
advantage of the common parsing function parse_flags_and_rev().

Signed-off-by: Jon Seymour <jon.seymour@gmail.com>
---
 git-stash.sh |   38 +++-----------------------------------
 1 files changed, 3 insertions(+), 35 deletions(-)

diff --git a/git-stash.sh b/git-stash.sh
index 42b0da2..ba68f1e 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -358,40 +358,8 @@ assert_stash_ref() {
 }
 
 apply_stash () {
-	applied_stash=
-	unstash_index=
 
-	while test $# != 0
-	do
-		case "$1" in
-		--index)
-			unstash_index=t
-			;;
-		-q|--quiet)
-			GIT_QUIET=t
-			;;
-		*)
-			break
-			;;
-		esac
-		shift
-	done
-
-	if test $# = 0
-	then
-		have_stash || die 'Nothing to apply'
-		applied_stash="$ref_stash@{0}"
-	else
-		applied_stash="$*"
-	fi
-
-	# stash records the work tree, and is a merge between the
-	# base commit (first parent) and the index tree (second parent).
-	s=$(git rev-parse --quiet --verify --default $ref_stash "$@") &&
-	w_tree=$(git rev-parse --quiet --verify "$s:") &&
-	b_tree=$(git rev-parse --quiet --verify "$s^1:") &&
-	i_tree=$(git rev-parse --quiet --verify "$s^2:") ||
-		die "$*: no valid stashed state found"
+	assert_stash_like "$@"
 
 	git update-index -q --refresh &&
 	git diff-files --quiet --ignore-submodules ||
@@ -402,7 +370,7 @@ apply_stash () {
 		die 'Cannot apply a stash in the middle of a merge'
 
 	unstashed_index_tree=
-	if test -n "$unstash_index" && test "$b_tree" != "$i_tree" &&
+	if test -n "$INDEX_OPTION" && test "$b_tree" != "$i_tree" &&
 			test "$c_tree" != "$i_tree"
 	then
 		git diff-tree --binary $s^2^..$s^2 | git apply --cached
@@ -447,7 +415,7 @@ apply_stash () {
 	else
 		# Merge conflict; keep the exit status from merge-recursive
 		status=$?
-		if test -n "$unstash_index"
+		if test -n "$INDEX_OPTION"
 		then
 			echo >&2 'Index was not unstashed.'
 		fi
-- 
1.7.2.1.95.g4fabf

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v5 3/8] detached-stash: simplify stash_drop
  2010-08-18 13:09 [PATCH v5 0/8] detached-stash: regularise handling of stash arguments by git stash Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 1/8] detached-stash: introduce parse_flags_and_revs function Jon Seymour
  2010-08-18 13:09 ` [PATCH v5 2/8] detached-stash: simplify stash_apply Jon Seymour
@ 2010-08-18 13:09 ` Jon Seymour
  2 siblings, 0 replies; 4+ messages in thread
From: Jon Seymour @ 2010-08-18 13:09 UTC (permalink / raw)
  To: git; +Cc: gitster, j6t, Jon Seymour

Previously, git stash drop would fail noisily while executing git reflog
delete if the specified revision was not a stash reference.

Now, git stash drop fails with an error message which more precisely
indicates the reason for failure.

Furthermore, git stash drop will now fail with a non-zero status code
if stash@{n} specifies a stash log entry that does not actually exist.

This change in behaviour is achieved by delegating argument parsing
to the common parse_flags_and_rev() function (via a call to
assert_stash_ref).

Signed-off-by: Jon Seymour <jon.seymour@gmail.com>
---
 git-stash.sh |   31 +++----------------------------
 1 files changed, 3 insertions(+), 28 deletions(-)

diff --git a/git-stash.sh b/git-stash.sh
index ba68f1e..750f360 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -424,35 +424,10 @@ apply_stash () {
 }
 
 drop_stash () {
-	have_stash || die 'No stash entries to drop'
+	assert_stash_ref "$@"
 
-	while test $# != 0
-	do
-		case "$1" in
-		-q|--quiet)
-			GIT_QUIET=t
-			;;
-		*)
-			break
-			;;
-		esac
-		shift
-	done
-
-	if test $# = 0
-	then
-		set x "$ref_stash@{0}"
-		shift
-	fi
-	# Verify supplied argument looks like a stash entry
-	s=$(git rev-parse --verify "$@") &&
-	git rev-parse --verify "$s:"   > /dev/null 2>&1 &&
-	git rev-parse --verify "$s^1:" > /dev/null 2>&1 &&
-	git rev-parse --verify "$s^2:" > /dev/null 2>&1 ||
-		die "$*: not a valid stashed state"
-
-	git reflog delete --updateref --rewrite "$@" &&
-		say "Dropped $* ($s)" || die "$*: Could not drop stash entry"
+	git reflog delete --updateref --rewrite "${REV}" &&
+		say "Dropped ${REV} ($s)" || die "${REV}: Could not drop stash entry"
 
 	# clear_stash if we just dropped the last stash entry
 	git rev-parse --verify "$ref_stash@{0}" > /dev/null 2>&1 || clear_stash
-- 
1.7.2.1.95.g4fabf

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-08-18 13:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-18 13:09 [PATCH v5 0/8] detached-stash: regularise handling of stash arguments by git stash Jon Seymour
2010-08-18 13:09 ` [PATCH v5 1/8] detached-stash: introduce parse_flags_and_revs function Jon Seymour
2010-08-18 13:09 ` [PATCH v5 2/8] detached-stash: simplify stash_apply Jon Seymour
2010-08-18 13:09 ` [PATCH v5 3/8] detached-stash: simplify stash_drop Jon Seymour

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).