diff options
author | Ben Straub <bstraub@github.com> | 2012-07-31 15:38:12 -0700 |
---|---|---|
committer | Ben Straub <bstraub@github.com> | 2012-07-31 15:38:12 -0700 |
commit | e4bac3c4692834e6d0ca607aca229ddcae0ba2b7 (patch) | |
tree | f92323cd67cfadb1f412742e03644ff73cc2a009 | |
parent | 8e4aae1ae5f9f023641ab4046dfee6c744e58e13 (diff) | |
download | libgit2-e4bac3c4692834e6d0ca607aca229ddcae0ba2b7.tar.gz |
Checkout: crlf filter.
-rw-r--r-- | src/crlf.c | 88 | ||||
-rw-r--r-- | tests-clar/checkout/checkout.c | 12 |
2 files changed, 83 insertions, 17 deletions
diff --git a/src/crlf.c b/src/crlf.c index f68938e61..509e55897 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -184,6 +184,85 @@ static int crlf_apply_to_odb(git_filter *self, git_buf *dest, const git_buf *sou return drop_crlf(dest, source); } +static int convert_line_endings(git_buf *dest, const git_buf *source, const char *ending) +{ + const char *scan = git_buf_cstr(source), + *next, + *scan_end = git_buf_cstr(source) + git_buf_len(source); + + while ((next = memchr(scan, '\n', scan_end - scan)) != NULL) { + if (next > scan) + git_buf_put(dest, scan, next-scan); + git_buf_puts(dest, ending); + scan = next + 1; + } + + git_buf_put(dest, scan, scan_end - scan); + return 0; +} + +static const char *line_ending(struct crlf_filter *filter) +{ + switch (filter->attrs.crlf_action) { + case GIT_CRLF_BINARY: + case GIT_CRLF_INPUT: + return "\n"; + + case GIT_CRLF_CRLF: + return "\r\n"; + + case GIT_CRLF_AUTO: + case GIT_CRLF_TEXT: + case GIT_CRLF_GUESS: + break; + + default: + goto line_ending_error; + } + + switch (filter->attrs.eol) { + case GIT_EOL_UNSET: + return GIT_EOL_NATIVE == GIT_EOL_CRLF + ? "\r\n" + : "\n"; + + case GIT_EOL_CRLF: + return "\r\n"; + + case GIT_EOL_LF: + return "\n"; + + default: + goto line_ending_error; + } + +line_ending_error: + giterr_set(GITERR_INVALID, "Invalid input to line ending filter"); + return NULL; +} + +static int crlf_apply_to_workdir(git_filter *self, git_buf *dest, const git_buf *source) +{ + struct crlf_filter *filter = (struct crlf_filter *)self; + const char *workdir_ending = NULL; + + assert (self && dest && source); + + /* Empty file? Nothing to do. */ + if (git_buf_len(source) == 0) + return 0; + + /* Determine proper line ending */ + workdir_ending = line_ending(filter); + if (!workdir_ending) return -1; + + /* If the line ending is '\n', just copy the input */ + if (!strcmp(workdir_ending, "\n")) + return git_buf_puts(dest, git_buf_cstr(source)); + + return convert_line_endings(dest, source, workdir_ending); +} + static int find_and_add_filter(git_vector *filters, git_repository *repo, const char *path, int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source)) { @@ -207,8 +286,7 @@ static int find_and_add_filter(git_vector *filters, git_repository *repo, const if (ca.crlf_action == GIT_CRLF_GUESS) { int auto_crlf; - if ((error = git_repository__cvar( - &auto_crlf, repo, GIT_CVAR_AUTO_CRLF)) < 0) + if ((error = git_repository__cvar(&auto_crlf, repo, GIT_CVAR_AUTO_CRLF)) < 0) return error; if (auto_crlf == GIT_AUTO_CRLF_FALSE) @@ -227,12 +305,6 @@ static int find_and_add_filter(git_vector *filters, git_repository *repo, const return git_vector_insert(filters, filter); } -static int crlf_apply_to_workdir(git_filter *self, git_buf *dest, const git_buf *source) -{ - /* TODO */ - return -1; -} - int git_filter_add__crlf_to_odb(git_vector *filters, git_repository *repo, const char *path) { return find_and_add_filter(filters, repo, path, &crlf_apply_to_odb); diff --git a/tests-clar/checkout/checkout.c b/tests-clar/checkout/checkout.c index 5099c4e16..9551cba47 100644 --- a/tests-clar/checkout/checkout.c +++ b/tests-clar/checkout/checkout.c @@ -58,15 +58,9 @@ void test_checkout_checkout__crlf(void) "new.txt text eol=lf\n"; cl_git_mkfile("./testrepo/.gitattributes", attributes); cl_git_pass(git_checkout_head(g_repo, NULL, NULL)); - /* TODO: enable these when crlf is ready */ - /* test_file_contents("./testrepo/README", "hey there\n"); */ - /* test_file_contents("./testrepo/new.txt", "my new file\n"); */ - /* test_file_contents("./testrepo/branch_file.txt", "hi\r\nbye!\r\n"); */ -} - -void test_checkout_checkout__stats(void) -{ - /* TODO */ + test_file_contents("./testrepo/README", "hey there\n"); + test_file_contents("./testrepo/new.txt", "my new file\n"); + test_file_contents("./testrepo/branch_file.txt", "hi\r\nbye!\r\n"); } static void enable_symlinks(bool enable) |