On 5/9/2018 10:42 AM, Jeff King wrote:
On Wed, May 09, 2018 at 02:15:38PM +0000, Derrick Stolee wrote:

The commit-graph file lives in the .git/objects/info directory.
Previously, a failure to acquire the commit-graph.lock file was
assumed to be due to the lack of the info directory, so a mkdir()
was called. This gave incorrect messaging if instead the lockfile
was open by another process:

   "fatal: cannot mkdir .git/objects/info: File exists"

Rearrange the expectations of this directory existing to avoid
this error, and instead show the typical message when a lockfile
already exists.
Sounds like a reasonable bug fix.

Your cover letter is way longer than this description. Should some of
that background perhaps go in the commit message?

I did want a place to include the full die() message in the new behavior, but that seemed like overkill for the commit message.

(I would go so far as to say that sending a cover letter for a single
patch is an anti-pattern, because the commit message should be able to
stand on its own).

@@ -754,23 +755,14 @@ void write_commit_graph(const char *obj_dir,
        compute_generation_numbers(&commits);
graph_name = get_commit_graph_filename(obj_dir);
-       fd = hold_lock_file_for_update(&lk, graph_name, 0);
- if (fd < 0) {
-               struct strbuf folder = STRBUF_INIT;
-               strbuf_addstr(&folder, graph_name);
-               strbuf_setlen(&folder, strrchr(folder.buf, '/') - folder.buf);
-
-               if (mkdir(folder.buf, 0777) < 0)
-                       die_errno(_("cannot mkdir %s"), folder.buf);
-               strbuf_release(&folder);
-
-               fd = hold_lock_file_for_update(&lk, graph_name, 
LOCK_DIE_ON_ERROR);
-
-               if (fd < 0)
-                       die_errno("unable to create '%s'", graph_name);
-       }
+       strbuf_addstr(&folder, graph_name);
+       strbuf_setlen(&folder, strrchr(folder.buf, '/') - folder.buf);
+       if (!file_exists(folder.buf) && mkdir(folder.buf, 0777) < 0)
+               die_errno(_("cannot mkdir %s"), folder.buf);
+       strbuf_release(&folder);
The result is racy if somebody else is trying to create the directory at
the same time. For that you'd want to notice EEXIST coming from mkdir
and consider that a success.

I think you probably ought to be calling adjust_shared_perm() on the
result, too, in case core.sharedrepository is configured.

If you use safe_create_leading_directories(), it should handle both.
Something like:

   if (safe_create_leading_directories(graph_name))
        die_errno(_("unable to create leading directories of %s"),
                  graph_name));

I think I'm holding it right; that function is a little short on
documentation, but it's the standard way to do this in Git's codebase,
and you can find lots of example callers.

Thanks for this method. I was unfamiliar with it. Saves the effort of creating the strbuf, too.

Thanks,
-Stolee

Reply via email to