From: Junio C Hamano <junkio@cox.net>
To: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Cc: Sergey Vlasov <vsu@altlinux.ru>, git@vger.kernel.org
Subject: Re: [RFC] multi_ack protocol v2
Date: Thu, 27 Oct 2005 10:45:18 -0700 [thread overview]
Message-ID: <7vwtjy3lch.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <Pine.LNX.4.63.0510271227490.2724@wbgn013.biozentrum.uni-wuerzburg.de> (Johannes Schindelin's message of "Thu, 27 Oct 2005 12:47:24 +0200 (CEST)")
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> On Thu, 27 Oct 2005, Sergey Vlasov wrote:
>
>> Actually, there is another way to pass some data from the server
>> which would be ignored by older clients - at the first stage,
>> when upload-pack sends the list of refs to the client:
>>
>> packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname, '\0',
>> server_capabilities);
>
> That exploits that packet_write() uses vnsprintf() to find out the length,
> not strlen(). Sweet.
OK.
> get_remote_heads() would need to store the server_capabilities, maybe with
> a function "server_supports(const char *extension_string)"
Another thing that would probably be helpful is to redo
get_remote_heads() slightly differently, so that it can return
information on *all* refs the other end has. We need to extend
"struct ref" to mark which one was actually matched/ignored by
path_match() and ignore_funny. An completely untested patch is
attached, based on fetch-pack that still runs rev-list as an
external process, to outline the idea.
---
diff --git a/cache.h b/cache.h
index 2e36cc5..d39a006 100644
--- a/cache.h
+++ b/cache.h
@@ -329,6 +329,7 @@ struct ref {
unsigned char old_sha1[20];
unsigned char new_sha1[20];
unsigned char force;
+ unsigned char matched; /* when using REPORT_ALL */
struct ref *peer_ref; /* when renaming */
char name[0];
};
@@ -339,7 +340,9 @@ extern int path_match(const char *path,
extern int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
int nr_refspec, char **refspec, int all);
extern int get_ack(int fd, unsigned char *result_sha1);
-extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, int ignore_funny);
+#define GET_REMOTE_HEADS_IGNORE_FUNNY 1
+#define GET_REMOTE_HEADS_REPORT_ALL 2
+extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, int match_options);
extern struct packed_git *parse_pack_index(unsigned char *sha1);
extern struct packed_git *parse_pack_index_file(const unsigned char *sha1,
diff --git a/clone-pack.c b/clone-pack.c
index 9609219..8b63183 100644
--- a/clone-pack.c
+++ b/clone-pack.c
@@ -250,7 +250,7 @@ static int clone_pack(int fd[2], int nr_
struct ref *refs;
int status;
- get_remote_heads(fd[0], &refs, nr_match, match, 1);
+ get_remote_heads(fd[0], &refs, nr_match, match, GET_REMOTE_HEADS_IGNORE_FUNNY);
if (!refs) {
packet_flush(fd[1]);
die("no matching remote head");
diff --git a/connect.c b/connect.c
index b171c5d..f7a3550 100644
--- a/connect.c
+++ b/connect.c
@@ -12,8 +12,11 @@
* Read all the refs from the other end
*/
struct ref **get_remote_heads(int in, struct ref **list,
- int nr_match, char **match, int ignore_funny)
+ int nr_match, char **match, int match_options)
{
+ int ignore_funny = match_options & GET_REMOTE_HEADS_IGNORE_FUNNY;
+ int report_all = match_options & GET_REMOTE_HEADS_REPORT_ALL;
+
*list = NULL;
for (;;) {
struct ref *ref;
@@ -21,6 +24,7 @@ struct ref **get_remote_heads(int in, st
static char buffer[1000];
char *name;
int len;
+ int matched = 1;
len = packet_read_line(in, buffer, sizeof(buffer));
if (!len)
@@ -28,17 +32,22 @@ struct ref **get_remote_heads(int in, st
if (buffer[len-1] == '\n')
buffer[--len] = 0;
- if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ')
- die("protocol error: expected sha/ref, got '%s'", buffer);
+ if (len < 42 || get_sha1_hex(buffer, old_sha1) ||
+ buffer[40] != ' ')
+ die("protocol error: expected sha/ref, got '%s'",
+ buffer);
name = buffer + 41;
- if (ignore_funny && 45 < len && !memcmp(name, "refs/", 5) &&
- check_ref_format(name + 5))
- continue;
+ if ((ignore_funny && 45 < len && !memcmp(name, "refs/", 5) &&
+ check_ref_format(name + 5)) ||
+ (nr_match && !path_match(name, nr_match, match))) {
+ if (!report_all)
+ continue;
+ matched = 0;
+ }
- if (nr_match && !path_match(name, nr_match, match))
- continue;
ref = xcalloc(1, sizeof(*ref) + len - 40);
+ ref->matched = matched;
memcpy(ref->old_sha1, old_sha1, 20);
memcpy(ref->name, buffer + 41, len - 40);
*list = ref;
diff --git a/fetch-pack.c b/fetch-pack.c
index 8566ab1..11fb1c1 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -13,6 +13,7 @@ static const char fetch_pack_usage[] =
static const char *exec = "git-upload-pack";
#define COMPLETE (1U << 0)
+#define EXCLUDE (1U << 1)
static int find_common(int fd[2], unsigned char *result_sha1,
struct ref *refs)
@@ -52,17 +53,24 @@ static int find_common(int fd[2], unsign
p = commit->parents;
while (p &&
rev_command_len + 44 < sizeof(rev_command)) {
- snprintf(rev_command + rev_command_len, 44,
- " ^%s",
- sha1_to_hex(p->item->object.sha1));
- rev_command_len += 43;
+ struct object *pobj = &(p->item->object);
+ if (!pobj->flags & EXCLUDE) {
+ snprintf(rev_command +
+ rev_command_len, 44,
+ " ^%s",
+ sha1_to_hex(pobj->sha1));
+ rev_command_len += 43;
+ }
+ pobj->flags |= EXCLUDE;
p = p->next;
}
continue;
}
repair:
- packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
- fetching++;
+ if (refs->matched) {
+ packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
+ fetching = 1;
+ }
}
packet_flush(fd[1]);
if (!fetching)
@@ -183,6 +191,8 @@ static int everything_local(struct ref *
unsigned char local[20];
struct object *o;
+ if (!refs->matched)
+ continue;
o = parse_object(remote);
if (!o || !(o->flags & COMPLETE)) {
retval = 0;
@@ -204,6 +214,16 @@ static int everything_local(struct ref *
return retval;
}
+static int no_matching_remote(struct ref *ref)
+{
+ while (ref)
+ if (ref->matched)
+ return 0;
+ else
+ ref = ref->next;
+ return 1;
+}
+
static int fetch_pack(int fd[2], int nr_match, char **match)
{
struct ref *ref;
@@ -211,8 +231,10 @@ static int fetch_pack(int fd[2], int nr_
int status;
pid_t pid;
- get_remote_heads(fd[0], &ref, nr_match, match, 1);
- if (!ref) {
+ get_remote_heads(fd[0], &ref, nr_match, match,
+ GET_REMOTE_HEADS_IGNORE_FUNNY |
+ GET_REMOTE_HEADS_REPORT_ALL);
+ if (no_matching_remote(ref)) {
packet_flush(fd[1]);
die("no matching remote head");
}
@@ -245,8 +267,9 @@ static int fetch_pack(int fd[2], int nr_
die("git-unpack-objects died with error code %d", code);
all_done:
while (ref) {
- printf("%s %s\n",
- sha1_to_hex(ref->old_sha1), ref->name);
+ if (ref->matched)
+ printf("%s %s\n",
+ sha1_to_hex(ref->old_sha1), ref->name);
ref = ref->next;
}
return 0;
diff --git a/send-pack.c b/send-pack.c
index 9f9a6e7..d7bb6c1 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -181,7 +181,8 @@ static int send_pack(int in, int out, in
int new_refs;
/* No funny business with the matcher */
- remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, 1);
+ remote_tail = get_remote_heads(in, &remote_refs, 0, NULL,
+ GET_REMOTE_HEADS_IGNORE_FUNNY);
get_local_heads();
/* match them up */
next prev parent reply other threads:[~2005-10-27 17:45 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-27 0:16 [RFC] multi_ack protocol v2 Johannes Schindelin
2005-10-27 7:13 ` Junio C Hamano
2005-10-27 9:37 ` Johannes Schindelin
2005-10-27 10:16 ` Sergey Vlasov
2005-10-27 10:47 ` Johannes Schindelin
2005-10-27 17:45 ` Junio C Hamano [this message]
2005-10-27 18:04 ` Johannes Schindelin
2005-10-27 19:15 ` Junio C Hamano
2005-10-27 9:11 ` Paul Mackerras
2005-10-27 10:54 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7vwtjy3lch.fsf@assigned-by-dhcp.cox.net \
--to=junkio@cox.net \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=vsu@altlinux.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).