source src/ident.c
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 | - | } |