2 #include "bundle-uri.h"
4 #include "object-store.h"
6 #include "run-command.h"
8 static int find_temp_filename(struct strbuf
*name
)
12 * Find a temporary filename that is available. This is briefly
13 * racy, but unlikely to collide.
15 fd
= odb_mkstemp(name
, "bundles/tmp_uri_XXXXXX");
17 warning(_("failed to create temporary file"));
26 static int download_https_uri_to_file(const char *file
, const char *uri
)
29 struct child_process cp
= CHILD_PROCESS_INIT
;
30 FILE *child_in
= NULL
, *child_out
= NULL
;
31 struct strbuf line
= STRBUF_INIT
;
34 strvec_pushl(&cp
.args
, "git-remote-https", uri
, NULL
);
38 if (start_command(&cp
))
41 child_in
= fdopen(cp
.in
, "w");
47 child_out
= fdopen(cp
.out
, "r");
53 fprintf(child_in
, "capabilities\n");
56 while (!strbuf_getline(&line
, child_out
)) {
59 if (!strcmp(line
.buf
, "get"))
62 strbuf_release(&line
);
65 result
= error(_("insufficient capabilities"));
69 fprintf(child_in
, "get %s %s\n\n", uri
, file
);
74 if (finish_command(&cp
))
81 static int copy_uri_to_file(const char *filename
, const char *uri
)
85 if (starts_with(uri
, "https:") ||
86 starts_with(uri
, "http:"))
87 return download_https_uri_to_file(filename
, uri
);
89 if (skip_prefix(uri
, "file://", &out
))
93 return copy_file(filename
, uri
, 0);
96 static int unbundle_from_file(struct repository
*r
, const char *file
)
100 struct bundle_header header
= BUNDLE_HEADER_INIT
;
101 struct string_list_item
*refname
;
102 struct strbuf bundle_ref
= STRBUF_INIT
;
103 size_t bundle_prefix_len
;
105 if ((bundle_fd
= read_bundle_header(file
, &header
)) < 0)
108 if ((result
= unbundle(r
, &header
, bundle_fd
, NULL
)))
112 * Convert all refs/heads/ from the bundle into refs/bundles/
113 * in the local repository.
115 strbuf_addstr(&bundle_ref
, "refs/bundles/");
116 bundle_prefix_len
= bundle_ref
.len
;
118 for_each_string_list_item(refname
, &header
.references
) {
119 struct object_id
*oid
= refname
->util
;
120 struct object_id old_oid
;
121 const char *branch_name
;
124 if (!skip_prefix(refname
->string
, "refs/heads/", &branch_name
))
127 strbuf_setlen(&bundle_ref
, bundle_prefix_len
);
128 strbuf_addstr(&bundle_ref
, branch_name
);
130 has_old
= !read_ref(bundle_ref
.buf
, &old_oid
);
131 update_ref("fetched bundle", bundle_ref
.buf
, oid
,
132 has_old
? &old_oid
: NULL
,
133 REF_SKIP_OID_VERIFICATION
,
134 UPDATE_REFS_MSG_ON_ERR
);
137 bundle_header_release(&header
);
141 int fetch_bundle_uri(struct repository
*r
, const char *uri
)
144 struct strbuf filename
= STRBUF_INIT
;
146 if ((result
= find_temp_filename(&filename
)))
149 if ((result
= copy_uri_to_file(filename
.buf
, uri
))) {
150 warning(_("failed to download bundle from URI '%s'"), uri
);
154 if ((result
= !is_bundle(filename
.buf
, 0))) {
155 warning(_("file at URI '%s' is not a bundle"), uri
);
159 if ((result
= unbundle_from_file(r
, filename
.buf
))) {
160 warning(_("failed to unbundle bundle from URI '%s'"), uri
);
165 unlink(filename
.buf
);
166 strbuf_release(&filename
);