8
* This should use the pathname to decide on whether it wants to do some
9
* more interesting conversions (automatic gzip/unzip, general format
10
* conversions etc etc), but by default it just does automatic CRLF<->LF
11
- * translation when the "auto_crlf" option is set.
11
+ * translation when the "crlf" attribute or "auto_crlf" option is set.
12
*/
13
14
-#define CRLF_GUESS (-1)
15
-#define CRLF_BINARY 0
16
-#define CRLF_TEXT 1
17
-#define CRLF_INPUT 2
14
+enum action {
15
+ CRLF_GUESS = -1,
16
+ CRLF_BINARY = 0,
17
+ CRLF_TEXT,
18
+ CRLF_INPUT,
19
+ CRLF_CRLF,
20
+ CRLF_AUTO,
21
+};
22
+
23
+enum eol {
24
+ EOL_UNSET,
25
+ EOL_LF,
26
+ EOL_CRLF,
27
+};
28
29
struct text_stat {
30
/* NUL, CR, LF and CRLF counts */
99
return 0;
100
}
101
92
-static void check_safe_crlf(const char *path, int action,
102
+static void check_safe_crlf(const char *path, enum action action,
103
struct text_stat *stats, enum safe_crlf checksafe)
104
{
105
if (!checksafe)
106
return;
107
98
- if (action == CRLF_INPUT || auto_crlf <= 0) {
108
+ if (action == CRLF_INPUT ||
109
+ (action == CRLF_GUESS && auto_crlf == AUTO_CRLF_INPUT)) {
110
/*
111
* CRLFs would not be restored by checkout:
112
* check if we'd remove CRLFs
117
else /* i.e. SAFE_CRLF_FAIL */
118
die("CRLF would be replaced by LF in %s.", path);
119
}
109
- } else if (auto_crlf > 0) {
120
+ } else if (action == CRLF_CRLF ||
121
+ (action == CRLF_GUESS && auto_crlf == AUTO_CRLF_TRUE)) {
122
/*
123
* CRLFs would be added by checkout:
124
* check if we have "naked" LFs
170
}
171
172
static int crlf_to_git(const char *path, const char *src, size_t len,
161
- struct strbuf *buf, int action, enum safe_crlf checksafe)
173
+ struct strbuf *buf, enum action action, enum safe_crlf checksafe)
174
{
175
struct text_stat stats;
176
char *dst;
177
166
- if ((action == CRLF_BINARY) || !auto_crlf || !len)
178
+ if (action == CRLF_BINARY ||
179
+ (action == CRLF_GUESS && auto_crlf == AUTO_CRLF_FALSE) || !len)
180
return 0;
181
182
gather_stats(src, len, &stats);
183
171
- if (action == CRLF_GUESS) {
184
+ if (action == CRLF_AUTO || action == CRLF_GUESS) {
185
/*
186
* We're currently not going to even try to convert stuff
187
* that has bare CR characters. Does anybody do that crazy
196
if (is_binary(len, &stats))
197
return 0;
198
186
- /*
187
- * If the file in the index has any CR in it, do not convert.
188
- * This is the new safer autocrlf handling.
189
- */
190
- if (has_cr_in_index(path))
191
- return 0;
199
+ if (action == CRLF_GUESS) {
200
+ /*
201
+ * If the file in the index has any CR in it, do not convert.
202
+ * This is the new safer autocrlf handling.
203
+ */
204
+ if (has_cr_in_index(path))
205
+ return 0;
206
+ }
207
}
208
209
check_safe_crlf(path, action, &stats, checksafe);
216
if (strbuf_avail(buf) + buf->len < len)
217
strbuf_grow(buf, len - buf->len);
218
dst = buf->buf;
204
- if (action == CRLF_GUESS) {
219
+ if (action == CRLF_AUTO || action == CRLF_GUESS) {
220
/*
221
* If we guessed, we already know we rejected a file with
222
* lone CR, and we can strip a CR without looking at what
239
}
240
241
static int crlf_to_worktree(const char *path, const char *src, size_t len,
227
- struct strbuf *buf, int action)
242
+ struct strbuf *buf, enum action action)
243
{
244
char *to_free = NULL;
245
struct text_stat stats;
246
247
if ((action == CRLF_BINARY) || (action == CRLF_INPUT) ||
233
- auto_crlf <= 0)
248
+ (action != CRLF_CRLF && auto_crlf != AUTO_CRLF_TRUE))
249
return 0;
250
251
if (!len)
261
if (stats.lf == stats.crlf)
262
return 0;
263
249
- if (action == CRLF_GUESS) {
250
- /* If we have any CR or CRLF line endings, we do not touch it */
251
- /* This is the new safer autocrlf-handling */
252
- if (stats.cr > 0 || stats.crlf > 0)
253
- return 0;
264
+ if (action == CRLF_AUTO || action == CRLF_GUESS) {
265
+ if (action == CRLF_GUESS) {
266
+ /* If we have any CR or CRLF line endings, we do not touch it */
267
+ /* This is the new safer autocrlf-handling */
268
+ if (stats.cr > 0 || stats.crlf > 0)
269
+ return 0;
270
+ }
271
272
/* If we have any bare CR characters, we're not going to touch it */
273
if (stats.cr != stats.crlf)
440
static void setup_convert_check(struct git_attr_check *check)
441
{
442
static struct git_attr *attr_crlf;
443
+ static struct git_attr *attr_eol;
444
static struct git_attr *attr_ident;
445
static struct git_attr *attr_filter;
446
447
if (!attr_crlf) {
448
attr_crlf = git_attr("crlf");
449
+ attr_eol = git_attr("eol");
450
attr_ident = git_attr("ident");
451
attr_filter = git_attr("filter");
452
user_convert_tail = &user_convert;
455
check[0].attr = attr_crlf;
456
check[1].attr = attr_ident;
457
check[2].attr = attr_filter;
458
+ check[3].attr = attr_eol;
459
}
460
461
static int count_ident(const char *cp, unsigned long size)
612
;
613
else if (!strcmp(value, "input"))
614
return CRLF_INPUT;
615
+ else if (!strcmp(value, "auto"))
616
+ return CRLF_AUTO;
617
return CRLF_GUESS;
618
}
619
620
+static int git_path_check_eol(const char *path, struct git_attr_check *check)
621
+{
622
+ const char *value = check->value;
623
+
624
+ if (ATTR_UNSET(value))
625
+ ;
626
+ else if (!strcmp(value, "lf"))
627
+ return EOL_LF;
628
+ else if (!strcmp(value, "crlf"))
629
+ return EOL_CRLF;
630
+ return EOL_UNSET;
631
+}
632
+
633
static struct convert_driver *git_path_check_convert(const char *path,
634
struct git_attr_check *check)
635
{
651
return !!ATTR_TRUE(value);
652
}
653
654
+enum action determine_action(enum action crlf_attr, enum eol eol_attr) {
655
+ if (crlf_attr == CRLF_BINARY)
656
+ return CRLF_BINARY;
657
+ if (eol_attr == EOL_LF)
658
+ return CRLF_INPUT;
659
+ if (eol_attr == EOL_CRLF)
660
+ return CRLF_CRLF;
661
+ return crlf_attr;
662
+}
663
+
664
int convert_to_git(const char *path, const char *src, size_t len,
665
struct strbuf *dst, enum safe_crlf checksafe)
666
{
622
- struct git_attr_check check[3];
623
- int crlf = CRLF_GUESS;
667
+ struct git_attr_check check[4];
668
+ enum action action = CRLF_GUESS;
669
+ enum eol eol = EOL_UNSET;
670
int ident = 0, ret = 0;
671
const char *filter = NULL;
672
673
setup_convert_check(check);
674
if (!git_checkattr(path, ARRAY_SIZE(check), check)) {
675
struct convert_driver *drv;
630
- crlf = git_path_check_crlf(path, check + 0);
676
+ action = git_path_check_crlf(path, check + 0);
677
ident = git_path_check_ident(path, check + 1);
678
drv = git_path_check_convert(path, check + 2);
679
+ eol = git_path_check_eol(path, check + 3);
680
if (drv && drv->clean)
681
filter = drv->clean;
682
}
686
src = dst->buf;
687
len = dst->len;
688
}
642
- ret |= crlf_to_git(path, src, len, dst, crlf, checksafe);
689
+ action = determine_action(action, eol);
690
+ ret |= crlf_to_git(path, src, len, dst, action, checksafe);
691
if (ret) {
692
src = dst->buf;
693
len = dst->len;
697
698
int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
699
{
652
- struct git_attr_check check[3];
653
- int crlf = CRLF_GUESS;
700
+ struct git_attr_check check[4];
701
+ enum action action = CRLF_GUESS;
702
+ enum eol eol = EOL_UNSET;
703
int ident = 0, ret = 0;
704
const char *filter = NULL;
705
706
setup_convert_check(check);
707
if (!git_checkattr(path, ARRAY_SIZE(check), check)) {
708
struct convert_driver *drv;
660
- crlf = git_path_check_crlf(path, check + 0);
709
+ action = git_path_check_crlf(path, check + 0);
710
ident = git_path_check_ident(path, check + 1);
711
drv = git_path_check_convert(path, check + 2);
712
+ eol = git_path_check_eol(path, check + 3);
713
if (drv && drv->smudge)
714
filter = drv->smudge;
715
}
719
src = dst->buf;
720
len = dst->len;
721
}
672
- ret |= crlf_to_worktree(path, src, len, dst, crlf);
722
+ action = determine_action(action, eol);
723
+ ret |= crlf_to_worktree(path, src, len, dst, action);
724
if (ret) {
725
src = dst->buf;
726
len = dst->len;