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

Re: [PATCH v14 24/40] receive-pack.c: use a reference transaction for updating the refs

From
Ronnie Sahlberg <sahlberg@google.com>
Date
Jun 11, 2014, 18:44 UTC
Message-ID
<CAL=YDWn8gFep1Hhp2gnQsd4PCuRT+vBb6wBcsbL9Sjriyf-ePw@mail.gmail.com>
In-Reply-To
<20140610231841.GC8557@google.com>
Thanks.

Done. I added a function to stop leaking commands too.

On Tue, Jun 10, 2014 at 4:18 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:
Show 182 quoted lines
> Ronnie Sahlberg wrote:
>
>> --- a/builtin/receive-pack.c
>> +++ b/builtin/receive-pack.c
>> @@ -46,6 +46,7 @@ static void *head_name_to_free;
>>  static int sent_capabilities;
>>  static int shallow_update;
>>  static const char *alt_shallow_file;
>> +static struct string_list error_strings = STRING_LIST_INIT_DUP;
> [...]
>> @@ -576,19 +576,31 @@ static const char *update(struct command *cmd, struct shallow_info *si)
> [...]
>> +             transaction = ref_transaction_begin(&err);
>> +             if (!transaction ||
>> +                 ref_transaction_update(transaction, namespaced_name,
>> +                                        new_sha1, old_sha1, 0, 1, &err) ||
>> +                 ref_transaction_commit(transaction, "push", &err)) {
>> +
>> +                     const char *str;
>> +                     string_list_append(&error_strings, err.buf);
>> +                     str = error_strings.items[error_strings.nr - 1].string;
> [...]
>> +                     return str;
> [...]
>> @@ -1215,5 +1227,6 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
>>               packet_flush(1);
>>       sha1_array_clear(&shallow);
>>       sha1_array_clear(&ref);
>> +     string_list_clear(&error_strings, 0);
>>       return 0;
>
> I think it's okay to let error strings accumulate like this because
> there will not be too many of them.  Still I wonder, would it work to
> change the convention to transfer ownership of the string to the caller?
>
> Ultimately 'commands' is leaked so we could even avoid the strdups but
> I'd rather leave it possible to clean up.
>
> Something like this:
>
> diff --git i/builtin/receive-pack.c w/builtin/receive-pack.c
> index 13f4a63..d8ab7b2 100644
> --- i/builtin/receive-pack.c
> +++ w/builtin/receive-pack.c
> @@ -46,7 +46,6 @@ static void *head_name_to_free;
>  static int sent_capabilities;
>  static int shallow_update;
>  static const char *alt_shallow_file;
> -static struct string_list error_strings = STRING_LIST_INIT_DUP;
>
>  static enum deny_action parse_deny_action(const char *var, const char *value)
>  {
> @@ -195,7 +194,7 @@ static void write_head_info(void)
>
>  struct command {
>         struct command *next;
> -       const char *error_string;
> +       char *error_string;
>         unsigned int skip_update:1,
>                      did_not_exist:1;
>         int index;
> @@ -469,7 +468,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
>         return 0;
>  }
>
> -static const char *update(struct command *cmd, struct shallow_info *si)
> +static char *update(struct command *cmd, struct shallow_info *si)
>  {
>         const char *name = cmd->ref_name;
>         struct strbuf namespaced_name_buf = STRBUF_INIT;
> @@ -589,12 +588,9 @@ static const char *update(struct command *cmd, struct shallow_info *si)
>                                            new_sha1, old_sha1, 0, 1, &err) ||
>                     ref_transaction_commit(transaction, "push", &err)) {
>
> -                       const char *str;
> -                       string_list_append(&error_strings, err.buf);
> -                       str = error_strings.items[error_strings.nr - 1].string;
> -                       strbuf_release(&err);
> -
> +                       char *str = strbuf_detach(&err, NULL);
>                         ref_transaction_free(transaction);
> +
>                         rp_error("%s", str);
>                         return str;
>                 }
> @@ -659,6 +655,9 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
>         char cmd_oldh[41], cmd_newh[41], dst_oldh[41], dst_newh[41];
>         int flag;
>
> +       if (cmd->error_string)
> +               die("BUG: check_alised_update called with failed cmd");
> +
>         strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
>         dst_name = resolve_ref_unsafe(buf.buf, sha1, 0, &flag);
>         strbuf_release(&buf);
> @@ -670,7 +669,7 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
>         if (!dst_name) {
>                 rp_error("refusing update to broken symref '%s'", cmd->ref_name);
>                 cmd->skip_update = 1;
> -               cmd->error_string = "broken symref";
> +               cmd->error_string = xstrdup("broken symref");
>                 return;
>         }
>
> @@ -696,8 +695,9 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
>                  cmd->ref_name, cmd_oldh, cmd_newh,
>                  dst_cmd->ref_name, dst_oldh, dst_newh);
>
> -       cmd->error_string = dst_cmd->error_string =
> -               "inconsistent aliased update";
> +       cmd->error_string = xstrdup("inconsistent aliased update");
> +       free(dst_cmd->error_string);
> +       dst_cmd->error_string = xstrdup("inconsistent aliased update");
>  }
>
>  static void check_aliased_updates(struct command *commands)
> @@ -745,7 +745,9 @@ static void set_connectivity_errors(struct command *commands,
>                 if (!check_everything_connected(command_singleton_iterator,
>                                                 0, &singleton))
>                         continue;
> -               cmd->error_string = "missing necessary objects";
> +               if (cmd->error_string)  /* can't happen */
> +                       continue;
> +               cmd->error_string = xstrdup("missing necessary objects");
>         }
>  }
>
> @@ -782,9 +784,9 @@ static void reject_updates_to_hidden(struct command *commands)
>                 if (cmd->error_string || !ref_is_hidden(cmd->ref_name))
>                         continue;
>                 if (is_null_sha1(cmd->new_sha1))
> -                       cmd->error_string = "deny deleting a hidden ref";
> +                       cmd->error_string = xstrdup("deny deleting a hidden ref");
>                 else
> -                       cmd->error_string = "deny updating a hidden ref";
> +                       cmd->error_string = xstrdup("deny updating a hidden ref");
>         }
>  }
>
> @@ -798,8 +800,11 @@ static void execute_commands(struct command *commands,
>         struct iterate_data data;
>
>         if (unpacker_error) {
> -               for (cmd = commands; cmd; cmd = cmd->next)
> -                       cmd->error_string = "unpacker error";
> +               for (cmd = commands; cmd; cmd = cmd->next) {
> +                       if (cmd->error_string)  /* can't happen */
> +                               continue;
> +                       cmd->error_string = xstrdup("unpacker error");
> +               }
>                 return;
>         }
>
> @@ -812,8 +817,9 @@ static void execute_commands(struct command *commands,
>
>         if (run_receive_hook(commands, "pre-receive", 0)) {
>                 for (cmd = commands; cmd; cmd = cmd->next) {
> -                       if (!cmd->error_string)
> -                               cmd->error_string = "pre-receive hook declined";
> +                       if (cmd->error_string)
> +                               continue;
> +                       cmd->error_string = xstrdup("pre-receive hook declined");
>                 }
>                 return;
>         }
> @@ -1091,7 +1097,8 @@ static void update_shallow_info(struct command *commands,
>                 if (is_null_sha1(cmd->new_sha1))
>                         continue;
>                 if (ref_status[cmd->index]) {
> -                       cmd->error_string = "shallow update not allowed";
> +                       free(cmd->error_string);
> +                       cmd->error_string = xstrdup("shallow update not allowed");
>                         cmd->skip_update = 1;
>                 }
>         }
> @@ -1227,6 +1234,5 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
>                 packet_flush(1);
>         sha1_array_clear(&shallow);
>         sha1_array_clear(&ref);
> -       string_list_clear(&error_strings, 0);
>         return 0;
>  }
Previous: Jonathan NiederNext: Ronnie Sahlberg
Message 32 of 51 in “Use ref transactions”
  1. 00/40 Use ref transactionsRonnie Sahlberg, Jun 6, 2014
  2. 01/40 refs.c: remove ref_transaction_rollbackRonnie Sahlberg, Jun 6, 2014
  3. 02/40 refs.c: ref_transaction_commit should not free the transactionRonnie Sahlberg, Jun 6, 2014
  4. 03/40 refs.c: constify the sha arguments for ref_transaction_create|delete|updateRonnie Sahlberg, Jun 6, 2014
  5. 04/40 refs.c: allow passing NULL to ref_transaction_freeRonnie Sahlberg, Jun 6, 2014
  6. 05/40 refs.c: add a strbuf argument to ref_transaction_commit for error loggingRonnie Sahlberg, Jun 6, 2014
  7. 06/40 refs.c: add an err argument to repack_without_refsRonnie Sahlberg, Jun 6, 2014
  8. Jonathan NiederJun 10, 2014
  9. Ronnie SahlbergJun 10, 2014
  10. 07/40 refs.c: make ref_update_reject_duplicates take a strbuf argument for errorsRonnie Sahlberg, Jun 6, 2014
  11. 08/40 refs.c: add an err argument to delete_ref_looseRonnie Sahlberg, Jun 6, 2014
  12. Jonathan NiederJun 10, 2014
  13. Ronnie SahlbergJun 11, 2014
  14. 09/40 refs.c: make update_ref_write update a strbuf on failureRonnie Sahlberg, Jun 6, 2014
  15. 10/40 update-ref: use err argument to get error from ref_transaction_commitRonnie Sahlberg, Jun 6, 2014
  16. 11/40 refs.c: remove the onerr argument to ref_transaction_commitRonnie Sahlberg, Jun 6, 2014
  17. 12/40 refs.c: change ref_transaction_update() to do error checking and return statusRonnie Sahlberg, Jun 6, 2014
  18. 13/40 refs.c: change ref_transaction_create to do error checking and return statusRonnie Sahlberg, Jun 6, 2014
  19. 14/40 refs.c: update ref_transaction_delete to check for error and return statusRonnie Sahlberg, Jun 6, 2014
  20. 15/40 refs.c: make ref_transaction_begin take an err argumentRonnie Sahlberg, Jun 6, 2014
  21. 16/40 refs.c: add transaction.status and track OPEN/CLOSED/ERRORRonnie Sahlberg, Jun 6, 2014
  22. Jonathan NiederJun 10, 2014
  23. 17/40 tag.c: use ref transactions when doing updatesRonnie Sahlberg, Jun 6, 2014
  24. 18/40 replace.c: use the ref transaction functions for updatesRonnie Sahlberg, Jun 6, 2014
  25. 19/40 commit.c: use ref transactions for updatesRonnie Sahlberg, Jun 6, 2014
  26. 20/40 sequencer.c: use ref transactions for all ref updatesRonnie Sahlberg, Jun 6, 2014
  27. 21/40 fast-import.c: change update_branch to use ref transactionsRonnie Sahlberg, Jun 6, 2014
  28. 22/40 branch.c: use ref transaction for all ref updatesRonnie Sahlberg, Jun 6, 2014
  29. 23/40 refs.c: change update_ref to use a transactionRonnie Sahlberg, Jun 6, 2014
  30. 24/40 receive-pack.c: use a reference transaction for updating the refsRonnie Sahlberg, Jun 6, 2014
  31. Jonathan NiederJun 10, 2014
  32. Ronnie SahlbergJun 11, 2014
  33. 25/40 fast-import.c: use a ref transaction when dumping tagsRonnie Sahlberg, Jun 6, 2014
  34. Jonathan NiederJun 10, 2014
  35. 26/40 walker.c: use ref transaction for ref updatesRonnie Sahlberg, Jun 6, 2014
  36. Jonathan NiederJun 10, 2014
  37. 27/40 refs.c: make lock_ref_sha1 staticRonnie Sahlberg, Jun 6, 2014
  38. 28/40 refs.c: remove the update_ref_lock functionRonnie Sahlberg, Jun 6, 2014
  39. 29/40 refs.c: remove the update_ref_write functionRonnie Sahlberg, Jun 6, 2014
  40. 30/40 refs.c: remove lock_ref_sha1Ronnie Sahlberg, Jun 6, 2014
  41. 31/40 refs.c: make prune_ref use a transaction to delete the refRonnie Sahlberg, Jun 6, 2014
  42. Jonathan NiederJun 10, 2014
  43. 32/40 refs.c: make delete_ref use a transactionRonnie Sahlberg, Jun 6, 2014
  44. 33/40 refs.c: pass the ref log message to _create/delete/update instead of _commitRonnie Sahlberg, Jun 6, 2014
  45. 34/40 refs.c: pass NULL as *flags to read_ref_fullRonnie Sahlberg, Jun 6, 2014
  46. 35/40 refs.c: move the check for valid refname to lock_ref_sha1_basicRonnie Sahlberg, Jun 6, 2014
  47. 36/40 refs.c: call lock_ref_sha1_basic directly from commitRonnie Sahlberg, Jun 6, 2014
  48. 37/40 refs.c: pass a skip list to name_conflict_fnRonnie Sahlberg, Jun 6, 2014
  49. 38/40 refs.c: propagate any errno==ENOTDIR from _commit back to the callersRonnie Sahlberg, Jun 6, 2014
  50. 39/40 fetch.c: change s_update_ref to use a ref transactionRonnie Sahlberg, Jun 6, 2014
  51. 40/40 refs.c: make write_ref_sha1 staticRonnie Sahlberg, Jun 6, 2014

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.