diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/blob.c | 8 | ||||
-rw-r--r-- | src/checkout.c | 2 | ||||
-rw-r--r-- | src/crlf.c | 7 | ||||
-rw-r--r-- | src/diff.c | 2 | ||||
-rw-r--r-- | src/diff_file.c | 2 | ||||
-rw-r--r-- | src/filter.c | 31 | ||||
-rw-r--r-- | src/filter.h | 3 | ||||
-rw-r--r-- | src/ident.c | 128 | ||||
-rw-r--r-- | src/repository.c | 3 |
9 files changed, 170 insertions, 16 deletions
diff --git a/src/blob.c b/src/blob.c index e6bba033a..97fd6f70d 100644 --- a/src/blob.c +++ b/src/blob.c @@ -195,7 +195,7 @@ int git_blob__create_from_paths( if (try_load_filters) /* Load the filters for writing this file to the ODB */ error = git_filter_list_load( - &fl, repo, hint_path, GIT_FILTER_TO_ODB); + &fl, repo, NULL, hint_path, GIT_FILTER_TO_ODB); if (error < 0) /* well, that didn't work */; @@ -331,19 +331,19 @@ int git_blob_is_binary(git_blob *blob) int git_blob_filtered_content( git_buffer *out, git_blob *blob, - const char *as_path, + const char *path, int check_for_binary_data) { int error = 0; git_filter_list *fl = NULL; - assert(blob && as_path && out); + assert(blob && path && out); if (check_for_binary_data && git_blob_is_binary(blob)) return 0; if (!(error = git_filter_list_load( - &fl, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE))) { + &fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE))) { error = git_filter_list_apply_to_blob(out, fl, blob); diff --git a/src/checkout.c b/src/checkout.c index 1def58b0a..7e79c9b5e 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -718,7 +718,7 @@ static int blob_content_to_file( if (!opts->disable_filters && !git_blob_is_binary(blob)) error = git_filter_list_load( - &fl, git_blob_owner(blob), path, GIT_FILTER_TO_WORKTREE); + &fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE); if (!error) error = git_filter_list_apply_to_blob(&out, fl, blob); diff --git a/src/crlf.c b/src/crlf.c index 99c154f70..f61a870da 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -324,11 +324,6 @@ static void crlf_cleanup( git__free(payload); } -static void crlf_shutdown(git_filter *self) -{ - git__free(self); -} - git_filter *git_crlf_filter_new(void) { struct crlf_filter *f = git__calloc(1, sizeof(struct crlf_filter)); @@ -336,7 +331,7 @@ git_filter *git_crlf_filter_new(void) f->f.version = GIT_FILTER_VERSION; f->f.attributes = "crlf eol text"; f->f.initialize = NULL; - f->f.shutdown = crlf_shutdown; + f->f.shutdown = git_filter_free; f->f.check = crlf_check; f->f.apply = crlf_apply; f->f.cleanup = crlf_cleanup; diff --git a/src/diff.c b/src/diff.c index b1cde36bc..4d9ace183 100644 --- a/src/diff.c +++ b/src/diff.c @@ -570,7 +570,7 @@ int git_diff__oid_for_file( } else { git_filter_list *fl = NULL; - result = git_filter_list_load(&fl, repo, path, GIT_FILTER_TO_ODB); + result = git_filter_list_load(&fl, repo, NULL, path, GIT_FILTER_TO_ODB); if (!result) { int fd = git_futils_open_ro(full_path.ptr); if (fd < 0) diff --git a/src/diff_file.c b/src/diff_file.c index e0e244b65..d02787c75 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -311,7 +311,7 @@ static int diff_file_content_load_workdir_file( goto cleanup; if ((error = git_filter_list_load( - &fl, fc->repo, fc->file->path, GIT_FILTER_TO_ODB)) < 0) + &fl, fc->repo, NULL, fc->file->path, GIT_FILTER_TO_ODB)) < 0) goto cleanup; /* if there are no filters, try to mmap the file */ diff --git a/src/filter.c b/src/filter.c index 79ccac0cf..f20611471 100644 --- a/src/filter.c +++ b/src/filter.c @@ -103,7 +103,23 @@ static int filter_registry_initialize(void) git__on_shutdown(filter_registry_shutdown); - return git_filter_register(GIT_FILTER_CRLF, git_crlf_filter_new(), 0); + /* try to register both default filters */ + { + git_filter *crlf = git_crlf_filter_new(); + git_filter *ident = git_ident_filter_new(); + + if (crlf && git_filter_register( + GIT_FILTER_CRLF, crlf, GIT_FILTER_CRLF_PRIORITY) < 0) + crlf = NULL; + if (ident && git_filter_register( + GIT_FILTER_IDENT, ident, GIT_FILTER_IDENT_PRIORITY) < 0) + ident = NULL; + + if (!crlf || !ident) + return -1; + } + + return 0; cleanup: git_vector_free(®->filters); @@ -132,7 +148,7 @@ static int filter_def_scan_attrs( if (scan > start) { (*nattr)++; - if (has_eq || *scan == '-' || *scan == '+' || *scan == '!') + if (has_eq || *start == '-' || *start == '+' || *start == '!') (*nmatch)++; if (has_eq) @@ -312,6 +328,11 @@ git_filter *git_filter_lookup(const char *name) return fdef->filter; } +void git_filter_free(git_filter *filter) +{ + git__free(filter); +} + git_repository *git_filter_source_repo(const git_filter_source *src) { return src->repo; @@ -410,6 +431,7 @@ int git_filter_list_new( int git_filter_list_load( git_filter_list **filters, git_repository *repo, + git_blob *blob, /* can be NULL */ const char *path, git_filter_mode_t mode) { @@ -426,6 +448,8 @@ int git_filter_list_load( src.repo = repo; src.path = path; src.mode = mode; + if (blob) + git_oid_cpy(&src.oid, git_blob_id(blob)); git_vector_foreach(&git__filter_registry->filters, idx, fdef) { const char **values = NULL; @@ -630,5 +654,8 @@ int git_filter_list_apply_to_blob( (char *)git_blob_rawcontent(blob), git_blob_rawsize(blob), 0 }; + if (filters) + git_oid_cpy(&filters->source.oid, git_blob_id(blob)); + return git_filter_list_apply_to_data(out, filters, &in); } diff --git a/src/filter.h b/src/filter.h index 1bde1e306..d0ace0f9a 100644 --- a/src/filter.h +++ b/src/filter.h @@ -19,10 +19,13 @@ typedef enum { GIT_CRLF_AUTO, } git_crlf_t; +extern void git_filter_free(git_filter *filter); + /* * Available filters */ extern git_filter *git_crlf_filter_new(void); +extern git_filter *git_ident_filter_new(void); #endif diff --git a/src/ident.c b/src/ident.c new file mode 100644 index 000000000..aedb973f9 --- /dev/null +++ b/src/ident.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "git2/sys/filter.h" +#include "filter.h" +#include "buffer.h" + +int ident_find_id( + const char **id_start, const char **id_end, const char *start, size_t len) +{ + const char *found; + + while (len > 0 && (found = memchr(start, '$', len)) != NULL) { + size_t remaining = len - (size_t)(found - start); + if (remaining < 3) + return GIT_ENOTFOUND; + if (found[1] == 'I' && found[2] == 'd') + break; + start = found + 1; + len = remaining - 1; + } + + if (len < 3) + return GIT_ENOTFOUND; + *id_start = found; + + if ((found = memchr(found + 3, '$', len - 3)) == NULL) + return GIT_ENOTFOUND; + + *id_end = found + 1; + return 0; +} + +static int ident_insert_id( + git_buffer *to, const git_buffer *from, const git_filter_source *src) +{ + char oid[GIT_OID_HEXSZ+1]; + const char *id_start, *id_end, *from_end = from->ptr + from->size; + size_t need_size; + git_buf to_buf = GIT_BUF_FROM_BUFFER(to); + + /* replace $Id$ with blob id */ + + if (!git_filter_source_id(src)) + return GIT_ENOTFOUND; + + git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src)); + + if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) + return GIT_ENOTFOUND; + + need_size = (size_t)(id_start - from->ptr) + + 5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ + + (size_t)(from_end - id_end); + + if (git_buf_grow(&to_buf, need_size) < 0) + return -1; + + git_buf_set(&to_buf, from->ptr, (size_t)(id_start - from->ptr)); + git_buf_put(&to_buf, "$Id: ", 5); + git_buf_put(&to_buf, oid, GIT_OID_HEXSZ); + git_buf_putc(&to_buf, '$'); + git_buf_put(&to_buf, id_end, (size_t)(from_end - id_end)); + + if (git_buf_oom(&to_buf)) + return -1; + + git_buffer_from_buf(to, &to_buf); + return 0; +} + +static int ident_remove_id( + git_buffer *to, const git_buffer *from) +{ + const char *id_start, *id_end, *from_end = from->ptr + from->size; + size_t need_size; + git_buf to_buf = GIT_BUF_FROM_BUFFER(to); + + if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) + return GIT_ENOTFOUND; + + need_size = (size_t)(id_start - from->ptr) + + 4 /* "$Id$" */ + (size_t)(from_end - id_end); + + if (git_buf_grow(&to_buf, need_size) < 0) + return -1; + + git_buf_set(&to_buf, from->ptr, (size_t)(id_start - from->ptr)); + git_buf_put(&to_buf, "$Id$", 4); + git_buf_put(&to_buf, id_end, (size_t)(from_end - id_end)); + + if (git_buf_oom(&to_buf)) + return -1; + + git_buffer_from_buf(to, &to_buf); + return 0; +} + +static int ident_apply( + git_filter *self, + void **payload, + git_buffer *to, + const git_buffer *from, + const git_filter_source *src) +{ + GIT_UNUSED(self); GIT_UNUSED(payload); + + if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) + return ident_insert_id(to, from, src); + else + return ident_remove_id(to, from); +} + +git_filter *git_ident_filter_new(void) +{ + git_filter *f = git__calloc(1, sizeof(git_filter)); + + f->version = GIT_FILTER_VERSION; + f->attributes = "+ident"; /* apply to files with ident attribute set */ + f->shutdown = git_filter_free; + f->apply = ident_apply; + + return f; +} diff --git a/src/repository.c b/src/repository.c index 94700e4e3..76e8228b7 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1671,7 +1671,8 @@ int git_repository_hashfile( /* passing empty string for "as_path" indicated --no-filters */ if (strlen(as_path) > 0) { - error = git_filter_list_load(&fl, repo, as_path, GIT_FILTER_TO_ODB); + error = git_filter_list_load( + &fl, repo, NULL, as_path, GIT_FILTER_TO_ODB); if (error < 0) return error; } else { |