summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2014-09-26 14:39:42 -0700
committerJunio C Hamano <gitster@pobox.com>2014-09-26 14:39:42 -0700
commit69a5bbbbfa2c659e819228c5e3cd5caa1d7f9a0b (patch)
treee1d2bc19ea9f13d5288e3509ab0d56e0cb2b1117 /refs.c
parent97b8860c071898d9e162678ea1035a8ced2f8b1f (diff)
parent9540ce5030853ffbb7e11c30aa59a5e45095d32c (diff)
downloadgit-69a5bbbbfa2c659e819228c5e3cd5caa1d7f9a0b.tar.gz
Merge branch 'jk/write-packed-refs-via-stdio'
Optimize the code path to write out the packed-refs file, which especially matters in a repository with a large number of refs. * jk/write-packed-refs-via-stdio: refs: write packed_refs file using stdio
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c39
1 files changed, 16 insertions, 23 deletions
diff --git a/refs.c b/refs.c
index 2ce5d69090..6378c98295 100644
--- a/refs.c
+++ b/refs.c
@@ -2190,25 +2190,12 @@ struct ref_lock *lock_any_ref_for_update(const char *refname,
* Write an entry to the packed-refs file for the specified refname.
* If peeled is non-NULL, write it as the entry's peeled value.
*/
-static void write_packed_entry(int fd, char *refname, unsigned char *sha1,
+static void write_packed_entry(FILE *fh, char *refname, unsigned char *sha1,
unsigned char *peeled)
{
- char line[PATH_MAX + 100];
- int len;
-
- len = snprintf(line, sizeof(line), "%s %s\n",
- sha1_to_hex(sha1), refname);
- /* this should not happen but just being defensive */
- if (len > sizeof(line))
- die("too long a refname '%s'", refname);
- write_or_die(fd, line, len);
-
- if (peeled) {
- if (snprintf(line, sizeof(line), "^%s\n",
- sha1_to_hex(peeled)) != PEELED_LINE_LENGTH)
- die("internal error");
- write_or_die(fd, line, PEELED_LINE_LENGTH);
- }
+ fprintf_or_die(fh, "%s %s\n", sha1_to_hex(sha1), refname);
+ if (peeled)
+ fprintf_or_die(fh, "^%s\n", sha1_to_hex(peeled));
}
/*
@@ -2216,13 +2203,12 @@ static void write_packed_entry(int fd, char *refname, unsigned char *sha1,
*/
static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data)
{
- int *fd = cb_data;
enum peel_status peel_status = peel_entry(entry, 0);
if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG)
error("internal error: %s is not a valid packed reference!",
entry->name);
- write_packed_entry(*fd, entry->name, entry->u.value.sha1,
+ write_packed_entry(cb_data, entry->name, entry->u.value.sha1,
peel_status == PEEL_PEELED ?
entry->u.value.peeled : NULL);
return 0;
@@ -2258,15 +2244,22 @@ int commit_packed_refs(void)
get_packed_ref_cache(&ref_cache);
int error = 0;
int save_errno = 0;
+ FILE *out;
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
- write_or_die(packed_ref_cache->lock->fd,
- PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER));
+ out = fdopen(packed_ref_cache->lock->fd, "w");
+ if (!out)
+ die_errno("unable to fdopen packed-refs descriptor");
+
+ fprintf_or_die(out, "%s", PACKED_REFS_HEADER);
do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache),
- 0, write_packed_entry_fn,
- &packed_ref_cache->lock->fd);
+ 0, write_packed_entry_fn, out);
+ if (fclose(out))
+ die_errno("write error");
+ packed_ref_cache->lock->fd = -1;
+
if (commit_lock_file(packed_ref_cache->lock)) {
save_errno = errno;
error = -1;