]> git.proxmox.com Git - libgit2.git/commitdiff
signature: straighten the creation of a signature
authornulltoken <emeric.fermas@gmail.com>
Sun, 3 Jul 2011 12:03:43 +0000 (14:03 +0200)
committerVicent Marti <tanoku@gmail.com>
Tue, 5 Jul 2011 00:21:26 +0000 (02:21 +0200)
 - Fails on empty name and/or email
 - Trims leading and trailing spaces of name and email

src/signature.c
tests/t04-commit.c

index b8356dacf3bf8b021b123e5fde13c40ec384d724..bc88a76e195420842fb663b10e3b599bc78e26a0 100644 (file)
@@ -33,25 +33,83 @@ void git_signature_free(git_signature *sig)
        if (sig == NULL)
                return;
 
-       free(sig->name);
-       free(sig->email);
+       if (sig->name)
+               free(sig->name);
+
+       if (sig->email)
+               free(sig->email);
+
        free(sig);
 }
 
+static const char *skip_leading_spaces(const char *buffer, const char *buffer_end)
+{
+       while (*buffer == ' ' && buffer < buffer_end)
+               buffer++;
+
+       return buffer;
+}
+
+static const char *skip_trailing_spaces(const char *buffer_start, const char *buffer_end)
+{
+       while (*buffer_end == ' ' && buffer_end > buffer_start)
+               buffer_end--;
+
+       return buffer_end;
+}
+
+static int process_trimming(const char *input, char **storage, const char *input_end, int fail_when_empty)
+{
+       const char *left, *right;
+       int trimmed_input_length;
+
+       left = skip_leading_spaces(input, input_end);
+       right = skip_trailing_spaces(input, input_end - 1);
+
+       if (right <= left)
+               if (fail_when_empty)
+                       return git__throw(GIT_EINVALIDARGS, "Failed to trim. Input is either empty or only contains spaces");
+               else
+                       right = left - 1;
+
+       trimmed_input_length = right - left + 1;
+
+       *storage = git__malloc(trimmed_input_length + 1);
+       if (*storage == NULL)
+               return GIT_ENOMEM;
+
+       memcpy(*storage, left, trimmed_input_length);
+       (*storage)[trimmed_input_length] = 0;
+
+       return GIT_SUCCESS;
+}
+
 git_signature *git_signature_new(const char *name, const char *email, git_time_t time, int offset)
 {
+       int error;
        git_signature *p = NULL;
 
+       assert(name && email);
+
        if ((p = git__malloc(sizeof(git_signature))) == NULL)
                goto cleanup;
 
-       p->name = git__strdup(name);
-       p->email = git__strdup(email);
-       p->when.time = time;
-       p->when.offset = offset;
+       memset(p, 0x0, sizeof(git_signature));
+
+       error = process_trimming(name, &p->name, name + strlen(name), 1);
+       if (error < GIT_SUCCESS) {
+               git__rethrow(GIT_EINVALIDARGS, "Failed to create signature. 'name' argument is invalid");
+               goto cleanup;
+       }
 
-       if (p->name == NULL || p->email == NULL)
+       error = process_trimming(email, &p->email, email + strlen(email), 1);
+       if (error < GIT_SUCCESS) {
+               git__rethrow(GIT_EINVALIDARGS, "Failed to create signature. 'email' argument is invalid");
                goto cleanup;
+       }
+
+       p->when.time = time;
+       p->when.offset = offset;
 
        return p;
 
@@ -149,46 +207,28 @@ static int parse_timezone_offset(const char *buffer, int *offset_out)
 }
 
 int process_next_token(const char **buffer_out, char **storage,
-       const char *token_end, const char *line_end)
+       const char *token_end, const char *right_boundary)
 {
-       int name_length = 0;
-       const char *buffer = *buffer_out;
-
-       /* Skip leading spaces before the name */
-       while (*buffer == ' ' && buffer < line_end)
-               buffer++;
-
-       name_length = token_end - buffer;
-
-       /* Trim trailing spaces after the name */
-       while (buffer[name_length - 1] == ' ' && name_length > 0)
-               name_length--;
-
-       *storage = git__malloc(name_length + 1);
-       if (*storage == NULL)
-               return GIT_ENOMEM;
+       int error = process_trimming(*buffer_out, storage, token_end, 0);
+       if (error < GIT_SUCCESS)
+               return error;
 
-       memcpy(*storage, buffer, name_length);
-       (*storage)[name_length] = 0;
-       buffer = token_end + 1;
+       *buffer_out = token_end + 1;
 
-       if (buffer > line_end)
+       if (*buffer_out > right_boundary)
                return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
 
-       *buffer_out = buffer;
        return GIT_SUCCESS;
 }
 
-const charscan_for_previous_token(const char *buffer, const char *left_boundary)
+const char *scan_for_previous_token(const char *buffer, const char *left_boundary)
 {
-       const char *start = buffer;
+       const char *start;
 
-       if (start <= left_boundary)
+       if (buffer <= left_boundary)
                return NULL;
 
-       /* Trim potential trailing spaces */
-       while (*start == ' ' && start > left_boundary)
-               start--;
+       start = skip_trailing_spaces(left_boundary, buffer);
 
        /* Search for previous occurence of space */
        while (start[-1] != ' ' && start > left_boundary)
index 52770720e42660ef2f2f176d514c1d7262a5defe..0f480e552fe8b1f757409da7c1ce5bce33e69bfa 100644 (file)
@@ -331,7 +331,6 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
                123456,
                -60);
 
-
        /* Parse an obviously invalid signature */
        TEST_SIGNATURE_PASS(
                "committer <>\n",
@@ -446,6 +445,39 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
 
 END_TEST
 
+static int try_build_signature(const char *name, const char *email, git_time_t time, int offset)
+{
+       git_signature *sign;
+       int error = GIT_SUCCESS;
+
+       sign = git_signature_new(name, email, time, offset);
+
+       if (sign == NULL)
+               error = GIT_ERROR;
+
+       git_signature_free((git_signature *)sign);
+
+       return error;
+}
+
+BEGIN_TEST(signature0, "creating a signature trims leading and trailing spaces")
+       git_signature *sign;
+       sign = git_signature_new("  nulltoken ", "   emeric.fermas@gmail.com     ", 1234567890, 60);
+       must_be_true(sign != NULL);
+       must_pass(strcmp(sign->name, "nulltoken"));
+       must_pass(strcmp(sign->email, "emeric.fermas@gmail.com"));
+       git_signature_free((git_signature *)sign);
+END_TEST
+
+BEGIN_TEST(signature1, "can not create a signature with empty name or email")
+       must_pass(try_build_signature("nulltoken", "emeric.fermas@gmail.com", 1234567890, 60));
+
+       must_fail(try_build_signature("", "emeric.fermas@gmail.com", 1234567890, 60));
+       must_fail(try_build_signature("   ", "emeric.fermas@gmail.com", 1234567890, 60));
+       must_fail(try_build_signature("nulltoken", "", 1234567890, 60));
+       must_fail(try_build_signature("nulltoken", "  ", 1234567890, 60));
+END_TEST
+
 /* External declaration for testing the buffer parsing method */
 int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int parse_flags);
 
@@ -722,4 +754,7 @@ BEGIN_SUITE(commit)
        ADD_TEST(write0);
 
        ADD_TEST(root0);
+
+       ADD_TEST(signature0);
+       ADD_TEST(signature1);
 END_SUITE