Re: [PATCH] Use perl instead of tac

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxx>, <b4ai4o$1u8vmt$2@xxxxxxxxxxxxxxxxxxxxxxx>

Attachment: signature.asc
Description: Digital signature http://en.wikipedia.org/wiki/OpenPGP


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux