git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Jörg Sommer" <joerg@alea.gnuu.de>
To: Brian Gernhardt <benji@silverinsanity.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] Use perl instead of tac
Date: Mon, 5 May 2008 00:13:20 +0200	[thread overview]
Message-ID: <20080504221319.GA14584@alea.gnuu.de> (raw)
In-Reply-To: <5374CF8E-3E6E-480B-A23B-13BE85C7ABCF@silverinsanity.com>

[-- Attachment #1: Type: text/plain, Size: 5613 bytes --]

Hallo Brian,

Brian Gernhardt schrieb am Wed 30. Apr, 11:25 (-0400):
> On Apr 30, 2008, at 5:02 AM, Jörg Sommer wrote:
>
>>> I also dislike the large lists this is carrying around in shell
>>> variables.  If I'm reading it correctly, the tag list could be  
>>> replaced
>>> by invocations of "git describe --exact-match".
>>
>> Yes. How to get all tags of a commit?
>>
>> % git tag foo v1.5.5
>> % git describe --exact-match 9d831805195ba40b62f632acc6bb6e53d3
>> warning: tag 'v1.5.5' is really 'foo' here
>> v1.5.5

And how can I get only tags no annotated tags? We can't recreate
annotated tags with git rebase.

> Those concerns being: overrunning the length of a shell variable,

Are you shure there is any such bounding? I didn't saw anything about the
size of a variables in IEEE 1003.1-2004, but didn't look very carfully.
All my shells (bash, dash, zsh) can handle more than 16777217 characters:

dash -c 'a=a; while :; do a=$a$a; echo $a | wc -c; done'

This would be a new version of create_extended_todo_list() without tac.
What do you think about it? Is it better readable? But there's a bug.

create_extended_todo_list () {
	# The idea of this function is to
	# 1. build a list of tags
	# 2. go through the list and
	#    * issue a reset command to the parent of the commit, if the last
	#      commit was not the parent of the current commit,
	#    * issue a pick command for simple commits,
	#    * issue for each merge commit a merge command with the hashs of
	#      the parent commits,
	#    * register each parent of a merge and issue a mark command
	#      (without an ID) after the commit for each registered commit and
	#    * issue a tag command, if the commit is in the tag list.
	# 3. Then go through the created list and
	#    * add an ID to each mark command and
	#    * replace all occurences of the hash in reset and merge commands
	#      by the mark ID
	test -e "$DOTEST"/cetl.tmp \
		&& die "Someone else uses our filename cetl.tmp." \
			"That's not nice"
	if test t = "${PRESERVE_TAGS:-}"
	then
		tag_list=$(git show-ref --abbrev=7 --tags | \
			(
			while read sha1 tag
			do
				tag=${tag#refs/tags/}
				if test ${last_sha1:-0000} = $sha1
				then
					saved_tags="$saved_tags:$tag"
				else
					printf "%s" "${last_sha1:+ $last_sha1#$saved_tags}"
					last_sha1=$sha1
					saved_tags=$tag
				fi
			done
			echo "${last_sha1:+ $last_sha1:$saved_tags}"
			) )
	else
		tag_list=
	fi
	mark_these_commits=
	while IFS=_ read commit parents subject
	do
		first_parent=${parents%% *}
		if test "${last_commit:-$SHORTUPSTREAM}" != $first_parent
		then
			test "$first_parent" = $SHORTUPSTREAM &&
				first_parent=$SHORTONTO
			echo reset $first_parent
		fi
		unset first_parent
		last_commit=$commit

		case "$parents" in
		*' '*)
			new_parents=
			for p in $parents
			do
				mark_these_commits=$(insert_value_at_key_into_list \
					"$commit" "$p" "$mark_these_commits")
				if test "$p" = $SHORTUPSTREAM
				then
					new_parents="$new_parents $SHORTONTO"
				else
					new_parents="$new_parents $p"
				fi
			done
			unset p
			echo merge $commit ${new_parents# * }
			unset new_parents
			;;
		*)
			echo "pick $commit $subject"
			;;
		esac

		if tmp=$(get_value_from_list $commit "$tag_list")
		then
			for t in $(echo $tmp | tr : ' ')
			do
				echo tag $t
			done
		fi
	done > "$DOTEST"/cetl.tmp
	unset commit parents subject

	commit_mark_list=
	next_mark=0
	last_commit=
	while read cmd args
	do
		case "$cmd" in
		pick)
			this_commit="${args%% *}"
			;;
		reset)
			this_commit=$args
			if tmp=$(get_value_from_list $args "$commit_mark_list")
			then
				args=":$tmp"
			fi
			;;
		merge)
			new_args=
			for i in ${args#* }
			do
				if tmp=$(get_value_from_list $i \
					"$commit_mark_list")
				then
					new_args="$new_args :$tmp"
				else
					new_args="$new_args $i"
				fi
			done
			this_commit="${args%% *}"
			args="$this_commit ${new_args# }"
			;;
		esac

		if tmp=$(get_value_from_list "$last_commit" \
			"$mark_these_commits") && \
			test "${this_commit:-$last_commit}" != $tmp
		then
			if tmp=$(get_value_from_list "$last_commit" \
				"$commit_mark_list")
			then
				test "$last_cmd" = reset -o "$last_cmd" = tag \
					|| echo mark ":$tmp"
			else
				commit_mark_list=$(insert_value_at_key_into_list \
					$next_mark $last_commit "$commit_mark_list")
				echo mark ":$next_mark"
				next_mark=$(($next_mark + 1))
			fi
		fi
		last_commit=${this_commit:-$last_commit}
		unset this_commit

		echo "$cmd $args"
		last_cmd=$cmd
	done < "$DOTEST"/cetl.tmp
	rm "$DOTEST"/cetl.tmp
	unset last_cmd last_commit next_mark cmd args tmp commit_mark_list \
		mark_these_commits
}

The problem is the mark command. If you walk from ONTO to HEAD trough the
list, you must know for a commit, if it is used _later_. But don't create
a mark if it is used immediately, e.g. pick; merge not pick; mark; merge.

If you walk from HEAD to ONTO, this is much easier. I delayed the mark
for the first head of a merge and checked if the next commit is this
commit. This way I keep the todo list clean and don't get something like
this for --first-parent:

pick abc
pick def
mark :0
merge 012 foreign-branch

Bye, Jörg.
-- 
Es ist außerdem ein weit verbreiteter Irrtum das USENET ‚helfen‘ soll.
Tatsächlich wurde USENET nachweislich zur persönlichen Belustigung
seiner Erfinder geschaffen.
Jörg Klemenz <joerg@gmx.net>, <b4ai4o$1u8vmt$2@ID-21915.news.dfncis.de>

[-- Attachment #2: Digital signature http://en.wikipedia.org/wiki/OpenPGP --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

  reply	other threads:[~2008-05-04 22:15 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-27  6:24 Use of tac in git-rebase--interactive Brian Gernhardt
2008-04-27  6:42 ` Jeff King
2008-04-27  6:55   ` [PATCH] Use perl instead of tac Brian Gernhardt
2008-04-28  7:44     ` [PATCH] rebase--interactive: Replace unportable 'tac' by a sed script Johannes Sixt
2008-04-28  8:19       ` Junio C Hamano
2008-04-28  8:58         ` Paolo Bonzini
2008-04-28  9:04       ` Jeff King
2008-04-28  9:11         ` Andreas Ericsson
2008-04-28 11:46     ` [PATCH] Use perl instead of tac Jörg Sommer
2008-04-28 12:58       ` Randal L. Schwartz
2008-04-28 13:12         ` David Symonds
2008-04-28 13:31           ` Paolo Bonzini
2008-04-28 14:11           ` Brian Gernhardt
2008-04-28 14:22             ` Johannes Schindelin
2008-04-28 15:15         ` Jörg Sommer
2008-04-28 17:26           ` Avery Pennarun
2008-04-28 17:34           ` Matthieu Moy
2008-04-28 17:50             ` Brian Gernhardt
2008-04-28 19:13           ` Brian Gernhardt
2008-04-30  9:02             ` Jörg Sommer
2008-04-30  9:39               ` Jörg Sommer
2008-04-30 16:12                 ` Brian Gernhardt
2008-04-30 15:25               ` Brian Gernhardt
2008-05-04 22:13                 ` Jörg Sommer [this message]
2008-05-06  4:32                   ` Brian Gernhardt
2008-04-28 13:46       ` Johannes Schindelin
2008-04-28 14:07         ` Brian Gernhardt
2008-04-28 14:20           ` Johannes Schindelin
2008-04-27  7:33 ` Use of tac in git-rebase--interactive しらいしななこ
2008-04-30  0:25   ` Junio C Hamano

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=20080504221319.GA14584@alea.gnuu.de \
    --to=joerg@alea.gnuu.de \
    --cc=benji@silverinsanity.com \
    --cc=git@vger.kernel.org \
    /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).