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 if (imsgbuf_init(&ibuf
, client
->fd
) == -1)
276 return got_error_from_errno("imsgbuf_init");
277 imsgbuf_allow_fdpass(&ibuf
);
279 err
= got_ref_list(&refs
, repo_write
.repo
, "",
280 got_ref_cmp_by_name
, NULL
);
284 memset(&irefs
, 0, sizeof(irefs
));
285 TAILQ_FOREACH(re
, &refs
, entry
) {
286 struct got_object_id
*id
;
289 if (got_ref_is_symbolic(re
->ref
))
294 /* Account for a peeled tag refs. */
295 err
= got_ref_resolve(&id
, repo_write
.repo
, re
->ref
);
298 err
= got_object_get_type(&obj_type
, repo_write
.repo
, id
);
302 if (obj_type
== GOT_OBJ_TYPE_TAG
)
306 if (imsg_compose(&ibuf
, GOTD_IMSG_REFLIST
, PROC_REPO_WRITE
,
307 repo_write
.pid
, -1, &irefs
, sizeof(irefs
)) == -1) {
308 err
= got_error_from_errno("imsg_compose REFLIST");
312 TAILQ_FOREACH(re
, &refs
, entry
) {
313 if (got_ref_is_symbolic(re
->ref
))
315 err
= send_ref(re
->ref
, &ibuf
);
320 err
= gotd_imsg_flush(&ibuf
);
322 got_ref_list_free(&refs
);
323 imsgbuf_clear(&ibuf
);
327 static const struct got_error
*
328 validate_namespace(const char *namespace)
330 size_t len
= strlen(namespace);
332 if (len
< 5 || strncmp("refs/", namespace, 5) != 0 ||
333 namespace[len
-1] != '/') {
334 return got_error_fmt(GOT_ERR_BAD_REF_NAME
,
335 "reference namespace '%s'", namespace);
341 static const struct got_error
*
342 protect_ref_namespace(const char *refname
, const char *namespace)
344 const struct got_error
*err
;
346 err
= validate_namespace(namespace);
350 if (strncmp(namespace, refname
, strlen(namespace)) == 0)
351 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
356 static const struct got_error
*
357 verify_object_type(struct got_object_id
*id
, int expected_obj_type
,
358 struct got_pack
*pack
, struct got_packidx
*packidx
)
360 const struct got_error
*err
;
361 char hex
[SHA1_DIGEST_STRING_LENGTH
];
362 struct got_object
*obj
;
366 idx
= got_packidx_get_object_idx(packidx
, id
);
368 got_object_id_hex(id
, hex
, sizeof(hex
));
369 return got_error_fmt(GOT_ERR_BAD_PACKFILE
,
370 "object %s is missing from pack file", hex
);
373 err
= got_object_open_from_packfile(&obj
, id
, pack
, packidx
,
374 idx
, repo_write
.repo
);
378 if (obj
->type
!= expected_obj_type
) {
379 got_object_id_hex(id
, hex
, sizeof(hex
));
380 got_object_type_label(&typestr
, expected_obj_type
);
381 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
382 "%s is not pointing at a %s object", hex
, typestr
);
384 got_object_close(obj
);
388 static const struct got_error
*
389 protect_tag_namespace(const char *namespace, struct got_pack
*pack
,
390 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
392 const struct got_error
*err
;
394 err
= validate_namespace(namespace);
398 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
399 strlen(namespace)) != 0)
402 if (!ref_update
->ref_is_new
)
403 return got_error_fmt(GOT_ERR_REFS_PROTECTED
, "%s", namespace);
405 return verify_object_type(&ref_update
->new_id
, GOT_OBJ_TYPE_TAG
,
409 static const struct got_error
*
410 protect_require_yca(struct got_object_id
*tip_id
,
411 size_t max_commits_to_traverse
, struct got_pack
*pack
,
412 struct got_packidx
*packidx
, struct got_reference
*ref
)
414 const struct got_error
*err
;
417 struct got_object_id
*expected_yca_id
= NULL
;
418 struct got_object
*obj
= NULL
;
419 struct got_commit_object
*commit
= NULL
;
420 char hex
[SHA1_DIGEST_STRING_LENGTH
];
421 const struct got_object_id_queue
*parent_ids
;
422 struct got_object_id_queue ids
;
423 struct got_object_qid
*pid
, *qid
;
424 struct got_object_idset
*traversed_set
= NULL
;
425 int found_yca
= 0, obj_type
;
429 err
= got_ref_resolve(&expected_yca_id
, repo_write
.repo
, ref
);
433 err
= got_object_get_type(&obj_type
, repo_write
.repo
, expected_yca_id
);
437 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
) {
438 got_object_id_hex(expected_yca_id
, hex
, sizeof(hex
));
439 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
440 "%s is not pointing at a commit object", hex
);
444 traversed_set
= got_object_idset_alloc();
445 if (traversed_set
== NULL
) {
446 err
= got_error_from_errno("got_object_idset_alloc");
450 err
= got_object_qid_alloc(&qid
, tip_id
);
453 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
454 while (!STAILQ_EMPTY(&ids
)) {
455 err
= check_cancelled(NULL
);
459 qid
= STAILQ_FIRST(&ids
);
460 if (got_object_id_cmp(&qid
->id
, expected_yca_id
) == 0) {
465 if (got_object_idset_num_elements(traversed_set
) >=
466 max_commits_to_traverse
)
469 if (got_object_idset_contains(traversed_set
, &qid
->id
)) {
470 STAILQ_REMOVE_HEAD(&ids
, entry
);
471 got_object_qid_free(qid
);
475 err
= got_object_idset_add(traversed_set
, &qid
->id
, NULL
);
479 err
= got_object_open(&obj
, repo_write
.repo
, &qid
->id
);
480 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
484 err
= got_object_commit_open(&commit
, repo_write
.repo
,
491 idx
= got_packidx_get_object_idx(packidx
, &qid
->id
);
493 got_object_id_hex(&qid
->id
, hex
, sizeof(hex
));
494 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
495 "object %s is missing from pack file", hex
);
499 err
= got_object_open_from_packfile(&obj
, &qid
->id
,
500 pack
, packidx
, idx
, repo_write
.repo
);
504 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
505 got_object_id_hex(&qid
->id
, hex
, sizeof(hex
));
506 err
= got_error_fmt(GOT_ERR_OBJ_TYPE
,
507 "%s is not pointing at a commit object",
512 err
= got_packfile_extract_object_to_mem(&buf
, &len
,
517 err
= got_object_parse_commit(&commit
, buf
, len
,
526 got_object_close(obj
);
529 STAILQ_REMOVE_HEAD(&ids
, entry
);
530 got_object_qid_free(qid
);
533 if (got_object_commit_get_nparents(commit
) == 0)
536 parent_ids
= got_object_commit_get_parent_ids(commit
);
537 STAILQ_FOREACH(pid
, parent_ids
, entry
) {
538 err
= check_cancelled(NULL
);
541 err
= got_object_qid_alloc(&qid
, &pid
->id
);
544 STAILQ_INSERT_TAIL(&ids
, qid
, entry
);
547 got_object_commit_close(commit
);
552 err
= got_error_fmt(GOT_ERR_REF_PROTECTED
, "%s",
553 got_ref_get_name(ref
));
556 got_object_idset_free(traversed_set
);
557 got_object_id_queue_free(&ids
);
560 got_object_close(obj
);
562 got_object_commit_close(commit
);
563 free(expected_yca_id
);
567 static const struct got_error
*
568 protect_branch_namespace(const char *namespace, struct got_pack
*pack
,
569 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
571 const struct got_error
*err
;
573 err
= validate_namespace(namespace);
577 if (strncmp(namespace, got_ref_get_name(ref_update
->ref
),
578 strlen(namespace)) != 0)
581 if (ref_update
->ref_is_new
) {
582 return verify_object_type(&ref_update
->new_id
,
583 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
586 return protect_require_yca(&ref_update
->new_id
,
587 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
591 static const struct got_error
*
592 protect_branch(const char *refname
, struct got_pack
*pack
,
593 struct got_packidx
*packidx
, struct gotd_ref_update
*ref_update
)
595 if (strcmp(refname
, got_ref_get_name(ref_update
->ref
)) != 0)
598 /* Always allow new branches to be created. */
599 if (ref_update
->ref_is_new
) {
600 return verify_object_type(&ref_update
->new_id
,
601 GOT_OBJ_TYPE_COMMIT
, pack
, packidx
);
604 return protect_require_yca(&ref_update
->new_id
,
605 be32toh(packidx
->hdr
.fanout_table
[0xff]), pack
, packidx
,
609 static const struct got_error
*
610 recv_ref_update(struct imsg
*imsg
)
612 static const char zero_id
[SHA1_DIGEST_LENGTH
];
613 const struct got_error
*err
= NULL
;
614 struct repo_write_client
*client
= &repo_write_client
;
615 struct gotd_imsg_ref_update iref
;
617 char *refname
= NULL
;
618 struct got_reference
*ref
= NULL
;
619 struct got_object_id
*id
= NULL
;
621 struct gotd_ref_update
*ref_update
= NULL
;
623 log_debug("ref-update received");
625 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
626 if (datalen
< sizeof(iref
))
627 return got_error(GOT_ERR_PRIVSEP_LEN
);
628 memcpy(&iref
, imsg
->data
, sizeof(iref
));
629 if (datalen
!= sizeof(iref
) + iref
.name_len
)
630 return got_error(GOT_ERR_PRIVSEP_LEN
);
632 if (imsgbuf_init(&ibuf
, client
->fd
))
633 return got_error_from_errno("imsgbuf_init");
634 imsgbuf_allow_fdpass(&ibuf
);
636 refname
= strndup(imsg
->data
+ sizeof(iref
), iref
.name_len
);
637 if (refname
== NULL
) {
638 err
= got_error_from_errno("strndup");
642 ref_update
= calloc(1, sizeof(*ref_update
));
643 if (ref_update
== NULL
) {
644 err
= got_error_from_errno("malloc");
648 memcpy(ref_update
->old_id
.hash
, iref
.old_id
, SHA1_DIGEST_LENGTH
);
649 memcpy(ref_update
->new_id
.hash
, iref
.new_id
, SHA1_DIGEST_LENGTH
);
651 err
= got_ref_open(&ref
, repo_write
.repo
, refname
, 0);
653 if (err
->code
!= GOT_ERR_NOT_REF
)
655 if (memcmp(ref_update
->new_id
.hash
,
656 zero_id
, sizeof(zero_id
)) == 0) {
657 err
= got_error_fmt(GOT_ERR_BAD_OBJ_ID
,
661 err
= got_ref_alloc(&ref
, refname
, &ref_update
->new_id
);
664 ref_update
->ref_is_new
= 1;
667 if (got_ref_is_symbolic(ref
)) {
668 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
669 "'%s' is a symbolic reference and cannot "
670 "be updated", got_ref_get_name(ref
));
673 if (strncmp("refs/", got_ref_get_name(ref
), 5) != 0) {
674 err
= got_error_fmt(GOT_ERR_BAD_REF_NAME
,
675 "%s: does not begin with 'refs/'",
676 got_ref_get_name(ref
));
680 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/got/");
683 err
= protect_ref_namespace(got_ref_get_name(ref
), "refs/remotes/");
687 if (!ref_update
->ref_is_new
) {
689 * Ensure the client's idea of this update is still valid.
690 * At this point we can only return an error, to prevent
691 * the client from uploading a pack file which will likely
692 * have to be discarded.
694 err
= got_ref_resolve(&id
, repo_write
.repo
, ref
);
698 if (got_object_id_cmp(id
, &ref_update
->old_id
) != 0) {
699 err
= got_error_fmt(GOT_ERR_REF_BUSY
,
700 "%s has been modified by someone else "
701 "while transaction was in progress",
702 got_ref_get_name(ref
));
707 gotd_imsg_send_ack(&ref_update
->new_id
, &ibuf
, PROC_REPO_WRITE
,
710 ref_update
->ref
= ref
;
711 if (memcmp(ref_update
->new_id
.hash
, zero_id
, sizeof(zero_id
)) == 0) {
712 ref_update
->delete_ref
= 1;
715 STAILQ_INSERT_HEAD(&client
->ref_updates
, ref_update
, entry
);
716 client
->nref_updates
++;
728 static const struct got_error
*
729 pack_index_progress(void *arg
, uint32_t nobj_total
, uint32_t nobj_indexed
,
730 uint32_t nobj_loose
, uint32_t nobj_resolved
)
732 int p_indexed
= 0, p_resolved
= 0;
733 int nobj_delta
= nobj_total
- nobj_loose
;
736 p_indexed
= (nobj_indexed
* 100) / nobj_total
;
739 p_resolved
= (nobj_resolved
* 100) / nobj_delta
;
741 if (p_resolved
> 0) {
742 log_debug("indexing %d objects %d%%; resolving %d deltas %d%%",
743 nobj_total
, p_indexed
, nobj_delta
, p_resolved
);
745 log_debug("indexing %d objects %d%%", nobj_total
, p_indexed
);
750 static const struct got_error
*
751 read_more_pack_stream(int infd
, BUF
*buf
, size_t minsize
)
753 const struct got_error
*err
= NULL
;
754 uint8_t readahead
[65536];
757 err
= got_poll_read_full(infd
, &have
,
758 readahead
, sizeof(readahead
), minsize
);
762 err
= buf_append(&newlen
, buf
, readahead
, have
);
768 static const struct got_error
*
769 copy_object_type_and_size(uint8_t *type
, uint64_t *size
, int infd
, int outfd
,
770 off_t
*outsize
, BUF
*buf
, size_t *buf_pos
, struct got_hash
*ctx
)
772 const struct got_error
*err
= NULL
;
777 off_t obj_offset
= *outsize
;
780 /* We do not support size values which don't fit in 64 bit. */
782 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
783 "packfile offset %lld", (long long)obj_offset
);
785 if (buf_len(buf
) - *buf_pos
< sizeof(sizebuf
[0])) {
786 err
= read_more_pack_stream(infd
, buf
,
792 sizebuf
[i
] = buf_getc(buf
, *buf_pos
);
793 *buf_pos
+= sizeof(sizebuf
[i
]);
796 t
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_TYPE_MASK
) >>
797 GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT
;
798 s
= (sizebuf
[i
] & GOT_PACK_OBJ_SIZE0_VAL_MASK
);
800 size_t shift
= 4 + 7 * (i
- 1);
801 s
|= ((sizebuf
[i
] & GOT_PACK_OBJ_SIZE_VAL_MASK
) <<
805 } while (sizebuf
[i
- 1] & GOT_PACK_OBJ_SIZE_MORE
);
807 err
= got_pack_hwrite(outfd
, sizebuf
, i
, ctx
);
817 static const struct got_error
*
818 copy_ref_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
819 struct got_hash
*ctx
)
821 const struct got_error
*err
= NULL
;
822 size_t remain
= buf_len(buf
) - *buf_pos
;
824 if (remain
< SHA1_DIGEST_LENGTH
) {
825 err
= read_more_pack_stream(infd
, buf
,
826 SHA1_DIGEST_LENGTH
- remain
);
831 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
832 SHA1_DIGEST_LENGTH
, ctx
);
836 *buf_pos
+= SHA1_DIGEST_LENGTH
;
840 static const struct got_error
*
841 copy_offset_delta(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
842 struct got_hash
*ctx
)
844 const struct got_error
*err
= NULL
;
848 off_t obj_offset
= *outsize
;
851 /* We do not support offset values which don't fit in 64 bit. */
853 return got_error_fmt(GOT_ERR_OBJ_TOO_LARGE
,
854 "packfile offset %lld", (long long)obj_offset
);
856 if (buf_len(buf
) - *buf_pos
< sizeof(offbuf
[0])) {
857 err
= read_more_pack_stream(infd
, buf
,
863 offbuf
[i
] = buf_getc(buf
, *buf_pos
);
864 *buf_pos
+= sizeof(offbuf
[i
]);
867 o
= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
871 o
+= (offbuf
[i
] & GOT_PACK_OBJ_DELTA_OFF_VAL_MASK
);
874 } while (offbuf
[i
- 1] & GOT_PACK_OBJ_DELTA_OFF_MORE
);
876 if (o
< sizeof(struct got_packfile_hdr
) || o
> *outsize
)
877 return got_error(GOT_ERR_PACK_OFFSET
);
879 err
= got_pack_hwrite(outfd
, offbuf
, i
, ctx
);
887 static const struct got_error
*
888 copy_zstream(int infd
, int outfd
, off_t
*outsize
, BUF
*buf
, size_t *buf_pos
,
889 struct got_hash
*ctx
)
891 const struct got_error
*err
= NULL
;
895 size_t consumed_total
= 0;
896 off_t zstream_offset
= *outsize
;
898 memset(&z
, 0, sizeof(z
));
902 zret
= inflateInit(&z
);
905 return got_error_from_errno("inflateInit");
906 if (zret
== Z_MEM_ERROR
) {
908 return got_error_from_errno("inflateInit");
910 return got_error_msg(GOT_ERR_DECOMPRESSION
,
911 "inflateInit failed");
914 while (zret
!= Z_STREAM_END
) {
915 size_t last_total_in
, consumed
;
918 * Decompress into the void. Object data will be parsed
919 * later, when the pack file is indexed. For now, we just
920 * want to locate the end of the compressed stream.
922 while (zret
!= Z_STREAM_END
&& buf_len(buf
) - *buf_pos
> 0) {
923 last_total_in
= z
.total_in
;
924 z
.next_in
= buf_get(buf
) + *buf_pos
;
925 z
.avail_in
= buf_len(buf
) - *buf_pos
;
926 z
.next_out
= voidbuf
;
927 z
.avail_out
= sizeof(voidbuf
);
929 zret
= inflate(&z
, Z_SYNC_FLUSH
);
930 if (zret
!= Z_OK
&& zret
!= Z_BUF_ERROR
&&
931 zret
!= Z_STREAM_END
) {
932 err
= got_error_fmt(GOT_ERR_DECOMPRESSION
,
933 "packfile offset %lld",
934 (long long)zstream_offset
);
937 consumed
= z
.total_in
- last_total_in
;
939 err
= got_pack_hwrite(outfd
, buf_get(buf
) + *buf_pos
,
944 err
= buf_discard(buf
, *buf_pos
+ consumed
);
949 consumed_total
+= consumed
;
952 if (zret
!= Z_STREAM_END
) {
953 err
= read_more_pack_stream(infd
, buf
, 1);
960 *outsize
+= consumed_total
;
966 static const struct got_error
*
967 validate_object_type(int obj_type
)
970 case GOT_OBJ_TYPE_BLOB
:
971 case GOT_OBJ_TYPE_COMMIT
:
972 case GOT_OBJ_TYPE_TREE
:
973 case GOT_OBJ_TYPE_TAG
:
974 case GOT_OBJ_TYPE_REF_DELTA
:
975 case GOT_OBJ_TYPE_OFFSET_DELTA
:
981 return got_error(GOT_ERR_OBJ_TYPE
);
984 static const struct got_error
*
985 ensure_all_objects_exist_locally(struct gotd_ref_updates
*ref_updates
)
987 const struct got_error
*err
= NULL
;
988 struct gotd_ref_update
*ref_update
;
989 struct got_object
*obj
;
991 STAILQ_FOREACH(ref_update
, ref_updates
, entry
) {
992 err
= got_object_open(&obj
, repo_write
.repo
,
993 &ref_update
->new_id
);
996 got_object_close(obj
);
1002 static const struct got_error
*
1003 recv_packdata(off_t
*outsize
, uint32_t *nobj
, uint8_t *sha1
,
1004 int infd
, int outfd
)
1006 const struct got_error
*err
;
1007 struct repo_write_client
*client
= &repo_write_client
;
1008 struct got_packfile_hdr hdr
;
1011 struct got_hash ctx
;
1012 uint8_t expected_sha1
[SHA1_DIGEST_LENGTH
];
1013 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1015 size_t buf_pos
= 0, remain
;
1021 /* if only deleting references there's nothing to read */
1022 if (client
->nref_updates
== client
->nref_del
)
1025 got_hash_init(&ctx
, GOT_HASH_SHA1
);
1027 err
= got_poll_read_full(infd
, &have
, &hdr
, sizeof(hdr
), sizeof(hdr
));
1030 if (have
!= sizeof(hdr
))
1031 return got_error_msg(GOT_ERR_BAD_PACKFILE
, "short pack file");
1034 if (hdr
.signature
!= htobe32(GOT_PACKFILE_SIGNATURE
))
1035 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1036 "bad packfile signature");
1037 if (hdr
.version
!= htobe32(GOT_PACKFILE_VERSION
))
1038 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1039 "bad packfile version");
1041 *nobj
= be32toh(hdr
.nobjects
);
1044 * Clients which are creating new references only
1045 * will send us an empty pack file.
1047 if (client
->nref_updates
> 0 &&
1048 client
->nref_updates
== client
->nref_new
)
1052 * Clients which only move existing refs will send us an empty
1053 * pack file. All referenced objects must exist locally.
1055 err
= ensure_all_objects_exist_locally(&client
->ref_updates
);
1057 if (err
->code
!= GOT_ERR_NO_OBJ
)
1059 return got_error_msg(GOT_ERR_BAD_PACKFILE
,
1060 "bad packfile with zero objects");
1063 client
->nref_move
= client
->nref_updates
;
1067 log_debug("expecting %d objects", *nobj
);
1069 err
= got_pack_hwrite(outfd
, &hdr
, sizeof(hdr
), &ctx
);
1073 err
= buf_alloc(&buf
, 65536);
1077 while (nhave
!= *nobj
) {
1081 err
= copy_object_type_and_size(&obj_type
, &obj_size
,
1082 infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1086 err
= validate_object_type(obj_type
);
1090 if (obj_type
== GOT_OBJ_TYPE_REF_DELTA
) {
1091 err
= copy_ref_delta(infd
, outfd
, outsize
,
1092 buf
, &buf_pos
, &ctx
);
1095 } else if (obj_type
== GOT_OBJ_TYPE_OFFSET_DELTA
) {
1096 err
= copy_offset_delta(infd
, outfd
, outsize
,
1097 buf
, &buf_pos
, &ctx
);
1102 err
= copy_zstream(infd
, outfd
, outsize
, buf
, &buf_pos
, &ctx
);
1109 log_debug("received %u objects", *nobj
);
1111 got_hash_final(&ctx
, expected_sha1
);
1113 remain
= buf_len(buf
) - buf_pos
;
1114 if (remain
< SHA1_DIGEST_LENGTH
) {
1115 err
= read_more_pack_stream(infd
, buf
,
1116 SHA1_DIGEST_LENGTH
- remain
);
1121 got_sha1_digest_to_str(expected_sha1
, hex
, sizeof(hex
));
1122 log_debug("expect SHA1: %s", hex
);
1123 got_sha1_digest_to_str(buf_get(buf
) + buf_pos
, hex
, sizeof(hex
));
1124 log_debug("actual SHA1: %s", hex
);
1126 if (memcmp(buf_get(buf
) + buf_pos
, expected_sha1
,
1127 SHA1_DIGEST_LENGTH
) != 0) {
1128 err
= got_error(GOT_ERR_PACKFILE_CSUM
);
1132 memcpy(sha1
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1134 w
= write(outfd
, expected_sha1
, SHA1_DIGEST_LENGTH
);
1136 err
= got_error_from_errno("write");
1139 if (w
!= SHA1_DIGEST_LENGTH
) {
1140 err
= got_error(GOT_ERR_IO
);
1144 *outsize
+= SHA1_DIGEST_LENGTH
;
1146 if (fsync(outfd
) == -1) {
1147 err
= got_error_from_errno("fsync");
1150 if (lseek(outfd
, 0L, SEEK_SET
) == -1) {
1151 err
= got_error_from_errno("lseek");
1159 static const struct got_error
*
1160 report_pack_status(const struct got_error
*unpack_err
)
1162 const struct got_error
*err
= NULL
;
1163 struct repo_write_client
*client
= &repo_write_client
;
1164 struct gotd_imsg_packfile_status istatus
;
1166 struct imsgbuf ibuf
;
1167 const char *unpack_ok
= "unpack ok\n";
1170 if (imsgbuf_init(&ibuf
, client
->fd
))
1171 return got_error_from_errno("imsgbuf_init");
1172 imsgbuf_allow_fdpass(&ibuf
);
1175 istatus
.reason_len
= strlen(unpack_err
->msg
);
1177 istatus
.reason_len
= strlen(unpack_ok
);
1179 len
= sizeof(istatus
) + istatus
.reason_len
;
1180 wbuf
= imsg_create(&ibuf
, GOTD_IMSG_PACKFILE_STATUS
, PROC_REPO_WRITE
,
1181 repo_write
.pid
, len
);
1183 err
= got_error_from_errno("imsg_create PACKFILE_STATUS");
1187 if (imsg_add(wbuf
, &istatus
, sizeof(istatus
)) == -1) {
1188 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1192 if (imsg_add(wbuf
, err
? err
->msg
: unpack_ok
,
1193 istatus
.reason_len
) == -1) {
1194 err
= got_error_from_errno("imsg_add PACKFILE_STATUS");
1198 imsg_close(&ibuf
, wbuf
);
1200 err
= gotd_imsg_flush(&ibuf
);
1202 imsgbuf_clear(&ibuf
);
1206 static const struct got_error
*
1207 recv_packfile(int *have_packfile
, struct imsg
*imsg
)
1209 const struct got_error
*err
= NULL
, *unpack_err
;
1210 struct repo_write_client
*client
= &repo_write_client
;
1211 struct gotd_imsg_recv_packfile ireq
;
1212 struct got_object_id id
;
1213 FILE *tempfiles
[3] = { NULL
, NULL
, NULL
};
1214 struct repo_tempfile
{
1217 } repo_tempfiles
[3] = { { - 1, - 1 }, { - 1, - 1 }, { - 1, - 1 }, };
1220 struct got_ratelimit rl
;
1221 struct got_pack
*pack
= NULL
;
1222 off_t pack_filesize
= 0;
1225 log_debug("packfile request received");
1228 got_ratelimit_init(&rl
, 2, 0);
1230 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1231 if (datalen
!= sizeof(ireq
))
1232 return got_error(GOT_ERR_PRIVSEP_LEN
);
1233 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
1235 if (client
->pack_pipe
== -1 || client
->packidx_fd
== -1)
1236 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1238 pack
= &client
->pack
;
1239 memset(pack
, 0, sizeof(*pack
));
1240 pack
->fd
= imsg_get_fd(imsg
);
1241 if (pack
->fd
== -1) {
1242 err
= got_error(GOT_ERR_PRIVSEP_NO_FD
);
1246 err
= got_delta_cache_alloc(&pack
->delta_cache
);
1250 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1251 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1252 err
= got_repo_temp_fds_get(&t
->fd
, &t
->idx
, repo_write
.repo
);
1257 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1261 fd
= dup(repo_tempfiles
[i
].fd
);
1263 err
= got_error_from_errno("dup");
1266 f
= fdopen(fd
, "w+");
1268 err
= got_error_from_errno("fdopen");
1275 log_debug("receiving pack data");
1276 unpack_err
= recv_packdata(&pack_filesize
, &nobj
,
1277 client
->pack_sha1
, client
->pack_pipe
, pack
->fd
);
1278 if (ireq
.report_status
) {
1279 err
= report_pack_status(unpack_err
);
1281 /* Git clients hang up after sending the pack file. */
1282 if (err
->code
== GOT_ERR_EOF
)
1291 log_debug("pack data received");
1294 * Clients which are creating new references only will
1295 * send us an empty pack file.
1298 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1299 client
->nref_updates
> 0 &&
1300 client
->nref_updates
== client
->nref_new
)
1304 * Clients which are deleting references only will send
1308 client
->nref_del
> 0 &&
1309 client
->nref_updates
== client
->nref_del
)
1313 * Clients which only move existing refs will send us an empty
1314 * pack file. All referenced objects must exist locally.
1317 pack_filesize
== sizeof(struct got_packfile_hdr
) &&
1318 client
->nref_move
> 0 &&
1319 client
->nref_updates
== client
->nref_move
)
1322 pack
->filesize
= pack_filesize
;
1325 memset(&id
, 0, sizeof(id
));
1326 memcpy(&id
.hash
, client
->pack_sha1
, SHA1_DIGEST_LENGTH
);
1327 id
.algo
= GOT_HASH_SHA1
;
1329 log_debug("begin indexing pack (%lld bytes in size)",
1330 (long long)pack
->filesize
);
1331 err
= got_pack_index(pack
, client
->packidx_fd
,
1332 tempfiles
[0], tempfiles
[1], tempfiles
[2], &id
,
1333 pack_index_progress
, NULL
, &rl
);
1336 log_debug("done indexing pack");
1338 if (fsync(client
->packidx_fd
) == -1) {
1339 err
= got_error_from_errno("fsync");
1342 if (lseek(client
->packidx_fd
, 0L, SEEK_SET
) == -1)
1343 err
= got_error_from_errno("lseek");
1345 if (close(client
->pack_pipe
) == -1 && err
== NULL
)
1346 err
= got_error_from_errno("close");
1347 client
->pack_pipe
= -1;
1348 for (i
= 0; i
< nitems(repo_tempfiles
); i
++) {
1349 struct repo_tempfile
*t
= &repo_tempfiles
[i
];
1351 got_repo_temp_fds_put(t
->idx
, repo_write
.repo
);
1353 for (i
= 0; i
< nitems(tempfiles
); i
++) {
1354 if (tempfiles
[i
] && fclose(tempfiles
[i
]) == EOF
&& err
== NULL
)
1355 err
= got_error_from_errno("fclose");
1358 got_pack_close(pack
);
1362 static const struct got_error
*
1363 verify_packfile(void)
1365 const struct got_error
*err
= NULL
, *close_err
;
1366 struct repo_write_client
*client
= &repo_write_client
;
1367 struct gotd_ref_update
*ref_update
;
1368 struct got_packidx
*packidx
= NULL
;
1370 char *id_str
= NULL
;
1371 struct got_object
*obj
= NULL
;
1372 struct got_pathlist_entry
*pe
;
1373 char hex
[SHA1_DIGEST_STRING_LENGTH
];
1375 if (STAILQ_EMPTY(&client
->ref_updates
)) {
1376 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1377 "cannot verify pack file without any ref-updates");
1380 if (client
->pack
.fd
== -1) {
1381 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1382 "invalid pack file handle during pack verification");
1384 if (client
->packidx_fd
== -1) {
1385 return got_error_msg(GOT_ERR_BAD_REQUEST
,
1386 "invalid pack index handle during pack verification");
1389 if (fstat(client
->packidx_fd
, &sb
) == -1)
1390 return got_error_from_errno("pack index fstat");
1392 packidx
= malloc(sizeof(*packidx
));
1393 memset(packidx
, 0, sizeof(*packidx
));
1394 packidx
->fd
= client
->packidx_fd
;
1395 client
->packidx_fd
= -1;
1396 packidx
->len
= sb
.st_size
;
1398 err
= got_packidx_init_hdr(packidx
, 1, client
->pack
.filesize
);
1402 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1403 if (ref_update
->delete_ref
)
1406 RB_FOREACH(pe
, got_pathlist_head
, repo_write
.protected_tag_namespaces
) {
1407 err
= protect_tag_namespace(pe
->path
, &client
->pack
,
1408 packidx
, ref_update
);
1414 * Objects which already exist in our repository need
1415 * not be present in the pack file.
1417 err
= got_object_open(&obj
, repo_write
.repo
,
1418 &ref_update
->new_id
);
1419 if (err
&& err
->code
!= GOT_ERR_NO_OBJ
)
1423 got_object_close(obj
);
1426 int idx
= got_packidx_get_object_idx(packidx
,
1427 &ref_update
->new_id
);
1429 got_object_id_hex(&ref_update
->new_id
,
1431 err
= got_error_fmt(GOT_ERR_BAD_PACKFILE
,
1432 "object %s is missing from pack file",
1438 RB_FOREACH(pe
, got_pathlist_head
, repo_write
.protected_branch_namespaces
)
1440 err
= protect_branch_namespace(pe
->path
,
1441 &client
->pack
, packidx
, ref_update
);
1445 RB_FOREACH(pe
, got_pathlist_head
, repo_write
.protected_branches
)
1447 err
= protect_branch(pe
->path
, &client
->pack
,
1448 packidx
, ref_update
);
1455 close_err
= got_packidx_close(packidx
);
1456 if (close_err
&& err
== NULL
)
1460 got_object_close(obj
);
1464 static const struct got_error
*
1465 protect_refs_from_deletion(void)
1467 const struct got_error
*err
= NULL
;
1468 struct repo_write_client
*client
= &repo_write_client
;
1469 struct gotd_ref_update
*ref_update
;
1470 struct got_pathlist_entry
*pe
;
1471 const char *refname
;
1473 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1474 if (!ref_update
->delete_ref
)
1477 refname
= got_ref_get_name(ref_update
->ref
);
1479 RB_FOREACH(pe
, got_pathlist_head
,
1480 repo_write
.protected_tag_namespaces
) {
1481 err
= protect_ref_namespace(refname
, pe
->path
);
1486 RB_FOREACH(pe
, got_pathlist_head
,
1487 repo_write
.protected_branch_namespaces
) {
1488 err
= protect_ref_namespace(refname
, pe
->path
);
1493 RB_FOREACH(pe
, got_pathlist_head
, repo_write
.protected_branches
)
1495 if (strcmp(refname
, pe
->path
) == 0) {
1496 return got_error_fmt(GOT_ERR_REF_PROTECTED
,
1505 static const struct got_error
*
1506 install_packfile(struct gotd_imsgev
*iev
)
1508 struct repo_write_client
*client
= &repo_write_client
;
1509 struct gotd_imsg_packfile_install inst
;
1512 memset(&inst
, 0, sizeof(inst
));
1513 memcpy(inst
.pack_sha1
, client
->pack_sha1
, SHA1_DIGEST_LENGTH
);
1515 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_PACKFILE_INSTALL
,
1516 PROC_REPO_WRITE
, -1, &inst
, sizeof(inst
));
1518 return got_error_from_errno("imsg_compose PACKFILE_INSTALL");
1523 static const struct got_error
*
1524 send_ref_updates_start(int nref_updates
, struct gotd_imsgev
*iev
)
1526 struct gotd_imsg_ref_updates_start istart
;
1529 memset(&istart
, 0, sizeof(istart
));
1530 istart
.nref_updates
= nref_updates
;
1532 ret
= gotd_imsg_compose_event(iev
, GOTD_IMSG_REF_UPDATES_START
,
1533 PROC_REPO_WRITE
, -1, &istart
, sizeof(istart
));
1535 return got_error_from_errno("imsg_compose REF_UPDATES_START");
1541 static const struct got_error
*
1542 send_ref_update(struct gotd_ref_update
*ref_update
, struct gotd_imsgev
*iev
)
1544 struct gotd_imsg_ref_update iref
;
1545 const char *refname
= got_ref_get_name(ref_update
->ref
);
1549 memset(&iref
, 0, sizeof(iref
));
1550 memcpy(iref
.old_id
, ref_update
->old_id
.hash
, SHA1_DIGEST_LENGTH
);
1551 memcpy(iref
.new_id
, ref_update
->new_id
.hash
, SHA1_DIGEST_LENGTH
);
1552 iref
.ref_is_new
= ref_update
->ref_is_new
;
1553 iref
.delete_ref
= ref_update
->delete_ref
;
1554 iref
.name_len
= strlen(refname
);
1556 len
= sizeof(iref
) + iref
.name_len
;
1557 wbuf
= imsg_create(&iev
->ibuf
, GOTD_IMSG_REF_UPDATE
, PROC_REPO_WRITE
,
1558 repo_write
.pid
, len
);
1560 return got_error_from_errno("imsg_create REF_UPDATE");
1562 if (imsg_add(wbuf
, &iref
, sizeof(iref
)) == -1)
1563 return got_error_from_errno("imsg_add REF_UPDATE");
1564 if (imsg_add(wbuf
, refname
, iref
.name_len
) == -1)
1565 return got_error_from_errno("imsg_add REF_UPDATE");
1567 imsg_close(&iev
->ibuf
, wbuf
);
1569 gotd_imsg_event_add(iev
);
1573 static const struct got_error
*
1574 update_refs(struct gotd_imsgev
*iev
)
1576 const struct got_error
*err
= NULL
;
1577 struct repo_write_client
*client
= &repo_write_client
;
1578 struct gotd_ref_update
*ref_update
;
1580 err
= send_ref_updates_start(client
->nref_updates
, iev
);
1584 STAILQ_FOREACH(ref_update
, &client
->ref_updates
, entry
) {
1585 err
= send_ref_update(ref_update
, iev
);
1593 static const struct got_error
*
1594 receive_pack_pipe(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1596 struct repo_write_client
*client
= &repo_write_client
;
1599 log_debug("receiving pack pipe descriptor");
1601 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1603 return got_error(GOT_ERR_PRIVSEP_LEN
);
1605 if (client
->pack_pipe
!= -1)
1606 return got_error(GOT_ERR_PRIVSEP_MSG
);
1608 client
->pack_pipe
= imsg_get_fd(imsg
);
1609 if (client
->pack_pipe
== -1)
1610 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1615 static const struct got_error
*
1616 receive_pack_idx(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
1618 struct repo_write_client
*client
= &repo_write_client
;
1621 log_debug("receiving pack index output file");
1623 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
1625 return got_error(GOT_ERR_PRIVSEP_LEN
);
1627 if (client
->packidx_fd
!= -1)
1628 return got_error(GOT_ERR_PRIVSEP_MSG
);
1630 client
->packidx_fd
= imsg_get_fd(imsg
);
1631 if (client
->packidx_fd
== -1)
1632 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
1637 static const struct got_error
*
1638 notify_removed_ref(const char *refname
, struct got_object_id
*id
,
1639 struct gotd_imsgev
*iev
, int fd
)
1641 const struct got_error
*err
;
1644 err
= got_object_id_str(&id_str
, id
);
1648 dprintf(fd
, "Removed %s: %s\n", refname
, id_str
);
1654 format_author(char *author
)
1658 smallerthan
= strchr(author
, '<');
1659 if (smallerthan
&& smallerthan
[1] != '\0')
1660 author
= smallerthan
+ 1;
1661 author
[strcspn(author
, "@>")] = '\0';
1666 static const struct got_error
*
1667 print_commit_oneline(struct got_commit_object
*commit
, struct got_object_id
*id
,
1668 struct got_repository
*repo
, int fd
)
1670 const struct got_error
*err
= NULL
;
1671 char *id_str
= NULL
, *logmsg0
= NULL
;
1673 char *committer
= NULL
, *author
= NULL
;
1674 time_t committer_time
;
1676 err
= got_object_id_str(&id_str
, id
);
1680 committer_time
= got_object_commit_get_committer_time(commit
);
1682 err
= got_object_commit_get_logmsg(&logmsg0
, commit
);
1687 while (isspace((unsigned char)s
[0]))
1690 nl
= strchr(s
, '\n');
1695 if (strcmp(got_object_commit_get_author(commit
),
1696 got_object_commit_get_committer(commit
)) != 0) {
1697 author
= strdup(got_object_commit_get_author(commit
));
1698 if (author
== NULL
) {
1699 err
= got_error_from_errno("strdup");
1702 dprintf(fd
, "%lld %.7s %.8s %s\n", (long long)committer_time
,
1703 id_str
, format_author(author
), s
);
1705 committer
= strdup(got_object_commit_get_committer(commit
));
1706 dprintf(fd
, "%lld %.7s %.8s %s\n", (long long)committer_time
,
1707 id_str
, format_author(committer
), s
);
1710 if (fsync(fd
) == -1 && err
== NULL
)
1711 err
= got_error_from_errno("fsync");
1720 static const struct got_error
*
1721 print_diffstat(struct got_diffstat_cb_arg
*dsa
, int fd
)
1723 struct got_pathlist_entry
*pe
;
1725 RB_FOREACH(pe
, got_pathlist_head
, dsa
->paths
) {
1726 struct got_diff_changed_path
*cp
= pe
->data
;
1727 int pad
= dsa
->max_path_len
- pe
->path_len
+ 1;
1729 dprintf(fd
, " %c %s%*c | %*d+ %*d-\n", cp
->status
,
1730 pe
->path
, pad
, ' ', dsa
->add_cols
+ 1, cp
->add
,
1731 dsa
->rm_cols
+ 1, cp
->rm
);
1734 "\n%d file%s changed, %d insertion%s(+), %d deletion%s(-)\n\n",
1735 dsa
->nfiles
, dsa
->nfiles
> 1 ? "s" : "", dsa
->ins
,
1736 dsa
->ins
!= 1 ? "s" : "", dsa
->del
, dsa
->del
!= 1 ? "s" : "");
1741 static const struct got_error
*
1742 print_commit(struct got_commit_object
*commit
, struct got_object_id
*id
,
1743 struct got_repository
*repo
, struct got_pathlist_head
*changed_paths
,
1744 struct got_diffstat_cb_arg
*diffstat
, int fd
)
1746 const struct got_error
*err
= NULL
;
1747 char *id_str
, *logmsg0
, *logmsg
, *line
;
1748 time_t committer_time
;
1749 const char *author
, *committer
;
1751 err
= got_object_id_str(&id_str
, id
);
1755 dprintf(fd
, "commit %s\n", id_str
);
1758 dprintf(fd
, "from: %s\n", got_object_commit_get_author(commit
));
1759 author
= got_object_commit_get_author(commit
);
1760 committer
= got_object_commit_get_committer(commit
);
1761 if (strcmp(author
, committer
) != 0)
1762 dprintf(fd
, "via: %s\n", committer
);
1763 committer_time
= got_object_commit_get_committer_time(commit
);
1764 dprintf(fd
, "date: %lld\n", (long long)committer_time
);
1765 if (got_object_commit_get_nparents(commit
) > 1) {
1766 const struct got_object_id_queue
*parent_ids
;
1767 struct got_object_qid
*qid
;
1769 parent_ids
= got_object_commit_get_parent_ids(commit
);
1770 STAILQ_FOREACH(qid
, parent_ids
, entry
) {
1771 err
= got_object_id_str(&id_str
, &qid
->id
);
1774 dprintf(fd
, "parent %d: %s\n", n
++, id_str
);
1780 err
= got_object_commit_get_logmsg(&logmsg0
, commit
);
1784 dprintf(fd
, "messagelen: %zu\n", strlen(logmsg0
));
1788 line
= strsep(&logmsg
, "\n");
1790 dprintf(fd
, " %s\n", line
);
1794 err
= print_diffstat(diffstat
, fd
);
1798 if (fsync(fd
) == -1 && err
== NULL
)
1799 err
= got_error_from_errno("fsync");
1805 static const struct got_error
*
1806 get_changed_paths(struct got_pathlist_head
*paths
,
1807 struct got_commit_object
*commit
, struct got_repository
*repo
,
1808 struct got_diffstat_cb_arg
*dsa
)
1810 const struct got_error
*err
= NULL
;
1811 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
1812 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
1813 struct got_object_qid
*qid
;
1814 got_diff_blob_cb cb
= got_diff_tree_collect_changed_paths
;
1815 FILE *f1
= repo_write
.diff
.f1
, *f2
= repo_write
.diff
.f2
;
1816 int fd1
= repo_write
.diff
.fd1
, fd2
= repo_write
.diff
.fd2
;
1819 cb
= got_diff_tree_compute_diffstat
;
1821 err
= got_opentemp_truncate(f1
);
1824 err
= got_opentemp_truncate(f2
);
1827 err
= got_opentemp_truncatefd(fd1
);
1830 err
= got_opentemp_truncatefd(fd2
);
1834 qid
= STAILQ_FIRST(got_object_commit_get_parent_ids(commit
));
1836 struct got_commit_object
*pcommit
;
1837 err
= got_object_open_as_commit(&pcommit
, repo
,
1842 tree_id1
= got_object_id_dup(
1843 got_object_commit_get_tree_id(pcommit
));
1844 if (tree_id1
== NULL
) {
1845 got_object_commit_close(pcommit
);
1846 return got_error_from_errno("got_object_id_dup");
1848 got_object_commit_close(pcommit
);
1853 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
1858 tree_id2
= got_object_commit_get_tree_id(commit
);
1859 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
1863 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
1864 cb
, dsa
? (void *)dsa
: paths
, dsa
? 1 : 0);
1867 got_object_tree_close(tree1
);
1869 got_object_tree_close(tree2
);
1874 static const struct got_error
*
1875 print_commits(struct got_object_id
*root_id
, struct got_object_id
*end_id
,
1876 struct got_repository
*repo
, int fd
)
1878 const struct got_error
*err
;
1879 struct got_commit_graph
*graph
;
1880 struct got_object_id_queue reversed_commits
;
1881 struct got_object_qid
*qid
;
1882 struct got_commit_object
*commit
= NULL
;
1883 struct got_pathlist_head changed_paths
;
1885 const int shortlog_threshold
= 50;
1887 STAILQ_INIT(&reversed_commits
);
1888 RB_INIT(&changed_paths
);
1890 /* XXX first-parent only for now */
1891 err
= got_commit_graph_open(&graph
, "/", 1);
1894 err
= got_commit_graph_bfsort(graph
, root_id
, repo
,
1895 check_cancelled
, NULL
);
1899 struct got_object_id id
;
1901 err
= got_commit_graph_iter_next(&id
, graph
, repo
,
1902 check_cancelled
, NULL
);
1904 if (err
->code
== GOT_ERR_ITER_COMPLETED
)
1909 err
= got_object_open_as_commit(&commit
, repo
, &id
);
1913 if (end_id
&& got_object_id_cmp(&id
, end_id
) == 0)
1916 err
= got_object_qid_alloc(&qid
, &id
);
1920 STAILQ_INSERT_HEAD(&reversed_commits
, qid
, entry
);
1922 got_object_commit_close(commit
);
1928 STAILQ_FOREACH(qid
, &reversed_commits
, entry
) {
1929 struct got_diffstat_cb_arg dsa
= { 0, 0, 0, 0, 0, 0,
1930 &changed_paths
, 0, 0, GOT_DIFF_ALGORITHM_PATIENCE
};
1932 err
= got_object_open_as_commit(&commit
, repo
, &qid
->id
);
1936 if (ncommits
> shortlog_threshold
) {
1937 err
= print_commit_oneline(commit
, &qid
->id
,
1942 err
= get_changed_paths(&changed_paths
, commit
,
1946 err
= print_commit(commit
, &qid
->id
, repo
,
1947 &changed_paths
, &dsa
, fd
);
1949 got_object_commit_close(commit
);
1951 got_pathlist_free(&changed_paths
, GOT_PATHLIST_FREE_ALL
);
1955 got_object_commit_close(commit
);
1956 while (!STAILQ_EMPTY(&reversed_commits
)) {
1957 qid
= STAILQ_FIRST(&reversed_commits
);
1958 STAILQ_REMOVE_HEAD(&reversed_commits
, entry
);
1959 got_object_qid_free(qid
);
1961 got_pathlist_free(&changed_paths
, GOT_PATHLIST_FREE_ALL
);
1962 got_commit_graph_close(graph
);
1966 static const struct got_error
*
1967 print_tag(struct got_object_id
*id
,
1968 const char *refname
, struct got_repository
*repo
, int fd
)
1970 const struct got_error
*err
= NULL
;
1971 struct got_tag_object
*tag
= NULL
;
1972 const char *tagger
= NULL
;
1973 char *id_str
= NULL
, *tagmsg0
= NULL
, *tagmsg
, *line
;
1976 err
= got_object_open_as_tag(&tag
, repo
, id
);
1980 tagger
= got_object_tag_get_tagger(tag
);
1981 tagger_time
= got_object_tag_get_tagger_time(tag
);
1982 err
= got_object_id_str(&id_str
,
1983 got_object_tag_get_object_id(tag
));
1987 dprintf(fd
, "tag %s\n", refname
);
1988 dprintf(fd
, "from: %s\n", tagger
);
1989 dprintf(fd
, "date: %lld\n", (long long)tagger_time
);
1991 switch (got_object_tag_get_object_type(tag
)) {
1992 case GOT_OBJ_TYPE_BLOB
:
1993 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_BLOB
, id_str
);
1995 case GOT_OBJ_TYPE_TREE
:
1996 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_TREE
, id_str
);
1998 case GOT_OBJ_TYPE_COMMIT
:
1999 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_COMMIT
, id_str
);
2001 case GOT_OBJ_TYPE_TAG
:
2002 dprintf(fd
, "object: %s %s\n", GOT_OBJ_LABEL_TAG
, id_str
);
2008 tagmsg0
= strdup(got_object_tag_get_message(tag
));
2009 if (tagmsg0
== NULL
) {
2010 err
= got_error_from_errno("strdup");
2014 dprintf(fd
, "messagelen: %zu\n", strlen(tagmsg0
));
2018 line
= strsep(&tagmsg
, "\n");
2020 dprintf(fd
, " %s\n", line
);
2025 got_object_tag_close(tag
);
2030 static const struct got_error
*
2031 notify_changed_ref(const char *refname
, struct got_object_id
*old_id
,
2032 struct got_object_id
*new_id
, struct gotd_imsgev
*iev
, int fd
)
2034 const struct got_error
*err
;
2035 int old_obj_type
, new_obj_type
;
2037 char *new_id_str
= NULL
;
2039 err
= got_object_get_type(&old_obj_type
, repo_write
.repo
, old_id
);
2043 err
= got_object_get_type(&new_obj_type
, repo_write
.repo
, new_id
);
2047 switch (new_obj_type
) {
2048 case GOT_OBJ_TYPE_COMMIT
:
2049 err
= print_commits(new_id
,
2050 old_obj_type
== GOT_OBJ_TYPE_COMMIT
? old_id
: NULL
,
2051 repo_write
.repo
, fd
);
2053 case GOT_OBJ_TYPE_TAG
:
2054 err
= print_tag(new_id
, refname
, repo_write
.repo
, fd
);
2057 err
= got_object_type_label(&label
, new_obj_type
);
2060 err
= got_object_id_str(&new_id_str
, new_id
);
2063 dprintf(fd
, "%s: %s object %s\n", refname
, label
, new_id_str
);
2071 static const struct got_error
*
2072 notify_created_ref(const char *refname
, struct got_object_id
*id
,
2073 struct gotd_imsgev
*iev
, int fd
)
2075 const struct got_error
*err
;
2078 err
= got_object_get_type(&obj_type
, repo_write
.repo
, id
);
2082 if (obj_type
== GOT_OBJ_TYPE_TAG
)
2083 return print_tag(id
, refname
, repo_write
.repo
, fd
);
2085 return print_commits(id
, NULL
, repo_write
.repo
, fd
);
2088 static const struct got_error
*
2089 render_notification(struct imsg
*imsg
, struct gotd_imsgev
*iev
)
2091 const struct got_error
*err
= NULL
;
2092 struct gotd_imsg_notification_content ireq
;
2093 size_t datalen
, len
;
2094 char *refname
= NULL
;
2098 fd
= imsg_get_fd(imsg
);
2100 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
2102 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2103 if (datalen
< sizeof(ireq
)) {
2104 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2108 memcpy(&ireq
, imsg
->data
, sizeof(ireq
));
2110 if (datalen
!= sizeof(ireq
) + ireq
.refname_len
) {
2111 err
= got_error(GOT_ERR_PRIVSEP_LEN
);
2115 refname
= strndup(imsg
->data
+ sizeof(ireq
), ireq
.refname_len
);
2116 if (refname
== NULL
) {
2117 err
= got_error_from_errno("strndup");
2121 switch (ireq
.action
) {
2122 case GOTD_NOTIF_ACTION_CREATED
:
2123 err
= notify_created_ref(refname
, &ireq
.new_id
, iev
, fd
);
2125 case GOTD_NOTIF_ACTION_REMOVED
:
2126 err
= notify_removed_ref(refname
, &ireq
.old_id
, iev
, fd
);
2128 case GOTD_NOTIF_ACTION_CHANGED
:
2129 err
= notify_changed_ref(refname
, &ireq
.old_id
, &ireq
.new_id
,
2136 if (fsync(fd
) == -1) {
2137 err
= got_error_from_errno("fsync");
2141 len
= sizeof(ireq
) + ireq
.refname_len
;
2142 wbuf
= imsg_create(&iev
->ibuf
, GOTD_IMSG_NOTIFY
, PROC_REPO_WRITE
,
2143 repo_write
.pid
, len
);
2145 err
= got_error_from_errno("imsg_create REF");
2148 if (imsg_add(wbuf
, &ireq
, sizeof(ireq
)) == -1) {
2149 err
= got_error_from_errno("imsg_add NOTIFY");
2152 if (imsg_add(wbuf
, refname
, ireq
.refname_len
) == -1) {
2153 err
= got_error_from_errno("imsg_add NOTIFY");
2157 imsg_close(&iev
->ibuf
, wbuf
);
2158 gotd_imsg_event_add(iev
);
2161 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
2162 err
= got_error_from_errno("close");
2167 repo_write_dispatch_session(int fd
, short event
, void *arg
)
2169 const struct got_error
*err
= NULL
;
2170 struct gotd_imsgev
*iev
= arg
;
2171 struct imsgbuf
*ibuf
= &iev
->ibuf
;
2173 struct repo_write_client
*client
= &repo_write_client
;
2175 int shut
= 0, have_packfile
= 0;
2177 if (event
& EV_READ
) {
2178 if ((n
= imsgbuf_read(ibuf
)) == -1)
2179 fatal("imsgbuf_read error");
2180 if (n
== 0) /* Connection closed. */
2184 if (event
& EV_WRITE
) {
2185 err
= gotd_imsg_flush(ibuf
);
2187 fatalx("%s", err
->msg
);
2191 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
2192 fatal("%s: imsg_get error", __func__
);
2193 if (n
== 0) /* No more messages. */
2196 if (imsg
.hdr
.type
!= GOTD_IMSG_LIST_REFS_INTERNAL
&&
2197 !repo_write
.refs_listed
) {
2198 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2202 switch (imsg
.hdr
.type
) {
2203 case GOTD_IMSG_LIST_REFS_INTERNAL
:
2204 err
= list_refs(&imsg
);
2206 log_warnx("ls-refs: %s", err
->msg
);
2208 case GOTD_IMSG_REF_UPDATE
:
2209 err
= recv_ref_update(&imsg
);
2211 log_warnx("ref-update: %s", err
->msg
);
2213 case GOTD_IMSG_PACKFILE_PIPE
:
2214 err
= receive_pack_pipe(&imsg
, iev
);
2216 log_warnx("receiving pack pipe: %s", err
->msg
);
2220 case GOTD_IMSG_PACKIDX_FILE
:
2221 err
= receive_pack_idx(&imsg
, iev
);
2223 log_warnx("receiving pack index: %s",
2228 case GOTD_IMSG_RECV_PACKFILE
:
2229 err
= protect_refs_from_deletion();
2232 err
= recv_packfile(&have_packfile
, &imsg
);
2234 log_warnx("receive packfile: %s", err
->msg
);
2237 if (have_packfile
) {
2238 err
= verify_packfile();
2240 log_warnx("verify packfile: %s",
2244 err
= install_packfile(iev
);
2246 log_warnx("install packfile: %s",
2251 * Ensure we re-read the pack index list
2254 repo_write
.repo
->pack_path_mtime
.tv_sec
= 0;
2255 repo_write
.repo
->pack_path_mtime
.tv_nsec
= 0;
2257 err
= update_refs(iev
);
2259 log_warnx("update refs: %s", err
->msg
);
2262 case GOTD_IMSG_NOTIFY
:
2263 err
= render_notification(&imsg
, iev
);
2265 log_warnx("render notification: %s", err
->msg
);
2270 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
2277 if (!shut
&& check_cancelled(NULL
) == NULL
) {
2279 gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
2280 client
->id
, err
) == -1) {
2281 log_warnx("could not send error to parent: %s",
2284 gotd_imsg_event_add(iev
);
2286 /* This pipe is dead. Remove its event handler */
2287 event_del(&iev
->ev
);
2288 event_loopexit(NULL
);
2292 static const struct got_error
*
2293 recv_connect(struct imsg
*imsg
)
2295 struct gotd_imsgev
*iev
= &repo_write
.session_iev
;
2298 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
2300 return got_error(GOT_ERR_PRIVSEP_LEN
);
2302 if (repo_write
.session_fd
!= -1)
2303 return got_error(GOT_ERR_PRIVSEP_MSG
);
2305 repo_write
.session_fd
= imsg_get_fd(imsg
);
2306 if (repo_write
.session_fd
== -1)
2307 return got_error(GOT_ERR_PRIVSEP_NO_FD
);
2309 if (imsgbuf_init(&iev
->ibuf
, repo_write
.session_fd
) == -1)
2310 return got_error_from_errno("imsgbuf_init");
2311 imsgbuf_allow_fdpass(&iev
->ibuf
);
2312 iev
->handler
= repo_write_dispatch_session
;
2313 iev
->events
= EV_READ
;
2314 iev
->handler_arg
= NULL
;
2315 event_set(&iev
->ev
, iev
->ibuf
.fd
, EV_READ
,
2316 repo_write_dispatch_session
, iev
);
2317 gotd_imsg_event_add(iev
);
2323 repo_write_dispatch(int fd
, short event
, void *arg
)
2325 const struct got_error
*err
= NULL
;
2326 struct gotd_imsgev
*iev
= arg
;
2327 struct imsgbuf
*ibuf
= &iev
->ibuf
;
2331 struct repo_write_client
*client
= &repo_write_client
;
2333 if (event
& EV_READ
) {
2334 if ((n
= imsgbuf_read(ibuf
)) == -1)
2335 fatal("imsgbuf_read error");
2336 if (n
== 0) { /* Connection closed. */
2342 if (event
& EV_WRITE
) {
2343 err
= gotd_imsg_flush(ibuf
);
2345 fatalx("%s", err
->msg
);
2348 while (err
== NULL
) {
2349 err
= check_cancelled(NULL
);
2352 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
2353 fatal("%s: imsg_get", __func__
);
2354 if (n
== 0) /* No more messages. */
2357 switch (imsg
.hdr
.type
) {
2358 case GOTD_IMSG_CONNECT_REPO_CHILD
:
2359 err
= recv_connect(&imsg
);
2362 log_debug("unexpected imsg %d", imsg
.hdr
.type
);
2363 err
= got_error(GOT_ERR_PRIVSEP_MSG
);
2370 if (err
&& gotd_imsg_send_error_event(iev
, PROC_REPO_WRITE
,
2371 client
->id
, err
) == -1)
2372 log_warnx("could not send error to parent: %s", err
->msg
);
2375 gotd_imsg_event_add(iev
);
2377 /* This pipe is dead. Remove its event handler */
2378 event_del(&iev
->ev
);
2379 event_loopexit(NULL
);
2384 repo_write_main(const char *title
, const char *repo_path
,
2385 int *pack_fds
, int *temp_fds
,
2386 FILE *diff_f1
, FILE *diff_f2
, int diff_fd1
, int diff_fd2
,
2387 struct got_pathlist_head
*protected_tag_namespaces
,
2388 struct got_pathlist_head
*protected_branch_namespaces
,
2389 struct got_pathlist_head
*protected_branches
)
2391 const struct got_error
*err
= NULL
;
2392 struct repo_write_client
*client
= &repo_write_client
;
2393 struct gotd_imsgev iev
;
2396 client
->pack_pipe
= -1;
2397 client
->packidx_fd
= -1;
2398 client
->pack
.fd
= -1;
2400 repo_write
.title
= title
;
2401 repo_write
.pid
= getpid();
2402 repo_write
.pack_fds
= pack_fds
;
2403 repo_write
.temp_fds
= temp_fds
;
2404 repo_write
.session_fd
= -1;
2405 repo_write
.session_iev
.ibuf
.fd
= -1;
2406 repo_write
.protected_tag_namespaces
= protected_tag_namespaces
;
2407 repo_write
.protected_branch_namespaces
= protected_branch_namespaces
;
2408 repo_write
.protected_branches
= protected_branches
;
2409 repo_write
.diff
.f1
= diff_f1
;
2410 repo_write
.diff
.f2
= diff_f2
;
2411 repo_write
.diff
.fd1
= diff_fd1
;
2412 repo_write
.diff
.fd2
= diff_fd2
;
2414 STAILQ_INIT(&repo_write_client
.ref_updates
);
2416 err
= got_repo_open(&repo_write
.repo
, repo_path
, NULL
, pack_fds
);
2419 if (!got_repo_is_bare(repo_write
.repo
)) {
2420 err
= got_error_msg(GOT_ERR_NOT_GIT_REPO
,
2421 "bare git repository required");
2424 if (got_repo_get_object_format(repo_write
.repo
) != GOT_HASH_SHA1
) {
2425 err
= got_error_msg(GOT_ERR_NOT_IMPL
,
2426 "sha256 object IDs unsupported in network protocol");
2430 got_repo_temp_fds_set(repo_write
.repo
, temp_fds
);
2432 signal(SIGINT
, catch_sigint
);
2433 signal(SIGTERM
, catch_sigterm
);
2434 signal(SIGPIPE
, SIG_IGN
);
2435 signal(SIGHUP
, SIG_IGN
);
2437 if (imsgbuf_init(&iev
.ibuf
, GOTD_FILENO_MSG_PIPE
) == -1) {
2438 err
= got_error_from_errno("imsgbuf_init");
2441 imsgbuf_allow_fdpass(&iev
.ibuf
);
2442 iev
.handler
= repo_write_dispatch
;
2443 iev
.events
= EV_READ
;
2444 iev
.handler_arg
= NULL
;
2445 event_set(&iev
.ev
, iev
.ibuf
.fd
, EV_READ
, repo_write_dispatch
, &iev
);
2446 if (gotd_imsg_compose_event(&iev
, GOTD_IMSG_REPO_CHILD_READY
,
2447 PROC_REPO_WRITE
, -1, NULL
, 0) == -1) {
2448 err
= got_error_from_errno("imsg compose REPO_CHILD_READY");
2454 if (fclose(diff_f1
) == EOF
&& err
== NULL
)
2455 err
= got_error_from_errno("fclose");
2456 if (fclose(diff_f2
) == EOF
&& err
== NULL
)
2457 err
= got_error_from_errno("fclose");
2458 if (close(diff_fd1
) == -1 && err
== NULL
)
2459 err
= got_error_from_errno("close");
2460 if (close(diff_fd2
) == -1 && err
== NULL
)
2461 err
= got_error_from_errno("close");
2463 log_warnx("%s: %s", title
, err
->msg
);
2464 repo_write_shutdown();
2468 repo_write_shutdown(void)
2470 struct repo_write_client
*client
= &repo_write_client
;
2471 struct gotd_ref_update
*ref_update
;
2473 log_debug("%s: shutting down", repo_write
.title
);
2475 while (!STAILQ_EMPTY(&client
->ref_updates
)) {
2476 ref_update
= STAILQ_FIRST(&client
->ref_updates
);
2477 STAILQ_REMOVE_HEAD(&client
->ref_updates
, entry
);
2478 got_ref_close(ref_update
->ref
);
2482 got_pack_close(&client
->pack
);
2483 if (client
->fd
!= -1)
2485 if (client
->pack_pipe
!= -1)
2486 close(client
->pack_pipe
);
2487 if (client
->packidx_fd
!= -1)
2488 close(client
->packidx_fd
);
2490 if (repo_write
.repo
)
2491 got_repo_close(repo_write
.repo
);
2492 got_repo_pack_fds_close(repo_write
.pack_fds
);
2493 got_repo_temp_fds_close(repo_write
.temp_fds
);
2494 if (repo_write
.session_fd
!= -1)
2495 close(repo_write
.session_fd
);