@matheusbsbs / matheus-bagliano / commits / 6eb996b570
Fork 0

Add support for external programs for handling native fetches

transport_get() can call transport_native_helper_init() to have list and fetch-ref operations handled by running a separate program as: git remote-<something> <remote> [<url>] This program then accepts, on its stdin, "list" and "fetch <hex> <name>" commands; the former prints out a list of available refs and either their hashes or what they are symrefs to, while the latter fetches them into the local object database and prints a newline when done. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Daniel Barkalow committed Aug 5, 2009 at 01:01 UTC 6eb996b5707b6d14cf9875a9231f4e909a443665
4 files changed +243
Documentation/git-remote-helpers.txt new
+71
@@ -0,0 +1,71 @@
1 +git-remote-helpers(1)
2 +=====================
3 +
4 +NAME
5 +----
6 +git-remote-helpers - Helper programs for interoperation with remote git
7 +
8 +SYNOPSIS
9 +--------
10 +'git remote-<transport>' <remote>
11 +
12 +DESCRIPTION
13 +-----------
14 +
15 +These programs are normally not used directly by end users, but are
16 +invoked by various git programs that interact with remote repositories
17 +when the repository they would operate on will be accessed using
18 +transport code not linked into the main git binary. Various particular
19 +helper programs will behave as documented here.
20 +
21 +COMMANDS
22 +--------
23 +
24 +Commands are given by the caller on the helper's standard input, one per line.
25 +
26 +'capabilities'::
27 + Lists the capabilities of the helper, one per line, ending
28 + with a blank line.
29 +
30 +'list'::
31 + Lists the refs, one per line, in the format "<value> <name>
32 + [<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
33 + a symref, or "?" to indicate that the helper could not get the
34 + value of the ref. A space-separated list of attributes follows
35 + the name; unrecognized attributes are ignored. After the
36 + complete list, outputs a blank line.
37 +
38 +'fetch' <sha1> <name>::
39 + Fetches the given object, writing the necessary objects to the
40 + database. Outputs a blank line when the fetch is
41 + complete. Only objects which were reported in the ref list
42 + with a sha1 may be fetched this way.
43 ++
44 +Supported if the helper has the "fetch" capability.
45 +
46 +If a fatal error occurs, the program writes the error message to
47 +stderr and exits. The caller should expect that a suitable error
48 +message has been printed if the child closes the connection without
49 +completing a valid response for the current command.
50 +
51 +Additional commands may be supported, as may be determined from
52 +capabilities reported by the helper.
53 +
54 +CAPABILITIES
55 +------------
56 +
57 +'fetch'::
58 + This helper supports the 'fetch' command.
59 +
60 +REF LIST ATTRIBUTES
61 +-------------------
62 +
63 +None are defined yet, but the caller must accept any which are supplied.
64 +
65 +Documentation
66 +-------------
67 +Documentation by Daniel Barkalow.
68 +
69 +GIT
70 +---
71 +Part of the linkgit:git[1] suite
Makefile
+1
@@ -549,6 +549,7 @@ LIB_OBJS += symlinks.o
549 LIB_OBJS += tag.o
550 LIB_OBJS += trace.o
551 LIB_OBJS += transport.o
552 +LIB_OBJS += transport-helper.o
553 LIB_OBJS += tree-diff.o
554 LIB_OBJS += tree.o
555 LIB_OBJS += tree-walk.o
transport-helper.c new
+168
@@ -0,0 +1,168 @@
1 +#include "cache.h"
2 +#include "transport.h"
3 +
4 +#include "run-command.h"
5 +#include "commit.h"
6 +#include "diff.h"
7 +#include "revision.h"
8 +
9 +struct helper_data
10 +{
11 + const char *name;
12 + struct child_process *helper;
13 + unsigned fetch : 1;
14 +};
15 +
16 +static struct child_process *get_helper(struct transport *transport)
17 +{
18 + struct helper_data *data = transport->data;
19 + struct strbuf buf = STRBUF_INIT;
20 + struct child_process *helper;
21 + FILE *file;
22 +
23 + if (data->helper)
24 + return data->helper;
25 +
26 + helper = xcalloc(1, sizeof(*helper));
27 + helper->in = -1;
28 + helper->out = -1;
29 + helper->err = 0;
30 + helper->argv = xcalloc(4, sizeof(*helper->argv));
31 + strbuf_addf(&buf, "remote-%s", data->name);
32 + helper->argv[0] = strbuf_detach(&buf, NULL);
33 + helper->argv[1] = transport->remote->name;
34 + helper->argv[2] = transport->url;
35 + helper->git_cmd = 1;
36 + if (start_command(helper))
37 + die("Unable to run helper: git %s", helper->argv[0]);
38 + data->helper = helper;
39 +
40 + write_in_full(data->helper->in, "capabilities\n", 13);
41 + file = fdopen(helper->out, "r");
42 + while (1) {
43 + if (strbuf_getline(&buf, file, '\n') == EOF)
44 + exit(128); /* child died, message supplied already */
45 +
46 + if (!*buf.buf)
47 + break;
48 + if (!strcmp(buf.buf, "fetch"))
49 + data->fetch = 1;
50 + }
51 + return data->helper;
52 +}
53 +
54 +static int disconnect_helper(struct transport *transport)
55 +{
56 + struct helper_data *data = transport->data;
57 + if (data->helper) {
58 + write_in_full(data->helper->in, "\n", 1);
59 + close(data->helper->in);
60 + finish_command(data->helper);
61 + free((char *)data->helper->argv[0]);
62 + free(data->helper->argv);
63 + free(data->helper);
64 + data->helper = NULL;
65 + }
66 + return 0;
67 +}
68 +
69 +static int fetch_with_fetch(struct transport *transport,
70 + int nr_heads, const struct ref **to_fetch)
71 +{
72 + struct child_process *helper = get_helper(transport);
73 + FILE *file = fdopen(helper->out, "r");
74 + int i;
75 + struct strbuf buf = STRBUF_INIT;
76 +
77 + for (i = 0; i < nr_heads; i++) {
78 + struct ref *posn = to_fetch[i];
79 + if (posn->status & REF_STATUS_UPTODATE)
80 + continue;
81 + write_in_full(helper->in, "fetch ", 6);
82 + write_in_full(helper->in, sha1_to_hex(posn->old_sha1), 40);
83 + write_in_full(helper->in, " ", 1);
84 + write_in_full(helper->in, posn->name, strlen(posn->name));
85 + write_in_full(helper->in, "\n", 1);
86 + if (strbuf_getline(&buf, file, '\n') == EOF)
87 + exit(128); /* child died, message supplied already */
88 + }
89 + return 0;
90 +}
91 +
92 +static int fetch(struct transport *transport,
93 + int nr_heads, const struct ref **to_fetch)
94 +{
95 + struct helper_data *data = transport->data;
96 + int i, count;
97 +
98 + count = 0;
99 + for (i = 0; i < nr_heads; i++)
100 + if (!(to_fetch[i]->status & REF_STATUS_UPTODATE))
101 + count++;
102 +
103 + if (!count)
104 + return 0;
105 +
106 + if (data->fetch)
107 + return fetch_with_fetch(transport, nr_heads, to_fetch);
108 +
109 + return -1;
110 +}
111 +
112 +static struct ref *get_refs_list(struct transport *transport, int for_push)
113 +{
114 + struct child_process *helper;
115 + struct ref *ret = NULL;
116 + struct ref **tail = &ret;
117 + struct ref *posn;
118 + struct strbuf buf = STRBUF_INIT;
119 + FILE *file;
120 +
121 + helper = get_helper(transport);
122 + write_in_full(helper->in, "list\n", 5);
123 +
124 + file = fdopen(helper->out, "r");
125 + while (1) {
126 + char *eov, *eon;
127 + if (strbuf_getline(&buf, file, '\n') == EOF)
128 + exit(128); /* child died, message supplied already */
129 +
130 + if (!*buf.buf)
131 + break;
132 +
133 + eov = strchr(buf.buf, ' ');
134 + if (!eov)
135 + die("Malformed response in ref list: %s", buf.buf);
136 + eon = strchr(eov + 1, ' ');
137 + *eov = '\0';
138 + if (eon)
139 + *eon = '\0';
140 + *tail = alloc_ref(eov + 1);
141 + if (buf.buf[0] == '@')
142 + (*tail)->symref = xstrdup(buf.buf + 1);
143 + else if (buf.buf[0] != '?')
144 + get_sha1_hex(buf.buf, (*tail)->old_sha1);
145 + tail = &((*tail)->next);
146 + }
147 + strbuf_release(&buf);
148 +
149 + for (posn = ret; posn; posn = posn->next)
150 + resolve_remote_symref(posn, ret);
151 +
152 + return ret;
153 +}
154 +
155 +int transport_helper_init(struct transport *transport)
156 +{
157 + struct helper_data *data = xcalloc(sizeof(*data), 1);
158 + char *eom = strchr(transport->url, ':');
159 + if (!eom)
160 + return -1;
161 + data->name = xstrndup(transport->url, eom - transport->url);
162 +
163 + transport->data = data;
164 + transport->get_refs_list = get_refs_list;
165 + transport->fetch = fetch;
166 + transport->disconnect = disconnect_helper;
167 + return 0;
168 +}
transport.h
+3
@@ -77,4 +77,7 @@ void transport_unlock_pack(struct transport *transport);
77 int transport_disconnect(struct transport *transport);
78 char *transport_anonymize_url(const char *url);
79
80 +/* Transport methods defined outside transport.c */
81 +int transport_helper_init(struct transport *transport);
82 +
83 #endif