2 * Copyright (c) 2023 Omar Polo <op@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>
20 #include <sys/types.h>
30 #include "got_error.h"
31 #include "got_cancel.h"
32 #include "got_reference.h"
33 #include "got_repository_admin.h" /* XXX for pack_progress */
34 #include "got_object.h"
35 #include "got_opentemp.h"
36 #include "got_repository_dump.h"
38 #include "got_lib_delta.h"
39 #include "got_lib_object.h"
40 #include "got_lib_object_idset.h"
41 #include "got_lib_ratelimit.h"
42 #include "got_lib_pack_create.h"
44 #define GIT_BUNDLE_SIGNATURE_V2 "# v2 git bundle"
47 struct got_object_id
**ids
;
52 static const struct got_error
*
53 idvec_push(struct idvec
*v
, struct got_object_id
*id
)
58 if (v
->len
== v
->size
) {
59 newsize
= v
->size
+ 8;
60 t
= reallocarray(v
->ids
, newsize
, sizeof(*v
->ids
));
62 return got_error_from_errno("reallocarray");
67 v
->ids
[v
->len
++] = id
;
72 idvec_free(struct idvec
*v
)
76 for (i
= 0; i
< v
->len
; ++i
)
81 const struct got_error
*
82 got_repo_dump(FILE *out
, struct got_reflist_head
*include_refs
,
83 struct got_reflist_head
*exclude_refs
, struct got_repository
*repo
,
84 got_pack_progress_cb progress_cb
, void *progress_arg
,
85 got_cancel_cb cancel_cb
, void *cancel_arg
)
87 const struct got_error
*err
= NULL
;
88 struct got_ratelimit rl
;
89 uint8_t packsha
[SHA1_DIGEST_LENGTH
];
90 FILE *delta_cache
= NULL
;
91 struct got_reflist_entry
*e
;
92 struct got_object_id
*id
= NULL
;
93 struct got_commit_object
*commit
= NULL
;
94 struct idvec ours
, theirs
;
95 char *nl
, *s
, *hex
, *logmsg
= NULL
;
99 got_ratelimit_init(&rl
, 0, 500);
101 memset(&ours
, 0, sizeof(ours
));
102 memset(&theirs
, 0, sizeof(theirs
));
104 r
= fprintf(out
, "%s\n", GIT_BUNDLE_SIGNATURE_V2
);
105 if (r
!= strlen(GIT_BUNDLE_SIGNATURE_V2
) + 1)
106 return got_ferror(out
, GOT_ERR_IO
);
108 TAILQ_FOREACH(e
, exclude_refs
, entry
) {
109 err
= got_ref_resolve(&id
, repo
, e
->ref
);
113 idvec_push(&theirs
, id
);
117 err
= got_object_open_as_commit(&commit
, repo
, id
);
121 err
= got_object_commit_get_logmsg(&logmsg
, commit
);
126 while (isspace((unsigned char)*s
))
128 nl
= strchr(s
, '\n');
132 err
= got_object_id_str(&hex
, id
);
135 fprintf(out
, "-%s %s\n", hex
, s
);
138 got_object_commit_close(commit
);
145 TAILQ_FOREACH(e
, include_refs
, entry
) {
146 err
= got_ref_resolve(&id
, repo
, e
->ref
);
150 err
= idvec_push(&ours
, id
);
154 refname
= got_ref_get_name(e
->ref
);
156 err
= got_object_id_str(&hex
, id
);
159 fprintf(out
, "%s %s\n", hex
, refname
);
163 if (fputc('\n', out
) == EOF
|| fflush(out
) == EOF
) {
164 err
= got_ferror(out
, GOT_ERR_IO
);
168 delta_cache
= got_opentemp();
169 if (delta_cache
== NULL
) {
170 err
= got_error_from_errno("got_opentemp");
174 err
= got_pack_create(&packsha
[0], fileno(out
), delta_cache
,
175 theirs
.ids
, theirs
.len
, ours
.ids
, ours
.len
,
176 repo
, 0, 0, 0, progress_cb
, progress_arg
, &rl
,
177 cancel_cb
, cancel_arg
);
183 got_object_commit_close(commit
);
184 if (delta_cache
&& fclose(delta_cache
) == EOF
&& err
== NULL
)
185 err
= got_error_from_errno("fclose");