]> git.proxmox.com Git - libgit2.git/blame - src/ident.c
Upload to experimental
[libgit2.git] / src / ident.c
CommitLineData
4b11f25a
RB
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
eae0bfdc
PP
8#include "common.h"
9
4b11f25a
RB
10#include "git2/sys/filter.h"
11#include "filter.h"
e579e0f7 12#include "str.h"
4b11f25a 13
a9f51e43 14static int ident_find_id(
4b11f25a
RB
15 const char **id_start, const char **id_end, const char *start, size_t len)
16{
eefc32d5 17 const char *end = start + len, *found = NULL;
4b11f25a 18
eefc32d5
RB
19 while (len > 3 && (found = memchr(start, '$', len)) != NULL) {
20 size_t remaining = (size_t)(end - found) - 1;
4b11f25a
RB
21 if (remaining < 3)
22 return GIT_ENOTFOUND;
eefc32d5 23
4b11f25a 24 start = found + 1;
eefc32d5
RB
25 len = remaining;
26
27 if (start[0] == 'I' && start[1] == 'd')
28 break;
4b11f25a
RB
29 }
30
eefc32d5 31 if (len < 3 || !found)
4b11f25a
RB
32 return GIT_ENOTFOUND;
33 *id_start = found;
34
eefc32d5 35 if ((found = memchr(start + 2, '$', len - 2)) == NULL)
4b11f25a
RB
36 return GIT_ENOTFOUND;
37
38 *id_end = found + 1;
39 return 0;
40}
41
42static int ident_insert_id(
e579e0f7 43 git_str *to, const git_str *from, const git_filter_source *src)
4b11f25a
RB
44{
45 char oid[GIT_OID_HEXSZ+1];
46 const char *id_start, *id_end, *from_end = from->ptr + from->size;
47 size_t need_size;
4b11f25a
RB
48
49 /* replace $Id$ with blob id */
50
51 if (!git_filter_source_id(src))
eefc32d5 52 return GIT_PASSTHROUGH;
4b11f25a
RB
53
54 git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src));
55
56 if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
eefc32d5 57 return GIT_PASSTHROUGH;
4b11f25a
RB
58
59 need_size = (size_t)(id_start - from->ptr) +
1ecbcd8e 60 5 /* "$Id: " */ + GIT_OID_HEXSZ + 2 /* " $" */ +
4b11f25a
RB
61 (size_t)(from_end - id_end);
62
e579e0f7 63 if (git_str_grow(to, need_size) < 0)
4b11f25a
RB
64 return -1;
65
e579e0f7
MB
66 git_str_set(to, from->ptr, (size_t)(id_start - from->ptr));
67 git_str_put(to, "$Id: ", 5);
68 git_str_put(to, oid, GIT_OID_HEXSZ);
69 git_str_put(to, " $", 2);
70 git_str_put(to, id_end, (size_t)(from_end - id_end));
4b11f25a 71
e579e0f7 72 return git_str_oom(to) ? -1 : 0;
4b11f25a
RB
73}
74
75static int ident_remove_id(
e579e0f7 76 git_str *to, const git_str *from)
4b11f25a
RB
77{
78 const char *id_start, *id_end, *from_end = from->ptr + from->size;
79 size_t need_size;
4b11f25a
RB
80
81 if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
eefc32d5 82 return GIT_PASSTHROUGH;
4b11f25a
RB
83
84 need_size = (size_t)(id_start - from->ptr) +
85 4 /* "$Id$" */ + (size_t)(from_end - id_end);
86
e579e0f7 87 if (git_str_grow(to, need_size) < 0)
4b11f25a
RB
88 return -1;
89
e579e0f7
MB
90 git_str_set(to, from->ptr, (size_t)(id_start - from->ptr));
91 git_str_put(to, "$Id$", 4);
92 git_str_put(to, id_end, (size_t)(from_end - id_end));
4b11f25a 93
e579e0f7 94 return git_str_oom(to) ? -1 : 0;
4b11f25a
RB
95}
96
97static int ident_apply(
a9f51e43
RB
98 git_filter *self,
99 void **payload,
e579e0f7
MB
100 git_str *to,
101 const git_str *from,
4b11f25a
RB
102 const git_filter_source *src)
103{
104 GIT_UNUSED(self); GIT_UNUSED(payload);
105
eab3746b 106 /* Don't filter binary files */
e579e0f7 107 if (git_str_is_binary(from))
eefc32d5 108 return GIT_PASSTHROUGH;
eab3746b 109
4b11f25a
RB
110 if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
111 return ident_insert_id(to, from, src);
112 else
113 return ident_remove_id(to, from);
114}
115
c25aa7cd
PP
116static int ident_stream(
117 git_writestream **out,
118 git_filter *self,
119 void **payload,
120 const git_filter_source *src,
121 git_writestream *next)
122{
123 return git_filter_buffered_stream_new(out,
124 self, ident_apply, NULL, payload, src, next);
125}
126
4b11f25a
RB
127git_filter *git_ident_filter_new(void)
128{
129 git_filter *f = git__calloc(1, sizeof(git_filter));
dfda1cf5
JG
130 if (f == NULL)
131 return NULL;
4b11f25a
RB
132
133 f->version = GIT_FILTER_VERSION;
134 f->attributes = "+ident"; /* apply to files with ident attribute set */
135 f->shutdown = git_filter_free;
c25aa7cd 136 f->stream = ident_stream;
4b11f25a
RB
137
138 return f;
139}