Could you explain s/sha1/NULL/ here in the proposed log message?
Good question.
Passing sha1 to delete_ref() doesn't add any safety, because the same
sha1 was just read a moment before, and it is not used for anything
else. So the check only protects us from a concurrent update to
newrefname between the call to read_ref_full() and the call to
delete_ref(). But such a race is indistinguishable from the case that a
modification to newrefname happens just before the call to
read_ref_full(), which would have the same outcome as the new code. So
the "sha1" check only adds ways for the rename() to fail in situations
where nothing harmful would have happened anyway.
That being said, this is a very unlikely race, and I don't think it
matters much either way. In any case, the change s/sha1/NULL/ here seems
orthogonal to the rest of the patch.
David, you wrote the original version of this patch. Am I overlooking
something?
Michael
Could you explain s/sha1/NULL/ here in the proposed log message?
Good question.
Passing sha1 to delete_ref() doesn't add any safety, because the same
sha1 was just read a moment before, and it is not used for anything
else. So the check only protects us from a concurrent update to
newrefname between the call to read_ref_full() and the call to
delete_ref(). But such a race is indistinguishable from the case that
a
modification to newrefname happens just before the call to
read_ref_full(), which would have the same outcome as the new code.
So
the "sha1" check only adds ways for the rename() to fail in
situations
where nothing harmful would have happened anyway.
That being said, this is a very unlikely race, and I don't think it
matters much either way. In any case, the change s/sha1/NULL/ here
seems
orthogonal to the rest of the patch.
David, you wrote the original version of this patch. Am I overlooking
something?
I think I might have been handling some weird case related to symbolic
refs, but I don't recall the details. Your argument seems right to me.
Could you explain s/sha1/NULL/ here in the proposed log message?
Good question.
Passing sha1 to delete_ref() doesn't add any safety, because the same
sha1 was just read a moment before, and it is not used for anything
else. So the check only protects us from a concurrent update to
newrefname between the call to read_ref_full() and the call to
delete_ref(). But such a race is indistinguishable from the case that
a
modification to newrefname happens just before the call to
read_ref_full(), which would have the same outcome as the new code.
So
the "sha1" check only adds ways for the rename() to fail in
situations
where nothing harmful would have happened anyway.
That being said, this is a very unlikely race, and I don't think it
matters much either way. In any case, the change s/sha1/NULL/ here
seems
orthogonal to the rest of the patch.
David, you wrote the original version of this patch. Am I overlooking
something?
I think I might have been handling some weird case related to symbolic
refs, but I don't recall the details. Your argument seems right to me.
Doh, of course. I should have just changed it back to `sha1` and run the
test suite, then I would have seen the failure...
The point is that `read_ref_full()` is now called with
`RESOLVE_REF_NO_RECURSE` turned on. So if `newrefname` is a symbolic
reference, then `read_ref_full()` sets `sha1` to zeros. But the
pre-check for `delete_ref()` compares `old_sha1` to the recursively
resolved value of the reference, so that check would fail. (In fact,
`ref_transaction_delete()` refuses even to add the deletion to the
transaction if `old_sha1` is zeros, so it doesn't even get that far.)
So for shallow technical reasons we can't pass `sha1` to `delete_ref()`
anymore, and for the deeper reasons discussed in this thread that's not
a problem.
I'll document this in v2 of this patch.
Michael