2 * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "got_compat.h"
19 #include <sys/queue.h>
21 #include <sys/types.h>
38 #include "got_error.h"
39 #include "got_repository.h"
40 #include "got_object.h"
41 #include "got_reference.h"
44 #include "got_cancel.h"
45 #include "got_commit_graph.h"
46 #include "got_opentemp.h"
48 #include "got_lib_delta.h"
49 #include "got_lib_delta_cache.h"
50 #include "got_lib_hash.h"
51 #include "got_lib_object.h"
52 #include "got_lib_object_cache.h"
53 #include "got_lib_object_idset.h"
54 #include "got_lib_object_parse.h"
55 #include "got_lib_ratelimit.h"
56 #include "got_lib_pack.h"
57 #include "got_lib_pack_index.h"
58 #include "got_lib_repository.h"
59 #include "got_lib_poll.h"
63 #include "repo_write.h"
66 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
69 static struct repo_write
{
72 struct got_repository
*repo
;
76 struct gotd_imsgev session_iev
;
77 struct got_pathlist_head
*protected_tag_namespaces
;
78 struct got_pathlist_head
*protected_branch_namespaces
;
79 struct got_pathlist_head
*protected_branches
;
89 struct gotd_ref_update
{
90 STAILQ_ENTRY(gotd_ref_update
) entry
;
91 struct got_reference
*ref
;
94 struct got_object_id old_id
;
95 struct got_object_id new_id
;
97 STAILQ_HEAD(gotd_ref_updates
, gotd_ref_update
);
99 static struct repo_write_client
{
103 struct got_pack pack
;
104 uint8_t pack_sha1
[SHA1_DIGEST_LENGTH
];
106 struct gotd_ref_updates ref_updates
;
113 static volatile sig_atomic_t sigint_received
;
114 static volatile sig_atomic_t sigterm_received
;
117 catch_sigint(int signo
)
123 catch_sigterm(int signo
)
125 sigterm_received
= 1;
128 static const struct got_error
*
129 check_cancelled(void *arg
)
131 if (sigint_received
|| sigterm_received
)
132 return got_error(GOT_ERR_CANCELLED
);
137 static const struct got_error
*
138 send_peeled_tag_ref(struct got_reference
*ref
, struct got_object
*obj
,
139 struct imsgbuf
*ibuf
)
141 const struct got_error
*err
= NULL
;
142 struct got_tag_object
*tag
;
144 char *peeled_refname
= NULL
;
145 struct got_object_id
*id
;
148 err
= got_object_tag_open(&tag
, repo_write
.repo
, obj
);
152 if (asprintf(&peeled_refname
, "%s^{}", got_ref_get_name(ref
)) == -1) {
153 err
= got_error_from_errno("asprintf");
157 id
= got_object_tag_get_object_id(tag
);
158 namelen
= strlen(peeled_refname
);
160 len
= sizeof(struct gotd_imsg_ref
) + namelen
;
161 if (len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
) {
162 err
= got_error(GOT_ERR_NO_SPACE
);
166 wbuf
= imsg_create(ibuf
, GOTD_IMSG_REF
, PROC_REPO_WRITE
,
167 repo_write
.pid
, len
);
169 err
= got_error_from_errno("imsg_create REF");
173 /* Keep in sync with struct gotd_imsg_ref definition. */
174 if (imsg_add(wbuf
, id
->hash
, SHA1_DIGEST_LENGTH
) == -1) {
175 err
= got_error_from_errno("imsg_add REF");
178 if (imsg_add(wbuf
, &namelen
, sizeof(namelen
)) == -1) {
179 err
= got_error_from_errno("imsg_add REF");
182 if (imsg_add(wbuf
, peeled_refname
, namelen
) == -1) {
183 err
= got_error_from_errno("imsg_add REF");
187 imsg_close(ibuf
, wbuf
);
189 got_object_tag_close(tag
);
193 static const struct got_error
*
194 send_ref(struct got_reference
*ref
, struct imsgbuf
*ibuf
)
196 const struct got_error
*err
;
197 const char *refname
= got_ref_get_name(ref
);
199 struct got_object_id
*id
= NULL
;
200 struct got_object
*obj
= NULL
;
204 namelen
= strlen(refname
);
206 len
= sizeof(struct gotd_imsg_ref
) + namelen
;
207 if (len
> MAX_IMSGSIZE
- IMSG_HEADER_SIZE
)
208 return got_error(GOT_ERR_NO_SPACE
);
210 err
= got_ref_resolve(&id
, repo_write
.repo
, ref
);
214 wbuf
= imsg_create(ibuf
, GOTD_IMSG_REF
, PROC_REPO_WRITE
,
215 repo_write
.pid
, len
);
217 err
= got_error_from_errno("imsg_create REF");
221 /* Keep in sync with struct gotd_imsg_ref definition. */
222 if (imsg_add(wbuf
, id
->hash
, SHA1_DIGEST_LENGTH
) == -1)
223 return got_error_from_errno("imsg_add REF");
224 if (imsg_add(wbuf
, &namelen
, sizeof(namelen
)) == -1)
225 return got_error_from_errno("imsg_add REF");
226 if (imsg_add(wbuf
, refname
, namelen
) == -1)
227 return got_error_from_errno("imsg_add REF");
229 imsg_close(ibuf
, wbuf
);
231 err
= got_object_open(&obj
, repo_write
.repo
, id
);
234 if (obj
->type
== GOT_OBJ_TYPE_TAG
)
235 err
= send_peeled_tag_ref(ref
, obj
, ibuf
);
238 got_object_close(obj
);
243 static const struct got_error
*
244 list_refs(struct imsg
*imsg
)
246 const struct got_error
*err
;
247 struct repo_write_client
*client
= &repo_write_client
;
248 struct got_reflist_head refs
;
249 struct got_reflist_entry
*re
;
251 struct gotd_imsg_reflist irefs
;
256 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
258 return got_error(GOT_ERR_PRIVSEP_LEN
);
260 if (repo_write
.refs_listed
) {
261 return got_error_msg(GOT_ERR_CLIENT_ID
,
262 "duplicate list-refs request");
264 repo_write
.refs_listed
= 1;
266 client
->fd
= imsg_get_fd(imsg
);
267 if (client
->fd
== -1)
268 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
270 client
->nref_updates
= 0;
271 client
->nref_del
= 0;
272 client
->nref_new
= 0;
273 client
->nref_move
= 0;
275 imsg_init(&ibuf
, client
->fd
);
277 err
= got_ref_list(&refs
, repo_write
.repo
, "",
278 got_ref_cmp_by_name
, NULL
);
282 memset(&irefs
, 0, sizeof(irefs
));
283 TAILQ_FOREACH(re
, &refs
, entry
) {
284 struct got_object_id
*id
;
287 if (got_ref_is_symbolic(re
->ref
))
292 /* Account for a peeled tag refs. */
293 err
= got_ref_resolve(&id
, repo_write
.repo
, re
->ref
);
296 err
= got_object_get_type(&obj_type
, repo_write
.repo
, id
);
300 if (obj_type
== GOT_OBJ_TYPE_TAG
)
304 if (imsg_compose(&ibuf
, GOTD_IMSG_REFLIST
, PROC_REPO_WRITE
,
305 repo_write
.pid
, -1, &irefs
, sizeof(irefs
)) == -1) {
306 err
= got_error_from_errno("imsg_compose REFLIST");
310 TAILQ_FOREACH(re
, &refs
, entry
) {
311 if (got_ref_is_symbolic(re
->ref
))
313 err
= send_ref(re
->ref
, &ibuf
);
318 err
= gotd_imsg_flush(&ibuf
);
320 got_ref_list_free(&refs
);
325 static const struct got_error
*
326 validate_namespace(const char *namespace)
328 size_t len
= strlen(namespace);
330 if (len
< 5 || strncmp("refs/", namespace, 5) != 0 ||
331 namespace[len
-1] != '/') {
332 return got_error_fmt(GOT_ERR_BAD_REF_NAME
,
333 "reference namespace '%s'", namespace);
339 static const struct got_error
*
340 protect_ref_namespace(const char *refname
, const char *namespace)
342 const struct got_error
*err
;
344 err
= validate_namespace(namespace);
348 if (strncmp(namespace, refname
, strlen(namespace)) == 0)
349 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
354 static const struct got_error
*
355 verify_object_type(struct got_object_id
*id
, int expected_obj_type
,
356 struct got_pack
*pack
, struct got_packidx
*packidx
)
358 const struct got_error
*err
;
359 char hex
[SHA1_DIGEST_STRING_LENGTH
];
360 struct got_object
*obj
;
364 idx
= got_packidx_get_object_idx(packidx
, id
);
366 got_object_id_hex(id
, hex
, sizeof(hex
));
367 return got_error_fmt(GOT_ERR_BAD_PACKFILE
,
368 "object %s is missing from pack file", hex
);
371 err
= got_object_open_from_packfile(&obj
, id
, pack
, packidx
,
372 idx
, repo_write
.repo
);
376 if (obj
->type
!= expected_obj_type
) {
377 got_object_id_hex(id
, hex
, sizeof(hex
));
378 got_object_type_label(&typestr
, expected_obj_type
);
379 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
380 "%s is not pointing at a %s object", hex
, typestr
);
382 got_object_close(obj
);
386 static const struct got_error
*
387 protect_tag_namespace(const char *namespace, struct got_pack
*pack
,
388 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
390 const struct got_error
*err
;
392 err
= validate_namespace(namespace);
396 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
397 strlen(namespace)) != 0)
400 if (!ref_update
->ref_is_new
)
401 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
403 return verify_object_type(&ref_update
->new_id
, GOT_OBJ_TYPE_TAG
,
407 static const struct got_error
*
408 protect_require_yca(struct got_object_id
*tip_id
,
409 size_t max_commits_to_traverse
, struct got_pack
*pack
,
410 struct got_packidx
*packidx
, struct got_reference
*ref
)
412 const struct got_error
*err
;
415 struct got_object_id
*expected_yca_id
= NULL
;
416 struct got_object
*obj
= NULL
;
417 struct got_commit_object
*commit
= NULL
;
418 char hex
[SHA1_DIGEST_STRING_LENGTH
];
419 const struct got_object_id_queue
*parent_ids
;
420 struct got_object_id_queue ids
;
421 struct got_object_qid
*pid
, *qid
;
422 struct got_object_idset
*traversed_set
= NULL
;
423 int found_yca
= 0, obj_type
;
427 err
= got_ref_resolve(&expected_yca_id
, repo_write
.repo
, ref
);
431 err
= got_object_get_type(&obj_type
, repo_write
.repo
, expected_yca_id
);
435 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
) {
436 got_object_id_hex(expected_yca_id
, hex
, sizeof(hex
));
437 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
438 "%s is not pointing at a commit object", hex
);
442 traversed_set
= got_object_idset_alloc();
443 if (traversed_set
== NULL
) {
444 err
= got_error_from_errno("got_object_idset_alloc");
448 err
= got_object_qid_alloc(&qid
, tip_id
);
451 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
452 while (!STAILQ_EMPTY(&ids
)) {
453 err
= check_cancelled(NULL
);
457 qid
= STAILQ_FIRST(&ids
);
458 if (got_object_id_cmp(&qid
->id
, expected_yca_id
) == 0) {
463 if (got_object_idset_num_elements(traversed_set
) >=
464 max_commits_to_traverse
)
467 if (got_object_idset_contains(traversed_set
, &qid
->id
)) {
468 STAILQ_REMOVE_HEAD(&ids
, entry
);
469 got_object_qid_free(qid
);
473 err
= got_object_idset_add(traversed_set
, &qid
->id
, NULL
);
477 err
= got_object_open(&obj
, repo_write
.repo
, &qid
->id
);
478 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
482 err
= got_object_commit_open(&commit
, repo_write
.repo
,
489 idx
= got_packidx_get_object_idx(packidx
, &qid
->id
);
491 got_object_id_hex(&qid
->id
, hex
, sizeof(hex
));
492 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
493 "object %s is missing from pack file", hex
);
497 err
= got_object_open_from_packfile(&obj
, &qid
->id
,
498 pack
, packidx
, idx
, repo_write
.repo
);
502 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
503 got_object_id_hex(&qid
->id
, hex
, sizeof(hex
));
504 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
505 "%s is not pointing at a commit object",
510 err
= got_packfile_extract_object_to_mem(&buf
, &len
,
515 err
= got_object_parse_commit(&commit
, buf
, len
,
524 got_object_close(obj
);
527 STAILQ_REMOVE_HEAD(&ids
, entry
);
528 got_object_qid_free(qid
);
531 if (got_object_commit_get_nparents(commit
) == 0)
534 parent_ids
= got_object_commit_get_parent_ids(commit
);
535 STAILQ_FOREACH(pid
, parent_ids
, entry
) {
536 err
= check_cancelled(NULL
);
539 err
= got_object_qid_alloc(&qid
, &pid
->id
);
542 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
545 got_object_commit_close(commit
);
550 err
= got_error_fmt(GOT_ERR_REF_PROTECTED
, "%s",
551 got_ref_get_name(ref
));
554 got_object_idset_free(traversed_set
);
555 got_object_id_queue_free(&ids
);
558 got_object_close(obj
);
560 got_object_commit_close(commit
);
561 free(expected_yca_id
);
565 static const struct got_error
*
566 protect_branch_namespace(const char *namespace, struct got_pack
*pack
,
567 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
569 const struct got_error
*err
;
571 err
= validate_namespace(namespace);
575 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
576 strlen(namespace)) != 0)
579 if (ref_update
->ref_is_new
) {
580 return verify_object_type(&ref_update
->new_id
,
581 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
584 return protect_require_yca(&ref_update
->new_id
,
585 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
589 static const struct got_error
*
590 protect_branch(const char *refname
, struct got_pack
*pack
,
591 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
593 if (strcmp(refname
, got_ref_get_name(ref_update
->ref
)) != 0)
596 /* Always allow new branches to be created. */
597 if (ref_update
->ref_is_new
) {
598 return verify_object_type(&ref_update
->new_id
,
599 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
602 return protect_require_yca(&ref_update
->new_id
,
603 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
607 static const struct got_error
*
608 recv_ref_update(struct imsg
*imsg
)
610 static const char zero_id
[SHA1_DIGEST_LENGTH
];
611 const struct got_error
*err
= NULL
;
612 struct repo_write_client
*client
= &repo_write_client
;
613 struct gotd_imsg_ref_update iref
;
615 char *refname
= NULL
;
616 struct got_reference
*ref
= NULL
;
617 struct got_object_id
*id
= NULL
;
619 struct gotd_ref_update
*ref_update
= NULL
;
621 log_debug("ref-update received");
623 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
624 if (datalen
< sizeof(iref
))
625 return got_error(GOT_ERR_PRIVSEP_LEN
);
626 memcpy(&iref
, imsg
->data
, sizeof(iref
));
627 if (datalen
!= sizeof(iref
) + iref
.name_len
)
628 return got_error(GOT_ERR_PRIVSEP_LEN
);
630 imsg_init(&ibuf
, client
->fd
);
632 refname
= strndup(imsg
->data
+ sizeof(iref
), iref
.name_len
);
634 return got_error_from_errno("strndup");
636 ref_update
= calloc(1, sizeof(*ref_update
));
637 if (ref_update
== NULL
) {
638 err
= got_error_from_errno("malloc");
642 memcpy(ref_update
->old_id
.hash
, iref
.old_id
, SHA1_DIGEST_LENGTH
);
643 memcpy(ref_update
->new_id
.hash
, iref
.new_id
, SHA1_DIGEST_LENGTH
);
645 err
= got_ref_open(&ref
, repo_write
.repo
, refname
, 0);
647 if (err
->code
!= GOT_ERR_NOT_REF
)
649 if (memcmp(ref_update
->new_id
.hash
,
650 zero_id
, sizeof(zero_id
)) == 0) {
651 err
= got_error_fmt(GOT_ERR_BAD_OBJ_ID
,
655 err
= got_ref_alloc(&ref
, refname
, &ref_update
->new_id
);
658 ref_update
->ref_is_new
= 1;
661 if (got_ref_is_symbolic(ref
)) {
662 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
663 "'%s' is a symbolic reference and cannot "
664 "be updated", got_ref_get_name(ref
));
667 if (strncmp("refs/", got_ref_get_name(ref
), 5) != 0) {
668 err
= got_error_fmt(GOT_ERR_BAD_REF_NAME
,
669 "%s: does not begin with 'refs/'",
670 got_ref_get_name(ref
));
674 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/got/");
677 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/remotes/");
681 if (!ref_update
->ref_is_new
) {
683 * Ensure the client's idea of this update is still valid.
684 * At this point we can only return an error, to prevent
685 * the client from uploading a pack file which will likely
686 * have to be discarded.
688 err
= got_ref_resolve(&id
, repo_write
.repo
, ref
);
692 if (got_object_id_cmp(id
, &ref_update
->old_id
) != 0) {
693 err
= got_error_fmt(GOT_ERR_REF_BUSY
,
694 "%s has been modified by someone else "
695 "while transaction was in progress",
696 got_ref_get_name(ref
));
701 gotd_imsg_send_ack(&ref_update
->new_id
, &ibuf
, PROC_REPO_WRITE
,
704 ref_update
->ref
= ref
;
705 if (memcmp(ref_update
->new_id
.hash
, zero_id
, sizeof(zero_id
)) == 0) {
706 ref_update
->delete_ref
= 1;
709 STAILQ_INSERT_HEAD(&client
->ref_updates
, ref_update
, entry
);
710 client
->nref_updates
++;
722 static const struct got_error
*
723 pack_index_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
724 uint32_t nobj_loose
, uint32_t nobj_resolved
)
726 int p_indexed
= 0, p_resolved
= 0;
727 int nobj_delta
= nobj_total
- nobj_loose
;
730 p_indexed
= (nobj_indexed
* 100) / nobj_total
;
733 p_resolved
= (nobj_resolved
* 100) / nobj_delta
;
735 if (p_resolved
> 0) {
736 log_debug("indexing %d objects %d%%; resolving %d deltas %d%%",
737 nobj_total
, p_indexed
, nobj_delta
, p_resolved
);
739 log_debug("indexing %d objects %d%%", nobj_total
, p_indexed
);
744 static const struct got_error
*
745 read_more_pack_stream(int infd
, BUF
*buf
, size_t minsize
)
747 const struct got_error
*err
= NULL
;
748 uint8_t readahead
[65536];
751 err
= got_poll_read_full(infd
, &have
,
752 readahead
, sizeof(readahead
), minsize
);
756 err
= buf_append(&newlen
, buf
, readahead
, have
);
762 static const struct got_error
*
763 copy_object_type_and_size(uint8_t *type
, uint64_t *size
, int infd
, int outfd
,
764 off_t
*outsize
, BUF
*buf
, size_t *buf_pos
, struct got_hash
*ctx
)
766 const struct got_error
*err
= NULL
;
771 off_t obj_offset
= *outsize
;
774 /* We do not support size values which don't fit in 64 bit. */
776 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
777 "packfile offset %lld", (long long)obj_offset
);
779 if (buf_len(buf
) - *buf_pos
< sizeof(sizebuf
[0])) {
780 err
= read_more_pack_stream(infd
, buf
,
786 sizebuf
[i
] = buf_getc(buf
, *buf_pos
);
787 *buf_pos
+= sizeof(sizebuf
[i
]);
790 t
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_TYPE_MASK
) >>
791 GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT
;
792 s
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_VAL_MASK
);
794 size_t shift
= 4 + 7 * (i
- 1);
795 s
|= ((sizebuf
[i
] & GOT_PACK_OBJ_SIZE_VAL_MASK
) <<
799 } while (sizebuf
[i
- 1] & GOT_PACK_OBJ_SIZE_MORE
);
801 err
= got_pack_hwrite(outfd
, sizebuf
, i
, ctx
);
811 static const struct got_error
*
812 copy_ref_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
813 struct got_hash
*ctx
)
815 const struct got_error
*err
= NULL
;
816 size_t remain
= buf_len(buf
) - *buf_pos
;
818 if (remain
< SHA1_DIGEST_LENGTH
) {
819 err
= read_more_pack_stream(infd
, buf
,
820 SHA1_DIGEST_LENGTH
- remain
);
825 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
826 SHA1_DIGEST_LENGTH
, ctx
);
830 *buf_pos
+= SHA1_DIGEST_LENGTH
;
834 static const struct got_error
*
835 copy_offset_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
836 struct got_hash
*ctx
)
838 const struct got_error
*err
= NULL
;
842 off_t obj_offset
= *outsize
;
845 /* We do not support offset values which don't fit in 64 bit. */
847 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
848 "packfile offset %lld", (long long)obj_offset
);
850 if (buf_len(buf
) - *buf_pos
< sizeof(offbuf
[0])) {
851 err
= read_more_pack_stream(infd
, buf
,
857 offbuf
[i
] = buf_getc(buf
, *buf_pos
);
858 *buf_pos
+= sizeof(offbuf
[i
]);
861 o
= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
865 o
+= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
868 } while (offbuf
[i
- 1] & GOT_PACK_OBJ_DELTA_OFF_MORE
);
870 if (o
< sizeof(struct got_packfile_hdr
) || o
> *outsize
)
871 return got_error(GOT_ERR_PACK_OFFSET
);
873 err
= got_pack_hwrite(outfd
, offbuf
, i
, ctx
);
881 static const struct got_error
*
882 copy_zstream(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
883 struct got_hash
*ctx
)
885 const struct got_error
*err
= NULL
;
889 size_t consumed_total
= 0;
890 off_t zstream_offset
= *outsize
;
892 memset(&z
, 0, sizeof(z
));
896 zret
= inflateInit(&z
);
899 return got_error_from_errno("inflateInit");
900 if (zret
== Z_MEM_ERROR
) {
902 return got_error_from_errno("inflateInit");
904 return got_error_msg(GOT_ERR_DECOMPRESSION
,
905 "inflateInit failed");
908 while (zret
!= Z_STREAM_END
) {
909 size_t last_total_in
, consumed
;
912 * Decompress into the void. Object data will be parsed
913 * later, when the pack file is indexed. For now, we just
914 * want to locate the end of the compressed stream.
916 while (zret
!= Z_STREAM_END
&& buf_len(buf
) - *buf_pos
> 0) {
917 last_total_in
= z
.total_in
;
918 z
.next_in
= buf_get(buf
) + *buf_pos
;
919 z
.avail_in
= buf_len(buf
) - *buf_pos
;
920 z
.next_out
= voidbuf
;
921 z
.avail_out
= sizeof(voidbuf
);
923 zret
= inflate(&z
, Z_SYNC_FLUSH
);
924 if (zret
!= Z_OK
&& zret
!= Z_BUF_ERROR
&&
925 zret
!= Z_STREAM_END
) {
926 err
= got_error_fmt(GOT_ERR_DECOMPRESSION
,
927 "packfile offset %lld",
928 (long long)zstream_offset
);
931 consumed
= z
.total_in
- last_total_in
;
933 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
938 err
= buf_discard(buf
, *buf_pos
+ consumed
);
943 consumed_total
+= consumed
;
946 if (zret
!= Z_STREAM_END
) {
947 err
= read_more_pack_stream(infd
, buf
, 1);
954 *outsize
+= consumed_total
;
960 static const struct got_error
*
961 validate_object_type(int obj_type
)
964 case GOT_OBJ_TYPE_BLOB
:
965 case GOT_OBJ_TYPE_COMMIT
:
966 case GOT_OBJ_TYPE_TREE
:
967 case GOT_OBJ_TYPE_TAG
:
968 case GOT_OBJ_TYPE_REF_DELTA
:
969 case GOT_OBJ_TYPE_OFFSET_DELTA
:
975 return got_error(GOT_ERR_OBJ_TYPE
);
978 static const struct got_error
*
979 ensure_all_objects_exist_locally(struct gotd_ref_updates
*ref_updates
)
981 const struct got_error
*err
= NULL
;
982 struct gotd_ref_update
*ref_update
;
983 struct got_object
*obj
;
985 STAILQ_FOREACH(ref_update
, ref_updates
, entry
) {
986 err
= got_object_open(&obj
, repo_write
.repo
,
987 &ref_update
->new_id
);
990 got_object_close(obj
);
996 static const struct got_error
*
997 recv_packdata(off_t
*outsize
, uint32_t *nobj
, uint8_t *sha1
,
1000 const struct got_error
*err
;
1001 struct repo_write_client
*client
= &repo_write_client
;
1002 struct got_packfile_hdr hdr
;
1005 struct got_hash ctx
;
1006 uint8_t expected_sha1
[SHA1_DIGEST_LENGTH
];
1007 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1009 size_t buf_pos
= 0, remain
;
1015 /* if only deleting references there's nothing to read */
1016 if (client
->nref_updates
== client
->nref_del
)
1019 got_hash_init(&ctx
, GOT_HASH_SHA1
);
1021 err
= got_poll_read_full(infd
, &have
, &hdr
, sizeof(hdr
), sizeof(hdr
));
1024 if (have
!= sizeof(hdr
))
1025 return got_error_msg(GOT_ERR_BAD_PACKFILE
, "short pack file");
1028 if (hdr
.signature
!= htobe32(GOT_PACKFILE_SIGNATURE
))
1029 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1030 "bad packfile signature");
1031 if (hdr
.version
!= htobe32(GOT_PACKFILE_VERSION
))
1032 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1033 "bad packfile version");
1035 *nobj
= be32toh(hdr
.nobjects
);
1038 * Clients which are creating new references only
1039 * will send us an empty pack file.
1041 if (client
->nref_updates
> 0 &&
1042 client
->nref_updates
== client
->nref_new
)
1046 * Clients which only move existing refs will send us an empty
1047 * pack file. All referenced objects must exist locally.
1049 err
= ensure_all_objects_exist_locally(&client
->ref_updates
);
1051 if (err
->code
!= GOT_ERR_NO_OBJ
)
1053 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1054 "bad packfile with zero objects");
1057 client
->nref_move
= client
->nref_updates
;
1061 log_debug("expecting %d objects", *nobj
);
1063 err
= got_pack_hwrite(outfd
, &hdr
, sizeof(hdr
), &ctx
);
1067 err
= buf_alloc(&buf
, 65536);
1071 while (nhave
!= *nobj
) {
1075 err
= copy_object_type_and_size(&obj_type
, &obj_size
,
1076 infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1080 err
= validate_object_type(obj_type
);
1084 if (obj_type
== GOT_OBJ_TYPE_REF_DELTA
) {
1085 err
= copy_ref_delta(infd
, outfd
, outsize
,
1086 buf
, &buf_pos
, &ctx
);
1089 } else if (obj_type
== GOT_OBJ_TYPE_OFFSET_DELTA
) {
1090 err
= copy_offset_delta(infd
, outfd
, outsize
,
1091 buf
, &buf_pos
, &ctx
);
1096 err
= copy_zstream(infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1103 log_debug("received %u objects", *nobj
);
1105 got_hash_final(&ctx
, expected_sha1
);
1107 remain
= buf_len(buf
) - buf_pos
;
1108 if (remain
< SHA1_DIGEST_LENGTH
) {
1109 err
= read_more_pack_stream(infd
, buf
,
1110 SHA1_DIGEST_LENGTH
- remain
);
1115 got_sha1_digest_to_str(expected_sha1
, hex
, sizeof(hex
));
1116 log_debug("expect SHA1: %s", hex
);
1117 got_sha1_digest_to_str(buf_get(buf
) + buf_pos
, hex
, sizeof(hex
));
1118 log_debug("actual SHA1: %s", hex
);
1120 if (memcmp(buf_get(buf
) + buf_pos
, expected_sha1
,
1121 SHA1_DIGEST_LENGTH
) != 0) {
1122 err
= got_error(GOT_ERR_PACKFILE_CSUM
);
1126 memcpy(sha1
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1128 w
= write(outfd
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1130 err
= got_error_from_errno("write");
1133 if (w
!= SHA1_DIGEST_LENGTH
) {
1134 err
= got_error(GOT_ERR_IO
);
1138 *outsize
+= SHA1_DIGEST_LENGTH
;
1140 if (fsync(outfd
) == -1) {
1141 err
= got_error_from_errno("fsync");
1144 if (lseek(outfd
, 0L, SEEK_SET
) == -1) {
1145 err
= got_error_from_errno("lseek");
1153 static const struct got_error
*
1154 report_pack_status(const struct got_error
*unpack_err
)
1156 const struct got_error
*err
= NULL
;
1157 struct repo_write_client
*client
= &repo_write_client
;
1158 struct gotd_imsg_packfile_status istatus
;
1160 struct imsgbuf ibuf
;
1161 const char *unpack_ok
= "unpack ok\n";
1164 imsg_init(&ibuf
, client
->fd
);
1167 istatus
.reason_len
= strlen(unpack_err
->msg
);
1169 istatus
.reason_len
= strlen(unpack_ok
);
1171 len
= sizeof(istatus
) + istatus
.reason_len
;
1172 wbuf
= imsg_create(&ibuf
, GOTD_IMSG_PACKFILE_STATUS
, PROC_REPO_WRITE
,
1173 repo_write
.pid
, len
);
1175 err
= got_error_from_errno("imsg_create PACKFILE_STATUS");
1179 if (imsg_add(wbuf
, &istatus
, sizeof(istatus
)) == -1) {
1180 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1184 if (imsg_add(wbuf
, err
? err
->msg
: unpack_ok
,
1185 istatus
.reason_len
) == -1) {
1186 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1190 imsg_close(&ibuf
, wbuf
);
1192 err
= gotd_imsg_flush(&ibuf
);
1198 static const struct got_error
*
1199 recv_packfile(int *have_packfile
, struct imsg
*imsg
)
1201 const struct got_error
*err
= NULL
, *unpack_err
;
1202 struct repo_write_client
*client
= &repo_write_client
;
1203 struct gotd_imsg_recv_packfile ireq
;
1204 struct got_object_id id
;
1205 FILE *tempfiles
[3] = { NULL
, NULL
, NULL
};
1206 struct repo_tempfile
{
1209 } repo_tempfiles
[3] = { { - 1, - 1 }, { - 1, - 1 }, { - 1, - 1 }, };
1212 struct imsgbuf ibuf
;
1213 struct got_ratelimit rl
;
1214 struct got_pack
*pack
= NULL
;
1215 off_t pack_filesize
= 0;
1218 log_debug("packfile request received");
1221 got_ratelimit_init(&rl
, 2, 0);
1223 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1224 if (datalen
!= sizeof(ireq
))
1225 return got_error(GOT_ERR_PRIVSEP_LEN
);
1226 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1228 if (client
->pack_pipe
== -1 || client
->packidx_fd
== -1)
1229 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1231 imsg_init(&ibuf
, client
->fd
);
1233 pack
= &client
->pack
;
1234 memset(pack
, 0, sizeof(*pack
));
1235 pack
->fd
= imsg_get_fd(imsg
);
1237 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1239 err
= got_delta_cache_alloc(&pack
->delta_cache
);
1243 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1244 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1245 err
= got_repo_temp_fds_get(&t
->fd
, &t
->idx
, repo_write
.repo
);
1250 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1254 fd
= dup(repo_tempfiles
[i
].fd
);
1256 err
= got_error_from_errno("dup");
1259 f
= fdopen(fd
, "w+");
1261 err
= got_error_from_errno("fdopen");
1268 err
= gotd_imsg_flush(&ibuf
);
1272 log_debug("receiving pack data");
1273 unpack_err
= recv_packdata(&pack_filesize
, &nobj
,
1274 client
->pack_sha1
, client
->pack_pipe
, pack
->fd
);
1275 if (ireq
.report_status
) {
1276 err
= report_pack_status(unpack_err
);
1278 /* Git clients hang up after sending the pack file. */
1279 if (err
->code
== GOT_ERR_EOF
)
1288 log_debug("pack data received");
1291 * Clients which are creating new references only will
1292 * send us an empty pack file.
1295 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1296 client
->nref_updates
> 0 &&
1297 client
->nref_updates
== client
->nref_new
)
1301 * Clients which are deleting references only will send
1305 client
->nref_del
> 0 &&
1306 client
->nref_updates
== client
->nref_del
)
1310 * Clients which only move existing refs will send us an empty
1311 * pack file. All referenced objects must exist locally.
1314 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1315 client
->nref_move
> 0 &&
1316 client
->nref_updates
== client
->nref_move
)
1319 pack
->filesize
= pack_filesize
;
1322 memset(&id
, 0, sizeof(id
));
1323 memcpy(&id
.hash
, client
->pack_sha1
, SHA1_DIGEST_LENGTH
);
1324 id
.algo
= GOT_HASH_SHA1
;
1326 log_debug("begin indexing pack (%lld bytes in size)",
1327 (long long)pack
->filesize
);
1328 err
= got_pack_index(pack
, client
->packidx_fd
,
1329 tempfiles
[0], tempfiles
[1], tempfiles
[2], &id
,
1330 pack_index_progress
, NULL
, &rl
);
1333 log_debug("done indexing pack");
1335 if (fsync(client
->packidx_fd
) == -1) {
1336 err
= got_error_from_errno("fsync");
1339 if (lseek(client
->packidx_fd
, 0L, SEEK_SET
) == -1)
1340 err
= got_error_from_errno("lseek");
1342 if (close(client
->pack_pipe
) == -1 && err
== NULL
)
1343 err
= got_error_from_errno("close");
1344 client
->pack_pipe
= -1;
1345 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1346 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1348 got_repo_temp_fds_put(t
->idx
, repo_write
.repo
);
1350 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1351 if (tempfiles
[i
] && fclose(tempfiles
[i
]) == EOF
&& err
== NULL
)
1352 err
= got_error_from_errno("fclose");
1355 got_pack_close(pack
);
1360 static const struct got_error
*
1361 verify_packfile(void)
1363 const struct got_error
*err
= NULL
, *close_err
;
1364 struct repo_write_client
*client
= &repo_write_client
;
1365 struct gotd_ref_update
*ref_update
;
1366 struct got_packidx
*packidx
= NULL
;
1368 char *id_str
= NULL
;
1369 struct got_object
*obj
= NULL
;
1370 struct got_pathlist_entry
*pe
;
1371 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1373 if (STAILQ_EMPTY(&client
->ref_updates
)) {
1374 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1375 "cannot verify pack file without any ref-updates");
1378 if (client
->pack
.fd
== -1) {
1379 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1380 "invalid pack file handle during pack verification");
1382 if (client
->packidx_fd
== -1) {
1383 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1384 "invalid pack index handle during pack verification");
1387 if (fstat(client
->packidx_fd
, &sb
) == -1)
1388 return got_error_from_errno("pack index fstat");
1390 packidx
= malloc(sizeof(*packidx
));
1391 memset(packidx
, 0, sizeof(*packidx
));
1392 packidx
->fd
= client
->packidx_fd
;
1393 client
->packidx_fd
= -1;
1394 packidx
->len
= sb
.st_size
;
1396 err
= got_packidx_init_hdr(packidx
, 1, client
->pack
.filesize
);
1400 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1401 if (ref_update
->delete_ref
)
1404 TAILQ_FOREACH(pe
, repo_write
.protected_tag_namespaces
, entry
) {
1405 err
= protect_tag_namespace(pe
->path
, &client
->pack
,
1406 packidx
, ref_update
);
1412 * Objects which already exist in our repository need
1413 * not be present in the pack file.
1415 err
= got_object_open(&obj
, repo_write
.repo
,
1416 &ref_update
->new_id
);
1417 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
1421 got_object_close(obj
);
1424 int idx
= got_packidx_get_object_idx(packidx
,
1425 &ref_update
->new_id
);
1427 got_object_id_hex(&ref_update
->new_id
,
1429 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
1430 "object %s is missing from pack file",
1436 TAILQ_FOREACH(pe
, repo_write
.protected_branch_namespaces
,
1438 err
= protect_branch_namespace(pe
->path
,
1439 &client
->pack
, packidx
, ref_update
);
1443 TAILQ_FOREACH(pe
, repo_write
.protected_branches
, entry
) {
1444 err
= protect_branch(pe
->path
, &client
->pack
,
1445 packidx
, ref_update
);
1452 close_err
= got_packidx_close(packidx
);
1453 if (close_err
&& err
== NULL
)
1457 got_object_close(obj
);
1461 static const struct got_error
*
1462 protect_refs_from_deletion(void)
1464 const struct got_error
*err
= NULL
;
1465 struct repo_write_client
*client
= &repo_write_client
;
1466 struct gotd_ref_update
*ref_update
;
1467 struct got_pathlist_entry
*pe
;
1468 const char *refname
;
1470 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1471 if (!ref_update
->delete_ref
)
1474 refname
= got_ref_get_name(ref_update
->ref
);
1476 TAILQ_FOREACH(pe
, repo_write
.protected_tag_namespaces
, entry
) {
1477 err
= protect_ref_namespace(refname
, pe
->path
);
1482 TAILQ_FOREACH(pe
, repo_write
.protected_branch_namespaces
,
1484 err
= protect_ref_namespace(refname
, pe
->path
);
1489 TAILQ_FOREACH(pe
, repo_write
.protected_branches
, entry
) {
1490 if (strcmp(refname
, pe
->path
) == 0) {
1491 return got_error_fmt(GOT_ERR_REF_PROTECTED
,
1500 static const struct got_error
*
1501 install_packfile(struct gotd_imsgev
*iev
)
1503 struct repo_write_client
*client
= &repo_write_client
;
1504 struct gotd_imsg_packfile_install inst
;
1507 memset(&inst
, 0, sizeof(inst
));
1508 memcpy(inst
.pack_sha1
, client
->pack_sha1
, SHA1_DIGEST_LENGTH
);
1510 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_PACKFILE_INSTALL
,
1511 PROC_REPO_WRITE
, -1, &inst
, sizeof(inst
));
1513 return got_error_from_errno("imsg_compose PACKFILE_INSTALL");
1518 static const struct got_error
*
1519 send_ref_updates_start(int nref_updates
, struct gotd_imsgev
*iev
)
1521 struct gotd_imsg_ref_updates_start istart
;
1524 memset(&istart
, 0, sizeof(istart
));
1525 istart
.nref_updates
= nref_updates
;
1527 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_REF_UPDATES_START
,
1528 PROC_REPO_WRITE
, -1, &istart
, sizeof(istart
));
1530 return got_error_from_errno("imsg_compose REF_UPDATES_START");
1536 static const struct got_error
*
1537 send_ref_update(struct gotd_ref_update
*ref_update
, struct gotd_imsgev
*iev
)
1539 struct gotd_imsg_ref_update iref
;
1540 const char *refname
= got_ref_get_name(ref_update
->ref
);
1544 memset(&iref
, 0, sizeof(iref
));
1545 memcpy(iref
.old_id
, ref_update
->old_id
.hash
, SHA1_DIGEST_LENGTH
);
1546 memcpy(iref
.new_id
, ref_update
->new_id
.hash
, SHA1_DIGEST_LENGTH
);
1547 iref
.ref_is_new
= ref_update
->ref_is_new
;
1548 iref
.delete_ref
= ref_update
->delete_ref
;
1549 iref
.name_len
= strlen(refname
);
1551 len
= sizeof(iref
) + iref
.name_len
;
1552 wbuf
= imsg_create(&iev
->ibuf
, GOTD_IMSG_REF_UPDATE
, PROC_REPO_WRITE
,
1553 repo_write
.pid
, len
);
1555 return got_error_from_errno("imsg_create REF_UPDATE");
1557 if (imsg_add(wbuf
, &iref
, sizeof(iref
)) == -1)
1558 return got_error_from_errno("imsg_add REF_UPDATE");
1559 if (imsg_add(wbuf
, refname
, iref
.name_len
) == -1)
1560 return got_error_from_errno("imsg_add REF_UPDATE");
1562 imsg_close(&iev
->ibuf
, wbuf
);
1564 gotd_imsg_event_add(iev
);
1568 static const struct got_error
*
1569 update_refs(struct gotd_imsgev
*iev
)
1571 const struct got_error
*err
= NULL
;
1572 struct repo_write_client
*client
= &repo_write_client
;
1573 struct gotd_ref_update
*ref_update
;
1575 err
= send_ref_updates_start(client
->nref_updates
, iev
);
1579 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1580 err
= send_ref_update(ref_update
, iev
);
1588 static const struct got_error
*
1589 receive_pack_pipe(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1591 struct repo_write_client
*client
= &repo_write_client
;
1594 log_debug("receiving pack pipe descriptor");
1596 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1598 return got_error(GOT_ERR_PRIVSEP_LEN
);
1600 if (client
->pack_pipe
!= -1)
1601 return got_error(GOT_ERR_PRIVSEP_MSG
);
1603 client
->pack_pipe
= imsg_get_fd(imsg
);
1604 if (client
->pack_pipe
== -1)
1605 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1610 static const struct got_error
*
1611 receive_pack_idx(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1613 struct repo_write_client
*client
= &repo_write_client
;
1616 log_debug("receiving pack index output file");
1618 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1620 return got_error(GOT_ERR_PRIVSEP_LEN
);
1622 if (client
->packidx_fd
!= -1)
1623 return got_error(GOT_ERR_PRIVSEP_MSG
);
1625 client
->packidx_fd
= imsg_get_fd(imsg
);
1626 if (client
->packidx_fd
== -1)
1627 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1632 static const struct got_error
*
1633 notify_removed_ref(const char *refname
, struct got_object_id
*id
,
1634 struct gotd_imsgev
*iev
, int fd
)
1636 const struct got_error
*err
;
1639 err
= got_object_id_str(&id_str
, id
);
1643 dprintf(fd
, "Removed %s: %s\n", refname
, id_str
);
1649 format_author(char *author
)
1653 smallerthan
= strchr(author
, '<');
1654 if (smallerthan
&& smallerthan
[1] != '\0')
1655 author
= smallerthan
+ 1;
1656 author
[strcspn(author
, "@>")] = '\0';
1661 static const struct got_error
*
1662 print_commit_oneline(struct got_commit_object
*commit
, struct got_object_id
*id
,
1663 struct got_repository
*repo
, int fd
)
1665 const struct got_error
*err
= NULL
;
1666 char *id_str
= NULL
, *logmsg0
= NULL
;
1668 char *committer
= NULL
, *author
= NULL
;
1669 time_t committer_time
;
1671 err
= got_object_id_str(&id_str
, id
);
1675 committer_time
= got_object_commit_get_committer_time(commit
);
1677 err
= got_object_commit_get_logmsg(&logmsg0
, commit
);
1682 while (isspace((unsigned char)s
[0]))
1685 nl
= strchr(s
, '\n');
1690 if (strcmp(got_object_commit_get_author(commit
),
1691 got_object_commit_get_committer(commit
)) != 0) {
1692 author
= strdup(got_object_commit_get_author(commit
));
1693 if (author
== NULL
) {
1694 err
= got_error_from_errno("strdup");
1697 dprintf(fd
, "%lld %.7s %.8s %s\n", (long long)committer_time
,
1698 id_str
, format_author(author
), s
);
1700 committer
= strdup(got_object_commit_get_committer(commit
));
1701 dprintf(fd
, "%lld %.7s %.8s %s\n", (long long)committer_time
,
1702 id_str
, format_author(committer
), s
);
1705 if (fsync(fd
) == -1 && err
== NULL
)
1706 err
= got_error_from_errno("fsync");
1715 static const struct got_error
*
1716 print_diffstat(struct got_diffstat_cb_arg
*dsa
, int fd
)
1718 struct got_pathlist_entry
*pe
;
1720 TAILQ_FOREACH(pe
, dsa
->paths
, entry
) {
1721 struct got_diff_changed_path
*cp
= pe
->data
;
1722 int pad
= dsa
->max_path_len
- pe
->path_len
+ 1;
1724 dprintf(fd
, " %c %s%*c | %*d+ %*d-\n", cp
->status
,
1725 pe
->path
, pad
, ' ', dsa
->add_cols
+ 1, cp
->add
,
1726 dsa
->rm_cols
+ 1, cp
->rm
);
1729 "\n%d file%s changed, %d insertion%s(+), %d deletion%s(-)\n\n",
1730 dsa
->nfiles
, dsa
->nfiles
> 1 ? "s" : "", dsa
->ins
,
1731 dsa
->ins
!= 1 ? "s" : "", dsa
->del
, dsa
->del
!= 1 ? "s" : "");
1736 static const struct got_error
*
1737 print_commit(struct got_commit_object
*commit
, struct got_object_id
*id
,
1738 struct got_repository
*repo
, struct got_pathlist_head
*changed_paths
,
1739 struct got_diffstat_cb_arg
*diffstat
, int fd
)
1741 const struct got_error
*err
= NULL
;
1742 char *id_str
, *logmsg0
, *logmsg
, *line
;
1743 time_t committer_time
;
1744 const char *author
, *committer
;
1746 err
= got_object_id_str(&id_str
, id
);
1750 dprintf(fd
, "commit %s\n", id_str
);
1753 dprintf(fd
, "from: %s\n", got_object_commit_get_author(commit
));
1754 author
= got_object_commit_get_author(commit
);
1755 committer
= got_object_commit_get_committer(commit
);
1756 if (strcmp(author
, committer
) != 0)
1757 dprintf(fd
, "via: %s\n", committer
);
1758 committer_time
= got_object_commit_get_committer_time(commit
);
1759 dprintf(fd
, "date: %lld\n", (long long)committer_time
);
1760 if (got_object_commit_get_nparents(commit
) > 1) {
1761 const struct got_object_id_queue
*parent_ids
;
1762 struct got_object_qid
*qid
;
1764 parent_ids
= got_object_commit_get_parent_ids(commit
);
1765 STAILQ_FOREACH(qid
, parent_ids
, entry
) {
1766 err
= got_object_id_str(&id_str
, &qid
->id
);
1769 dprintf(fd
, "parent %d: %s\n", n
++, id_str
);
1775 err
= got_object_commit_get_logmsg(&logmsg0
, commit
);
1779 dprintf(fd
, "messagelen: %zu\n", strlen(logmsg0
));
1783 line
= strsep(&logmsg
, "\n");
1785 dprintf(fd
, " %s\n", line
);
1789 err
= print_diffstat(diffstat
, fd
);
1793 if (fsync(fd
) == -1 && err
== NULL
)
1794 err
= got_error_from_errno("fsync");
1800 static const struct got_error
*
1801 get_changed_paths(struct got_pathlist_head
*paths
,
1802 struct got_commit_object
*commit
, struct got_repository
*repo
,
1803 struct got_diffstat_cb_arg
*dsa
)
1805 const struct got_error
*err
= NULL
;
1806 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
1807 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
1808 struct got_object_qid
*qid
;
1809 got_diff_blob_cb cb
= got_diff_tree_collect_changed_paths
;
1810 FILE *f1
= repo_write
.diff
.f1
, *f2
= repo_write
.diff
.f2
;
1811 int fd1
= repo_write
.diff
.fd1
, fd2
= repo_write
.diff
.fd2
;
1814 cb
= got_diff_tree_compute_diffstat
;
1816 err
= got_opentemp_truncate(f1
);
1819 err
= got_opentemp_truncate(f2
);
1822 err
= got_opentemp_truncatefd(fd1
);
1825 err
= got_opentemp_truncatefd(fd2
);
1829 qid
= STAILQ_FIRST(got_object_commit_get_parent_ids(commit
));
1831 struct got_commit_object
*pcommit
;
1832 err
= got_object_open_as_commit(&pcommit
, repo
,
1837 tree_id1
= got_object_id_dup(
1838 got_object_commit_get_tree_id(pcommit
));
1839 if (tree_id1
== NULL
) {
1840 got_object_commit_close(pcommit
);
1841 return got_error_from_errno("got_object_id_dup");
1843 got_object_commit_close(pcommit
);
1848 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
1853 tree_id2
= got_object_commit_get_tree_id(commit
);
1854 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
1858 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
1859 cb
, dsa
? (void *)dsa
: paths
, dsa
? 1 : 0);
1862 got_object_tree_close(tree1
);
1864 got_object_tree_close(tree2
);
1869 static const struct got_error
*
1870 print_commits(struct got_object_id
*root_id
, struct got_object_id
*end_id
,
1871 struct got_repository
*repo
, int fd
)
1873 const struct got_error
*err
;
1874 struct got_commit_graph
*graph
;
1875 struct got_object_id_queue reversed_commits
;
1876 struct got_object_qid
*qid
;
1877 struct got_commit_object
*commit
= NULL
;
1878 struct got_pathlist_head changed_paths
;
1880 const int shortlog_threshold
= 50;
1882 STAILQ_INIT(&reversed_commits
);
1883 TAILQ_INIT(&changed_paths
);
1885 /* XXX first-parent only for now */
1886 err
= got_commit_graph_open(&graph
, "/", 1);
1889 err
= got_commit_graph_bfsort(graph
, root_id
, repo
,
1890 check_cancelled
, NULL
);
1894 struct got_object_id id
;
1896 err
= got_commit_graph_iter_next(&id
, graph
, repo
,
1897 check_cancelled
, NULL
);
1899 if (err
->code
== GOT_ERR_ITER_COMPLETED
)
1904 err
= got_object_open_as_commit(&commit
, repo
, &id
);
1908 if (end_id
&& got_object_id_cmp(&id
, end_id
) == 0)
1911 err
= got_object_qid_alloc(&qid
, &id
);
1915 STAILQ_INSERT_HEAD(&reversed_commits
, qid
, entry
);
1917 got_object_commit_close(commit
);
1923 STAILQ_FOREACH(qid
, &reversed_commits
, entry
) {
1924 struct got_diffstat_cb_arg dsa
= { 0, 0, 0, 0, 0, 0,
1925 &changed_paths
, 0, 0, GOT_DIFF_ALGORITHM_PATIENCE
};
1927 err
= got_object_open_as_commit(&commit
, repo
, &qid
->id
);
1931 if (ncommits
> shortlog_threshold
) {
1932 err
= print_commit_oneline(commit
, &qid
->id
,
1937 err
= get_changed_paths(&changed_paths
, commit
,
1941 err
= print_commit(commit
, &qid
->id
, repo
,
1942 &changed_paths
, &dsa
, fd
);
1944 got_object_commit_close(commit
);
1946 got_pathlist_free(&changed_paths
, GOT_PATHLIST_FREE_ALL
);
1950 got_object_commit_close(commit
);
1951 while (!STAILQ_EMPTY(&reversed_commits
)) {
1952 qid
= STAILQ_FIRST(&reversed_commits
);
1953 STAILQ_REMOVE_HEAD(&reversed_commits
, entry
);
1954 got_object_qid_free(qid
);
1956 got_pathlist_free(&changed_paths
, GOT_PATHLIST_FREE_ALL
);
1957 got_commit_graph_close(graph
);
1961 static const struct got_error
*
1962 print_tag(struct got_object_id
*id
,
1963 const char *refname
, struct got_repository
*repo
, int fd
)
1965 const struct got_error
*err
= NULL
;
1966 struct got_tag_object
*tag
= NULL
;
1967 const char *tagger
= NULL
;
1968 char *id_str
= NULL
, *tagmsg0
= NULL
, *tagmsg
, *line
;
1971 err
= got_object_open_as_tag(&tag
, repo
, id
);
1975 tagger
= got_object_tag_get_tagger(tag
);
1976 tagger_time
= got_object_tag_get_tagger_time(tag
);
1977 err
= got_object_id_str(&id_str
,
1978 got_object_tag_get_object_id(tag
));
1982 dprintf(fd
, "tag %s\n", refname
);
1983 dprintf(fd
, "from: %s\n", tagger
);
1984 dprintf(fd
, "date: %lld\n", (long long)tagger_time
);
1986 switch (got_object_tag_get_object_type(tag
)) {
1987 case GOT_OBJ_TYPE_BLOB
:
1988 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_BLOB
, id_str
);
1990 case GOT_OBJ_TYPE_TREE
:
1991 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_TREE
, id_str
);
1993 case GOT_OBJ_TYPE_COMMIT
:
1994 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_COMMIT
, id_str
);
1996 case GOT_OBJ_TYPE_TAG
:
1997 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_TAG
, id_str
);
2003 tagmsg0
= strdup(got_object_tag_get_message(tag
));
2004 if (tagmsg0
== NULL
) {
2005 err
= got_error_from_errno("strdup");
2009 dprintf(fd
, "messagelen: %zu\n", strlen(tagmsg0
));
2013 line
= strsep(&tagmsg
, "\n");
2015 dprintf(fd
, " %s\n", line
);
2020 got_object_tag_close(tag
);
2025 static const struct got_error
*
2026 notify_changed_ref(const char *refname
, struct got_object_id
*old_id
,
2027 struct got_object_id
*new_id
, struct gotd_imsgev
*iev
, int fd
)
2029 const struct got_error
*err
;
2030 int old_obj_type
, new_obj_type
;
2032 char *new_id_str
= NULL
;
2034 err
= got_object_get_type(&old_obj_type
, repo_write
.repo
, old_id
);
2038 err
= got_object_get_type(&new_obj_type
, repo_write
.repo
, new_id
);
2042 switch (new_obj_type
) {
2043 case GOT_OBJ_TYPE_COMMIT
:
2044 err
= print_commits(new_id
,
2045 old_obj_type
== GOT_OBJ_TYPE_COMMIT
? old_id
: NULL
,
2046 repo_write
.repo
, fd
);
2048 case GOT_OBJ_TYPE_TAG
:
2049 err
= print_tag(new_id
, refname
, repo_write
.repo
, fd
);
2052 err
= got_object_type_label(&label
, new_obj_type
);
2055 err
= got_object_id_str(&new_id_str
, new_id
);
2058 dprintf(fd
, "%s: %s object %s\n", refname
, label
, new_id_str
);
2066 static const struct got_error
*
2067 notify_created_ref(const char *refname
, struct got_object_id
*id
,
2068 struct gotd_imsgev
*iev
, int fd
)
2070 const struct got_error
*err
;
2073 err
= got_object_get_type(&obj_type
, repo_write
.repo
, id
);
2077 if (obj_type
== GOT_OBJ_TYPE_TAG
)
2078 return print_tag(id
, refname
, repo_write
.repo
, fd
);
2080 return print_commits(id
, NULL
, repo_write
.repo
, fd
);
2083 static const struct got_error
*
2084 render_notification(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
2086 const struct got_error
*err
= NULL
;
2087 struct gotd_imsg_notification_content ireq
;
2088 size_t datalen
, len
;
2089 char *refname
= NULL
;
2093 fd
= imsg_get_fd(imsg
);
2095 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
2097 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2098 if (datalen
< sizeof(ireq
)) {
2099 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2103 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
2105 if (datalen
!= sizeof(ireq
) + ireq
.refname_len
) {
2106 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2110 refname
= strndup(imsg
->data
+ sizeof(ireq
), ireq
.refname_len
);
2111 if (refname
== NULL
) {
2112 err
= got_error_from_errno("strndup");
2116 switch (ireq
.action
) {
2117 case GOTD_NOTIF_ACTION_CREATED
:
2118 err
= notify_created_ref(refname
, &ireq
.new_id
, iev
, fd
);
2120 case GOTD_NOTIF_ACTION_REMOVED
:
2121 err
= notify_removed_ref(refname
, &ireq
.old_id
, iev
, fd
);
2123 case GOTD_NOTIF_ACTION_CHANGED
:
2124 err
= notify_changed_ref(refname
, &ireq
.old_id
, &ireq
.new_id
,
2131 if (fsync(fd
) == -1) {
2132 err
= got_error_from_errno("fsync");
2136 len
= sizeof(ireq
) + ireq
.refname_len
;
2137 wbuf
= imsg_create(&iev
->ibuf
, GOTD_IMSG_NOTIFY
, PROC_REPO_WRITE
,
2138 repo_write
.pid
, len
);
2140 err
= got_error_from_errno("imsg_create REF");
2143 if (imsg_add(wbuf
, &ireq
, sizeof(ireq
)) == -1) {
2144 err
= got_error_from_errno("imsg_add NOTIFY");
2147 if (imsg_add(wbuf
, refname
, ireq
.refname_len
) == -1) {
2148 err
= got_error_from_errno("imsg_add NOTIFY");
2152 imsg_close(&iev
->ibuf
, wbuf
);
2153 gotd_imsg_event_add(iev
);
2156 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
2157 err
= got_error_from_errno("close");
2162 repo_write_dispatch_session(int fd
, short event
, void *arg
)
2164 const struct got_error
*err
= NULL
;
2165 struct gotd_imsgev
*iev
= arg
;
2166 struct imsgbuf
*ibuf
= &iev
->ibuf
;
2168 struct repo_write_client
*client
= &repo_write_client
;
2170 int shut
= 0, have_packfile
= 0;
2172 if (event
& EV_READ
) {
2173 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
2174 fatal("imsg_read error");
2175 if (n
== 0) /* Connection closed. */
2179 if (event
& EV_WRITE
) {
2180 n
= msgbuf_write(&ibuf
->w
);
2181 if (n
== -1 && errno
!= EAGAIN
)
2182 fatal("msgbuf_write");
2183 if (n
== 0) /* Connection closed. */
2188 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
2189 fatal("%s: imsg_get error", __func__
);
2190 if (n
== 0) /* No more messages. */
2193 if (imsg
.hdr
.type
!= GOTD_IMSG_LIST_REFS_INTERNAL
&&
2194 !repo_write
.refs_listed
) {
2195 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2199 switch (imsg
.hdr
.type
) {
2200 case GOTD_IMSG_LIST_REFS_INTERNAL
:
2201 err
= list_refs(&imsg
);
2203 log_warnx("ls-refs: %s", err
->msg
);
2205 case GOTD_IMSG_REF_UPDATE
:
2206 err
= recv_ref_update(&imsg
);
2208 log_warnx("ref-update: %s", err
->msg
);
2210 case GOTD_IMSG_PACKFILE_PIPE
:
2211 err
= receive_pack_pipe(&imsg
, iev
);
2213 log_warnx("receiving pack pipe: %s", err
->msg
);
2217 case GOTD_IMSG_PACKIDX_FILE
:
2218 err
= receive_pack_idx(&imsg
, iev
);
2220 log_warnx("receiving pack index: %s",
2225 case GOTD_IMSG_RECV_PACKFILE
:
2226 err
= protect_refs_from_deletion();
2229 err
= recv_packfile(&have_packfile
, &imsg
);
2231 log_warnx("receive packfile: %s", err
->msg
);
2234 if (have_packfile
) {
2235 err
= verify_packfile();
2237 log_warnx("verify packfile: %s",
2241 err
= install_packfile(iev
);
2243 log_warnx("install packfile: %s",
2248 * Ensure we re-read the pack index list
2251 repo_write
.repo
->pack_path_mtime
.tv_sec
= 0;
2252 repo_write
.repo
->pack_path_mtime
.tv_nsec
= 0;
2254 err
= update_refs(iev
);
2256 log_warnx("update refs: %s", err
->msg
);
2259 case GOTD_IMSG_NOTIFY
:
2260 err
= render_notification(&imsg
, iev
);
2262 log_warnx("render notification: %s", err
->msg
);
2267 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
2274 if (!shut
&& check_cancelled(NULL
) == NULL
) {
2276 gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
2277 client
->id
, err
) == -1) {
2278 log_warnx("could not send error to parent: %s",
2281 gotd_imsg_event_add(iev
);
2283 /* This pipe is dead. Remove its event handler */
2284 event_del(&iev
->ev
);
2285 event_loopexit(NULL
);
2289 static const struct got_error
*
2290 recv_connect(struct imsg
*imsg
)
2292 struct gotd_imsgev
*iev
= &repo_write
.session_iev
;
2295 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2297 return got_error(GOT_ERR_PRIVSEP_LEN
);
2299 if (repo_write
.session_fd
!= -1)
2300 return got_error(GOT_ERR_PRIVSEP_MSG
);
2302 repo_write
.session_fd
= imsg_get_fd(imsg
);
2303 if (repo_write
.session_fd
== -1)
2304 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
2306 imsg_init(&iev
->ibuf
, repo_write
.session_fd
);
2307 iev
->handler
= repo_write_dispatch_session
;
2308 iev
->events
= EV_READ
;
2309 iev
->handler_arg
= NULL
;
2310 event_set(&iev
->ev
, iev
->ibuf
.fd
, EV_READ
,
2311 repo_write_dispatch_session
, iev
);
2312 gotd_imsg_event_add(iev
);
2318 repo_write_dispatch(int fd
, short event
, void *arg
)
2320 const struct got_error
*err
= NULL
;
2321 struct gotd_imsgev
*iev
= arg
;
2322 struct imsgbuf
*ibuf
= &iev
->ibuf
;
2326 struct repo_write_client
*client
= &repo_write_client
;
2328 if (event
& EV_READ
) {
2329 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
2330 fatal("imsg_read error");
2331 if (n
== 0) { /* Connection closed. */
2337 if (event
& EV_WRITE
) {
2338 n
= msgbuf_write(&ibuf
->w
);
2339 if (n
== -1 && errno
!= EAGAIN
)
2340 fatal("msgbuf_write");
2341 if (n
== 0) { /* Connection closed. */
2347 while (err
== NULL
) {
2348 err
= check_cancelled(NULL
);
2351 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
2352 fatal("%s: imsg_get", __func__
);
2353 if (n
== 0) /* No more messages. */
2356 switch (imsg
.hdr
.type
) {
2357 case GOTD_IMSG_CONNECT_REPO_CHILD
:
2358 err
= recv_connect(&imsg
);
2361 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
2362 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2369 if (err
&& gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
2370 client
->id
, err
) == -1)
2371 log_warnx("could not send error to parent: %s", err
->msg
);
2374 gotd_imsg_event_add(iev
);
2376 /* This pipe is dead. Remove its event handler */
2377 event_del(&iev
->ev
);
2378 event_loopexit(NULL
);
2383 repo_write_main(const char *title
, const char *repo_path
,
2384 int *pack_fds
, int *temp_fds
,
2385 FILE *diff_f1
, FILE *diff_f2
, int diff_fd1
, int diff_fd2
,
2386 struct got_pathlist_head
*protected_tag_namespaces
,
2387 struct got_pathlist_head
*protected_branch_namespaces
,
2388 struct got_pathlist_head
*protected_branches
)
2390 const struct got_error
*err
= NULL
;
2391 struct repo_write_client
*client
= &repo_write_client
;
2392 struct gotd_imsgev iev
;
2395 client
->pack_pipe
= -1;
2396 client
->packidx_fd
= -1;
2397 client
->pack
.fd
= -1;
2399 repo_write
.title
= title
;
2400 repo_write
.pid
= getpid();
2401 repo_write
.pack_fds
= pack_fds
;
2402 repo_write
.temp_fds
= temp_fds
;
2403 repo_write
.session_fd
= -1;
2404 repo_write
.session_iev
.ibuf
.fd
= -1;
2405 repo_write
.protected_tag_namespaces
= protected_tag_namespaces
;
2406 repo_write
.protected_branch_namespaces
= protected_branch_namespaces
;
2407 repo_write
.protected_branches
= protected_branches
;
2408 repo_write
.diff
.f1
= diff_f1
;
2409 repo_write
.diff
.f2
= diff_f2
;
2410 repo_write
.diff
.fd1
= diff_fd1
;
2411 repo_write
.diff
.fd2
= diff_fd2
;
2413 STAILQ_INIT(&repo_write_client
.ref_updates
);
2415 err
= got_repo_open(&repo_write
.repo
, repo_path
, NULL
, pack_fds
);
2418 if (!got_repo_is_bare(repo_write
.repo
)) {
2419 err
= got_error_msg(GOT_ERR_NOT_GIT_REPO
,
2420 "bare git repository required");
2423 if (got_repo_get_object_format(repo_write
.repo
) != GOT_HASH_SHA1
) {
2424 err
= got_error_msg(GOT_ERR_NOT_IMPL
,
2425 "sha256 object IDs unsupported in network protocol");
2429 got_repo_temp_fds_set(repo_write
.repo
, temp_fds
);
2431 signal(SIGINT
, catch_sigint
);
2432 signal(SIGTERM
, catch_sigterm
);
2433 signal(SIGPIPE
, SIG_IGN
);
2434 signal(SIGHUP
, SIG_IGN
);
2436 imsg_init(&iev
.ibuf
, GOTD_FILENO_MSG_PIPE
);
2437 iev
.handler
= repo_write_dispatch
;
2438 iev
.events
= EV_READ
;
2439 iev
.handler_arg
= NULL
;
2440 event_set(&iev
.ev
, iev
.ibuf
.fd
, EV_READ
, repo_write_dispatch
, &iev
);
2441 if (gotd_imsg_compose_event(&iev
, GOTD_IMSG_REPO_CHILD_READY
,
2442 PROC_REPO_WRITE
, -1, NULL
, 0) == -1) {
2443 err
= got_error_from_errno("imsg compose REPO_CHILD_READY");
2449 if (fclose(diff_f1
) == EOF
&& err
== NULL
)
2450 err
= got_error_from_errno("fclose");
2451 if (fclose(diff_f2
) == EOF
&& err
== NULL
)
2452 err
= got_error_from_errno("fclose");
2453 if (close(diff_fd1
) == -1 && err
== NULL
)
2454 err
= got_error_from_errno("close");
2455 if (close(diff_fd2
) == -1 && err
== NULL
)
2456 err
= got_error_from_errno("close");
2458 log_warnx("%s: %s", title
, err
->msg
);
2459 repo_write_shutdown();
2463 repo_write_shutdown(void)
2465 struct repo_write_client
*client
= &repo_write_client
;
2466 struct gotd_ref_update
*ref_update
;
2468 log_debug("%s: shutting down", repo_write
.title
);
2470 while (!STAILQ_EMPTY(&client
->ref_updates
)) {
2471 ref_update
= STAILQ_FIRST(&client
->ref_updates
);
2472 STAILQ_REMOVE_HEAD(&client
->ref_updates
, entry
);
2473 got_ref_close(ref_update
->ref
);
2477 got_pack_close(&client
->pack
);
2478 if (client
->fd
!= -1)
2480 if (client
->pack_pipe
!= -1)
2481 close(client
->pack_pipe
);
2482 if (client
->packidx_fd
!= -1)
2483 close(client
->packidx_fd
);
2485 if (repo_write
.repo
)
2486 got_repo_close(repo_write
.repo
);
2487 got_repo_pack_fds_close(repo_write
.pack_fds
);
2488 got_repo_temp_fds_close(repo_write
.temp_fds
);
2489 if (repo_write
.session_fd
!= -1)
2490 close(repo_write
.session_fd
);