3 #include "run-command.h"
6 * convert.c - convert a file when checking it out and checking it in.
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.
14 #define CRLF_GUESS (-1)
20 /* CR, LF and CRLF counts */
21 unsigned cr
, lf
, crlf
;
23 /* These are just approximations! */
24 unsigned printable
, nonprintable
;
27 static void gather_stats(const char *buf
, unsigned long size
, struct text_stat
*stats
)
31 memset(stats
, 0, sizeof(*stats
));
33 for (i
= 0; i
< size
; i
++) {
34 unsigned char c
= buf
[i
];
37 if (i
+1 < size
&& buf
[i
+1] == '\n')
47 stats
->nonprintable
++;
50 /* BS, HT, ESC and FF */
51 case '\b': case '\t': case '\033': case '\014':
55 stats
->nonprintable
++;
62 // If file ends with EOF then don't count this EOF as non-printable
63 if ( size
>= 1 && buf
[size
-1] == '\032' )
64 stats
->nonprintable
--;
68 * The same heuristics as diff.c::mmfile_is_binary()
70 static int is_binary(unsigned long size
, struct text_stat
*stats
)
73 if ((stats
->printable
>> 7) < stats
->nonprintable
)
76 * Other heuristics? Average line length might be relevant,
77 * as might LF vs CR vs CRLF counts..
79 * NOTE! It might be normal to have a low ratio of CRLF to LF
80 * (somebody starts with a LF-only file and edits it with an editor
81 * that adds CRLF only to lines that are added..). But do we
82 * want to support CR-only? Probably not.
87 static char *crlf_to_git(const char *path
, const char *src
, unsigned long *sizep
, int action
)
90 unsigned long size
, nsize
;
91 struct text_stat stats
;
93 if ((action
== CRLF_BINARY
) || !auto_crlf
)
100 gather_stats(src
, size
, &stats
);
102 /* No CR? Nothing to convert, regardless. */
106 if (action
== CRLF_GUESS
) {
108 * We're currently not going to even try to convert stuff
109 * that has bare CR characters. Does anybody do that crazy
112 if (stats
.cr
!= stats
.crlf
)
116 * And add some heuristics for binary vs text, of course...
118 if (is_binary(size
, &stats
))
123 * Ok, allocate a new buffer, fill it in, and return it
124 * to let the caller know that we switched buffers.
126 nsize
= size
- stats
.crlf
;
127 buffer
= xmalloc(nsize
);
131 if (action
== CRLF_GUESS
) {
133 * If we guessed, we already know we rejected a file with
134 * lone CR, and we can strip a CR without looking at what
138 unsigned char c
= *src
++;
144 unsigned char c
= *src
++;
145 if (! (c
== '\r' && (1 < size
&& *src
== '\n')))
153 static char *crlf_to_worktree(const char *path
, const char *src
, unsigned long *sizep
, int action
)
156 unsigned long size
, nsize
;
157 struct text_stat stats
;
160 if ((action
== CRLF_BINARY
) || (action
== CRLF_INPUT
) ||
168 gather_stats(src
, size
, &stats
);
170 /* No LF? Nothing to convert, regardless. */
174 /* Was it already in CRLF format? */
175 if (stats
.lf
== stats
.crlf
)
178 if (action
== CRLF_GUESS
) {
179 /* If we have any bare CR characters, we're not going to touch it */
180 if (stats
.cr
!= stats
.crlf
)
183 if (is_binary(size
, &stats
))
188 * Ok, allocate a new buffer, fill it in, and return it
189 * to let the caller know that we switched buffers.
191 nsize
= size
+ stats
.lf
- stats
.crlf
;
192 buffer
= xmalloc(nsize
);
198 unsigned char c
= *src
++;
199 if (c
== '\n' && last
!= '\r')
208 static int filter_buffer(const char *path
, const char *src
,
209 unsigned long size
, const char *cmd
)
212 * Spawn cmd and feed the buffer contents through its stdin.
214 struct child_process child_process
;
216 int write_err
, status
;
218 memset(&child_process
, 0, sizeof(child_process
));
220 if (pipe(pipe_feed
) < 0) {
221 error("cannot create pipe to run external filter %s", cmd
);
225 child_process
.pid
= fork();
226 if (child_process
.pid
< 0) {
227 error("cannot fork to run external filter %s", cmd
);
232 if (!child_process
.pid
) {
233 dup2(pipe_feed
[0], 0);
236 execlp("sh", "sh", "-c", cmd
, NULL
);
241 write_err
= (write_in_full(pipe_feed
[1], src
, size
) < 0);
242 if (close(pipe_feed
[1]))
245 error("cannot feed the input to external filter %s", cmd
);
247 status
= finish_command(&child_process
);
249 error("external filter %s failed %d", cmd
, -status
);
250 return (write_err
|| status
);
253 static char *apply_filter(const char *path
, const char *src
,
254 unsigned long *sizep
, const char *cmd
)
257 * Create a pipeline to have the command filter the buffer's
260 * (child --> cmd) --> us
262 const int SLOP
= 4096;
266 unsigned long dstsize
, dstalloc
;
267 struct child_process child_process
;
272 memset(&child_process
, 0, sizeof(child_process
));
274 if (pipe(pipe_feed
) < 0) {
275 error("cannot create pipe to run external filter %s", cmd
);
280 child_process
.pid
= fork();
281 if (child_process
.pid
< 0) {
282 error("cannot fork to run external filter %s", cmd
);
287 if (!child_process
.pid
) {
288 dup2(pipe_feed
[1], 1);
291 exit(filter_buffer(path
, src
, *sizep
, cmd
));
296 dst
= xmalloc(dstalloc
);
300 ssize_t numread
= xread(pipe_feed
[0], dst
+ dstsize
,
306 error("read from external filter %s failed", cmd
);
312 if (dstalloc
<= dstsize
+ SLOP
) {
313 dstalloc
= dstsize
+ SLOP
;
314 dst
= xrealloc(dst
, dstalloc
);
317 if (close(pipe_feed
[0])) {
318 error("read from external filter %s failed", cmd
);
323 status
= finish_command(&child_process
);
325 error("external filter %s failed %d", cmd
, -status
);
335 static struct convert_driver
{
337 struct convert_driver
*next
;
340 } *user_convert
, **user_convert_tail
;
342 static int read_convert_config(const char *var
, const char *value
)
344 const char *ep
, *name
;
346 struct convert_driver
*drv
;
349 * External conversion drivers are configured using
350 * "filter.<name>.variable".
352 if (prefixcmp(var
, "filter.") || (ep
= strrchr(var
, '.')) == var
+ 6)
356 for (drv
= user_convert
; drv
; drv
= drv
->next
)
357 if (!strncmp(drv
->name
, name
, namelen
) && !drv
->name
[namelen
])
361 drv
= xcalloc(1, sizeof(struct convert_driver
));
362 namebuf
= xmalloc(namelen
+ 1);
363 memcpy(namebuf
, name
, namelen
);
364 namebuf
[namelen
] = 0;
367 *user_convert_tail
= drv
;
368 user_convert_tail
= &(drv
->next
);
374 * filter.<name>.smudge and filter.<name>.clean specifies
379 * The command-line will not be interpolated in any way.
382 if (!strcmp("smudge", ep
)) {
384 return error("%s: lacks value", var
);
385 drv
->smudge
= strdup(value
);
389 if (!strcmp("clean", ep
)) {
391 return error("%s: lacks value", var
);
392 drv
->clean
= strdup(value
);
398 static void setup_convert_check(struct git_attr_check
*check
)
400 static struct git_attr
*attr_crlf
;
401 static struct git_attr
*attr_ident
;
402 static struct git_attr
*attr_filter
;
405 attr_crlf
= git_attr("crlf", 4);
406 attr_ident
= git_attr("ident", 5);
407 attr_filter
= git_attr("filter", 6);
408 user_convert_tail
= &user_convert
;
409 git_config(read_convert_config
);
411 check
[0].attr
= attr_crlf
;
412 check
[1].attr
= attr_ident
;
413 check
[2].attr
= attr_filter
;
416 static int count_ident(const char *cp
, unsigned long size
)
419 * "$Id: 0000000000000000000000000000000000000000 $" <=> "$Id$"
431 if (memcmp("Id", cp
, 2))
442 * "$Id: ... "; scan up to the closing dollar sign and discard.
456 static char *ident_to_git(const char *path
, const char *src
, unsigned long *sizep
, int ident
)
465 cnt
= count_ident(src
, size
);
470 for (dst
= buf
; size
; size
--) {
473 if ((ch
== '$') && (3 <= size
) &&
474 !memcmp("Id:", src
, 3)) {
475 unsigned long rem
= size
- 3;
476 const char *cp
= src
+ 3;
485 memcpy(dst
, "Id$", 3);
496 static char *ident_to_worktree(const char *path
, const char *src
, unsigned long *sizep
, int ident
)
501 unsigned char sha1
[20];
507 cnt
= count_ident(src
, size
);
511 hash_sha1_file(src
, size
, "blob", sha1
);
512 buf
= xmalloc(size
+ cnt
* 43);
514 for (dst
= buf
; size
; size
--) {
516 /* Fetch next source character, move the pointer on */
518 /* Copy the current character to the destination */
520 /* If the current character is "$" or there are less than three
521 * remaining bytes or the two bytes following this one are not
522 * "Id", then simply read the next character */
523 if ((ch
!= '$') || (size
< 3) || memcmp("Id", src
, 2))
527 * - There are more than 2 bytes remaining
528 * - The current three bytes are "$Id"
535 * It's possible that an expanded Id has crept its way into the
536 * repository, we cope with that by stripping the expansion out
539 /* Expanded keywords have "$Id:" at the front */
541 /* discard up to but not including the closing $ */
542 unsigned long rem
= size
- 3;
543 /* Point at first byte after the ":" */
546 * Throw away characters until either
548 * - we run out of bytes (rem == 0)
557 /* If the above finished because it ran out of characters, then
558 * this is an incomplete keyword, so don't run the expansion */
561 } else if (src
[2] == '$')
564 /* Anything other than "$Id:XXX$" or $Id$ and we skip the
568 /* cp is now pointing at the last $ of the keyword */
570 memcpy(dst
, "Id: ", 4);
572 memcpy(dst
, sha1_to_hex(sha1
), 40);
576 /* Adjust for the characters we've discarded */
580 /* Copy the final "$" */
589 static int git_path_check_crlf(const char *path
, struct git_attr_check
*check
)
591 const char *value
= check
->value
;
593 if (ATTR_TRUE(value
))
595 else if (ATTR_FALSE(value
))
597 else if (ATTR_UNSET(value
))
599 else if (!strcmp(value
, "input"))
604 static struct convert_driver
*git_path_check_convert(const char *path
,
605 struct git_attr_check
*check
)
607 const char *value
= check
->value
;
608 struct convert_driver
*drv
;
610 if (ATTR_TRUE(value
) || ATTR_FALSE(value
) || ATTR_UNSET(value
))
612 for (drv
= user_convert
; drv
; drv
= drv
->next
)
613 if (!strcmp(value
, drv
->name
))
618 static int git_path_check_ident(const char *path
, struct git_attr_check
*check
)
620 const char *value
= check
->value
;
622 return !!ATTR_TRUE(value
);
625 char *convert_to_git(const char *path
, const char *src
, unsigned long *sizep
)
627 struct git_attr_check check
[3];
628 int crlf
= CRLF_GUESS
;
633 setup_convert_check(check
);
634 if (!git_checkattr(path
, ARRAY_SIZE(check
), check
)) {
635 struct convert_driver
*drv
;
636 crlf
= git_path_check_crlf(path
, check
+ 0);
637 ident
= git_path_check_ident(path
, check
+ 1);
638 drv
= git_path_check_convert(path
, check
+ 2);
639 if (drv
&& drv
->clean
)
643 buf
= apply_filter(path
, src
, sizep
, filter
);
645 buf2
= crlf_to_git(path
, buf
? buf
: src
, sizep
, crlf
);
651 buf2
= ident_to_git(path
, buf
? buf
: src
, sizep
, ident
);
660 char *convert_to_working_tree(const char *path
, const char *src
, unsigned long *sizep
)
662 struct git_attr_check check
[3];
663 int crlf
= CRLF_GUESS
;
668 setup_convert_check(check
);
669 if (!git_checkattr(path
, ARRAY_SIZE(check
), check
)) {
670 struct convert_driver
*drv
;
671 crlf
= git_path_check_crlf(path
, check
+ 0);
672 ident
= git_path_check_ident(path
, check
+ 1);
673 drv
= git_path_check_convert(path
, check
+ 2);
674 if (drv
&& drv
->smudge
)
675 filter
= drv
->smudge
;
678 buf
= ident_to_worktree(path
, src
, sizep
, ident
);
680 buf2
= crlf_to_worktree(path
, buf
? buf
: src
, sizep
, crlf
);
686 buf2
= apply_filter(path
, buf
? buf
: src
, sizep
, filter
);
695 void *convert_sha1_file(const char *path
, const unsigned char *sha1
,
696 unsigned int mode
, enum object_type
*type
,
699 void *buffer
= read_sha1_file(sha1
, type
, size
);
700 if (S_ISREG(mode
) && buffer
) {
701 void *converted
= convert_to_working_tree(path
, buffer
, size
);