Subject: [COGITO PATCH] Heads and tags in subdirectories

From: Santi Béjar <[email-masked]>
Date: Wed, 01 Jun 2005 00:00:35 +0200

Keep heads and tags in their respective subtirectoris named as
the branch. This fixes the case where two repositoris have tags
with the same name.

Add a "-a" flag to cg-pull to download all the repositories heads,
so you can now do a "cg-log -r repo#branch" (cg-Xnormid repo#branch
job).

The transition is automatic when you do the first "cg-pull repo".

Signed-off-by: "Santi Béjar" <[email-masked]>

 cg-Xnormid |   14 ++++++++++-
 cg-commit  |    7 +++++
 cg-pull    |   72 +++++++++++++++++++++++++++++++++++++------------------------
 3 files changed, 62 insertions(+), 31 deletions(-)

diff --git a/cg-Xnormid b/cg-Xnormid
--- a/cg-Xnormid
+++ b/cg-Xnormid
@@ -16,15 +16,25 @@
 
 id="$1"
 
+repo=$(echo $id | cut -d '#' -f 1)
+(echo $repo | egrep -qv '[^a-zA-Z0-9_.@!:-]') || \
+	die "name contains invalid characters"
+id=$(echo $id | sed 's@#@/@')
+
 if [ ! "$id" ] || [ "$id" = "this" ] || [ "$id" = "HEAD" ]; then
 	read id < "$_git/HEAD"
 
-elif [ -r "$_git/refs/tags/$id" ]; then
+elif [ -r "$_git/refs/tags/$id" ] && [ ! -d "$_git/refs/tags/$id" ]; then
 	read id < "$_git/refs/tags/$id"
 
-elif [ -r "$_git/refs/heads/$id" ]; then
+elif [ -r "$_git/refs/heads/$id" ] && [ ! -d "$_git/refs/tags/$id" ]; then
 	read id < "$_git/refs/heads/$id"
 
+elif [ -r "$_git/branches/$id" ]; then
+	repobranch=$(cat "$_git/branches/$id" | cut -d '#' -f 2 -s)
+	repobranch=${repobranch:-master}
+	read id < "$_git/refs/heads/$id/$repobranch"
+
 # 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
 	idpref=${id:0:2}
diff --git a/cg-commit b/cg-commit
--- a/cg-commit
+++ b/cg-commit
@@ -141,7 +141,12 @@ if [ "$merging" ]; then
 	[ "$msgs" ] && echo -n 'Merge with '
 	[ -s $_git/merging-sym ] || cp $_git/merging $_git/merging-sym
 	for sym in $(cat $_git/merging-sym); do
-		uri=$(cat $_git/branches/$sym)
+		repo=$(echo $sym | cut -d '#' -f 1)
+		branch=$(echo $sym | cut -d '#' -f 2 -s)
+		uri=$(cat $_git/branches/$repo)
+		uribranch=$(echo $uri | cut -d '#' -f 2 -s)
+		[ -z "$uribranch" ] && [ -n "$branch" ] &&
+		[ "$branch" != master ] && uri=${uri}#$branch
 		[ "$uri" ] || uri="$sym"
 		echo "$uri" >>$LOGMSG
 		[ "$msgs" ] && echo "$uri"
diff --git a/cg-pull b/cg-pull
--- a/cg-pull
+++ b/cg-pull
@@ -6,23 +6,41 @@
 # Takes the branch name as an argument, defaulting to "origin".
 #
 # See `cg-branch-add` for some description.
+#
+# OPTIONS
+# -------
+# -a::
+#       Pull all the heads from repositori.
 
-USAGE="cg-pull [BRANCH_NAME]"
+USAGE="cg-pull [-a] [BRANCH_NAME]"
 
 . ${COGITO_LIB}cg-Xlib
 
-name=$1
-
+[ "$1" == "-a" ] && all=yes && shift
+name=$1 && shift
 
 [ "$name" ] || { [ -s $_git/refs/heads/origin ] && name=origin; }
 [ "$name" ] || die "where to pull from?"
-uri=$(cat "$_git/branches/$name" 2>/dev/null) || die "unknown branch: $name"
 
-rembranch=master
+repo=$(echo $name | cut -d '#' -f 1)
+repobranch=$(echo $name | cut -s -d '#' -f 2)
+
+uri=$(cat "$_git/branches/$name" 2>/dev/null) || die "unknown branch: $name"
 if echo "$uri" | grep -q '#'; then
+	[ -z "$repobranch" ] && repobranch=$(echo $uri | cut -d '#' -f 2)
 	rembranch=$(echo $uri | cut -d '#' -f 2)
 	uri=$(echo $uri | cut -d '#' -f 1)
 fi
+repobranch=${repobranch:-master}
+branch=$repo/$repobranch
+[ "$all" ] && repobranch=
+
+# So long we have:
+# $repo       = name of the repositori
+# $uri        = uri of the repositori
+# $repobranch = name of the branch in the repositori
+#               empty if we want all the branches
+# $branch     = name of the local branch in refs/heads/
 
 pull_progress() {
 	percentage=""
@@ -232,39 +250,37 @@ fi

 orig_head=
-[ -s "$_git/refs/heads/$name" ] && orig_head=$(cat "$_git/refs/heads/$name")
-
+[ -s "$_git/refs/heads/$branch" ] && orig_head=$(cat "$_git/refs/heads/$branch")
 
-mkdir -p $_git/refs/heads
-rsyncerr=
-$fetch -i "$uri/refs/heads/$rembranch" "$_git/refs/heads/$name" || rsyncerr=1
-if [ "$rsyncerr" ]; then
-	rsyncerr=
-	$fetch -s "$uri/heads/$rembranch" "$_git/refs/heads/$name" || rsyncerr=1
-fi
-if [ "$rsyncerr" ] && [ "$rembranch" = "master" ]; then
-	rsyncerr=
-	$fetch -s "$uri/HEAD" "$_git/refs/heads/$name" || rsyncerr=1
+# 2005/05 Convert old layout
+[ -f $_git/refs/heads/$repo ] && orig_head=$(cat $_git/refs/heads/$repo) &&
+rm -f $_git/refs/heads/$repo
+
+mkdir -p $_git/refs/heads/$repo
+if [ "$repobranch" ] ; then
+    $fetch -i "$uri/refs/heads/$repobranch" "$_git/refs/heads/$branch" ||
+    $fetch -s "$uri/heads/$repobranch" "$_git/refs/heads/$branch" ||
+    { [ "$repobranch" = "master" ] && $fetch -s "$uri/HEAD" "$_git/refs/heads/$branch"; } ||
+    rsyncerr=1
+else
+    $fetch -i -d "$uri/refs/heads" "$_git/refs/heads/$repo" ||
+    $fetch -s -d "$uri/heads" "$_git/refs/heads/$repo" ||
+    rsyncerr=1
 fi
-[ "$rsyncerr" ] && die "unable to get the head pointer of branch $rembranch"
+[ "$rsyncerr" ] && die "unable to get the head pointer of branch $repobranch"
 
 [ -d $_git_objects ] || mkdir -p $_git_objects
-$pull "$name" "$uri" || die "objects pull failed"
+$pull "$branch" "$uri" || die "objects pull failed"
 
-# FIXME: Warn about conflicting tag names?
 # XXX: We now throw stderr to /dev/null since not all repositories
 # may have tags/ and users were confused by the harmless errors.
-[ -d $_git/refs/tags ] || mkdir -p $_git/refs/tags
+[ -d $_git/refs/tags/$repo ] || mkdir -p $_git/refs/tags/$repo
 rsyncerr=
-$fetch -i -s -u -d "$uri/refs/tags" "$_git/refs/tags" || rsyncerr=1
-if [ "$rsyncerr" ]; then
-	rsyncerr=
-	$fetch -i -s -u -d "$uri/tags" "$_git/refs/tags" || rsyncerr=1
-fi
+$fetch -i -s -u -d "$uri/refs/tags" "$_git/refs/tags/$repo" ||
+$fetch -i -s -u -d "$uri/tags" "$_git/refs/tags/$repo" || rsyncerr=1
 [ "$rsyncerr" ] && echo "unable to get tags list (non-fatal)" >&2
 
-
-new_head=$(cat "$_git/refs/heads/$name")
+new_head=$(cat "$_git/refs/heads/$branch")
 
 if [ ! "$orig_head" ]; then
 	echo "New branch: $new_head"