git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Stephan Beyer <s-beyer@gmx.net>
Cc: git@vger.kernel.org,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Daniel Barkalow <barkalow@iabervon.org>,
	Christian Couder <chriscool@tuxfamily.org>
Subject: Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype
Date: Wed, 02 Jul 2008 18:45:06 -0700	[thread overview]
Message-ID: <7vbq1f68rh.fsf@gitster.siamese.dyndns.org> (raw)
In-Reply-To: 1214879914-17866-2-git-send-email-s-beyer@gmx.net

Stephan Beyer <s-beyer@gmx.net> writes:

> git sequencer is planned as a backend for user scripts
> that execute a sequence of git instructions and perhaps
> need manual intervention, for example git-rebase or git-am.

...
> +output () {
> +	case "$VERBOSE" in
> +	0)
> +		"$@" >/dev/null
> +		;;
> +	1)
> +		output=$("$@" 2>&1 )
> +		status=$?
> +		test $status -ne 0 && printf '%s\n' "$output"
> +		return $status
> +		;;
> +	2)
> +		"$@"
> +		;;
> +	esac
> +}

Perhaps misnamed?  This feels more like "do" or "perform" or "run".

> +require_clean_work_tree () {
> +	# test if working tree is dirty
> +	git rev-parse --verify HEAD >/dev/null &&
> +	git update-index --ignore-submodules --refresh &&
> +	git diff-files --quiet --ignore-submodules &&
> +	git diff-index --cached --quiet HEAD --ignore-submodules -- ||
> +	die 'Working tree is dirty'
> +}

When is it necessary to ignore submodules and why?  Are there cases where
submodules should not be ignored?

> +LAST_COUNT=
> +mark_action_done () {
> +	sed -e 1q <"$TODO" >>"$DONE"
> +	sed -e 1d <"$TODO" >"$TODO.new"
> +	mv -f "$TODO.new" "$TODO"
> +	if test "$VERBOSE" -gt 0
> +	then
> +		count=$(grep -c '^[^#]' <"$DONE")
> +		total=$(expr "$count" + "$(grep -c '^[^#]' <"$TODO")")

Here we are not counting lines that are comments as insns (I am not
complaining; just making a mental note).

> +		if test "$LAST_COUNT" != "$count"
> +		then
> +			LAST_COUNT="$count"
> +			test "$VERBOSE" -lt 1 ||
> +				printf 'Sequencing (%d/%d)\r' "$count" "$total"
> +			test "$VERBOSE" -lt 2 || echo
> +		fi
> +	fi
> +}
> +
> +# Generate message, patch and author script files
> +make_patch () {
> +	parent_sha1=$(git rev-parse --verify "$1"^) ||
> +		die "Cannot get patch for $1^"
> +	git diff-tree -p "$parent_sha1..$1" >"$PATCH"

Could there be a case where we need/want to deal with a root commit
without parents?

> +	test -f "$MSG" ||
> +		commit_message "$1" >"$MSG"
> +	test -f "$AUTHOR_SCRIPT" ||
> +		get_author_ident_from_commit "$1" >"$AUTHOR_SCRIPT"
> +}
> +
> +# Generate a patch and die with "conflict" status code
> +die_with_patch () {
> +	make_patch "$1"
> +	git rerere
> +	die_to_continue "$2"
> +}
> +
> +restore () {
> +	git rerere clear
> +
> +	HEADNAME=$(cat "$SEQ_DIR/head-name")
> +	HEAD=$(cat "$SEQ_DIR/head")

Perhaps

	read HEADNAME <"$SEQ_DIR/head-name"

provided if these values are $IFS safe?

> +	case $HEADNAME in
> +	refs/*)
> +		git symbolic-ref HEAD "$HEADNAME"
> +		;;
> +	esac &&
> +	output git reset --hard "$HEAD"
> +}
> +
> +has_action () {
> +	grep '^[^#]' "$1" >/dev/null
> +}
> +
> +# Check if text file $1 contains a commit message
> +has_message () {
> +	test -n "$(sed -n -e '/^Signed-off-by:/d;/^[^#]/p' <"$1")"
> +}

Makes one wonder if we would want to special case other kinds like
"Acked-by:" as well...

> +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1
> +pick_one () {
> +	what="$1"
> +	# we just assume that this is either cherry-pick or revert
> +	shift
> +
> +	# check for fast-forward if no options are given
> +	if expr "x$1" : 'x[^-]' >/dev/null
> +	then
> +		test "$(git rev-parse --verify "$1^")" = \
> +			"$(git rev-parse --verify HEAD)" &&
> +			output git reset --hard "$1" &&
> +			return
> +	fi
> +	test "$1" != '--edit' -a "$what" = 'revert' &&
> +		what='revert --no-edit'

This looks somewhat wrong.

When the history looks like ---A---B and we are at A, cherry-picking B can
be optimized to just advancing to B, but that optimization has a slight
difference (or two) in the semantics.

 (1) The committer information would not record the user and time of the
     sequencer operation, which actually may be a good thing.

 (2) When $what is revert, this codepath shouldn't be exercised, should it?

 (3) If B is a merge, even if $what is pick, this codepath shouldn't be
     exercised, should it?

As to the syntax I tend to prefer

	case "$1" in
        -*)	... do option thing ... ;;
        *)	... do other thing... ;;
        esac

So how about...

	case "$what,$1" in
        revert,--edit)
        	what='revert --no-edit' ;;
        revert,* | cherry-pick,-* )
        	;;
        *)
		if ! git rev-parse --verify "$1^2" &&
	                test "$(git rev-parse --verify "$1^") = \
                	"$(git rev-parse --verify HEAD)"
		then
                	output git reset --hard "$1"
			return
		fi
		;;
	esac

> +make_squash_message () {
> +	if test -f "$squash_msg"
> +	then
> +		count=$(($(sed -n -e 's/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p' \
> +			<"$squash_msg" | sed -n -e '$p')+1))
> +		echo "# This is a combination of $count commits."
> +		sed -e '1d' -e '2,/^./{
> +			/^$/d
> +		}' <"$squash_msg"
> +	else
> +		count=2
> +		echo '# This is a combination of 2 commits.'
> +		echo '# The first commit message is:'
> +		echo
> +		commit_message HEAD
> +	fi
> +	echo
> +	echo "# This is the $(nth_string "$count") commit message:"
> +	echo
> +	commit_message "$1"
> +}
> +
> +make_squash_message_multiple () {
> +	echo '# This is a dummy to get the 0.' >"$squash_msg"
> +	for cur_sha1 in $(git rev-list --reverse "$sha1..HEAD")
> +	do
> +		make_squash_message "$cur_sha1" >"$MSG"
> +		cp "$MSG" "$squash_msg"
> +	done
> +}

Hmm, I know this is how rebase-i is written, but we should be able to do
better than writing and flipping temporary times N times, shouldn't we?

> +peek_next_command () {
> +	sed -n -e '1s/ .*$//p' <"$TODO"
> +}

... which could respond "the next command is '#' (comment)", so we are
actively counting a comment as a step here.  Does this contradict with the
mental note we made earlier, and if so, does the discrepancy hurt us
somewhere in this program?

> +# If $1 is a mark, make a ref from it; otherwise keep it
> +mark_to_ref () {
> +	arg="$1"
> +	ref=$(expr "x$arg" : 'x:0*\([0-9][0-9]*\)$')

You might want to leave comments to describe constraints that led to this
slightly awkward regexp:

 * :0 is allowed
 * :01 is the same as :1

> +strategy_check () {
> +	case "$1" in
> +	resolve|recursive|octopus|ours|subtree|theirs)
> +		return
> +		;;
> +	esac
> +	todo_warn "Strategy '$1' not known."
> +}

Hmm.  Do we need to maintain list of available strategies here and then in
git-merge separately?

> +### Author script functions
> +
> +clean_author_script () {
> +	cat "$ORIG_AUTHOR_SCRIPT" >"$AUTHOR_SCRIPT"
> +}
> +
> +# Take "Name <e-mail>" in stdin and outputs author script
> +make_author_script_from_string () {
> +	sed -e 's/^\(.*\) <\(.*\)>.*$/GIT_AUTHOR_NAME="\1"\
> +GIT_AUTHOR_EMAIL="\2"\
> +GIT_AUTHOR_DATE=/'
> +}

If you are going to "."-source or eval the output from this, you would
need to quote the values a lot more robustly, wouldn't you?  Is this safe
against shell metacharacters in names, mails and/or space between unixtime
and the timezone information?

> +	if test -z "$AUTHOR"
> +	then
> +		sed -n -e '
> +			s/^Author: \(.*\)$/GIT_AUTHOR_NAME="\1"/p;
> +			s/^Email: \(.*\)$/GIT_AUTHOR_EMAIL="\1"/p;
> +			s/^Date: \(.*\)$/GIT_AUTHOR_DATE="\1"/p
> +		' <"$infofile" >>"$AUTHOR_SCRIPT"

The same comment on quoting applies here, I think.

> +		# If sed's result is empty, we keep the original
> +		# author script by appending.
> +	fi
> ...
> +	failed=
> +	with_author git apply $apply_opts --index "$PATCH" || failed=t
> +
> +	if test -n "$failed" -a -n "$threeway" && (with_author fallback_3way)
> +	then
> +		# Applying the patch to an earlier tree and merging the
> +		# result may have produced the same tree as ours.
> +		git diff-index --quiet --cached HEAD -- && {
> +			echo 'No changes -- Patch already applied.'
> +			return 0
> +			# XXX: do we want that?
> +		}
> +		# clear apply_status -- we have successfully merged.
> +		failed=
> +	fi
> +
> +	if test -n "$failed"
> +	then
> +		# XXX: This is just a stupid hack:
> +		with_author git apply $apply_opts --reject --index "$PATCH"

Please don't do this without being asked, if you are planning to use this
in "am" when 3-way fallback was not asked.  It _may_ make sense to give an
option to the users to ask for .rej if they prefer to work that way better
than working with 3-way merge fallback, but doing this without being asked
is not acceptable.

> +		die_to_continue 'Patch failed. See the .rej files.'
> +		# XXX: We actually needed a git-apply flag that creates
> +		# conflict markers and sets the DIFF_STATUS_UNMERGED flag.

That is what -3way is all about, and this codepath is when the user did
not ask for it, isn't it?

> +# Check the "pick" instruction
> +check_pick () {
> +	revert=
> +	mainline=
> +	while test $# -gt 1
> +	do
> ...
> +	done
> +
> +	if test -n "$mainline"
> +	then
> +		test -z "$revert" ||
> +			todo_error "Cannot use $revert together with --mainline."

Why not?  If you have this...

	---A---C---D
              /
          ---B

and you are at D, you may want to undo the merge you made at C and go back
to either A or B, which essentially is same as cherry-picking diff between
C and D on top of either A or B.  Both are valid operations aren't they?

The remainder of the review will have to be in a separate message..

  parent reply	other threads:[~2008-07-03  7:00 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-01  2:38 git sequencer prototype Stephan Beyer
2008-07-01  2:38 ` [RFC/PATCH 1/4] Add git-sequencer shell prototype Stephan Beyer
2008-07-01  2:38   ` [RFC/PATCH 2/4] Add git-sequencer prototype documentation Stephan Beyer
2008-07-01  2:38     ` [RFC/PATCH 3/4] Add git-sequencer test suite (t3350) Stephan Beyer
2008-07-01  2:38       ` [RFC/PATCH 4/4] Migrate git-am to use git-sequencer Stephan Beyer
2008-07-01  2:39         ` git-rebase-i migration to sequencer Stephan Beyer
2008-07-01  2:39           ` [PATCH 1/2] Make rebase--interactive use OPTIONS_SPEC Stephan Beyer
2008-07-01  2:39             ` [RFC/PATCH 2/2] Migrate git-rebase--i to use git-sequencer Stephan Beyer
2008-07-05 17:31       ` [RFC/PATCH 3/4] Add git-sequencer test suite (t3350) Stephan Beyer
2008-07-05 18:16         ` Junio C Hamano
2008-07-01 13:02     ` [RFC/PATCH 2/4] Add git-sequencer prototype documentation Jakub Narebski
2008-07-01 16:03       ` Stephan Beyer
2008-07-01 18:04         ` Jakub Narebski
2008-07-01 19:50           ` Stephan Beyer
2008-07-02  0:39             ` Jakub Narebski
2008-07-02  1:20               ` Junio C Hamano
2008-07-02  3:01                 ` Stephan Beyer
2008-07-05 17:00     ` [PATCH v2 " Stephan Beyer
2008-07-08 10:37       ` Jakub Narebski
2008-07-08 11:49         ` Stephan Beyer
2008-07-09  5:20         ` Karl Hasselström
2008-07-03  1:45   ` Junio C Hamano [this message]
2008-07-03 11:03     ` [RFC/PATCH 1/4] Add git-sequencer shell prototype Johannes Schindelin
2008-07-03 21:09       ` Stephan Beyer
2008-07-03 22:11         ` Junio C Hamano
2008-07-03 22:34           ` Stephan Beyer
2008-07-03 23:53         ` Johannes Schindelin
2008-07-04  0:38           ` Stephan Beyer
2008-07-04  1:03             ` Johannes Schindelin
2008-07-04  1:53               ` Stephan Beyer
2008-07-04 15:19                 ` [PATCH] Allow cherry-picking root commits Johannes Schindelin
2008-07-04 16:41                   ` Stephan Beyer
2008-07-06  1:05                   ` Junio C Hamano
2008-07-06  1:37                     ` Johannes Schindelin
2008-07-06 11:32                       ` t3503: Add test case for identical files Stephan Beyer
2008-07-06 11:35                   ` [PATCH] Allow cherry-picking root commits Stephan Beyer
2008-07-06 12:48                     ` Johannes Schindelin
2008-07-04  1:06           ` [RFC/PATCH 1/4] Add git-sequencer shell prototype Stephan Beyer
2008-07-04  1:11             ` Johannes Schindelin
2008-07-03 22:51       ` Junio C Hamano
2008-07-03 23:33       ` Stephan Beyer
2008-07-03 13:10   ` Jakub Narebski
2008-07-03 21:12     ` Stephan Beyer
2008-07-05 16:58   ` [PATCH v2 " Stephan Beyer
2008-07-01  8:51 ` git sequencer prototype Junio C Hamano
2008-07-01 14:53   ` Stephan Beyer
2008-07-04 21:00 ` Alex Riesen
2008-07-04 22:09   ` Junio C Hamano
2008-07-04 22:23     ` Stephan Beyer
2008-07-05  8:13     ` Alex Riesen
2008-07-05 10:12       ` Thomas Adam
2008-07-05 10:13       ` Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7vbq1f68rh.fsf@gitster.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=barkalow@iabervon.org \
    --cc=chriscool@tuxfamily.org \
    --cc=git@vger.kernel.org \
    --cc=s-beyer@gmx.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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 NNTP newsgroup(s).