File Coverage

deps/libgit2/src/ident.c
Criterion Covered Total %
statement 8 62 12.9
branch 1 36 2.7
condition n/a
subroutine n/a
pod n/a
total 9 98 9.1


line stmt bran cond sub pod time code
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 0           static int ident_find_id(
16             const char **id_start, const char **id_end, const char *start, size_t len)
17             {
18 0           const char *end = start + len, *found = NULL;
19              
20 0 0         while (len > 3 && (found = memchr(start, '$', len)) != NULL) {
    0          
21 0           size_t remaining = (size_t)(end - found) - 1;
22 0 0         if (remaining < 3)
23 0           return GIT_ENOTFOUND;
24              
25 0           start = found + 1;
26 0           len = remaining;
27              
28 0 0         if (start[0] == 'I' && start[1] == 'd')
    0          
29 0           break;
30             }
31              
32 0 0         if (len < 3 || !found)
    0          
33 0           return GIT_ENOTFOUND;
34 0           *id_start = found;
35              
36 0 0         if ((found = memchr(start + 2, '$', len - 2)) == NULL)
37 0           return GIT_ENOTFOUND;
38              
39 0           *id_end = found + 1;
40 0           return 0;
41             }
42              
43 0           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 0           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 0 0         if (!git_filter_source_id(src))
53 0           return GIT_PASSTHROUGH;
54              
55 0           git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src));
56              
57 0 0         if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
58 0           return GIT_PASSTHROUGH;
59              
60 0           need_size = (size_t)(id_start - from->ptr) +
61 0           5 /* "$Id: " */ + GIT_OID_HEXSZ + 2 /* " $" */ +
62 0           (size_t)(from_end - id_end);
63              
64 0 0         if (git_buf_grow(to, need_size) < 0)
65 0           return -1;
66              
67 0           git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
68 0           git_buf_put(to, "$Id: ", 5);
69 0           git_buf_put(to, oid, GIT_OID_HEXSZ);
70 0           git_buf_put(to, " $", 2);
71 0           git_buf_put(to, id_end, (size_t)(from_end - id_end));
72              
73 0 0         return git_buf_oom(to) ? -1 : 0;
74             }
75              
76 0           static int ident_remove_id(
77             git_buf *to, const git_buf *from)
78             {
79 0           const char *id_start, *id_end, *from_end = from->ptr + from->size;
80             size_t need_size;
81              
82 0 0         if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
83 0           return GIT_PASSTHROUGH;
84              
85 0           need_size = (size_t)(id_start - from->ptr) +
86 0           4 /* "$Id$" */ + (size_t)(from_end - id_end);
87              
88 0 0         if (git_buf_grow(to, need_size) < 0)
89 0           return -1;
90              
91 0           git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
92 0           git_buf_put(to, "$Id$", 4);
93 0           git_buf_put(to, id_end, (size_t)(from_end - id_end));
94              
95 0 0         return git_buf_oom(to) ? -1 : 0;
96             }
97              
98 0           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 0 0         if (git_buf_text_is_binary(from))
109 0           return GIT_PASSTHROUGH;
110              
111 0 0         if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
112 0           return ident_insert_id(to, from, src);
113             else
114 0           return ident_remove_id(to, from);
115             }
116              
117 86           git_filter *git_ident_filter_new(void)
118             {
119 86           git_filter *f = git__calloc(1, sizeof(git_filter));
120 86 50         if (f == NULL)
121 0           return NULL;
122              
123 86           f->version = GIT_FILTER_VERSION;
124 86           f->attributes = "+ident"; /* apply to files with ident attribute set */
125 86           f->shutdown = git_filter_free;
126 86           f->apply = ident_apply;
127              
128 86           return f;
129             }