git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH/WIP v3 04/31] am: implement patch queue mechanism

From
Paul Tan <pyokagan@gmail.com>
Date
Jun 19, 2015, 12:49 UTC
Message-ID
<CACRoPnSVWNOPPJAhJS1S-HbHUEVJ1p_jz-dnFmuk8Hh1NaMLwg@mail.gmail.com>
In-Reply-To
<xmqq7fr0eoho.fsf@gitster.dls.corp.google.com>
On Fri, Jun 19, 2015 at 4:43 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 28 quoted lines
> Paul Tan <pyokagan@gmail.com> writes:
>
>> diff --git a/builtin/am.c b/builtin/am.c
>> index dbc8836..af68c51 100644
>> --- a/builtin/am.c
>> +++ b/builtin/am.c
>> @@ -6,6 +6,158 @@
>>  #include "cache.h"
>>  #include "builtin.h"
>>  #include "exec_cmd.h"
>> +#include "parse-options.h"
>> +#include "dir.h"
>> +
>> +struct am_state {
>> +     /* state directory path */
>> +     struct strbuf dir;
>
> Is this a temporary variable you will append "/patch", etc. to form
> a different string to use for fopen() etc., or do you use separate
> strbufs for things like that and this is only used to initialize
> them?
>
>  - If the former then "dir" is a misnomer.
>
>  - If the latter, then it probably does not have to be a strbuf;
>    rather, it should probably be a "const char *".  Unless you pass
>    this directly to functions that take a strbuf, such as
>    remove_dir_recursively(), that is.

It's the latter, and yes it does not need to be an strbuf since it will not usually change.

However, I don't think it should be a const char*, as it means that the API user has to keep track of the lifetime of the "dir" string. Note that we will have to git_pathdup() as git_path() returns a static buffer:

char *dir = git_pathdup("rebase-apply");
struct am_state state;
am_state_init(&state);
state.dir = dir;
...stuff...
if (foo) {
     ... separate code path ...
     am_state_release(&state);
     free(dir);
     return 0;
}
... separate code path ...
am_state_release(&state);
free(dir);
return 0;
Note the additional memory bookkeeping.

Instead, I would rather the am_state struct take ownership of the "dir" string and free it in am_state_release(). So dir will be a char*:

struct am_state state;
am_state_init(&state, git_path("rebase-apply"));
... stuff ...
if (foo) {
     ... separate code path ...
     am_state_release(&state);
     return 0;
}
... separate code path ...
am_state_release(&state);
return 0;
Show 9 quoted lines
>> +/**
>> + * Release memory allocated by an am_state.
>> + */
>
> Everybody else in this file seems to say "Initializes", "Returns",
> "Reads", etc.  While I personally prefer to use imperative
> (i.e. give command to this function to "release memory allocated"),
> you would want to be consistent throughout the file; "Releases
> memory" would make it so.
OK
Show 19 quoted lines
>> +/**
>> + * Setup a new am session for applying patches
>> + */
>> +static void am_setup(struct am_state *state)
>> +{
>> +     if (mkdir(state->dir.buf, 0777) < 0 && errno != EEXIST)
>> +             die_errno(_("failed to create directory '%s'"), state->dir.buf);
>> +
>> +     write_file(am_path(state, "next"), 1, "%d", state->cur);
>> +
>> +     write_file(am_path(state, "last"), 1, "%d", state->last);
>
> These two lines are closely related pair; drop the blank in between.
>
> I am tno sure if write_file() is an appropriate thing to use,
> though.  What happens when you get interrupted after opening the
> file but before you manage to write and close?  Shouldn't we be
> doing the usual "write to temp, close and then rename to final"
> dance?  This comment applies to all the other use of write_file().

We could, although I don't think it would help us much. The state directory is made up of many different files, so even if we made modifications to single files atomic, there's no point if we terminate unexpectedly in the middle of writing multiple files to the state directory as the state, as a whole, is corrupted anyway.

So, we must be able to make updates to the entire state directory as a single transaction, which is a more difficult problem...

Furthermore, while applying patches, we may face abnormal termination between e.g. the patch application and commit, so I think it is safe to say that if abnormal termination occurs, we will not be able to reliably --resume or --skip anyway, and the user should just run --abort to go back to the last known state.

However, it would be an improvement if we wrote the "next" and "last" files last, as we use their presence to determine if we have an am session in progress or not, so if we terminate in am_setup() we will just have a stray directory. I will make this change in the next iteration.

Regards, Paul

Previous: Junio C HamanoNext: Johannes Schindelin
Message 15 of 64 in “Make git-am a builtin”
  1. 00/31 Make git-am a builtinPaul Tan, Jun 18, 2015
  2. 01/31 wrapper: implement xopen()Paul Tan, Jun 18, 2015
  3. Johannes SchindelinJun 24, 2015
  4. Stefan BellerJun 24, 2015
  5. Johannes SchindelinJun 24, 2015
  6. Paul TanJul 1, 2015
  7. Paul TanJul 1, 2015
  8. 02/31 wrapper: implement xfopen()Paul Tan, Jun 18, 2015
  9. 03/31 am: implement skeletal builtin amPaul Tan, Jun 18, 2015
  10. Junio C HamanoJun 18, 2015
  11. Paul TanJun 19, 2015
  12. 04/31 am: implement patch queue mechanismPaul Tan, Jun 18, 2015
  13. Stefan BellerJun 18, 2015
  14. Junio C HamanoJun 18, 2015
  15. Paul TanJun 19, 2015
  16. Johannes SchindelinJun 24, 2015
  17. Paul TanJun 25, 2015
  18. 05/31 am: split out mbox/maildir patches with git-mailsplitPaul Tan, Jun 18, 2015
  19. Junio C HamanoJun 18, 2015
  20. 06/31 am: detect mbox patchesPaul Tan, Jun 18, 2015
  21. Junio C HamanoJun 18, 2015
  22. Paul TanJun 24, 2015
  23. Johannes SchindelinJun 24, 2015
  24. Paul TanJun 25, 2015
  25. Paul TanJun 26, 2015
  26. 07/31 am: extract patch, message and authorship with git-mailinfoPaul Tan, Jun 18, 2015
  27. Junio C HamanoJun 18, 2015
  28. Paul TanJun 19, 2015
  29. Junio C HamanoJun 19, 2015
  30. Paul TanJun 24, 2015
  31. Junio C HamanoJun 24, 2015
  32. Paul TanJun 25, 2015
  33. Johannes SchindelinJun 24, 2015
  34. Paul TanJun 26, 2015
  35. Junio C HamanoJun 26, 2015
  36. 08/31 am: apply patch with git-applyPaul Tan, Jun 18, 2015
  37. Junio C HamanoJun 18, 2015
  38. 09/31 am: commit applied patchPaul Tan, Jun 18, 2015
  39. 10/31 am: refresh the index at startPaul Tan, Jun 18, 2015
  40. Junio C HamanoJun 18, 2015
  41. Paul TanJun 19, 2015
  42. 11/31 am: refuse to apply patches if index is dirtyPaul Tan, Jun 18, 2015
  43. 12/31 am: implement --resolved/--continuePaul Tan, Jun 18, 2015
  44. 13/31 am: implement --skipPaul Tan, Jun 18, 2015
  45. 14/31 am: implement --abortPaul Tan, Jun 18, 2015
  46. 15/31 am: don't accept patches when there's a session in progressPaul Tan, Jun 18, 2015
  47. 16/31 am: implement quiet optionPaul Tan, Jun 18, 2015
  48. 17/31 am: exit with user friendly message on patch failurePaul Tan, Jun 18, 2015
  49. 18/31 am: implement am --signoffPaul Tan, Jun 18, 2015
  50. 19/31 cache-tree: introduce write_index_as_tree()Paul Tan, Jun 18, 2015
  51. 20/31 am: implement 3-way mergePaul Tan, Jun 18, 2015
  52. 21/31 am: --rebasingPaul Tan, Jun 18, 2015
  53. 22/31 am: don't use git-mailinfo if --rebasingPaul Tan, Jun 18, 2015
  54. 23/31 am: handle stray state directoryPaul Tan, Jun 18, 2015
  55. 24/31 am: implement -k/--keep, --keep-non-patchPaul Tan, Jun 18, 2015
  56. 25/31 am: implement --[no-]message-id, am.messageidPaul Tan, Jun 18, 2015
  57. 26/31 am: support --keep-cr, am.keepcrPaul Tan, Jun 18, 2015
  58. 27/31 am: implement --[no-]scissorsPaul Tan, Jun 18, 2015
  59. 28/31 am: pass git-apply's options to git-applyPaul Tan, Jun 18, 2015
  60. 29/31 am: implement --ignore-datePaul Tan, Jun 18, 2015
  61. 30/31 am: implement --committer-date-is-author-datePaul Tan, Jun 18, 2015
  62. 31/31 am: implement -S/--gpg-sign, commit.gpgsignPaul Tan, Jun 18, 2015
  63. Paul TanJun 19, 2015
  64. Johannes SchindelinJun 19, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.