diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2015-06-22 16:03:01 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-06-22 13:17:11 -0700 |
commit | 58f233ce1ed67bbc31a429fde5c65d5050fdbd7d (patch) | |
tree | 8f767c602864bd958f26d0870c56322f256dac11 /refs.c | |
parent | repack_without_refs(): make function private (diff) | |
download | tgif-58f233ce1ed67bbc31a429fde5c65d5050fdbd7d.tar.xz |
initial_ref_transaction_commit(): function for initial ref creation
"git clone" uses shortcuts when creating the initial set of
references:
* It writes them directly to packed-refs.
* It doesn't lock the individual references (though it does lock the
packed-refs file).
* It doesn't check for refname conflicts between two new references or
between one new reference and any hypothetical old ones.
* It doesn't create reflog entries for the reference creations.
This functionality was implemented in builtin/clone.c. But really that
file shouldn't have such intimate knowledge of how references are
stored. So provide a new function in the refs API,
initial_ref_transaction_commit(), which can be used for initial
reference creation. The new function is based on the ref_transaction
interface.
This means that we can make some other functions private to the refs
module. That will be done in a followup commit.
It would seem to make sense to add a test here that there are no
existing references, because that is how the function *should* be
used. But in fact, the "testgit" remote helper appears to call it
*after* having set up refs/remotes/<name>/HEAD and
refs/remotes/<name>/master, so we can't be so strict. For now, the
function trusts its caller to only call it when it makes sense. Future
commits will add some more limited sanity checks.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 47 |
1 files changed, 47 insertions, 0 deletions
@@ -4076,6 +4076,53 @@ cleanup: return ret; } +int initial_ref_transaction_commit(struct ref_transaction *transaction, + struct strbuf *err) +{ + int ret = 0, i; + int n = transaction->nr; + struct ref_update **updates = transaction->updates; + + assert(err); + + if (transaction->state != REF_TRANSACTION_OPEN) + die("BUG: commit called for transaction that is not open"); + + for (i = 0; i < n; i++) { + struct ref_update *update = updates[i]; + + if ((update->flags & REF_HAVE_OLD) && + !is_null_sha1(update->old_sha1)) + die("BUG: initial ref transaction with old_sha1 set"); + } + + if (lock_packed_refs(0)) { + strbuf_addf(err, "unable to lock packed-refs file: %s", + strerror(errno)); + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + + for (i = 0; i < n; i++) { + struct ref_update *update = updates[i]; + + if ((update->flags & REF_HAVE_NEW) && + !is_null_sha1(update->new_sha1)) + add_packed_ref(update->refname, update->new_sha1); + } + + if (commit_packed_refs()) { + strbuf_addf(err, "unable to commit packed-refs file: %s", + strerror(errno)); + ret = TRANSACTION_GENERIC_ERROR; + goto cleanup; + } + +cleanup: + transaction->state = REF_TRANSACTION_CLOSED; + return ret; +} + char *shorten_unambiguous_ref(const char *refname, int strict) { int i; |