Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refs: optimise writing unchanged refs #1120

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions dulwich/refs.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,24 +902,29 @@ def set_if_equals(
probe_ref = os.path.dirname(probe_ref)

ensure_dir_exists(os.path.dirname(filename))
with GitFile(filename, "wb") as f:
if old_ref is not None:
try:
# read again while holding the lock
orig_ref = self.read_loose_ref(realname)
if orig_ref is None:
orig_ref = self.get_packed_refs().get(realname, ZERO_SHA)
if orig_ref != old_ref:

# first, check if we need to write anything at all without
# acquiring the lock, which triggers a fs write, close and
# thus fsync()
if self.read_loose_ref(realname) != new_ref:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, what about the case where somebody else has the lock open? Previously you'd get a FileLocked error, but now the code would run fine.

Perhaps it's better to just do what we previously did but f.abort() if orig_ref == new_ref ? That way you'd still avoid the fsync() - and you'd avoid an extra read if things have changed.

with GitFile(filename, "wb") as f:
if old_ref is not None:
try:
# read again while holding the lock
orig_ref = self.read_loose_ref(realname)
if orig_ref is None:
orig_ref = self.get_packed_refs().get(realname, ZERO_SHA)
if orig_ref != old_ref:
f.abort()
return False
except OSError:
f.abort()
return False
raise
try:
f.write(new_ref + b"\n")
except OSError:
f.abort()
raise
try:
f.write(new_ref + b"\n")
except OSError:
f.abort()
raise
self._log(
realname,
old_ref,
Expand Down