threads / discuss / 351

PATCH: Allow tree-id to return the ID of a tree object

Subject: PATCH: Allow tree-id to return the ID of a tree object

## tl;dr

8 messages between Apr 27, 2005 and May 2, 2005.

replies: 7people: 2as markdown or json

Philip Pokorny· Apr 27, 2005, 16:20 UTC · lore
While playing with cg-ls, I tried:

% cg-ls ... snip ... 100644 blob bc607fd55f6ce4e56ce87766369b5d4d55ec79af object.h 100755 blob f35877a6aa5b68d2fb4a388dcfa9b3e64262604e parent-id 040000 tree bfb75011c32589b282dd9c86621dadb0f0bb3866 ppc 100644 blob d922305ee0f5583bdfcb629f6d4061e11e0fa859 read-cache.c 100644 blob 1ad7ffc555b635fe57fa7834b12d71ff576be065 read-tree.c ... snip ... % cg-ls bfb75011c32589b282dd9c86621dadb0f0bb3866 <-- the ppc tree ID Invalid id: bfb75011c32589b282dd9c86621dadb0f0bb3866 usage: cat-file [-t | tagname] <sha1> usage: cat-file [-t | tagname] <sha1> Invalid id:

Shouldn't cg-ls give a listing of a sub-tree? The cg-help says it takes a TREE-ID?

The problem seems to be that tree-id really only accepts a commit-id and returns the TREE-ID of that commit.

So I modified commit-id, tree-id and parent-id to make them more similar in coding style, force "short-id" names to be at least 4 lower case letters, and have tree-id accept short, unambiguous ID's and bare SHA1-ID's.

Patch attached.
Index: commit-id
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/commit-id  (mode:100755 sha1:4efcb6bdfdb2b2c5744f5d4d47d92beb7777ed59)
+++ uncommitted/commit-id  (mode:100775)
@@ -9,22 +9,30 @@
 SHA1ONLY="^$SHA1$"
 
 id=$1
+
 if [ ! "$id" ] || [ "$id" = "this" ] || [ "$id" = "HEAD" ]; then
 	id=$(cat .git/HEAD)
-fi
 
-if (echo $id | egrep -vq "$SHA1ONLY") && [ -r ".git/refs/tags/$id" ]; then
+elif [ -r ".git/refs/tags/$id" ]; then
 	id=$(cat ".git/refs/tags/$id")
-fi
 
-if (echo $id | egrep -vq "$SHA1ONLY") && [ -r ".git/refs/heads/$id" ]; then
+elif [ -r ".git/refs/heads/$id" ]; then
 	id=$(cat ".git/refs/heads/$id")
-fi
 
-idpref=$(echo "$id" | cut -c -2)
-idpost=$(echo "$id" | cut -c 3-)
-if [ $(find ".git/objects/$idpref" -name "$idpost*" 2>/dev/null | wc -l) -eq 1 ]; then
-	id=$idpref$(basename $(echo .git/objects/$idpref/$idpost*))
+# Short id's must be lower case and at least 4 digits.
+elif [[ "$id" == [0-9a-z][0-9a-z][0-9a-z][0-9a-z]* ]]; then
+	idpost=${id#??}
+	idpref=${id%$idpost}
+
+	# Assign array elements to matching names
+	idmatch=($(echo .git/objects/$idpref/$idpost*))
+
+	if [ ${#idmatch[*]} -eq 1 ] && [ -r "$idmatch" ]; then
+		id=$idpref${idmatch#.git/objects/$idpref/}
+	elif [ ${#idmatch[*]} -gt 1 ]; then
+		echo "Ambiguous id: $id" >&2
+		exit 1
+	fi
 fi
 
 if echo $id | egrep -vq "$SHA1ONLY"; then
Index: tree-id
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/tree-id  (mode:100755 sha1:1495ff78af71b57e21653512932bcda88fe05454)
+++ uncommitted/tree-id  (mode:100775)
@@ -7,8 +7,35 @@
 
 SHA1="[A-Za-z0-9]{40}"
 TREE="^tree $SHA1$"
+SHA1ONLY="^$SHA1$"
 
-id=$(cat-file commit $(commit-id "$1") | egrep "$TREE" | cut -d ' ' -f 2)
+id=$1
+
+# Is it a commit?
+commit=$(commit-id $id 2>/dev/null)
+if [ "$commit" ]; then
+	id=$(cat-file commit "$commit") | egrep "$TREE" | cut -d ' ' -f 2)
+
+# Short id's must be lower case and at least 4 digits.
+elif [[ "$id" == [0-9a-z][0-9a-z][0-9a-z][0-9a-z]* ]]; then
+	idpost=${id#??}
+	idpref=${id%$idpost}
+
+	# Assign array elements to matching names
+	idmatch=($(echo .git/objects/$idpref/$idpost*))
+
+	if [ ${#idmatch[*]} -eq 1 ] && [ -r "$idmatch" ]; then
+		id=$idpref${idmatch#.git/objects/$idpref/}
+	elif [ ${#idmatch[*]} -gt 1 ]; then
+		echo "Ambiguous id: $id" >&2
+		exit 1
+	fi
+fi
+
+if echo $id | egrep -vq "$SHA1ONLY"; then
+	echo "Invalid id: $id" >&2
+	exit 1
+fi
 
 if [ "$(cat-file -t "$id")" != "tree" ]; then
 	echo "Invalid id: $id" >&2
Index: parent-id
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/parent-id  (mode:100755 sha1:f35877a6aa5b68d2fb4a388dcfa9b3e64262604e)
+++ uncommitted/parent-id  (mode:100775)
@@ -5,7 +5,8 @@
 #
 # Takes ID of the current commit, defaults to HEAD.
 
-PARENT="^parent [A-Za-z0-9]{40}$"
+SHA1="[A-Za-z0-9]{40}"
+PARENT="^parent $SHA1$"
 
 id=$(commit-id $1) || exit 1
 
Petr Baudis· Apr 27, 2005, 23:22 UTC · re: Philip Pokorny · lore

Re: PATCH: Allow tree-id to return the ID of a tree object

Dear diary, on Wed, Apr 27, 2005 at 06:20:55PM CEST, I got a letter where Philip Pokorny <ppokorny@mindspring.com> told me that...

Show 28 quoted lines
> While playing with cg-ls, I tried:
> 
> % cg-ls
> ... snip ...
> 100644  blob    bc607fd55f6ce4e56ce87766369b5d4d55ec79af        object.h
> 100755  blob    f35877a6aa5b68d2fb4a388dcfa9b3e64262604e        parent-id
> 040000  tree    bfb75011c32589b282dd9c86621dadb0f0bb3866        ppc
> 100644  blob    d922305ee0f5583bdfcb629f6d4061e11e0fa859        read-cache.c
> 100644  blob    1ad7ffc555b635fe57fa7834b12d71ff576be065        read-tree.c
> ... snip ...
> % cg-ls bfb75011c32589b282dd9c86621dadb0f0bb3866       <-- the ppc tree ID
> Invalid id: bfb75011c32589b282dd9c86621dadb0f0bb3866
> usage: cat-file [-t | tagname] <sha1>
> usage: cat-file [-t | tagname] <sha1>
> Invalid id:
> 
> 
> Shouldn't cg-ls give a listing of a sub-tree?  The cg-help says it takes
> a TREE-ID?
> 
> The problem seems to be that tree-id really only accepts a commit-id and
> returns the TREE-ID of that commit.
> 
> So I modified commit-id, tree-id and parent-id to make them more similar
> in coding style, force "short-id" names to be at least 4 lower case
> letters, and have tree-id accept short, unambiguous ID's and bare SHA1-ID's.
> 
> Patch attached.
Could you please functionally split and sign off your patch?

Also, I'd prefer not to have the sha1 completion logic duplicated; what about just having commit-id take a parameter not to validate its id? Actually, that's ugly too. I think the cleanest solution would be to reintroduce the cg-Xnormid, now to only really do the _common_ stuff - basically everything up to the typecheck (exclusively) in commit-id.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
Philip Pokorny· Apr 28, 2005, 07:11 UTC · re: Petr Baudis · lore

Re: PATCH[0/4]: Allow tree-id to return the ID of a tree object

Petr Baudis wrote:
>Could you please functionally split and sign off your patch?
>  
>
Apologies, I'm still a bit new to LKML etiquette...
Show 7 quoted lines
>Also, I'd prefer not to have the sha1 completion logic duplicated; what
>about just having commit-id take a parameter not to validate its id?
>Actually, that's ugly too. I think the cleanest solution would be to
>reintroduce the cg-Xnormid, now to only really do the _common_ stuff -
>basically everything up to the typecheck (exclusively) in commit-id.
>  
>

OK, so following this will be a new set of patches (I assume you mean one patch per file changed when you asked for a "functional split") that re-introduce cg-Xnormid, and then convert commit-id, tree-id, and parent-id to use the new core.

In re-writing these, I've put great effort into making the scripts *not* exec a sub-shell or process, so the bash constructs may look strange. I'm sure Linux can exec very quickly, but bash parses and executes even faster when it doesn't have to fork.

Philip Pokorny· Apr 28, 2005, 07:14 UTC · re: Petr Baudis · lore

Re: PATCH[1/4]: Allow tree-id to return the ID of a tree object

Patch to re-introduce cg-Xnormid for common ID normalizing.
Signed-off-by: Philip Pokorny <ppokorny@mindspring.com>
Index: cg-Xnormid
===================================================================
--- /dev/null  (tree:6ad600e20c89323c1d3049f75b8ca9b0a2d72167)
+++ uncommitted/cg-Xnormid  (mode:100755 sha1:6dc089c8d571f330e2e01d96f79616d6146840ee)
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+#
+# Normalize an ID to an SHA1 hash value
+#    Strings resolve in order:
+#       NULL, this, HEAD  => .git/HEAD
+#       <tags>
+#       <heads>
+#       short SHA1 (4 or more hex digits)
+#
+# Copyright (c) Philip Pokorny, 2005
+
+id="$1"
+
+if [ ! "$id" ] || [ "$id" = "this" ] || [ "$id" = "HEAD" ]; then
+	read id < .git/HEAD
+
+elif [ -r ".git/refs/tags/$id" ]; then
+	read id < ".git/refs/tags/$id"
+
+elif [ -r ".git/refs/heads/$id" ]; then
+	read id < ".git/refs/heads/$id"
+
+# Short id's must be lower case and at least 4 digits.
+elif [[ "$id" == [0-9a-z][0-9a-z][0-9a-z][0-9a-z]* ]]; then
+	idpost=${id#??}
+	idpref=${id%$idpost}
+
+	# Assign array elements to matching names
+	idmatch=(.git/objects/$idpref/$idpost*)
+
+	if [ ${#idmatch[*]} -eq 1 ] && [ -r "$idmatch" ]; then
+		id=$idpref${idmatch#.git/objects/$idpref/}
+	elif [ ${#idmatch[*]} -gt 1 ]; then
+		echo "Ambiguous id: $id" >&2
+		exit 1
+	fi
+fi
+
+# FIXME? Should we verify the existance of the ID in the object cache?
+
+# If we don't have a 40-char ID by now, it's an error
+if [ ${#id} -ne 40 ]; then
+	echo "Invalid id: $id" >&2
+	exit 1
+fi
+
+echo $id
Index: Makefile
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/Makefile  (mode:100644 sha1:d73bea1cbb9451a89b03d6066bf2ed7fec32fd31)
+++ uncommitted/Makefile  (mode:100664)
@@ -44,7 +44,7 @@
 	cg-add cg-admin-lsobj cg-cancel cg-clone cg-commit cg-diff \
 	cg-export cg-help cg-init cg-log cg-ls cg-merge cg-mkpatch \
 	cg-patch cg-pull cg-branch-add cg-branch-ls cg-rm cg-seek cg-status \
-	cg-tag cg-update cg-Xlib
+	cg-tag cg-update cg-Xlib cg-Xnormid
 
 COMMON=	read-cache.o
 
Philip Pokorny· Apr 28, 2005, 07:15 UTC · re: Petr Baudis · lore

Re: PATCH[2/4]: Allow tree-id to return the ID of a tree object

Convert commit-id to use the new cg-Xnormid internal script
Signed-off-by: Philip Pokorny <ppokorny@mindspring.com>
Index: commit-id
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/commit-id  (mode:100755 sha1:4efcb6bdfdb2b2c5744f5d4d47d92beb7777ed59)
+++ uncommitted/commit-id  (mode:100775)
@@ -1,39 +1,25 @@
 #!/usr/bin/env bash
 #
 # Get ID of commit associated with given id or HEAD.
+#
 # Copyright (c) Petr Baudis, 2005
 #
-# Takes the appropriate ID, defaults to HEAD.
-
-SHA1="[A-Za-z0-9]{40}"
-SHA1ONLY="^$SHA1$"
-
-id=$1
-if [ ! "$id" ] || [ "$id" = "this" ] || [ "$id" = "HEAD" ]; then
-	id=$(cat .git/HEAD)
-fi
 
-if (echo $id | egrep -vq "$SHA1ONLY") && [ -r ".git/refs/tags/$id" ]; then
-	id=$(cat ".git/refs/tags/$id")
-fi
-
-if (echo $id | egrep -vq "$SHA1ONLY") && [ -r ".git/refs/heads/$id" ]; then
-	id=$(cat ".git/refs/heads/$id")
-fi
+# Save for later error message
+orig="$1"
 
-idpref=$(echo "$id" | cut -c -2)
-idpost=$(echo "$id" | cut -c 3-)
-if [ $(find ".git/objects/$idpref" -name "$idpost*" 2>/dev/null | wc -l) -eq 1 ]; then
-	id=$idpref$(basename $(echo .git/objects/$idpref/$idpost*))
-fi
+# Normalize to SHA1 form
+id=$(cg-Xnormid "$orig")
 
-if echo $id | egrep -vq "$SHA1ONLY"; then
-	echo "Invalid id: $id" >&2
+if [ ! "$id" ]; then
+	# cg-Xnormid already reported the error
 	exit 1
 fi
 
-if [ "$(cat-file -t "$id")" != "commit" ]; then
-	echo "Invalid id: $id" >&2
+# cat-file will verify that $id is a valid SHA1 ID for us
+# If it isn't, we'll get '' back
+if [ "$(cat-file -t "$id" 2>/dev/null)" != "commit" ]; then
+	echo "Invalid commit id: $orig" >&2
 	exit 1
 fi
 
Philip Pokorny· May 2, 2005, 05:46 UTC · re: Philip Pokorny · lore

Re: PATCH[2/4]: Allow tree-id to return the ID of a tree object

Philip Pokorny wrote:
> Convert commit-id to use the new cg-Xnormid internal script
>
> Signed-off-by: Philip Pokorny <ppokorny@mindspring.com>

Were these patches accepted?? I ask because while I do seem to see the addition of the new cg-Xnormid, I don't see that tree-id and friends have been updated to use the new file.

But then again, I seem to be having trouble getting my git working 
directory to track or match the current head.  That would be:
    49612c471eebd26efe926a71752e254c1cdc382d
right?

Wait... Perhaps I'm seeing cg-Xnormid because it was an "other" file and therefore left in my directory. But that still doesn't explain why my checkedout cache doesn't show the results of the latest changes to cg-help... Even after running 'cg-update origin'

I'm so confused. It seems difficult to know exactly what the state of your cache actually *is* at any given time. Shouldn't cg-status tell you that you have modified, but uncommited files in your cache? Is there any way to know what the tree-id/commit-id your cache is an instance of? Do you have to 'cat .git/blocked' and 'ls -l .git/HEAD' to know?

In clearcase, I could 'ct lsview' and 'ct catcs' to see what my current view/cache was. I can't find the equivalent in cogito...

:v)
Philip Pokorny· Apr 28, 2005, 07:16 UTC · re: Petr Baudis · lore

Re: PATCH[3/4]: Allow tree-id to return the ID of a tree object

Convert tree-id to use cg-Xnormid to normalize an ID
Signed-off-by: Philip Pokorny <ppokorny@mindspring.com>
Index: tree-id
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/tree-id  (mode:100755 sha1:1495ff78af71b57e21653512932bcda88fe05454)
+++ uncommitted/tree-id  (mode:100775)
@@ -1,17 +1,31 @@
 #!/usr/bin/env bash
 #
 # Get ID of tree associated with given commit or HEAD.
+#
 # Copyright (c) Petr Baudis, 2005
 #
-# Takes ID of the appropriate commit, defaults to HEAD.
 
-SHA1="[A-Za-z0-9]{40}"
-TREE="^tree $SHA1$"
+# Save for later error message
+orig="$1"
 
-id=$(cat-file commit $(commit-id "$1") | egrep "$TREE" | cut -d ' ' -f 2)
+# Normalize to SHA1 form
+id=$(cg-Xnormid "$1")
+if [ ! "$id" ]; then
+	# cg-Xnormid already reported the error
+	exit 1
+fi
+
+# Is it a commit?
+idtype=$(cat-file -t $id 2>/dev/null)
+if [ "$idtype" = "commit" ]; then
+	# Get the tree
+	id=$(cat-file commit "$id" | sed -e 's/tree //;q')
+fi
 
-if [ "$(cat-file -t "$id")" != "tree" ]; then
-	echo "Invalid id: $id" >&2
+# cat-file will verify that $id is a valid SHA1 ID for us
+# If it isn't, we'll get '' back
+if [ "$(cat-file -t "$id" 2>/dev/null)" != "tree" ]; then
+	echo "Invalid tree id: $orig" >&2
 	exit 1
 fi
 
Philip Pokorny· Apr 28, 2005, 07:17 UTC · re: Petr Baudis · lore

Re: PATCH[4/4]: Allow tree-id to return the ID of a tree object

Convert parent-id to similar style and function as the new commit-id and tree-id.

NOTE: parent-id uses commit-id rather than cg-Xnormid directly
Signed-off-by: Philip Pokorny <ppokorny@mindspring.com>
Index: parent-id
===================================================================
--- 6ad600e20c89323c1d3049f75b8ca9b0a2d72167/parent-id  (mode:100755 sha1:f35877a6aa5b68d2fb4a388dcfa9b3e64262604e)
+++ uncommitted/parent-id  (mode:100775)
@@ -1,12 +1,19 @@
 #!/usr/bin/env bash
 #
 # Get ID of parent commit to a given revision or HEAD.
+# NOTE: will return multiple SHA1s if ID is a commit with multiple parents
+#
 # Copyright (c) Petr Baudis, 2005
 #
-# Takes ID of the current commit, defaults to HEAD.
 
-PARENT="^parent [A-Za-z0-9]{40}$"
+# Save for later error message
+orig="$1"
 
-id=$(commit-id $1) || exit 1
+# Normalize to SHA1 form and verify its a commit
+id=$(commit-id "$1")
+if [ ! "$id" ]; then
+	# commit-id already reported the error
+	exit 1
+fi
 
-cat-file commit $id | egrep "$PARENT" | cut -d ' ' -f 2
+cat-file commit $id | awk '/^parent/{print $2};/^$/{exit}'

← back to recent threads