Line Flow Count Block(s) Source
1 - /*
2 - * Copyright (C) the libgit2 contributors. All rights reserved.
3 - *
4 - * This file is part of libgit2, distributed under the GNU GPL v2 with
5 - * a Linking Exception. For full terms see the included COPYING file.
6 - */
7 -
8 - #include "common.h"
9 -
10 - #include "git2/types.h"
11 - #include "git2/net.h"
12 - #include "git2/repository.h"
13 - #include "git2/object.h"
14 - #include "git2/tag.h"
15 - #include "git2/transport.h"
16 - #include "git2/revwalk.h"
17 - #include "git2/odb_backend.h"
18 - #include "git2/pack.h"
19 - #include "git2/commit.h"
20 - #include "git2/revparse.h"
21 -
22 - #include "pack-objects.h"
23 - #include "refs.h"
24 - #include "posix.h"
25 - #include "path.h"
26 - #include "buffer.h"
27 - #include "repository.h"
28 - #include "odb.h"
29 - #include "push.h"
30 - #include "remote.h"
31 - #include "proxy.h"
32 -
33 - typedef struct {
34 - git_transport parent;
35 - git_remote *owner;
36 - char *url;
37 - int direction;
38 - int flags;
39 - git_atomic cancelled;
40 - git_repository *repo;
41 - git_transport_message_cb progress_cb;
42 - git_transport_message_cb error_cb;
43 - void *message_cb_payload;
44 - git_vector refs;
45 - unsigned connected : 1,
46 - have_refs : 1;
47 - } transport_local;
48 -
49 2280 2 static void free_head(git_remote_head *head)
50 - {
51 2280 2 git__free(head->name);
52 2280 3 git__free(head->symref_target);
53 2280 4 git__free(head);
54 2280 5 }
55 -
56 191 2 static void free_heads(git_vector *heads)
57 - {
58 - git_remote_head *head;
59 - size_t i;
60 -
61 2471 2,4-6 git_vector_foreach(heads, i, head)
62 2280 3 free_head(head);
63 -
64 191 7 git_vector_free(heads);
65 191 8 }
66 -
67 1838 2 static int add_ref(transport_local *t, const char *name)
68 - {
69 1838 2 const char peeled[] = "^{}";
70 - git_reference *ref, *resolved;
71 - git_remote_head *head;
72 - git_oid obj_id;
73 1838 2 git_object *obj = NULL, *target = NULL;
74 1838 2 git_buf buf = GIT_BUF_INIT;
75 - int error;
76 -
77 1838 2,3 if ((error = git_reference_lookup(&ref, t->repo, name)) < 0)
78 ##### 4 return error;
79 -
80 1838 5 error = git_reference_resolve(&resolved, ref);
81 1838 6 if (error < 0) {
82 7 7 git_reference_free(ref);
83 7 8,9 if (!strcmp(name, GIT_HEAD_FILE) && error == GIT_ENOTFOUND) {
84 - /* This is actually okay. Empty repos often have a HEAD that
85 - * points to a nonexistent "refs/heads/master". */
86 7 10 git_error_clear();
87 7 11 return 0;
88 - }
89 ##### 12 return error;
90 - }
91 -
92 1831 13,14 git_oid_cpy(&obj_id, git_reference_target(resolved));
93 1831 15 git_reference_free(resolved);
94 -
95 1831 16 head = git__calloc(1, sizeof(git_remote_head));
96 1831 17,18 GIT_ERROR_CHECK_ALLOC(head);
97 -
98 1831 19 head->name = git__strdup(name);
99 1831 20,21 GIT_ERROR_CHECK_ALLOC(head->name);
100 -
101 1831 22 git_oid_cpy(&head->oid, &obj_id);
102 -
103 1831 23,24 if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
104 74 25,26 head->symref_target = git__strdup(git_reference_symbolic_target(ref));
105 74 27,28 GIT_ERROR_CHECK_ALLOC(head->symref_target);
106 - }
107 1831 29 git_reference_free(ref);
108 -
109 1831 30,31 if ((error = git_vector_insert(&t->refs, head)) < 0) {
110 ##### 32 free_head(head);
111 ##### 33 return error;
112 - }
113 -
114 - /* If it's not a tag, we don't need to try to peel it */
115 1831 34,35 if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
116 1271 36 return 0;
117 -
118 560 37,38 if ((error = git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJECT_ANY)) < 0)
119 ##### 39 return error;
120 -
121 560 40 head = NULL;
122 -
123 - /* If it's not an annotated tag, or if we're mocking
124 - * git-receive-pack, just get out */
125 560 40-42 if (git_object_type(obj) != GIT_OBJECT_TAG ||
126 479 42 t->direction != GIT_DIRECTION_FETCH) {
127 111 43 git_object_free(obj);
128 111 44 return 0;
129 - }
130 -
131 - /* And if it's a tag, peel it, and add it to the list */
132 449 45 head = git__calloc(1, sizeof(git_remote_head));
133 449 46,47 GIT_ERROR_CHECK_ALLOC(head);
134 -
135 449 48,49 if (git_buf_join(&buf, 0, name, peeled) < 0) {
136 ##### 50 free_head(head);
137 ##### 51 return -1;
138 - }
139 449 52 head->name = git_buf_detach(&buf);
140 -
141 449 53,54 if (!(error = git_tag_peel(&target, (git_tag *)obj))) {
142 449 55,56 git_oid_cpy(&head->oid, git_object_id(target));
143 -
144 449 57,58 if ((error = git_vector_insert(&t->refs, head)) < 0) {
145 ##### 59 free_head(head);
146 - }
147 - }
148 -
149 449 60 git_object_free(obj);
150 449 61 git_object_free(target);
151 -
152 449 62 return error;
153 - }
154 -
155 100 2 static int store_refs(transport_local *t)
156 - {
157 - size_t i;
158 - git_remote_head *head;
159 100 2 git_strarray ref_names = {0};
160 -
161 100 2,3 assert(t);
162 -
163 100 4,5 if (git_reference_list(&ref_names, t->repo) < 0)
164 ##### 6 goto on_error;
165 -
166 - /* Clear all heads we might have fetched in a previous connect */
167 100 7,10-12 git_vector_foreach(&t->refs, i, head) {
168 ##### 8 git__free(head->name);
169 ##### 9 git__free(head);
170 - }
171 -
172 - /* Clear the vector so we can reuse it */
173 100 13 git_vector_clear(&t->refs);
174 -
175 - /* Sort the references first */
176 100 14 git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb);
177 -
178 - /* Add HEAD iff direction is fetch */
179 100 15-17 if (t->direction == GIT_DIRECTION_FETCH && add_ref(t, GIT_HEAD_FILE) < 0)
180 ##### 18 goto on_error;
181 -
182 1854 19,23,24 for (i = 0; i < ref_names.count; ++i) {
183 1754 20,21 if (add_ref(t, ref_names.strings[i]) < 0)
184 ##### 22 goto on_error;
185 - }
186 -
187 100 25 t->have_refs = 1;
188 100 25 git_strarray_dispose(&ref_names);
189 100 26 return 0;
190 -
191 - on_error:
192 ##### 27 git_vector_free(&t->refs);
193 ##### 28 git_strarray_dispose(&ref_names);
194 ##### 29 return -1;
195 - }
196 -
197 - /*
198 - * Try to open the url as a git directory. The direction doesn't
199 - * matter in this case because we're calculating the heads ourselves.
200 - */
201 108 2 static int local_connect(
202 - git_transport *transport,
203 - const char *url,
204 - git_credential_acquire_cb cred_acquire_cb,
205 - void *cred_acquire_payload,
206 - const git_proxy_options *proxy,
207 - int direction, int flags)
208 - {
209 - git_repository *repo;
210 - int error;
211 108 2 transport_local *t = (transport_local *) transport;
212 - const char *path;
213 108 2 git_buf buf = GIT_BUF_INIT;
214 -
215 - GIT_UNUSED(cred_acquire_cb);
216 - GIT_UNUSED(cred_acquire_payload);
217 - GIT_UNUSED(proxy);
218 -
219 108 2 if (t->connected)
220 8 3 return 0;
221 -
222 100 4 free_heads(&t->refs);
223 -
224 100 5 t->url = git__strdup(url);
225 100 6,7 GIT_ERROR_CHECK_ALLOC(t->url);
226 100 8 t->direction = direction;
227 100 8 t->flags = flags;
228 -
229 - /* 'url' may be a url or path; convert to a path */
230 100 8,9 if ((error = git_path_from_url_or_path(&buf, url)) < 0) {
231 ##### 10 git_buf_dispose(&buf);
232 ##### 11 return error;
233 - }
234 100 12 path = git_buf_cstr(&buf);
235 -
236 100 13 error = git_repository_open(&repo, path);
237 -
238 100 14 git_buf_dispose(&buf);
239 -
240 100 15 if (error < 0)
241 ##### 16 return -1;
242 -
243 100 17 t->repo = repo;
244 -
245 100 17,18 if (store_refs(t) < 0)
246 ##### 19 return -1;
247 -
248 100 20 t->connected = 1;
249 -
250 100 20 return 0;
251 - }
252 -
253 311 2 static int local_ls(const git_remote_head ***out, size_t *size, git_transport *transport)
254 - {
255 311 2 transport_local *t = (transport_local *)transport;
256 -
257 311 2 if (!t->have_refs) {
258 ##### 3 git_error_set(GIT_ERROR_NET, "the transport has not yet loaded the refs");
259 ##### 4 return -1;
260 - }
261 -
262 311 5 *out = (const git_remote_head **)t->refs.contents;
263 311 5 *size = t->refs.length;
264 -
265 311 5 return 0;
266 - }
267 -
268 36 2 static int local_negotiate_fetch(
269 - git_transport *transport,
270 - git_repository *repo,
271 - const git_remote_head * const *refs,
272 - size_t count)
273 - {
274 36 2 transport_local *t = (transport_local*)transport;
275 - git_remote_head *rhead;
276 - unsigned int i;
277 -
278 - GIT_UNUSED(refs);
279 - GIT_UNUSED(count);
280 -
281 - /* Fill in the loids */
282 1078 2,11-13 git_vector_foreach(&t->refs, i, rhead) {
283 - git_object *obj;
284 -
285 1042 3 int error = git_revparse_single(&obj, repo, rhead->name);
286 1042 4 if (!error)
287 1 5,6 git_oid_cpy(&rhead->loid, git_object_id(obj));
288 1041 7 else if (error != GIT_ENOTFOUND)
289 ##### 8 return error;
290 - else
291 1041 9 git_error_clear();
292 1042 10 git_object_free(obj);
293 - }
294 -
295 36 14 return 0;
296 - }
297 -
298 7 2 static int local_push_update_remote_ref(
299 - git_repository *remote_repo,
300 - const char *lref,
301 - const char *rref,
302 - git_oid *loid,
303 - git_oid *roid)
304 - {
305 - int error;
306 7 2 git_reference *remote_ref = NULL;
307 -
308 - /* check for lhs, if it's empty it means to delete */
309 7 2 if (lref[0] != '\0') {
310 - /* Create or update a ref */
311 5 4 error = git_reference_create(NULL, remote_repo, rref, loid,
312 5 3 !git_oid_is_zero(roid), NULL);
313 - } else {
314 - /* Delete a ref */
315 2 5,6 if ((error = git_reference_lookup(&remote_ref, remote_repo, rref)) < 0) {
316 ##### 7 if (error == GIT_ENOTFOUND)
317 ##### 8 error = 0;
318 ##### 9 return error;
319 - }
320 -
321 2 10 error = git_reference_delete(remote_ref);
322 2 11 git_reference_free(remote_ref);
323 - }
324 -
325 7 12 return error;
326 - }
327 -
328 93 2 static int transfer_to_push_transfer(const git_indexer_progress *stats, void *payload)
329 - {
330 93 2 const git_remote_callbacks *cbs = payload;
331 -
332 93 2,3 if (!cbs || !cbs->push_transfer_progress)
333 93 4 return 0;
334 -
335 ##### 5 return cbs->push_transfer_progress(stats->received_objects, stats->total_objects, stats->received_bytes,
336 - cbs->payload);
337 - }
338 -
339 8 2 static int local_push(
340 - git_transport *transport,
341 - git_push *push,
342 - const git_remote_callbacks *cbs)
343 - {
344 8 2 transport_local *t = (transport_local *)transport;
345 8 2 git_repository *remote_repo = NULL;
346 - push_spec *spec;
347 8 2 char *url = NULL;
348 - const char *path;
349 8 2 git_buf buf = GIT_BUF_INIT, odb_path = GIT_BUF_INIT;
350 - int error;
351 - size_t j;
352 -
353 - GIT_UNUSED(cbs);
354 -
355 - /* 'push->remote->url' may be a url or path; convert to a path */
356 8 2,3 if ((error = git_path_from_url_or_path(&buf, push->remote->url)) < 0) {
357 ##### 4 git_buf_dispose(&buf);
358 ##### 5 return error;
359 - }
360 8 6 path = git_buf_cstr(&buf);
361 -
362 8 7 error = git_repository_open(&remote_repo, path);
363 -
364 8 8 git_buf_dispose(&buf);
365 -
366 8 9 if (error < 0)
367 ##### 10 return error;
368 -
369 - /* We don't currently support pushing locally to non-bare repos. Proper
370 - non-bare repo push support would require checking configs to see if
371 - we should override the default 'don't let this happen' behavior.
372 -
373 - Note that this is only an issue when pushing to the current branch,
374 - but we forbid all pushes just in case */
375 8 11 if (!remote_repo->is_bare) {
376 1 12 error = GIT_EBAREREPO;
377 1 12 git_error_set(GIT_ERROR_INVALID, "local push doesn't (yet) support pushing to non-bare repos.");
378 1 13 goto on_error;
379 - }
380 -
381 7 14,15 if ((error = git_repository_item_path(&odb_path, remote_repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0
382 7 16,17 || (error = git_buf_joinpath(&odb_path, odb_path.ptr, "pack")) < 0)
383 - goto on_error;
384 -
385 7 18 error = git_packbuilder_write(push->pb, odb_path.ptr, 0, transfer_to_push_transfer, (void *) cbs);
386 7 19 git_buf_dispose(&odb_path);
387 -
388 7 20 if (error < 0)
389 ##### 21 goto on_error;
390 -
391 7 22 push->unpack_ok = 1;
392 -
393 14 22,53-55 git_vector_foreach(&push->specs, j, spec) {
394 - push_status *status;
395 - const git_error *last;
396 7 23 char *ref = spec->refspec.dst;
397 -
398 7 23 status = git__calloc(1, sizeof(push_status));
399 7 24 if (!status)
400 ##### 25 goto on_error;
401 -
402 7 26 status->ref = git__strdup(ref);
403 7 27 if (!status->ref) {
404 ##### 28 git_push_status_free(status);
405 ##### 29 goto on_error;
406 - }
407 -
408 7 30 error = local_push_update_remote_ref(remote_repo, spec->refspec.src, spec->refspec.dst,
409 - &spec->loid, &spec->roid);
410 -
411 7 31 switch (error) {
412 - case GIT_OK:
413 7 32 break;
414 - case GIT_EINVALIDSPEC:
415 ##### 33 status->msg = git__strdup("funny refname");
416 ##### 34 break;
417 - case GIT_ENOTFOUND:
418 ##### 35 status->msg = git__strdup("Remote branch not found to delete");
419 ##### 36 break;
420 - default:
421 ##### 37 last = git_error_last();
422 -
423 ##### 38,39 if (last && last->message)
424 ##### 40,41 status->msg = git__strdup(last->message);
425 - else
426 ##### 42,43 status->msg = git__strdup("Unspecified error encountered");
427 ##### 44 break;
428 - }
429 -
430 - /* failed to allocate memory for a status message */
431 7 45,46 if (error < 0 && !status->msg) {
432 ##### 47 git_push_status_free(status);
433 ##### 48 goto on_error;
434 - }
435 -
436 - /* failed to insert the ref update status */
437 7 49,50 if ((error = git_vector_insert(&push->status, status)) < 0) {
438 ##### 51 git_push_status_free(status);
439 ##### 52 goto on_error;
440 - }
441 - }
442 -
443 7 56 if (push->specs.length) {
444 7 57 int flags = t->flags;
445 7 57 url = git__strdup(t->url);
446 -
447 7 58-60,62 if (!url || t->parent.close(&t->parent) < 0 ||
448 7 61 t->parent.connect(&t->parent, url,
449 - NULL, NULL, NULL, GIT_DIRECTION_PUSH, flags))
450 - goto on_error;
451 - }
452 -
453 7 63 error = 0;
454 -
455 - on_error:
456 8 64 git_repository_free(remote_repo);
457 8 65 git__free(url);
458 -
459 8 66 return error;
460 - }
461 -
462 - typedef struct foreach_data {
463 - git_indexer_progress *stats;
464 - git_indexer_progress_cb progress_cb;
465 - void *progress_payload;
466 - git_odb_writepack *writepack;
467 - } foreach_data;
468 -
469 4061 2 static int foreach_cb(void *buf, size_t len, void *payload)
470 - {
471 4061 2 foreach_data *data = (foreach_data*)payload;
472 -
473 4061 2 data->stats->received_bytes += len;
474 4061 2 return data->writepack->append(data->writepack, buf, len, data->stats);
475 - }
476 -
477 - static const char *counting_objects_fmt = "Counting objects %d\r";
478 - static const char *compressing_objects_fmt = "Compressing objects: %.0f%% (%d/%d)";
479 -
480 108 2 static int local_counting(int stage, unsigned int current, unsigned int total, void *payload)
481 - {
482 108 2 git_buf progress_info = GIT_BUF_INIT;
483 108 2 transport_local *t = payload;
484 - int error;
485 -
486 108 2 if (!t->progress_cb)
487 105 3 return 0;
488 -
489 3 4 if (stage == GIT_PACKBUILDER_ADDING_OBJECTS) {
490 1 5 git_buf_printf(&progress_info, counting_objects_fmt, current);
491 2 6 } else if (stage == GIT_PACKBUILDER_DELTAFICATION) {
492 2 7 float perc = (((float) current) / total) * 100;
493 2 7 git_buf_printf(&progress_info, compressing_objects_fmt, perc, current, total);
494 2 8 if (current == total)
495 1 9 git_buf_printf(&progress_info, ", done\n");
496 - else
497 1 10 git_buf_putc(&progress_info, '\r');
498 -
499 - }
500 -
501 3 11,12 if (git_buf_oom(&progress_info))
502 ##### 13 return -1;
503 -
504 3 14-16 error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload);
505 3 17 git_buf_dispose(&progress_info);
506 -
507 3 18 return error;
508 - }
509 -
510 2 2 static int foreach_reference_cb(git_reference *reference, void *payload)
511 - {
512 2 2 git_revwalk *walk = (git_revwalk *)payload;
513 - int error;
514 -
515 2 2,3 if (git_reference_type(reference) != GIT_REFERENCE_DIRECT) {
516 1 4 git_reference_free(reference);
517 1 5 return 0;
518 - }
519 -
520 1 6,7 error = git_revwalk_hide(walk, git_reference_target(reference));
521 - /* The reference is in the local repository, so the target may not
522 - * exist on the remote. It also may not be a commit. */
523 1 8,9 if (error == GIT_ENOTFOUND || error == GIT_ERROR_INVALID) {
524 1 10 git_error_clear();
525 1 11 error = 0;
526 - }
527 -
528 1 12 git_reference_free(reference);
529 -
530 1 13 return error;
531 - }
532 -
533 36 2 static int local_download_pack(
534 - git_transport *transport,
535 - git_repository *repo,
536 - git_indexer_progress *stats,
537 - git_indexer_progress_cb progress_cb,
538 - void *progress_payload)
539 - {
540 36 2 transport_local *t = (transport_local*)transport;
541 36 2 git_revwalk *walk = NULL;
542 - git_remote_head *rhead;
543 - unsigned int i;
544 36 2 int error = -1;
545 36 2 git_packbuilder *pack = NULL;
546 36 2 git_odb_writepack *writepack = NULL;
547 36 2 git_odb *odb = NULL;
548 36 2 git_buf progress_info = GIT_BUF_INIT;
549 -
550 36 2,3 if ((error = git_revwalk_new(&walk, t->repo)) < 0)
551 ##### 4 goto cleanup;
552 36 5 git_revwalk_sorting(walk, GIT_SORT_TIME);
553 -
554 36 6,7 if ((error = git_packbuilder_new(&pack, t->repo)) < 0)
555 ##### 8 goto cleanup;
556 -
557 36 9 git_packbuilder_set_callbacks(pack, local_counting, t);
558 -
559 36 10 stats->total_objects = 0;
560 36 10 stats->indexed_objects = 0;
561 36 10 stats->received_objects = 0;
562 36 10 stats->received_bytes = 0;
563 -
564 1078 10,21,23,24 git_vector_foreach(&t->refs, i, rhead) {
565 - git_object *obj;
566 1042 11,12 if ((error = git_object_lookup(&obj, t->repo, &rhead->oid, GIT_OBJECT_ANY)) < 0)
567 ##### 13,22 goto cleanup;
568 -
569 1042 14,15 if (git_object_type(obj) == GIT_OBJECT_COMMIT) {
570 - /* Revwalker includes only wanted commits */
571 720 16 error = git_revwalk_push(walk, &rhead->oid);
572 - } else {
573 - /* Tag or some other wanted object. Add it on its own */
574 322 17 error = git_packbuilder_insert_recur(pack, &rhead->oid, rhead->name);
575 - }
576 1042 18 git_object_free(obj);
577 1042 19 if (error < 0)
578 ##### 20 goto cleanup;
579 - }
580 -
581 36 25,26 if ((error = git_reference_foreach(repo, foreach_reference_cb, walk)))
582 ##### 27 goto cleanup;
583 -
584 36 28,29 if ((error = git_packbuilder_insert_walk(pack, walk)))
585 ##### 30 goto cleanup;
586 -
587 36 31-33 if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0)
588 ##### 34 goto cleanup;
589 -
590 36 35,38,39 if (t->progress_cb &&
591 1 36,37 (error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload)) < 0)
592 ##### 40 goto cleanup;
593 -
594 - /* Walk the objects, building a packfile */
595 36 41,42 if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
596 ##### 43 goto cleanup;
597 -
598 - /* One last one with the newline */
599 36 44 git_buf_clear(&progress_info);
600 36 45,46 git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack));
601 36 47,48 if ((error = git_buf_putc(&progress_info, '\n')) < 0)
602 ##### 49 goto cleanup;
603 -
604 36 50,53,54 if (t->progress_cb &&
605 1 51,52 (error = t->progress_cb(git_buf_cstr(&progress_info), (int)git_buf_len(&progress_info), t->message_cb_payload)) < 0)
606 ##### 55 goto cleanup;
607 -
608 36 56,57 if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)
609 ##### 58 goto cleanup;
610 -
611 - /* Write the data to the ODB */
612 - {
613 36 59 foreach_data data = {0};
614 36 59 data.stats = stats;
615 36 59 data.progress_cb = progress_cb;
616 36 59 data.progress_payload = progress_payload;
617 36 59 data.writepack = writepack;
618 -
619 - /* autodetect */
620 36 59 git_packbuilder_set_threads(pack, 0);
621 -
622 36 60,61 if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0)
623 1 62 goto cleanup;
624 - }
625 -
626 35 63 error = writepack->commit(writepack, stats);
627 -
628 - cleanup:
629 36 64,65 if (writepack) writepack->free(writepack);
630 36 66 git_buf_dispose(&progress_info);
631 36 67 git_packbuilder_free(pack);
632 36 68 git_revwalk_free(walk);
633 36 69 return error;
634 - }
635 -
636 61 2 static int local_set_callbacks(
637 - git_transport *transport,
638 - git_transport_message_cb progress_cb,
639 - git_transport_message_cb error_cb,
640 - git_transport_certificate_check_cb certificate_check_cb,
641 - void *message_cb_payload)
642 - {
643 61 2 transport_local *t = (transport_local *)transport;
644 -
645 - GIT_UNUSED(certificate_check_cb);
646 -
647 61 2 t->progress_cb = progress_cb;
648 61 2 t->error_cb = error_cb;
649 61 2 t->message_cb_payload = message_cb_payload;
650 -
651 61 2 return 0;
652 - }
653 -
654 266 2 static int local_is_connected(git_transport *transport)
655 - {
656 266 2 transport_local *t = (transport_local *)transport;
657 -
658 266 2 return t->connected;
659 - }
660 -
661 ##### 2 static int local_read_flags(git_transport *transport, int *flags)
662 - {
663 ##### 2 transport_local *t = (transport_local *)transport;
664 -
665 ##### 2 *flags = t->flags;
666 -
667 ##### 2 return 0;
668 - }
669 -
670 ##### 2 static void local_cancel(git_transport *transport)
671 - {
672 ##### 2 transport_local *t = (transport_local *)transport;
673 -
674 ##### 2 git_atomic_set(&t->cancelled, 1);
675 ##### 3 }
676 -
677 191 2 static int local_close(git_transport *transport)
678 - {
679 191 2 transport_local *t = (transport_local *)transport;
680 -
681 191 2 t->connected = 0;
682 -
683 191 2 if (t->repo) {
684 100 3 git_repository_free(t->repo);
685 100 4 t->repo = NULL;
686 - }
687 -
688 191 5 if (t->url) {
689 100 6 git__free(t->url);
690 100 7 t->url = NULL;
691 - }
692 -
693 191 8 return 0;
694 - }
695 -
696 91 2 static void local_free(git_transport *transport)
697 - {
698 91 2 transport_local *t = (transport_local *)transport;
699 -
700 91 2 free_heads(&t->refs);
701 -
702 - /* Close the transport, if it's still open. */
703 91 3 local_close(transport);
704 -
705 - /* Free the transport */
706 91 4 git__free(t);
707 91 5 }
708 -
709 - /**************
710 - * Public API *
711 - **************/
712 -
713 91 2 int git_transport_local(git_transport **out, git_remote *owner, void *param)
714 - {
715 - int error;
716 - transport_local *t;
717 -
718 - GIT_UNUSED(param);
719 -
720 91 2 t = git__calloc(1, sizeof(transport_local));
721 91 3,4 GIT_ERROR_CHECK_ALLOC(t);
722 -
723 91 5 t->parent.version = GIT_TRANSPORT_VERSION;
724 91 5 t->parent.set_callbacks = local_set_callbacks;
725 91 5 t->parent.connect = local_connect;
726 91 5 t->parent.negotiate_fetch = local_negotiate_fetch;
727 91 5 t->parent.download_pack = local_download_pack;
728 91 5 t->parent.push = local_push;
729 91 5 t->parent.close = local_close;
730 91 5 t->parent.free = local_free;
731 91 5 t->parent.ls = local_ls;
732 91 5 t->parent.is_connected = local_is_connected;
733 91 5 t->parent.read_flags = local_read_flags;
734 91 5 t->parent.cancel = local_cancel;
735 -
736 91 5,6 if ((error = git_vector_init(&t->refs, 0, NULL)) < 0) {
737 ##### 7 git__free(t);
738 ##### 8 return error;
739 - }
740 -
741 91 9 t->owner = owner;
742 -
743 91 9 *out = (git_transport *) t;
744 -
745 91 9 return 0;
746 - }