]> git.ipfire.org Git - thirdparty/git.git/blame - bundle-uri.c
bundle-uri: use plain string in find_temp_filename()
[thirdparty/git.git] / bundle-uri.c
CommitLineData
53a50892
DS
1#include "cache.h"
2#include "bundle-uri.h"
3#include "bundle.h"
4#include "object-store.h"
5#include "refs.h"
6#include "run-command.h"
7
23b6d00b 8static char *find_temp_filename(void)
53a50892
DS
9{
10 int fd;
23b6d00b 11 struct strbuf name = STRBUF_INIT;
53a50892
DS
12 /*
13 * Find a temporary filename that is available. This is briefly
14 * racy, but unlikely to collide.
15 */
23b6d00b 16 fd = odb_mkstemp(&name, "bundles/tmp_uri_XXXXXX");
53a50892
DS
17 if (fd < 0) {
18 warning(_("failed to create temporary file"));
23b6d00b 19 return NULL;
53a50892
DS
20 }
21
22 close(fd);
23b6d00b
DS
23 unlink(name.buf);
24 return strbuf_detach(&name, NULL);
53a50892
DS
25}
26
59c1752a 27static int download_https_uri_to_file(const char *file, const char *uri)
53a50892 28{
59c1752a
DS
29 int result = 0;
30 struct child_process cp = CHILD_PROCESS_INIT;
31 FILE *child_in = NULL, *child_out = NULL;
32 struct strbuf line = STRBUF_INIT;
33 int found_get = 0;
34
35 strvec_pushl(&cp.args, "git-remote-https", uri, NULL);
36 cp.in = -1;
37 cp.out = -1;
38
39 if (start_command(&cp))
40 return 1;
41
42 child_in = fdopen(cp.in, "w");
43 if (!child_in) {
44 result = 1;
45 goto cleanup;
46 }
47
48 child_out = fdopen(cp.out, "r");
49 if (!child_out) {
50 result = 1;
51 goto cleanup;
52 }
53
54 fprintf(child_in, "capabilities\n");
55 fflush(child_in);
56
57 while (!strbuf_getline(&line, child_out)) {
58 if (!line.len)
59 break;
60 if (!strcmp(line.buf, "get"))
61 found_get = 1;
62 }
63 strbuf_release(&line);
64
65 if (!found_get) {
66 result = error(_("insufficient capabilities"));
67 goto cleanup;
68 }
69
70 fprintf(child_in, "get %s %s\n\n", uri, file);
71
72cleanup:
73 if (child_in)
74 fclose(child_in);
75 if (finish_command(&cp))
76 return 1;
77 if (child_out)
78 fclose(child_out);
79 return result;
80}
81
82static int copy_uri_to_file(const char *filename, const char *uri)
83{
84 const char *out;
85
86 if (starts_with(uri, "https:") ||
87 starts_with(uri, "http:"))
88 return download_https_uri_to_file(filename, uri);
89
90 if (skip_prefix(uri, "file://", &out))
91 uri = out;
92
93 /* Copy as a file */
94 return copy_file(filename, uri, 0);
53a50892
DS
95}
96
97static int unbundle_from_file(struct repository *r, const char *file)
98{
99 int result = 0;
100 int bundle_fd;
101 struct bundle_header header = BUNDLE_HEADER_INIT;
102 struct string_list_item *refname;
103 struct strbuf bundle_ref = STRBUF_INIT;
104 size_t bundle_prefix_len;
105
106 if ((bundle_fd = read_bundle_header(file, &header)) < 0)
107 return 1;
108
109 if ((result = unbundle(r, &header, bundle_fd, NULL)))
110 return 1;
111
112 /*
113 * Convert all refs/heads/ from the bundle into refs/bundles/
114 * in the local repository.
115 */
116 strbuf_addstr(&bundle_ref, "refs/bundles/");
117 bundle_prefix_len = bundle_ref.len;
118
119 for_each_string_list_item(refname, &header.references) {
120 struct object_id *oid = refname->util;
121 struct object_id old_oid;
122 const char *branch_name;
123 int has_old;
124
125 if (!skip_prefix(refname->string, "refs/heads/", &branch_name))
126 continue;
127
128 strbuf_setlen(&bundle_ref, bundle_prefix_len);
129 strbuf_addstr(&bundle_ref, branch_name);
130
131 has_old = !read_ref(bundle_ref.buf, &old_oid);
132 update_ref("fetched bundle", bundle_ref.buf, oid,
133 has_old ? &old_oid : NULL,
134 REF_SKIP_OID_VERIFICATION,
135 UPDATE_REFS_MSG_ON_ERR);
136 }
137
138 bundle_header_release(&header);
139 return result;
140}
141
142int fetch_bundle_uri(struct repository *r, const char *uri)
143{
144 int result = 0;
23b6d00b 145 char *filename;
53a50892 146
23b6d00b
DS
147 if (!(filename = find_temp_filename())) {
148 result = -1;
53a50892 149 goto cleanup;
23b6d00b 150 }
53a50892 151
23b6d00b 152 if ((result = copy_uri_to_file(filename, uri))) {
53a50892
DS
153 warning(_("failed to download bundle from URI '%s'"), uri);
154 goto cleanup;
155 }
156
23b6d00b 157 if ((result = !is_bundle(filename, 0))) {
53a50892
DS
158 warning(_("file at URI '%s' is not a bundle"), uri);
159 goto cleanup;
160 }
161
23b6d00b 162 if ((result = unbundle_from_file(r, filename))) {
53a50892
DS
163 warning(_("failed to unbundle bundle from URI '%s'"), uri);
164 goto cleanup;
165 }
166
167cleanup:
23b6d00b
DS
168 if (filename)
169 unlink(filename);
170 free(filename);
53a50892
DS
171 return result;
172}