Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Commit

Permalink
C: normalize reflog messages
Browse files Browse the repository at this point in the history
This behavior can be overridden with config.exact_log_message
  • Loading branch information
hanwen committed Jun 15, 2020
1 parent 358b6ad commit 785f745
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
7 changes: 7 additions & 0 deletions c/include/reftable.h
Expand Up @@ -101,6 +101,8 @@ enum reftable_error {
- on writing a record with NULL ref_name.
- on writing a reftable_ref_record outside the table limits
- on writing a ref or log record before the stack's next_update_index
- on writing a log record with multiline message with
exact_log_message unset
- on reading a reftable_ref_record from log iterator, or vice versa.
*/
REFTABLE_API_ERROR = -6,
Expand Down Expand Up @@ -155,6 +157,11 @@ struct reftable_write_options {
/* boolean: do not check ref names for validity or dir/file conflicts.
*/
int skip_name_check;

/* boolean: copy log messages exactly. If unset, check that the message
* is a single line, and add '\n' if missing.
*/
int exact_log_message;
};

/* reftable_block_stats holds statistics for a single block type */
Expand Down
61 changes: 60 additions & 1 deletion c/stack_test.c
Expand Up @@ -310,7 +310,9 @@ static void test_reftable_stack_add(void)
{
int i = 0;
int err = 0;
struct reftable_write_options cfg = { 0 };
struct reftable_write_options cfg = {
.exact_log_message = true,
};
struct reftable_stack *st = NULL;
char dir[256] = "/tmp/stack_test.XXXXXX";
struct reftable_ref_record refs[2] = { { 0 } };
Expand Down Expand Up @@ -380,6 +382,61 @@ static void test_reftable_stack_add(void)
clear_dir(dir);
}

static void test_reftable_stack_log_normalize(void)
{
int err = 0;
struct reftable_write_options cfg = {
0,
};
struct reftable_stack *st = NULL;
char dir[256] = "/tmp/stack_test.XXXXXX";

byte h1[SHA1_SIZE] = { 0x01 }, h2[SHA1_SIZE] = { 0x02 };

struct reftable_log_record input = {
.ref_name = "branch",
.update_index = 1,
.new_hash = h1,
.old_hash = h2,
};
struct reftable_log_record dest = {
.update_index = 0,
};
struct write_log_arg arg = {
.log = &input,
.update_index = 1,
};

assert(mkdtemp(dir));
err = reftable_new_stack(&st, dir, cfg);
assert_err(err);

input.message = "one\ntwo";
err = reftable_stack_add(st, &write_test_log, &arg);
assert(err == REFTABLE_API_ERROR);

input.message = "one";
err = reftable_stack_add(st, &write_test_log, &arg);
assert_err(err);

err = reftable_stack_read_log(st, input.ref_name, &dest);
assert_err(err);
assert(0 == strcmp(dest.message, "one\n"));

input.message = "two\n";
arg.update_index = 2;
err = reftable_stack_add(st, &write_test_log, &arg);
assert_err(err);
err = reftable_stack_read_log(st, input.ref_name, &dest);
assert_err(err);
assert(0 == strcmp(dest.message, "two\n"));

/* cleanup */
reftable_stack_destroy(st);
reftable_log_record_clear(&dest);
clear_dir(dir);
}

static void test_reftable_stack_tombstone(void)
{
int i = 0;
Expand Down Expand Up @@ -718,6 +775,8 @@ int stack_test_main(int argc, const char *argv[])
&test_reftable_stack_update_index_check);
add_test_case("test_reftable_stack_lock_failure",
&test_reftable_stack_lock_failure);
add_test_case("test_reftable_stack_log_normalize",
&test_reftable_stack_log_normalize);
add_test_case("test_reftable_stack_tombstone",
&test_reftable_stack_tombstone);
add_test_case("test_reftable_stack_add_one",
Expand Down
21 changes: 21 additions & 0 deletions c/writer.c
Expand Up @@ -289,6 +289,8 @@ int reftable_writer_add_log(struct reftable_writer *w,
struct reftable_log_record *log)
{
struct reftable_record rec = { 0 };
char *input_log_message = log->message;
struct slice cleaned_message = SLICE_INIT;
int err;
if (log->ref_name == NULL)
return REFTABLE_API_ERROR;
Expand All @@ -300,11 +302,30 @@ int reftable_writer_add_log(struct reftable_writer *w,
return err;
}

if (!w->opts.exact_log_message && log->message != NULL) {
slice_set_string(&cleaned_message, log->message);

while (cleaned_message.len &&
cleaned_message.buf[cleaned_message.len - 1] == '\n')
cleaned_message.len--;
if (strchr(slice_as_string(&cleaned_message), '\n')) {
// multiple lines not allowed.
err = REFTABLE_API_ERROR;
goto done;
}
slice_addstr(&cleaned_message, "\n");
log->message = (char *)slice_as_string(&cleaned_message);
}

w->next -= w->pending_padding;
w->pending_padding = 0;

reftable_record_from_log(&rec, log);
err = writer_add_record(w, &rec);

done:
log->message = input_log_message;
slice_release(&cleaned_message);
return err;
}

Expand Down

0 comments on commit 785f745

Please sign in to comment.