{"thread":{"id":"4767","subject":"Improve git-peek-remote","startedAt":"2006-07-04T19:29:10Z","lastAt":"2006-07-04T20:01:06Z","messageCount":2,"participants":["Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"23240","messageId":"Pine.LNX.4.64.0607041222110.12404@g5.osdl.org","threadId":"4767","inReplyTo":null,"subject":"Improve git-peek-remote","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-07-04T19:29:10Z","receivedAt":"2006-07-04T19:29:10Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nThis makes git-peek-remote able to basically do everything that \ngit-ls-remote does (but obviously just for the native protocol, so no \nhttp[s]: or rsync: support).\n\nThe default behaviour is the same, but you can now give a mixture of \n\"--refs\", \"--tags\" and \"--heads\" flags, where \"--refs\" forces \ngit-peek-remote to only show real refs (ie none of the fakey tag lookups, \nbut also not the special pseudo-refs like HEAD and MERGE_HEAD).\n\nThe \"--tags\" and \"--heads\" flags respectively limit the output to just \nregular tags and heads, of course.\n\nYou can still also ask to limit them by name too.\n\nYou can combine the flags, so\n\n\tgit peek-remote --refs --tags .\n\nwill show all local _true_ tags, without the generated tag lookups \n(compare the output without the \"--refs\" flag).\n\nAnd \"--tags --heads\" will show both tags and heads, but will avoid (for \nexample) any special refs outside of the standard locations.\n\nI'm also planning on adding a \"--ignore-local\" flag that allows us to ask \nit to ignore any refs that we already have in the local tree, but that's \nan independent thing.\n\nAll this is obviously gearing up to making \"git fetch\" cheaper.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\n cache.h       |    6 +++++-\n connect.c     |   35 +++++++++++++++++++++++++++++++----\n peek-remote.c |   28 +++++++++++++++++++++-------\n send-pack.c   |    2 +-\n 4 files changed, 58 insertions(+), 13 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 84770bf..7b5c91c 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -322,13 +322,17 @@ struct ref {\n \tchar name[FLEX_ARRAY]; /* more */\n };\n \n+#define REF_NORMAL\t(1u << 0)\n+#define REF_HEADS\t(1u << 1)\n+#define REF_TAGS\t(1u << 2)\n+\n extern int git_connect(int fd[2], char *url, const char *prog);\n extern int finish_connect(pid_t pid);\n extern int path_match(const char *path, int nr, char **match);\n extern int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n \t\t      int nr_refspec, char **refspec, int all);\n extern int get_ack(int fd, unsigned char *result_sha1);\n-extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, int ignore_funny);\n+extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags);\n extern int server_supports(const char *feature);\n \n extern struct packed_git *parse_pack_index(unsigned char *sha1);\ndiff --git a/connect.c b/connect.c\nindex 9a87bd9..4422a0d 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -12,11 +12,40 @@ #include <signal.h>\n \n static char *server_capabilities = NULL;\n \n+static int check_ref(const char *name, int len, unsigned int flags)\n+{\n+\tif (!flags)\n+\t\treturn 1;\n+\n+\tif (len > 45 || memcmp(name, \"refs/\", 5))\n+\t\treturn 0;\n+\n+\t/* Skip the \"refs/\" part */\n+\tname += 5;\n+\tlen -= 5;\n+\n+\t/* REF_NORMAL means that we don't want the magic fake tag refs */\n+\tif ((flags & REF_NORMAL) && check_ref_format(name) < 0)\n+\t\treturn 0;\n+\n+\t/* REF_HEADS means that we want regular branch heads */\n+\tif ((flags & REF_HEADS) && !memcmp(name, \"heads/\", 6))\n+\t\treturn 1;\n+\n+\t/* REF_TAGS means that we want tags */\n+\tif ((flags & REF_TAGS) && !memcmp(name, \"tags/\", 5))\n+\t\treturn 1;\n+\n+\t/* All type bits clear means that we are ok with anything */\n+\treturn !(flags & ~REF_NORMAL);\n+}\n+\n /*\n  * Read all the refs from the other end\n  */\n struct ref **get_remote_heads(int in, struct ref **list,\n-\t\t\t      int nr_match, char **match, int ignore_funny)\n+\t\t\t      int nr_match, char **match,\n+\t\t\t      unsigned int flags)\n {\n \t*list = NULL;\n \tfor (;;) {\n@@ -43,10 +72,8 @@ struct ref **get_remote_heads(int in, st\n \t\t\tserver_capabilities = strdup(name + name_len + 1);\n \t\t}\n \n-\t\tif (ignore_funny && 45 < len && !memcmp(name, \"refs/\", 5) &&\n-\t\t    check_ref_format(name + 5))\n+\t\tif (!check_ref(name, name_len, flags))\n \t\t\tcontinue;\n-\n \t\tif (nr_match && !path_match(name, nr_match, match))\n \t\t\tcontinue;\n \t\tref = xcalloc(1, sizeof(*ref) + len - 40);\ndiff --git a/fetch-pack.c b/fetch-pack.c\ndiff --git a/peek-remote.c b/peek-remote.c\nindex a90cf22..2b30980 100644\n--- a/peek-remote.c\n+++ b/peek-remote.c\n@@ -7,11 +7,11 @@ static const char peek_remote_usage[] =\n \"git-peek-remote [--exec=upload-pack] [host:]directory\";\n static const char *exec = \"git-upload-pack\";\n \n-static int peek_remote(int fd[2])\n+static int peek_remote(int fd[2], unsigned flags)\n {\n \tstruct ref *ref;\n \n-\tget_remote_heads(fd[0], &ref, 0, NULL, 0);\n+\tget_remote_heads(fd[0], &ref, 0, NULL, flags);\n \tpacket_flush(fd[1]);\n \n \twhile (ref) {\n@@ -28,6 +28,7 @@ int main(int argc, char **argv)\n \tint fd[2];\n \tpid_t pid;\n \tint nongit = 0;\n+\tunsigned flags = 0;\n \n \tsetup_git_directory_gently(&nongit);\n \n@@ -35,22 +36,35 @@ int main(int argc, char **argv)\n \t\tchar *arg = argv[i];\n \n \t\tif (*arg == '-') {\n-\t\t\tif (!strncmp(\"--exec=\", arg, 7))\n+\t\t\tif (!strncmp(\"--exec=\", arg, 7)) {\n \t\t\t\texec = arg + 7;\n-\t\t\telse\n-\t\t\t\tusage(peek_remote_usage);\n-\t\t\tcontinue;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!strcmp(\"--tags\", arg)) {\n+\t\t\t\tflags |= REF_TAGS;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!strcmp(\"--heads\", arg)) {\n+\t\t\t\tflags |= REF_HEADS;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!strcmp(\"--refs\", arg)) {\n+\t\t\t\tflags |= REF_NORMAL;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tusage(peek_remote_usage);\n \t\t}\n \t\tdest = arg;\n \t\tbreak;\n \t}\n+\n \tif (!dest || i != argc - 1)\n \t\tusage(peek_remote_usage);\n \n \tpid = git_connect(fd, dest, exec);\n \tif (pid < 0)\n \t\treturn 1;\n-\tret = peek_remote(fd);\n+\tret = peek_remote(fd, flags);\n \tclose(fd[0]);\n \tclose(fd[1]);\n \tfinish_connect(pid);\ndiff --git a/send-pack.c b/send-pack.c\nindex af93b11..4019a4b 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -239,7 +239,7 @@ static int send_pack(int in, int out, in\n \tint expect_status_report = 0;\n \n \t/* No funny business with the matcher */\n-\tremote_tail = get_remote_heads(in, &remote_refs, 0, NULL, 1);\n+\tremote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL);\n \tget_local_heads();\n \n \t/* Does the other end support the reporting? */\n"},{"id":"23241","messageId":"Pine.LNX.4.64.0607041258310.12404@g5.osdl.org","threadId":"4767","inReplyTo":"Pine.LNX.4.64.0607041222110.12404@g5.osdl.org","subject":"Re: Improve git-peek-remote","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-07-04T20:01:06Z","receivedAt":"2006-07-04T20:01:06Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 4 Jul 2006, Linus Torvalds wrote:\n> \n> This makes git-peek-remote able to basically do everything that \n> git-ls-remote does (but obviously just for the native protocol, so no \n> http[s]: or rsync: support).\n\nBtw, if it wasn't clear - it's not actually a git-ls-remote replacement \nyet, even for native protocols. It doesn't actually do the remote URL \nthing, so you can't do simple things like\n\n\tgit peek-remote origin\n\nfor example. \n\nThings like \"git fetch\", that do their own remote parsing anyway, don't \nactually care, but I thought I'd mention it anyway, just so nobody gets \nsurprised.\n\n\t\tLinus\n"}]}