]>
Commit | Line | Data |
---|---|---|
44b1ff4c VM |
1 | /* |
2 | * Copyright (C) 2009-2012 the libgit2 contributors | |
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 | #include "fileops.h" | |
10 | #include "hash.h" | |
11 | #include "filter.h" | |
12 | ||
13 | /* Fresh from Core Git. I wonder what we could use this for... */ | |
14 | void git_text__stat(git_text_stats *stats, git_buf *text) | |
15 | { | |
16 | size_t i; | |
17 | ||
18 | memset(stats, 0, sizeof(*stats)); | |
19 | ||
20 | for (i = 0; i < text->size; i++) { | |
21 | unsigned char c = text->ptr[i]; | |
22 | ||
23 | if (c == '\r') { | |
24 | stats->cr++; | |
25 | ||
26 | if (i + 1 < text->size && text->ptr[i + 1] == '\n') | |
27 | stats->crlf++; | |
28 | ||
29 | continue; | |
30 | } | |
31 | ||
32 | if (c == '\n') { | |
33 | stats->lf++; | |
34 | continue; | |
35 | } | |
36 | ||
37 | if (c == 127) | |
38 | /* DEL */ | |
39 | stats->nonprintable++; | |
40 | ||
41 | else if (c < 32) { | |
42 | switch (c) { | |
43 | /* BS, HT, ESC and FF */ | |
44 | case '\b': case '\t': case '\033': case '\014': | |
45 | stats->printable++; | |
46 | break; | |
47 | case 0: | |
48 | stats->nul++; | |
49 | /* fall through */ | |
50 | default: | |
51 | stats->nonprintable++; | |
52 | } | |
53 | } | |
54 | else | |
55 | stats->printable++; | |
56 | } | |
57 | ||
58 | /* If file ends with EOF then don't count this EOF as non-printable. */ | |
59 | if (text->size >= 1 && text->ptr[text->size - 1] == '\032') | |
60 | stats->nonprintable--; | |
61 | } | |
62 | ||
63 | /* | |
64 | * Fresh from Core Git | |
65 | */ | |
66 | int git_text__is_binary(git_text_stats *stats) | |
67 | { | |
68 | if (stats->nul) | |
69 | return 1; | |
70 | ||
71 | if ((stats->printable >> 7) < stats->nonprintable) | |
72 | return 1; | |
73 | /* | |
74 | * Other heuristics? Average line length might be relevant, | |
75 | * as might LF vs CR vs CRLF counts.. | |
76 | * | |
77 | * NOTE! It might be normal to have a low ratio of CRLF to LF | |
78 | * (somebody starts with a LF-only file and edits it with an editor | |
79 | * that adds CRLF only to lines that are added..). But do we | |
80 | * want to support CR-only? Probably not. | |
81 | */ | |
82 | return 0; | |
83 | } | |
84 | ||
85 | int git_filter__load_for_file(git_vector *filters, git_repository *repo, const char *full_path, int mode) | |
86 | { | |
87 | /* We don't load any filters yet. HAHA */ | |
88 | return 0; | |
89 | } | |
90 | ||
91 | int git_filter__apply(git_buf *dest, git_buf *source, git_vector *filters, const char *filename) | |
92 | { | |
93 | unsigned int src, dst, i; | |
94 | git_buf *dbuffer[2]; | |
95 | ||
96 | dbuffer[0] = source; | |
97 | dbuffer[1] = dest; | |
98 | ||
99 | src = 0; | |
100 | ||
101 | /* Pre-grow the destination buffer to more or less the size | |
102 | * we expect it to have */ | |
103 | if (git_buf_grow(dest, source->size) < 0) | |
104 | return GIT_ENOMEM; | |
105 | ||
106 | for (i = 0; i < filters->length; ++i) { | |
107 | git_filter_cb filter = git_vector_get(filters, i); | |
108 | dst = (src + 1) % 2; | |
109 | ||
110 | git_buf_clear(dbuffer[dst]); | |
111 | ||
112 | /* Apply the filter, from dbuffer[src] to dbuffer[dst]; | |
113 | * if the filtering is canceled by the user mid-filter, | |
114 | * we skip to the next filter without changing the source | |
115 | * of the double buffering (so that the text goes through | |
116 | * cleanly). | |
117 | */ | |
118 | if (filter(dbuffer[dst], dbuffer[src], filename) == 0) { | |
119 | src = (src + 1) % 2; | |
120 | } | |
121 | ||
122 | if (git_buf_oom(dbuffer[dst])) | |
123 | return GIT_ENOMEM; | |
124 | } | |
125 | ||
126 | /* Ensure that the output ends up in dbuffer[1] (i.e. the dest) */ | |
127 | if (dst != 1) { | |
128 | git_buf_swap(dest, source); | |
129 | } | |
130 | ||
131 | return GIT_SUCCESS; | |
132 | } |