sequencer: remove the 'arg' field from todo_item

The 'arg' field of todo_item used to store the address of the first byte of the parameter of a command in a todo list. It was associated with the length of the parameter (the 'arg_len' field). This replaces the 'arg' field by 'arg_offset'. This new field does not store the address of the parameter, but the position of the first character of the parameter in the buffer. todo_item_get_arg() is added to return the address of the parameter of an item. This will prevent todo_list_add_exec_commands() from having to do awful pointer arithmetics when growing the todo list buffer. Signed-off-by: Alban Gruin <alban.gruin@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Alban Gruin committed Jan 29, 2019 at 16:01 UTC 6ad656db9b2d2426a0a884b431e8adc9877101bc
2 files changed +42 -31
sequencer.c
+38 -29
@@ -1999,8 +1999,14 @@ static struct todo_item *append_new_todo(struct todo_list *todo_list)
1999 return todo_list->items + todo_list->nr++;
2000 }
2001
2002 +const char *todo_item_get_arg(struct todo_list *todo_list,
2003 + struct todo_item *item)
2004 +{
2005 + return todo_list->buf.buf + item->arg_offset;
2006 +}
2007 +
2008 static int parse_insn_line(struct repository *r, struct todo_item *item,
2003 - const char *bol, char *eol)
2009 + const char *buf, const char *bol, char *eol)
2010 {
2011 struct object_id commit_oid;
2012 char *end_of_object_name;
@@ -2014,7 +2020,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
2020 if (bol == eol || *bol == '\r' || *bol == comment_line_char) {
2021 item->command = TODO_COMMENT;
2022 item->commit = NULL;
2017 - item->arg = bol;
2023 + item->arg_offset = bol - buf;
2024 item->arg_len = eol - bol;
2025 return 0;
2026 }
@@ -2041,7 +2047,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
2047 return error(_("%s does not accept arguments: '%s'"),
2048 command_to_string(item->command), bol);
2049 item->commit = NULL;
2044 - item->arg = bol;
2050 + item->arg_offset = bol - buf;
2051 item->arg_len = eol - bol;
2052 return 0;
2053 }
@@ -2053,7 +2059,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
2059 if (item->command == TODO_EXEC || item->command == TODO_LABEL ||
2060 item->command == TODO_RESET) {
2061 item->commit = NULL;
2056 - item->arg = bol;
2062 + item->arg_offset = bol - buf;
2063 item->arg_len = (int)(eol - bol);
2064 return 0;
2065 }
@@ -2067,7 +2073,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
2073 } else {
2074 item->flags |= TODO_EDIT_MERGE_MSG;
2075 item->commit = NULL;
2070 - item->arg = bol;
2076 + item->arg_offset = bol - buf;
2077 item->arg_len = (int)(eol - bol);
2078 return 0;
2079 }
@@ -2079,8 +2085,9 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
2085 status = get_oid(bol, &commit_oid);
2086 *end_of_object_name = saved;
2087
2082 - item->arg = end_of_object_name + strspn(end_of_object_name, " \t");
2083 - item->arg_len = (int)(eol - item->arg);
2088 + bol = end_of_object_name + strspn(end_of_object_name, " \t");
2089 + item->arg_offset = bol - buf;
2090 + item->arg_len = (int)(eol - bol);
2091
2092 if (status < 0)
2093 return -1;
@@ -2108,11 +2115,11 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf,
2115
2116 item = append_new_todo(todo_list);
2117 item->offset_in_buf = p - todo_list->buf.buf;
2111 - if (parse_insn_line(r, item, p, eol)) {
2118 + if (parse_insn_line(r, item, buf, p, eol)) {
2119 res = error(_("invalid line %d: %.*s"),
2120 i, (int)(eol - p), p);
2121 item->command = TODO_COMMENT + 1;
2115 - item->arg = p;
2122 + item->arg_offset = p - buf;
2123 item->arg_len = (int)(eol - p);
2124 item->commit = NULL;
2125 }
@@ -2452,7 +2459,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,
2459
2460 item->command = command;
2461 item->commit = commit;
2455 - item->arg = NULL;
2462 + item->arg_offset = 0;
2463 item->arg_len = 0;
2464 item->offset_in_buf = todo_list->buf.len;
2465 subject_len = find_commit_subject(commit_buffer, &subject);
@@ -3491,6 +3498,8 @@ static int pick_commits(struct repository *r,
3498
3499 while (todo_list->current < todo_list->nr) {
3500 struct todo_item *item = todo_list->items + todo_list->current;
3501 + const char *arg = todo_item_get_arg(todo_list, item);
3502 +
3503 if (save_todo(todo_list, opts))
3504 return -1;
3505 if (is_rebase_i(opts)) {
@@ -3542,10 +3551,9 @@ static int pick_commits(struct repository *r,
3551 fprintf(stderr,
3552 _("Stopped at %s... %.*s\n"),
3553 short_commit_name(commit),
3545 - item->arg_len, item->arg);
3554 + item->arg_len, arg);
3555 return error_with_patch(r, commit,
3547 - item->arg, item->arg_len, opts, res,
3548 - !res);
3556 + arg, item->arg_len, opts, res, !res);
3557 }
3558 if (is_rebase_i(opts) && !res)
3559 record_in_rewritten(&item->commit->object.oid,
@@ -3554,7 +3562,7 @@ static int pick_commits(struct repository *r,
3562 if (res == 1)
3563 intend_to_amend();
3564 return error_failed_squash(r, item->commit, opts,
3557 - item->arg_len, item->arg);
3565 + item->arg_len, arg);
3566 } else if (res && is_rebase_i(opts) && item->commit) {
3567 int to_amend = 0;
3568 struct object_id oid;
@@ -3573,16 +3581,16 @@ static int pick_commits(struct repository *r,
3581 to_amend = 1;
3582
3583 return res | error_with_patch(r, item->commit,
3576 - item->arg, item->arg_len, opts,
3584 + arg, item->arg_len, opts,
3585 res, to_amend);
3586 }
3587 } else if (item->command == TODO_EXEC) {
3580 - char *end_of_arg = (char *)(item->arg + item->arg_len);
3588 + char *end_of_arg = (char *)(arg + item->arg_len);
3589 int saved = *end_of_arg;
3590 struct stat st;
3591
3592 *end_of_arg = '\0';
3585 - res = do_exec(r, item->arg);
3593 + res = do_exec(r, arg);
3594 *end_of_arg = saved;
3595
3596 /* Reread the todo file if it has changed. */
@@ -3599,14 +3607,14 @@ static int pick_commits(struct repository *r,
3607 todo_list->current = -1;
3608 }
3609 } else if (item->command == TODO_LABEL) {
3602 - if ((res = do_label(r, item->arg, item->arg_len)))
3610 + if ((res = do_label(r, arg, item->arg_len)))
3611 reschedule = 1;
3612 } else if (item->command == TODO_RESET) {
3605 - if ((res = do_reset(r, item->arg, item->arg_len, opts)))
3613 + if ((res = do_reset(r, arg, item->arg_len, opts)))
3614 reschedule = 1;
3615 } else if (item->command == TODO_MERGE) {
3616 if ((res = do_merge(r, item->commit,
3609 - item->arg, item->arg_len,
3617 + arg, item->arg_len,
3618 item->flags, opts)) < 0)
3619 reschedule = 1;
3620 else if (item->commit)
@@ -3615,9 +3623,8 @@ static int pick_commits(struct repository *r,
3623 if (res > 0)
3624 /* failed with merge conflicts */
3625 return error_with_patch(r, item->commit,
3618 - item->arg,
3619 - item->arg_len, opts,
3620 - res, 0);
3626 + arg, item->arg_len,
3627 + opts, res, 0);
3628 } else if (!is_noop(item->command))
3629 return error(_("unknown command %d"), item->command);
3630
@@ -3632,9 +3639,8 @@ static int pick_commits(struct repository *r,
3639 if (item->commit)
3640 return error_with_patch(r,
3641 item->commit,
3635 - item->arg,
3636 - item->arg_len, opts,
3637 - res, 0);
3642 + arg, item->arg_len,
3643 + opts, res, 0);
3644 }
3645
3646 todo_list->current++;
@@ -4575,7 +4581,8 @@ int transform_todos(struct repository *r, unsigned flags)
4581 for (item = todo_list.items, i = 0; i < todo_list.nr; i++, item++) {
4582 /* if the item is not a command write it and continue */
4583 if (item->command >= TODO_COMMENT) {
4578 - strbuf_addf(&buf, "%.*s\n", item->arg_len, item->arg);
4584 + strbuf_addf(&buf, "%.*s\n", item->arg_len,
4585 + todo_item_get_arg(&todo_list, item));
4586 continue;
4587 }
4588
@@ -4605,7 +4612,8 @@ int transform_todos(struct repository *r, unsigned flags)
4612 if (!item->arg_len)
4613 strbuf_addch(&buf, '\n');
4614 else
4608 - strbuf_addf(&buf, " %.*s\n", item->arg_len, item->arg);
4615 + strbuf_addf(&buf, " %.*s\n", item->arg_len,
4616 + todo_item_get_arg(&todo_list, item));
4617 }
4618
4619 i = write_message(buf.buf, buf.len, todo_file, 0);
@@ -4681,7 +4689,8 @@ int check_todo_list(struct repository *r)
4689 if (commit && !*commit_seen_at(&commit_seen, commit)) {
4690 strbuf_addf(&missing, " - %s %.*s\n",
4691 short_commit_name(commit),
4684 - item->arg_len, item->arg);
4692 + item->arg_len,
4693 + todo_item_get_arg(&todo_list, item));
4694 *commit_seen_at(&commit_seen, commit) = 1;
4695 }
4696 }
sequencer.h
+4 -2
@@ -104,9 +104,9 @@ struct todo_item {
104 enum todo_command command;
105 struct commit *commit;
106 unsigned int flags;
107 - const char *arg;
107 int arg_len;
109 - size_t offset_in_buf;
108 + /* The offset of the command and its argument in the strbuf */
109 + size_t offset_in_buf, arg_offset;
110 };
111
112 struct todo_list {
@@ -122,6 +122,8 @@ struct todo_list {
122 int todo_list_parse_insn_buffer(struct repository *r, char *buf,
123 struct todo_list *todo_list);
124 void todo_list_release(struct todo_list *todo_list);
125 +const char *todo_item_get_arg(struct todo_list *todo_list,
126 + struct todo_item *item);
127
128 /* Call this to setup defaults before parsing command line options */
129 void sequencer_init_config(struct replay_opts *opts);