<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/refs.c, branch v2.15.2</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v2.15.2</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v2.15.2'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2017-10-07T01:32:13Z</updated>
<entry>
<title>refs_resolve_ref_unsafe: handle d/f conflicts for writes</title>
<updated>2017-10-07T01:32:13Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2017-10-06T14:42:17Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=a1c1d8170dbc4a108dd2c05d2f93049d49e61328'/>
<id>urn:sha1:a1c1d8170dbc4a108dd2c05d2f93049d49e61328</id>
<content type='text'>
If our call to refs_read_raw_ref() fails, we check errno to
see if the ref is simply missing, or if we encountered a
more serious error. If it's just missing, then in "write"
mode (i.e., when RESOLVE_REFS_READING is not set), this is
perfectly fine.

However, checking for ENOENT isn't sufficient to catch all
missing-ref cases. In the filesystem backend, we may also
see EISDIR when we try to resolve "a" and "a/b" exists.
Likewise, we may see ENOTDIR if we try to resolve "a/b" and
"a" exists. In both of those cases, we know that our
resolved ref doesn't exist, but we return an error (rather
than reporting the refname and returning a null sha1).

This has been broken for a long time, but nobody really
noticed because the next step after resolving without the
READING flag is usually to lock the ref and write it. But in
both of those cases, the write will fail with the same
errno due to the directory/file conflict.

There are two cases where we can notice this, though:

  1. If we try to write "a" and there's a leftover directory
     already at "a", even though there is no ref "a/b". The
     actual write is smart enough to move the empty "a" out
     of the way.

     This is reasonably rare, if only because the writing
     code has to do an independent resolution before trying
     its write (because the actual update_ref() code handles
     this case fine). The notes-merge code does this, and
     before the fix in the prior commit t3308 erroneously
     expected this case to fail.

  2. When resolving symbolic refs, we typically do not use
     the READING flag because we want to resolve even
     symrefs that point to unborn refs. Even if those unborn
     refs could not actually be written because of d/f
     conflicts with existing refs.

     You can see this by asking "git symbolic-ref" to report
     the target of a symref pointing past a d/f conflict.

We can fix the problem by recognizing the other "missing"
errnos and treating them like ENOENT. This should be safe to
do even for callers who are then going to actually write the
ref, because the actual writing process will fail if the d/f
conflict is a real one (and t1404 checks these cases).

Arguably this should be the responsibility of the
files-backend to normalize all "missing ref" errors into
ENOENT (since something like EISDIR may not be meaningful at
all to a database backend). However other callers of
refs_read_raw_ref() may actually care about the distinction;
putting this into resolve_ref() is the minimal fix for now.

The new tests in t1401 use git-symbolic-ref, which is the
most direct way to check the resolution by itself.
Interestingly we actually had a test that setup this case
already, but we only used it to verify that the funny state
could be overwritten, not that it could be resolved.

We also add a new test in t3200, as "branch -m" was the
original motivation for looking into this. What happens is
this:

  0. HEAD is pointing to branch "a"

  1. The user asks to rename "a" to "a/b".

  2. We create "a/b" and delete "a".

  3. We then try to update any worktree HEADs that point to
     the renamed ref (including the main repo HEAD). To do
     that, we have to resolve each HEAD. But now our HEAD is
     pointing at "a", and we get EISDIR due to the loose
     "a/b". As a result, we think there is no HEAD, and we
     do not update it. It now points to the bogus "a".

Interestingly this case used to work, but only accidentally.
Before 31824d180d (branch: fix branch renaming not updating
HEADs correctly, 2017-08-24), we'd update any HEAD which we
couldn't resolve. That was wrong, but it papered over the
fact that we were incorrectly failing to resolve HEAD.

So while the bug demonstrated by the git-symbolic-ref is
quite old, the regression to "branch -m" is recent.

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'mh/mmap-packed-refs'</title>
<updated>2017-10-03T06:42:50Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2017-10-03T06:42:50Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=1a2e1a76ec2cbbafe60ffd124f673f62045fb0d3'/>
<id>urn:sha1:1a2e1a76ec2cbbafe60ffd124f673f62045fb0d3</id>
<content type='text'>
Operations that do not touch (majority of) packed refs have been
optimized by making accesses to packed-refs file lazy; we no longer
pre-parse everything, and an access to a single ref in the
packed-refs does not touch majority of irrelevant refs, either.

* mh/mmap-packed-refs: (21 commits)
  packed-backend.c: rename a bunch of things and update comments
  mmapped_ref_iterator: inline into `packed_ref_iterator`
  ref_cache: remove support for storing peeled values
  packed_ref_store: get rid of the `ref_cache` entirely
  ref_store: implement `refs_peel_ref()` generically
  packed_read_raw_ref(): read the reference from the mmapped buffer
  packed_ref_iterator_begin(): iterate using `mmapped_ref_iterator`
  read_packed_refs(): ensure that references are ordered when read
  packed_ref_cache: keep the `packed-refs` file mmapped if possible
  packed-backend.c: reorder some definitions
  mmapped_ref_iterator_advance(): no peeled value for broken refs
  mmapped_ref_iterator: add iterator over a packed-refs file
  packed_ref_cache: remember the file-wide peeling state
  read_packed_refs(): read references with minimal copying
  read_packed_refs(): make parsing of the header line more robust
  read_packed_refs(): only check for a header at the top of the file
  read_packed_refs(): use mmap to read the `packed-refs` file
  die_unterminated_line(), die_invalid_line(): new functions
  packed_ref_cache: add a backlink to the associated `packed_ref_store`
  prefix_ref_iterator: break when we leave the prefix
  ...
</content>
</entry>
<entry>
<title>Merge branch 'sd/branch-copy'</title>
<updated>2017-10-03T06:42:48Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2017-10-03T06:42:48Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=3b48045c6c73a51834a2f83440a30225485ee431'/>
<id>urn:sha1:3b48045c6c73a51834a2f83440a30225485ee431</id>
<content type='text'>
"git branch" learned "-c/-C" to create a new branch by copying an
existing one.

* sd/branch-copy:
  branch: fix "copy" to never touch HEAD
  branch: add a --copy (-c) option to go with --move (-m)
  branch: add test for -m renaming multiple config sections
  config: create a function to format section headers
</content>
</entry>
<entry>
<title>Merge branch 'rs/resolve-ref-optional-result'</title>
<updated>2017-09-28T05:47:56Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2017-09-28T05:47:56Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=73ecdc606eedbfd98ec66d50d44b3374425fd13b'/>
<id>urn:sha1:73ecdc606eedbfd98ec66d50d44b3374425fd13b</id>
<content type='text'>
Code clean-up.

* rs/resolve-ref-optional-result:
  refs: pass NULL to resolve_ref_unsafe() if hash is not needed
  refs: pass NULL to refs_resolve_ref_unsafe() if hash is not needed
  refs: make sha1 output parameter of refs_resolve_ref_unsafe() optional
</content>
</entry>
<entry>
<title>ref_store: implement `refs_peel_ref()` generically</title>
<updated>2017-09-25T09:02:46Z</updated>
<author>
<name>Michael Haggerty</name>
<email>mhagger@alum.mit.edu</email>
</author>
<published>2017-09-25T08:00:14Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ba1c052fa616eb93a654375e8b9d59daa47c28a8'/>
<id>urn:sha1:ba1c052fa616eb93a654375e8b9d59daa47c28a8</id>
<content type='text'>
We're about to stop storing packed refs in a `ref_cache`. That means
that the only way we have left to optimize `peel_ref()` is by checking
whether the reference being peeled is the one currently being iterated
over (in `current_ref_iter`), and if so, using `ref_iterator_peel()`.
But this can be done generically; it doesn't have to be implemented
per-backend.

So implement `refs_peel_ref()` in `refs.c` and remove the `peel_ref()`
method from the refs API.

This removes the last callers of a couple of functions, so delete
them. More cleanup to come...

Signed-off-by: Michael Haggerty &lt;mhagger@alum.mit.edu&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'tg/refs-allowed-flags'</title>
<updated>2017-09-25T06:24:07Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2017-09-25T06:24:07Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=d019010559b26784b0aea6cf08b43f576ef027f9'/>
<id>urn:sha1:d019010559b26784b0aea6cf08b43f576ef027f9</id>
<content type='text'>
API error-proofing which happens to also squelch warnings from GCC.

* tg/refs-allowed-flags:
  refs: strip out not allowed flags from ref_transaction_update
</content>
</entry>
<entry>
<title>Merge branch 'jn/per-repo-object-store-fixes'</title>
<updated>2017-09-25T06:24:07Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2017-09-25T06:24:06Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ceb7a01aac907f124ca9bc0d768336e7c0aaa944'/>
<id>urn:sha1:ceb7a01aac907f124ca9bc0d768336e7c0aaa944</id>
<content type='text'>
Step #0 of a planned &amp; larger series to make the in-core object
store per in-core repository object.

* jn/per-repo-object-store-fixes:
  replace-objects: evaluate replacement refs without using the object store
  push, fetch: error out for submodule entries not pointing to commits
  pack: make packed_git_mru global a value instead of a pointer
</content>
</entry>
<entry>
<title>Merge branch 'jk/write-in-full-fix'</title>
<updated>2017-09-25T06:24:06Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2017-09-25T06:24:06Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c50424a6f07f17ff9b06927606df650cd73a09a3'/>
<id>urn:sha1:c50424a6f07f17ff9b06927606df650cd73a09a3</id>
<content type='text'>
Many codepaths did not diagnose write failures correctly when disks
go full, due to their misuse of write_in_full() helper function,
which have been corrected.

* jk/write-in-full-fix:
  read_pack_header: handle signed/unsigned comparison in read result
  config: flip return value of store_write_*()
  notes-merge: use ssize_t for write_in_full() return value
  pkt-line: check write_in_full() errors against "&lt; 0"
  convert less-trivial versions of "write_in_full() != len"
  avoid "write_in_full(fd, buf, len) != len" pattern
  get-tar-commit-id: check write_in_full() return against 0
  config: avoid "write_in_full(fd, buf, len) &lt; len" pattern
</content>
</entry>
<entry>
<title>refs: pass NULL to resolve_ref_unsafe() if hash is not needed</title>
<updated>2017-09-24T01:18:21Z</updated>
<author>
<name>René Scharfe</name>
<email>l.s.r@web.de</email>
</author>
<published>2017-09-23T09:45:04Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=744c040b19412fa5075810eb1aced105fad96726'/>
<id>urn:sha1:744c040b19412fa5075810eb1aced105fad96726</id>
<content type='text'>
This allows us to get rid of some write-only variables, among them seven
SHA1 buffers.

Signed-off-by: Rene Scharfe &lt;l.s.r@web.de&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>refs: make sha1 output parameter of refs_resolve_ref_unsafe() optional</title>
<updated>2017-09-24T01:18:18Z</updated>
<author>
<name>René Scharfe</name>
<email>l.s.r@web.de</email>
</author>
<published>2017-09-23T09:41:45Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=54fad6614fc6b61ee6eb4a5b3daa7a2239019b49'/>
<id>urn:sha1:54fad6614fc6b61ee6eb4a5b3daa7a2239019b49</id>
<content type='text'>
Allow callers of refs_resolve_ref_unsafe() to pass NULL if they don't
need the resolved hash value.  We already allow the same for the flags
parameter.  This new leniency is inherited by the various wrappers like
resolve_ref_unsafe().

Signed-off-by: Rene Scharfe &lt;l.s.r@web.de&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
</feed>
