diff options
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 28 |
1 files changed, 28 insertions, 0 deletions
@@ -3041,6 +3041,13 @@ static int write_ref_sha1(struct ref_lock *lock, errno = EINVAL; return -1; } + if (lock->lk->fd == -1 && reopen_lock_file(lock->lk) == -1) { + int save_errno = errno; + error("Couldn't reopen %s", lock->lk->filename.buf); + unlock_ref(lock); + errno = save_errno; + return -1; + } if (write_in_full(lock->lk->fd, sha1_to_hex(sha1), 40) != 40 || write_in_full(lock->lk->fd, &term, 1) != 1 || close_ref(lock) < 0) { @@ -3718,6 +3725,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, struct strbuf *err) { int ret = 0, i; + unsigned int remaining_fds; int n = transaction->nr; struct ref_update **updates = transaction->updates; struct string_list refs_to_delete = STRING_LIST_INIT_NODUP; @@ -3733,6 +3741,20 @@ int ref_transaction_commit(struct ref_transaction *transaction, return 0; } + /* + * We need to open many files in a large transaction, so come up with + * a reasonable maximum. We still keep some spares for stdin/out and + * other open files. Experiments determined we need more fds when + * running inside our test suite than directly in the shell. It's + * unclear where these fds come from. 25 should be a reasonable large + * number though. + */ + remaining_fds = get_max_fd_limit(); + if (remaining_fds > 25) + remaining_fds -= 25; + else + remaining_fds = 0; + /* Copy, sort, and reject duplicate refs */ qsort(updates, n, sizeof(*updates), ref_update_compare); if (ref_update_reject_duplicates(updates, n, err)) { @@ -3762,6 +3784,12 @@ int ref_transaction_commit(struct ref_transaction *transaction, update->refname); goto cleanup; } + if (!(flags & REF_HAVE_NEW) || + is_null_sha1(update->new_sha1) || + remaining_fds == 0) + close_lock_file(update->lock->lk); + else + remaining_fds--; } /* Perform updates first so live commits remain referenced */ |