@@ -178,8 +178,8 @@ static int parse_next_oid(const char **next, const char *end,
* line_termination is set.
*/
-static const char *parse_cmd_update(struct ref_transaction *transaction,
- const char *next, const char *end)
+static void parse_cmd_update(struct ref_transaction *transaction,
+ const char *next, const char *end)
{
struct strbuf err = STRBUF_INIT;
char *refname;
@@ -212,12 +212,10 @@ static const char *parse_cmd_update(struct ref_transaction *transaction,
update_flags = default_flags;
free(refname);
strbuf_release(&err);
-
- return next;
}
-static const char *parse_cmd_create(struct ref_transaction *transaction,
- const char *next, const char *end)
+static void parse_cmd_create(struct ref_transaction *transaction,
+ const char *next, const char *end)
{
struct strbuf err = STRBUF_INIT;
char *refname;
@@ -247,12 +245,10 @@ static const char *parse_cmd_create(struct ref_transaction *transaction,
update_flags = default_flags;
free(refname);
strbuf_release(&err);
-
- return next;
}
-static const char *parse_cmd_delete(struct ref_transaction *transaction,
- const char *next, const char *end)
+static void parse_cmd_delete(struct ref_transaction *transaction,
+ const char *next, const char *end)
{
struct strbuf err = STRBUF_INIT;
char *refname;
@@ -286,12 +282,10 @@ static const char *parse_cmd_delete(struct ref_transaction *transaction,
update_flags = default_flags;
free(refname);
strbuf_release(&err);
-
- return next;
}
-static const char *parse_cmd_verify(struct ref_transaction *transaction,
- const char *next, const char *end)
+static void parse_cmd_verify(struct ref_transaction *transaction,
+ const char *next, const char *end)
{
struct strbuf err = STRBUF_INIT;
char *refname;
@@ -318,12 +312,10 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
update_flags = default_flags;
free(refname);
strbuf_release(&err);
-
- return next;
}
-static const char *parse_cmd_option(struct ref_transaction *transaction,
- const char *next, const char *end)
+static void parse_cmd_option(struct ref_transaction *transaction,
+ const char *next, const char *end)
{
const char *rest;
if (!skip_prefix(next, " ", &next))
@@ -332,48 +324,49 @@ static const char *parse_cmd_option(struct ref_transaction *transaction,
update_flags |= REF_NO_DEREF;
else
die("option unknown: %s", next);
- return rest;
}
static const struct parse_cmd {
const char *prefix;
- const char *(*fn)(struct ref_transaction *, const char *, const char *);
+ void (*fn)(struct ref_transaction *, const char *, const char *);
+ /*
+ * If using NUL-terminated format, only the first argument will be
+ * available in the first line. In case a command expects more than one
+ * argument, we thus have to fetch an additional `extra_lines` number
+ * of lines.
+ */
+ unsigned extra_lines;
} command[] = {
- { "update", parse_cmd_update },
- { "create", parse_cmd_create },
- { "delete", parse_cmd_delete },
- { "verify", parse_cmd_verify },
- { "option", parse_cmd_option },
+ { "update", parse_cmd_update, 2 },
+ { "create", parse_cmd_create, 1 },
+ { "delete", parse_cmd_delete, 1 },
+ { "verify", parse_cmd_verify, 1 },
+ { "option", parse_cmd_option, 0 },
};
static void update_refs_stdin(void)
{
struct strbuf input = STRBUF_INIT, err = STRBUF_INIT;
struct ref_transaction *transaction;
- const char *next;
- int i;
-
- if (strbuf_read(&input, 0, 1000) < 0)
- die_errno("could not read from stdin");
- next = input.buf;
+ int i, j;
transaction = ref_transaction_begin(&err);
if (!transaction)
die("%s", err.buf);
/* Read each line dispatch its command */
- while (next < input.buf + input.len) {
+ while (!strbuf_getwholeline(&input, stdin, line_termination)) {
const struct parse_cmd *cmd = NULL;
- if (*next == line_termination)
+ if (*input.buf == line_termination)
die("empty command in input");
- else if (isspace(*next))
- die("whitespace before command: %s", next);
+ else if (isspace(*input.buf))
+ die("whitespace before command: %s", input.buf);
for (i = 0; i < ARRAY_SIZE(command); i++) {
const char *prefix = command[i].prefix;
- if (!skip_prefix(next, prefix, &next))
+ if (!starts_with(input.buf, prefix))
continue;
/*
@@ -389,10 +382,19 @@ static void update_refs_stdin(void)
break;
}
if (!cmd)
- die("unknown command: %s", next);
+ die("unknown command: %s", input.buf);
- next = cmd->fn(transaction, next, input.buf + input.len);
- next++;
+ /*
+ * Read extra lines if NUL-terminated. Do not raise an error in
+ * case there is an early EOF to let the command handle missing
+ * arguments with a proper error message.
+ */
+ for (j = 0; line_termination == '\0' && j < cmd->extra_lines; j++)
+ if (strbuf_appendwholeline(&input, stdin, line_termination))
+ break;
+
+ cmd->fn(transaction, input.buf + strlen(cmd->prefix),
+ input.buf + input.len);
}
if (ref_transaction_commit(transaction, &err))