* [PATCH/RFC] Implemented glob support in pull refspecs
@ 2006-11-22 22:13 Andy Parkins
2006-11-23 7:24 ` [PATCH 1/3] git-fetch: reuse ls-remote result Junio C Hamano
0 siblings, 1 reply; 4+ messages in thread
From: Andy Parkins @ 2006-11-22 22:13 UTC (permalink / raw)
To: git
git-ls-remote is now called early on and the list categorised into heads and
tags. Any time a refspec has a "*" in the remote part, the git-ls-remote head
list is searched for matches against that refspec. If found then the part of
the remote ref that matches the "*" is substituted into the local part of the
refspec.
This allows refspecs like
refs/heads/*:refs/remotes/origin/*
Which will ensure that all branches on the remote are created locally.
Note, no local branch will be deleted, so if it is deleted upstream it will
remain in the local repository.
As an added bonus, because the output of git-ls-remote is now stored, the other
calls to it for tag processing are replaced with simple accesses to the
previously stored remote tag list
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
The problem with this patch is that I had to disable the safety check
in git-parse-remote.sh to allow the "*" in the refspec. I'm not sure what
the appropriate place to put that call now is? Perhaps after the expansion
of the globbed refspecs?
git-fetch.sh | 77 +++++++++++++++++++++++++++++++++++++++++++++-----
git-parse-remote.sh | 10 +++---
2 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/git-fetch.sh b/git-fetch.sh
index eb32476..1875fe9 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -224,6 +224,24 @@ case "$update_head_ok" in
;;
esac
+# Prefetch the remote list and categorise it into tags and heads
+remotereflist=$(git-ls-remote $upload_pack "$remote")
+remoteheads=
+remotetags=
+for ref in $remotereflist
+do
+ # Convert the tab to a comma so that the case below works
+ ref=$(echo $ref | sed -e "s/\t/,/")
+ case $ref in
+ *,refs/heads/*)
+ remoteheads="$remoteheads$ref$LF"
+ ;;
+ *,refs/tags/*)
+ remotetags="$remotetags$ref$LF"
+ ;;
+ esac
+done
+
# If --tags (and later --heads or --all) is specified, then we are
# not talking about defaults stored in Pull: line of remotes or
# branches file, and just fetch those and refspecs explicitly given.
@@ -232,12 +250,9 @@ esac
reflist=$(get_remote_refs_for_fetch "$@")
if test "$tags"
then
- taglist=`IFS=" " &&
- (
- git-ls-remote $upload_pack --tags "$remote" ||
- echo fail ouch
- ) |
- while read sha1 name
+ taglist=`IFS="," &&
+ echo -n $remotetags |
+ while read sha1 name
do
case "$sha1" in
fail)
@@ -263,6 +278,52 @@ then
fi
fi
+# Expand any refspecs that contain "*"
+newreflist=
+for refspec in $reflist
+do
+ remotename=$(expr "z$refspec" : 'z\([^:]*\):')
+ localname=$(expr "z$refspec" : 'z[^:]*:\(.*\)')
+ if gotglob=$(expr "z$remotename" : 'zrefs/.*/\*$')
+ then
+ # If this is a glob-containing ref, then expand it using every
+ # matching remote head
+ for remoteref in $remoteheads
+ do
+ # remoteheads stores the heads with the hashes still present
+ remoteref=$(expr "$remoteref" : "$_x40,\\(.*\\)")
+
+ # For example, if
+ # remotename = refs/heads/*
+ # localname = refs/remotes/up/*
+ # Then we find a potential remote head of
+ # remoteref = refs/heads/branchname
+
+ # First see if it matches the remotename glob
+ case $remoteref in
+ $remotename)
+ # So we know remoteref is the going to be the remote
+ # in the new fetch line, however we need to substitute the
+ # "*" in the local part to get the local name
+ # First we manufacture the regexps to do the work
+ remotereg=$(echo $remotename | sed -e 's/\*/\\(.*\\)/')
+ remotebranch=$(expr "$remoteref" : "$remotereg")
+ # Now substitute this into the localname
+ localref=$(echo $localname | sed -e "s|\\*|$remotebranch|")
+ # And construct the new refspec
+ newreflist="$newreflist$remoteref:$localref$LF"
+ ;;
+ esac
+
+ done
+ else
+ # Non glob refs just get copied literally
+ newreflist="$newreflist$ref$LF"
+ fi
+done
+reflist=$newreflist
+
+
fetch_main () {
reflist="$1"
refs=
@@ -430,8 +491,8 @@ case "$no_tags$tags" in
*:refs/*)
# effective only when we are following remote branch
# using local tracking branch.
- taglist=$(IFS=" " &&
- git-ls-remote $upload_pack --tags "$remote" |
+ taglist=$(IFS="," &&
+ echo -n $remotetags |
sed -n -e 's|^\('"$_x40"'\) \(refs/tags/.*\)^{}$|\1 \2|p' \
-e 's|^\('"$_x40"'\) \(refs/tags/.*\)$|\1 \2|p' |
while read sha1 name
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index c325ef7..e541144 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -145,11 +145,11 @@ canon_refs_list_for_fetch () {
*) local="refs/heads/$local" ;;
esac
- if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
- then
- git-check-ref-format "$local_ref_name" ||
- die "* refusing to create funny ref '$local_ref_name' locally"
- fi
+# if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
+# then
+# git-check-ref-format "$local_ref_name" ||
+# die "* refusing to create funny ref '$local_ref_name' locally"
+# fi
echo "${dot_prefix}${force}${remote}:${local}"
done
}
--
1.4.3.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 1/3] git-fetch: reuse ls-remote result.
2006-11-22 22:13 [PATCH/RFC] Implemented glob support in pull refspecs Andy Parkins
@ 2006-11-23 7:24 ` Junio C Hamano
0 siblings, 0 replies; 4+ messages in thread
From: Junio C Hamano @ 2006-11-23 7:24 UTC (permalink / raw)
To: git; +Cc: Andy Parkins
This will become necessary to update the dumb protocol
transports to fetch from a repository with packed and then
pruned tags.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* I am doing this to allow dumb protocol transports to work
with a repository with packed and then pruned refs, but it
should be reusable for other purposes, such as wildcarding the
refspecs Andy is interested in.
git-fetch.sh | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/git-fetch.sh b/git-fetch.sh
index eb32476..170c2cb 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -88,6 +88,10 @@ then
: >"$GIT_DIR/FETCH_HEAD"
fi
+# Global that is reused later
+ls_remote_result=$(git ls-remote $upload_pack "$remote") ||
+ die "Cannot find the reflist at $remote"
+
append_fetch_head () {
head_="$1"
remote_="$2"
@@ -233,10 +237,7 @@ reflist=$(get_remote_refs_for_fetch "$@"
if test "$tags"
then
taglist=`IFS=" " &&
- (
- git-ls-remote $upload_pack --tags "$remote" ||
- echo fail ouch
- ) |
+ echo "$ls_remote_result" |
while read sha1 name
do
case "$sha1" in
@@ -245,6 +246,8 @@ then
esac
case "$name" in
*^*) continue ;;
+ refs/tags/*) ;;
+ *) continue ;;
esac
if git-check-ref-format "$name"
then
@@ -431,7 +434,7 @@ case "$no_tags$tags" in
# effective only when we are following remote branch
# using local tracking branch.
taglist=$(IFS=" " &&
- git-ls-remote $upload_pack --tags "$remote" |
+ echo "$ls_remote_result" |
sed -n -e 's|^\('"$_x40"'\) \(refs/tags/.*\)^{}$|\1 \2|p' \
-e 's|^\('"$_x40"'\) \(refs/tags/.*\)$|\1 \2|p' |
while read sha1 name
--
1.4.4.1.g77614
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH/RFC] Implemented glob support in pull refspecs
@ 2006-11-23 8:33 Andy Parkins
2006-11-23 8:46 ` Andy Parkins
0 siblings, 1 reply; 4+ messages in thread
From: Andy Parkins @ 2006-11-23 8:33 UTC (permalink / raw)
To: git
git-ls-remote is now called early on and the list categorised into heads and
tags. Any time a refspec has a "*" in the remote part, the git-ls-remote head
list is searched for matches against that refspec. If found then the part of
the remote ref that matches the "*" is substituted into the local part of the
refspec.
This allows refspecs like
refs/heads/*:refs/remotes/origin/*
Which will ensure that all branches on the remote are created locally.
Note, no local branch will be deleted, so if it is deleted upstream it will
remain in the local repository.
As an added bonus, because the output of git-ls-remote is now stored, the other
calls to it for tag processing are replaced with simple accesses to the
previously stored remote tag list
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
The problem with this patch is that I've removed the sanity check in
git-parse-remote.sh using git-check-ref-format. Where should I do this now?
Perhaps after the expansion of the glob?
git-fetch.sh | 77 +++++++++++++++++++++++++++++++++++++++++++++-----
git-parse-remote.sh | 10 +++---
2 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/git-fetch.sh b/git-fetch.sh
index eb32476..1875fe9 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -224,6 +224,24 @@ case "$update_head_ok" in
;;
esac
+# Prefetch the remote list and categorise it into tags and heads
+remotereflist=$(git-ls-remote $upload_pack "$remote")
+remoteheads=
+remotetags=
+for ref in $remotereflist
+do
+ # Convert the tab to a comma so that the case below works
+ ref=$(echo $ref | sed -e "s/\t/,/")
+ case $ref in
+ *,refs/heads/*)
+ remoteheads="$remoteheads$ref$LF"
+ ;;
+ *,refs/tags/*)
+ remotetags="$remotetags$ref$LF"
+ ;;
+ esac
+done
+
# If --tags (and later --heads or --all) is specified, then we are
# not talking about defaults stored in Pull: line of remotes or
# branches file, and just fetch those and refspecs explicitly given.
@@ -232,12 +250,9 @@ esac
reflist=$(get_remote_refs_for_fetch "$@")
if test "$tags"
then
- taglist=`IFS=" " &&
- (
- git-ls-remote $upload_pack --tags "$remote" ||
- echo fail ouch
- ) |
- while read sha1 name
+ taglist=`IFS="," &&
+ echo -n $remotetags |
+ while read sha1 name
do
case "$sha1" in
fail)
@@ -263,6 +278,52 @@ then
fi
fi
+# Expand any refspecs that contain "*"
+newreflist=
+for refspec in $reflist
+do
+ remotename=$(expr "z$refspec" : 'z\([^:]*\):')
+ localname=$(expr "z$refspec" : 'z[^:]*:\(.*\)')
+ if gotglob=$(expr "z$remotename" : 'zrefs/.*/\*$')
+ then
+ # If this is a glob-containing ref, then expand it using every
+ # matching remote head
+ for remoteref in $remoteheads
+ do
+ # remoteheads stores the heads with the hashes still present
+ remoteref=$(expr "$remoteref" : "$_x40,\\(.*\\)")
+
+ # For example, if
+ # remotename = refs/heads/*
+ # localname = refs/remotes/up/*
+ # Then we find a potential remote head of
+ # remoteref = refs/heads/branchname
+
+ # First see if it matches the remotename glob
+ case $remoteref in
+ $remotename)
+ # So we know remoteref is the going to be the remote
+ # in the new fetch line, however we need to substitute the
+ # "*" in the local part to get the local name
+ # First we manufacture the regexps to do the work
+ remotereg=$(echo $remotename | sed -e 's/\*/\\(.*\\)/')
+ remotebranch=$(expr "$remoteref" : "$remotereg")
+ # Now substitute this into the localname
+ localref=$(echo $localname | sed -e "s|\\*|$remotebranch|")
+ # And construct the new refspec
+ newreflist="$newreflist$remoteref:$localref$LF"
+ ;;
+ esac
+
+ done
+ else
+ # Non glob refs just get copied literally
+ newreflist="$newreflist$ref$LF"
+ fi
+done
+reflist=$newreflist
+
+
fetch_main () {
reflist="$1"
refs=
@@ -430,8 +491,8 @@ case "$no_tags$tags" in
*:refs/*)
# effective only when we are following remote branch
# using local tracking branch.
- taglist=$(IFS=" " &&
- git-ls-remote $upload_pack --tags "$remote" |
+ taglist=$(IFS="," &&
+ echo -n $remotetags |
sed -n -e 's|^\('"$_x40"'\) \(refs/tags/.*\)^{}$|\1 \2|p' \
-e 's|^\('"$_x40"'\) \(refs/tags/.*\)$|\1 \2|p' |
while read sha1 name
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index c325ef7..e541144 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -145,11 +145,11 @@ canon_refs_list_for_fetch () {
*) local="refs/heads/$local" ;;
esac
- if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
- then
- git-check-ref-format "$local_ref_name" ||
- die "* refusing to create funny ref '$local_ref_name' locally"
- fi
+# if local_ref_name=$(expr "z$local" : 'zrefs/\(.*\)')
+# then
+# git-check-ref-format "$local_ref_name" ||
+# die "* refusing to create funny ref '$local_ref_name' locally"
+# fi
echo "${dot_prefix}${force}${remote}:${local}"
done
}
--
1.4.3.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-11-23 8:46 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-22 22:13 [PATCH/RFC] Implemented glob support in pull refspecs Andy Parkins
2006-11-23 7:24 ` [PATCH 1/3] git-fetch: reuse ls-remote result Junio C Hamano
-- strict thread matches above, loose matches on Subject: below --
2006-11-23 8:33 [PATCH/RFC] Implemented glob support in pull refspecs Andy Parkins
2006-11-23 8:46 ` Andy Parkins
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).