refs.c: remove impossible condition check from log_ref_write_fd

Fixup the lengths in log_ref_write_fd.

copy_msg will never return a length more than 2 greater than the length of
msg. The first byte that copy_msg copies will however be overwriting the
'\n' from the string generated by the sprintf which we have already accounted
for when padding maxlen with 83.
Thus we can initialize msglen to the length of msg plus 1 instead of plus 2.

Since msglen now provides the maximum size msg might be expanded to, we can
change the padding for maxlen from the arbitrary '100 bytes should be enough'
to 83: two sha1 values plus two spaces plus a '\n'.

Since len can never be greater than maxlen we do not need to check for that
condition.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: add a transaction function to append a reflog entry

Define a new transaction update type, UPDATE_LOG, and a new function
transaction_update_reflog. This function will lock the reflog and append
an entry to it during transaction commit.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: add a flag to allow reflog updates to truncate the log

Add a flag that allows us to truncate the reflog before we write the
update.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: only write reflog update if msg is non-NULL

When performing a reflog transaction update, only write to the reflog iff
msg is non-NULL. This can then be combined with REFLOG_TRUNCATE to perform
an update that only truncates but does not write.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: allow multiple reflog updates during a single transaction

Allow to make multiple reflog updates to the same ref during a transaction.
This means we only need to lock the reflog once, during the first update
that touches the reflog, and that all further updates can just write the
reflog entry since the reflog is already locked.

This allows us to write code such as:

t = transaction_begin()
transaction_reflog_update(t, "foo", REFLOG_TRUNCATE, NULL);
loop-over-somehting...
   transaction_reflog_update(t, "foo", 0, <message>);
transaction_commit(t)

where we first truncate the reflog and then build the new content one line at a
time.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
reflog.c: use a reflog transaction when writing during expire

Use a transaction for all updates during expire_reflog.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: rename log_ref_setup to create_reflog

log_ref_setup is used to do several semi-related things :
* sometimes it will create a new reflog including missing parent directories
  and cleaning up any conflicting stale directories in the path.
* fill in a filename buffer for the full path to the reflog.
* unconditionally re-adjust the permissions for the file.

This function is only called from two places: checkout.c where it is always
used to create a reflog and refs.c:log_ref_write where it sometimes are
used to create a reflog and sometimes just used to fill in the filename.

Rename log_ref_setup to create_reflog and change it to only take the
refname as argument to make its signature similar to delete_reflog and
reflog_exists. Change create_reflog to ignore log_all_ref_updates and
"unconditionally" create the reflog when called. Since checkout.c always
wants to create a reflog we can call create_reflog directly and avoid the
temp-and-log_all_ref_update dance.

In log_ref_write, only call create_reflog iff we want to create a reflog
and if the reflog does not yet exist. This means that for the common case
where we want to create a reflog which already exists we now only need to
perform a single lstat() to see that the log already exists instead of
performing, for every single update, a open(O_CREAT)+lstat()+close() thus
shaving off at least two system calls and saving several microseconds in the
process.

There is one behavior change in this patch. In the previous code we would
always unconditionally re-set the permission bits to 0660 in every call to
log_ref_setup, while we now only set the permissions when the file is initially
created.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: make unlock_ref/close_ref/commit_ref static

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
refs.c: remove lock_any_ref_for_update

No one is using this function so we can delete it.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>