From: Brandon Williams <bmwill@google.com>
To: git@vger.kernel.org
Cc: Brandon Williams <bmwill@google.com>
Subject: [WIP 14/15] upload_pack: introduce fetch server command
Date: Mon, 4 Dec 2017 15:58:22 -0800 [thread overview]
Message-ID: <20171204235823.63299-15-bmwill@google.com> (raw)
In-Reply-To: <20171204235823.63299-1-bmwill@google.com>
Introduce the 'fetch' server command.
Signed-off-by: Brandon Williams <bmwill@google.com>
---
serve.c | 2 +
upload-pack.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
upload-pack.h | 9 +++
3 files changed, 234 insertions(+)
create mode 100644 upload-pack.h
diff --git a/serve.c b/serve.c
index 36f77c365..7823ef0d9 100644
--- a/serve.c
+++ b/serve.c
@@ -6,6 +6,7 @@
#include "argv-array.h"
#include "ls-refs.h"
#include "serve.h"
+#include "upload-pack.h"
static int always_advertise(struct repository *r,
struct strbuf *value)
@@ -34,6 +35,7 @@ struct protocol_capability {
static struct protocol_capability capabilities[] = {
{ "agent", 0, agent_advertise, NULL },
{ "ls-refs", 0, always_advertise, ls_refs },
+ { "fetch", 0, always_advertise, upload_pack_v2 },
};
static void advertise_capabilities(void)
diff --git a/upload-pack.c b/upload-pack.c
index 3296831f8..dc4421ab3 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -20,6 +20,7 @@
#include "prio-queue.h"
#include "protocol.h"
#include "serve.h"
+#include "upload-pack.h"
static const char * const upload_pack_usage[] = {
N_("git upload-pack [<options>] <dir>"),
@@ -1041,6 +1042,228 @@ static void upload_pack(void)
}
}
+static int process_want(const char *line)
+{
+ const char *arg;
+ if (skip_prefix(line, "want ", &arg)) {
+ struct object_id oid;
+ struct object *o;
+
+ if (get_oid_hex(arg, &oid))
+ die("git upload-pack: protocol error, "
+ "expected to get oid, not '%s'", line);
+
+ o = parse_object(&oid);
+ if (!o) {
+ packet_write_fmt(1,
+ "ERR upload-pack: not our ref %s",
+ oid_to_hex(&oid));
+ die("git upload-pack: not our ref %s",
+ oid_to_hex(&oid));
+ }
+
+ if (!(o->flags & WANTED)) {
+ o->flags |= WANTED;
+ add_object_array(o, NULL, &want_obj);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_have(const char *line, struct oid_array *haves)
+{
+ const char *arg;
+ if (skip_prefix(line, "have ", &arg)) {
+ struct object_id oid;
+
+ if (get_oid_hex(arg, &oid))
+ die("git upload-pack: expected SHA1 object, got '%s'", arg);
+ oid_array_append(haves, &oid);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void process_args(struct argv_array *args, struct oid_array *haves_oid)
+{
+ int i;
+
+ for (i = 0; i < args->argc; i++) {
+ const char *arg = args->argv[i];
+
+ /* process want */
+ if (process_want(arg))
+ continue;
+ /* process have line */
+ if (parse_have(arg, haves_oid))
+ continue;
+
+ /* process args like thin-pack */
+ if (!strcmp(arg, "thin-pack")) {
+ use_thin_pack = 1;
+ continue;
+ }
+ if (!strcmp(arg, "ofs-delta")) {
+ use_ofs_delta = 1;
+ continue;
+ }
+ if (!strcmp(arg, "no-progress")) {
+ no_progress = 1;
+ continue;
+ }
+ if (!strcmp(arg, "include-tag")) {
+ use_include_tag = 1;
+ continue;
+ }
+
+ /* ignore unknown lines maybe? */
+ die("unexpect line: '%s'", arg);
+ }
+}
+
+static int process_haves(struct oid_array *haves, struct oid_array *common)
+{
+ int i;
+
+ /* Process haves */
+ for (i = 0; i < haves->nr; i++) {
+ const struct object_id *oid = &haves->oid[i];
+ struct object *o;
+ int we_knew_they_have = 0;
+
+ if (!has_object_file(oid))
+ continue;
+
+ oid_array_append(common, oid);
+
+ o = parse_object(oid);
+ if (!o)
+ die("oops (%s)", oid_to_hex(oid));
+ if (o->type == OBJ_COMMIT) {
+ struct commit_list *parents;
+ struct commit *commit = (struct commit *)o;
+ if (o->flags & THEY_HAVE)
+ we_knew_they_have = 1;
+ else
+ o->flags |= THEY_HAVE;
+ if (!oldest_have || (commit->date < oldest_have))
+ oldest_have = commit->date;
+ for (parents = commit->parents;
+ parents;
+ parents = parents->next)
+ parents->item->object.flags |= THEY_HAVE;
+ }
+ if (!we_knew_they_have)
+ add_object_array(o, NULL, &have_obj);
+ }
+
+ return 0;
+}
+
+static int send_acks(struct oid_array *acks, struct strbuf *response)
+{
+ int i;
+ /* Send Acks */
+ if (!acks->nr)
+ packet_buf_write(response, "NAK\n");
+
+ for (i = 0; i < acks->nr; i++) {
+ packet_buf_write(response, "ACK %s common\n",
+ oid_to_hex(&acks->oid[i]));
+ }
+
+ if (ok_to_give_up()) {
+ /* Send Ready */
+ packet_buf_write(response, "ACK %s ready\n",
+ oid_to_hex(&acks->oid[i-1]));
+ return 1;
+ }
+
+ return 0;
+}
+
+#define COMMON_START 0
+#define COMMON_DONE 1
+#define COMMON_READ_HAVES 2
+#define COMMON_PROCESS_HAVES 3
+
+static int get_common_commits_v2(struct oid_array *haves_oid)
+{
+ struct packet_reader reader;
+ int done = 0;
+ int state = haves_oid->nr ? COMMON_PROCESS_HAVES : COMMON_DONE;
+ struct oid_array common = OID_ARRAY_INIT;
+ struct strbuf response = STRBUF_INIT;
+ packet_reader_init(&reader, 0, NULL, 0);
+
+ while (state != COMMON_DONE) {
+ switch (state) {
+ case COMMON_START:
+ break;
+ case COMMON_READ_HAVES:
+ while (packet_reader_read(&reader) == PACKET_READ_NORMAL) {
+
+ if (parse_have(reader.line, haves_oid))
+ continue;
+ if (!strcmp(reader.line, "done")) {
+ done = 1;
+ continue;
+ }
+ }
+ if (reader.status != PACKET_READ_FLUSH)
+ die("ERROR");
+
+ state = COMMON_PROCESS_HAVES;
+ break;
+ case COMMON_PROCESS_HAVES:
+ process_haves(haves_oid, &common);
+ if (done) {
+ state = COMMON_DONE;
+ } else if (send_acks(&common, &response)) {
+ packet_buf_delim(&response);
+ state = COMMON_DONE;
+ } else {
+ /* Add Flush */
+ packet_buf_flush(&response);
+ state = COMMON_READ_HAVES;
+ }
+
+ /* Send response */
+ write_or_die(1, response.buf, response.len);
+ strbuf_reset(&response);
+ oid_array_clear(haves_oid);
+ oid_array_clear(&common);
+ break;
+ case COMMON_DONE:
+ break;
+ default:
+ BUG("invalid state");
+ }
+ }
+ return 0;
+}
+
+int upload_pack_v2(struct repository *r, struct argv_array *keys,
+ struct argv_array *args)
+{
+ struct oid_array haves_oid = OID_ARRAY_INIT;
+ use_sideband = LARGE_PACKET_MAX;
+ process_args(args, &haves_oid);
+
+ if (want_obj.nr) {
+ /* Determine Common Commits */
+ get_common_commits_v2(&haves_oid);
+ /* create packfile */
+ create_pack_file();
+ }
+
+ return 0;
+}
+
static int upload_pack_config(const char *var, const char *value, void *unused)
{
if (!strcmp("uploadpack.allowtipsha1inwant", var)) {
diff --git a/upload-pack.h b/upload-pack.h
new file mode 100644
index 000000000..54c429563
--- /dev/null
+++ b/upload-pack.h
@@ -0,0 +1,9 @@
+#ifndef UPLOAD_PACK_H
+#define UPLOAD_PACK_H
+
+struct repository;
+struct argv_array;
+extern int upload_pack_v2(struct repository *r, struct argv_array *keys,
+ struct argv_array *args);
+
+#endif /* UPLOAD_PACK_H */
--
2.15.1.424.g9478a66081-goog
next prev parent reply other threads:[~2017-12-04 23:59 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-20 17:18 [RFC] protocol version 2 Brandon Williams
2017-10-24 6:48 ` Junio C Hamano
2017-10-24 18:35 ` Brandon Williams
2017-10-25 1:22 ` Junio C Hamano
2017-10-26 0:59 ` Junio C Hamano
2017-10-25 13:09 ` Derrick Stolee
2017-10-25 18:10 ` Brandon Williams
2017-10-28 22:57 ` Philip Oakley
2017-10-31 18:42 ` Brandon Williams
2017-11-10 20:13 ` Jonathan Tan
2017-12-04 23:58 ` [WIP 00/15] " Brandon Williams
2017-12-04 23:58 ` [WIP 01/15] pkt-line: introduce packet_read_with_status Brandon Williams
2017-12-07 20:53 ` Stefan Beller
2017-12-08 18:03 ` Brandon Williams
2017-12-04 23:58 ` [WIP 02/15] pkt-line: introduce struct packet_reader Brandon Williams
2017-12-07 22:01 ` Stefan Beller
2017-12-08 18:11 ` Brandon Williams
2017-12-04 23:58 ` [WIP 03/15] pkt-line: add delim packet support Brandon Williams
2017-12-07 22:30 ` Stefan Beller
2017-12-08 20:08 ` Brandon Williams
2017-12-04 23:58 ` [WIP 04/15] upload-pack: convert to a builtin Brandon Williams
2017-12-06 21:59 ` Junio C Hamano
2017-12-07 16:14 ` Johannes Schindelin
2017-12-08 20:26 ` Junio C Hamano
2017-12-08 20:12 ` Brandon Williams
2017-12-04 23:58 ` [WIP 05/15] upload-pack: factor out processing lines Brandon Williams
2017-12-04 23:58 ` [WIP 06/15] transport: use get_refs_via_connect to get refs Brandon Williams
2017-12-06 22:10 ` Junio C Hamano
2017-12-07 18:40 ` Brandon Williams
2017-12-04 23:58 ` [WIP 07/15] connect: convert get_remote_heads to use struct packet_reader Brandon Williams
2017-12-06 22:39 ` Junio C Hamano
2017-12-08 20:19 ` Brandon Williams
2017-12-04 23:58 ` [WIP 08/15] connect: discover protocol version outside of get_remote_heads Brandon Williams
2017-12-07 18:50 ` Junio C Hamano
2017-12-07 19:04 ` Brandon Williams
2017-12-07 19:30 ` Junio C Hamano
2017-12-08 20:11 ` Brandon Williams
2017-12-04 23:58 ` [WIP 09/15] transport: store protocol version Brandon Williams
2017-12-04 23:58 ` [WIP 10/15] protocol: introduce enum protocol_version value protocol_v2 Brandon Williams
2017-12-04 23:58 ` [WIP 11/15] serve: introduce git-serve Brandon Williams
2017-12-07 23:42 ` Junio C Hamano
2017-12-08 20:25 ` Brandon Williams
2017-12-04 23:58 ` [WIP 12/15] ls-refs: introduce ls-refs server command Brandon Williams
2017-12-13 16:30 ` Philip Oakley
2017-12-04 23:58 ` [WIP 13/15] connect: request remote refs using v2 Brandon Williams
2017-12-04 23:58 ` Brandon Williams [this message]
2017-12-04 23:58 ` [WIP 15/15] fetch-pack: perform a fetch " Brandon Williams
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
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171204235823.63299-15-bmwill@google.com \
--to=bmwill@google.com \
--cc=git@vger.kernel.org \
/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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
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 read-only IMAP folder(s) and NNTP newsgroup(s).