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.h"
34 #include "got_repository_admin.h" /* XXX for pack_progress */
35 #include "got_object.h"
36 #include "got_opentemp.h"
37 #include "got_repository_dump.h"
39 #include "got_lib_delta.h"
40 #include "got_lib_hash.h"
41 #include "got_lib_object.h"
42 #include "got_lib_object_idset.h"
43 #include "got_lib_ratelimit.h"
44 #include "got_lib_pack_create.h"
46 #define GIT_BUNDLE_SIGNATURE_V2 "# v2 git bundle"
47 #define GIT_BUNDLE_SIGNATURE_V3 "# v3 git bundle"
50 struct got_object_id
**ids
;
55 static const struct got_error
*
56 idvec_push(struct idvec
*v
, struct got_object_id
*id
)
61 if (v
->len
== v
->size
) {
62 newsize
= v
->size
+ 8;
63 t
= reallocarray(v
->ids
, newsize
, sizeof(*v
->ids
));
65 return got_error_from_errno("reallocarray");
70 v
->ids
[v
->len
++] = id
;
75 idvec_free(struct idvec
*v
)
79 for (i
= 0; i
< v
->len
; ++i
)
84 const struct got_error
*
85 got_repo_dump(FILE *out
, struct got_reflist_head
*include_refs
,
86 struct got_reflist_head
*exclude_refs
, struct got_repository
*repo
,
87 got_pack_progress_cb progress_cb
, void *progress_arg
,
88 got_cancel_cb cancel_cb
, void *cancel_arg
)
90 const struct got_error
*err
= NULL
;
91 struct got_ratelimit rl
;
92 struct got_object_id packhash
;
93 FILE *delta_cache
= NULL
;
94 struct got_reflist_entry
*e
;
95 struct got_object_id
*id
= NULL
;
96 struct got_commit_object
*commit
= NULL
;
97 struct idvec ours
, theirs
;
98 char *nl
, *s
, *hex
, *logmsg
= NULL
;
99 const char *refname
, *signature
;
100 enum got_hash_algorithm algo
;
103 algo
= got_repo_get_object_format(repo
);
106 signature
= GIT_BUNDLE_SIGNATURE_V2
;
108 case GOT_HASH_SHA256
:
109 signature
= GIT_BUNDLE_SIGNATURE_V3
;
112 return got_error(GOT_ERR_OBJECT_FORMAT
);
115 got_ratelimit_init(&rl
, 0, 500);
117 memset(&ours
, 0, sizeof(ours
));
118 memset(&theirs
, 0, sizeof(theirs
));
120 r
= fprintf(out
, "%s\n", signature
);
121 if (r
!= strlen(GIT_BUNDLE_SIGNATURE_V2
) + 1)
122 return got_ferror(out
, GOT_ERR_IO
);
124 if (algo
== GOT_HASH_SHA256
)
125 fprintf(out
, "@object-format=sha256\n");
127 TAILQ_FOREACH(e
, exclude_refs
, entry
) {
128 err
= got_ref_resolve(&id
, repo
, e
->ref
);
132 idvec_push(&theirs
, id
);
136 err
= got_object_open_as_commit(&commit
, repo
, id
);
140 err
= got_object_commit_get_logmsg(&logmsg
, commit
);
145 while (isspace((unsigned char)*s
))
147 nl
= strchr(s
, '\n');
151 err
= got_object_id_str(&hex
, id
);
154 fprintf(out
, "-%s %s\n", hex
, s
);
157 got_object_commit_close(commit
);
164 TAILQ_FOREACH(e
, include_refs
, entry
) {
165 err
= got_ref_resolve(&id
, repo
, e
->ref
);
169 err
= idvec_push(&ours
, id
);
173 refname
= got_ref_get_name(e
->ref
);
175 err
= got_object_id_str(&hex
, id
);
178 fprintf(out
, "%s %s\n", hex
, refname
);
182 if (fputc('\n', out
) == EOF
|| fflush(out
) == EOF
) {
183 err
= got_ferror(out
, GOT_ERR_IO
);
187 delta_cache
= got_opentemp();
188 if (delta_cache
== NULL
) {
189 err
= got_error_from_errno("got_opentemp");
193 err
= got_pack_create(&packhash
, fileno(out
), delta_cache
,
194 theirs
.ids
, theirs
.len
, ours
.ids
, ours
.len
,
195 repo
, 0, 0, 0, progress_cb
, progress_arg
, &rl
,
196 cancel_cb
, cancel_arg
);
202 got_object_commit_close(commit
);
203 if (delta_cache
&& fclose(delta_cache
) == EOF
&& err
== NULL
)
204 err
= got_error_from_errno("fclose");