Line Flow Count Block(s) Source
1 - /*
2 - * Copyright (C) the libgit2 contributors. All rights reserved.
3 - *
4 - * This file is part of libgit2, distributed under the GNU GPL v2 with
5 - * a Linking Exception. For full terms see the included COPYING file.
6 - */
7 -
8 - #include "common.h"
9 -
10 - #include "git2/sys/filter.h"
11 - #include "filter.h"
12 - #include "buffer.h"
13 - #include "buf_text.h"
14 -
15 48 2 static int ident_find_id(
16 - const char **id_start, const char **id_end, const char *start, size_t len)
17 - {
18 48 2 const char *end = start + len, *found = NULL;
19 -
20 52 2,8,9 while (len > 3 && (found = memchr(start, '$', len)) != NULL) {
21 44 3 size_t remaining = (size_t)(end - found) - 1;
22 44 3 if (remaining < 3)
23 1 4 return GIT_ENOTFOUND;
24 -
25 43 5 start = found + 1;
26 43 5 len = remaining;
27 -
28 43 5,6 if (start[0] == 'I' && start[1] == 'd')
29 39 7 break;
30 - }
31 -
32 47 10,11 if (len < 3 || !found)
33 8 12 return GIT_ENOTFOUND;
34 39 13 *id_start = found;
35 -
36 39 13 if ((found = memchr(start + 2, '$', len - 2)) == NULL)
37 4 14 return GIT_ENOTFOUND;
38 -
39 35 15 *id_end = found + 1;
40 35 15 return 0;
41 - }
42 -
43 20 2 static int ident_insert_id(
44 - git_buf *to, const git_buf *from, const git_filter_source *src)
45 - {
46 - char oid[GIT_OID_HEXSZ+1];
47 20 2 const char *id_start, *id_end, *from_end = from->ptr + from->size;
48 - size_t need_size;
49 -
50 - /* replace $Id$ with blob id */
51 -
52 20 2,3 if (!git_filter_source_id(src))
53 ##### 4 return GIT_PASSTHROUGH;
54 -
55 20 5,6 git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src));
56 -
57 20 7,8 if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
58 5 9 return GIT_PASSTHROUGH;
59 -
60 15 10,10 need_size = (size_t)(id_start - from->ptr) +
61 15 10 5 /* "$Id: " */ + GIT_OID_HEXSZ + 2 /* " $" */ +
62 15 10 (size_t)(from_end - id_end);
63 -
64 15 10,11 if (git_buf_grow(to, need_size) < 0)
65 ##### 12 return -1;
66 -
67 15 13 git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
68 15 14 git_buf_put(to, "$Id: ", 5);
69 15 15 git_buf_put(to, oid, GIT_OID_HEXSZ);
70 15 16 git_buf_put(to, " $", 2);
71 15 17 git_buf_put(to, id_end, (size_t)(from_end - id_end));
72 -
73 15 18 return git_buf_oom(to) ? -1 : 0;
74 - }
75 -
76 28 2 static int ident_remove_id(
77 - git_buf *to, const git_buf *from)
78 - {
79 28 2 const char *id_start, *id_end, *from_end = from->ptr + from->size;
80 - size_t need_size;
81 -
82 28 2,3 if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
83 8 4 return GIT_PASSTHROUGH;
84 -
85 20 5,5 need_size = (size_t)(id_start - from->ptr) +
86 20 5 4 /* "$Id$" */ + (size_t)(from_end - id_end);
87 -
88 20 5,6 if (git_buf_grow(to, need_size) < 0)
89 ##### 7 return -1;
90 -
91 20 8 git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
92 20 9 git_buf_put(to, "$Id$", 4);
93 20 10 git_buf_put(to, id_end, (size_t)(from_end - id_end));
94 -
95 20 11 return git_buf_oom(to) ? -1 : 0;
96 - }
97 -
98 48 2 static int ident_apply(
99 - git_filter *self,
100 - void **payload,
101 - git_buf *to,
102 - const git_buf *from,
103 - const git_filter_source *src)
104 - {
105 - GIT_UNUSED(self); GIT_UNUSED(payload);
106 -
107 - /* Don't filter binary files */
108 48 2,3 if (git_buf_text_is_binary(from))
109 ##### 4 return GIT_PASSTHROUGH;
110 -
111 48 5,6 if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
112 20 7 return ident_insert_id(to, from, src);
113 - else
114 28 8 return ident_remove_id(to, from);
115 - }
116 -
117 9 2 git_filter *git_ident_filter_new(void)
118 - {
119 9 2 git_filter *f = git__calloc(1, sizeof(git_filter));
120 9 3 if (f == NULL)
121 ##### 4 return NULL;
122 -
123 9 5 f->version = GIT_FILTER_VERSION;
124 9 5 f->attributes = "+ident"; /* apply to files with ident attribute set */
125 9 5 f->shutdown = git_filter_free;
126 9 5 f->apply = ident_apply;
127 -
128 9 5 return f;
129 - }