rem = fill(path, pathlen, stk, check, num, rem);
        return 0;
 }
+
+static void setup_binary_check(struct git_attr_check *check)
+{
+       static struct git_attr *attr_binary;
+
+       if (!attr_binary)
+               attr_binary = git_attr("binary", 6);
+       check->attr = attr_binary;
+}
+
+int git_path_is_binary(const char *path)
+{
+       struct git_attr_check attr_binary_check;
+
+       setup_binary_check(&attr_binary_check);
+       return (!git_checkattr(path, 1, &attr_binary_check) &&
+               (0 < attr_binary_check.isset));
+}
 
 #include "cache.h"
+#include "attr.h"
+
 /*
  * convert.c - convert a file when checking it out and checking it in.
  *
        return 0;
 }
 
-int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
+static int autocrlf_to_git(const char *path, char **bufp, unsigned long *sizep)
 {
        char *buffer, *nbuf;
        unsigned long size, nsize;
        struct text_stat stats;
 
-       /*
-        * FIXME! Other pluggable conversions should go here,
-        * based on filename patterns. Right now we just do the
-        * stupid auto-CRLF one.
-        */
        if (!auto_crlf)
                return 0;
 
        return 1;
 }
 
-int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
+static int autocrlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
 {
        char *buffer, *nbuf;
        unsigned long size, nsize;
 
        return 1;
 }
+
+static void setup_crlf_check(struct git_attr_check *check)
+{
+       static struct git_attr *attr_crlf;
+
+       if (!attr_crlf)
+               attr_crlf = git_attr("crlf", 4);
+       check->attr = attr_crlf;
+}
+
+static int git_path_is_binary(const char *path)
+{
+       struct git_attr_check attr_crlf_check;
+
+       setup_crlf_check(&attr_crlf_check);
+
+       /*
+        * If crlf is not mentioned, default to autocrlf;
+        * disable autocrlf only when crlf attribute is explicitly
+        * unset.
+        */
+       return (!git_checkattr(path, 1, &attr_crlf_check) &&
+               (0 == attr_crlf_check.isset));
+}
+
+int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
+{
+       if (git_path_is_binary(path))
+               return 0;
+       return autocrlf_to_git(path, bufp, sizep);
+}
+
+int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
+{
+       if (git_path_is_binary(path))
+               return 0;
+       return autocrlf_to_working_tree(path, bufp, sizep);
+}
 
        }
 '
 
+test_expect_success '.gitattributes says two is binary' '
+
+       echo "two !crlf" >.gitattributes &&
+       rm -f tmp one dir/two &&
+       git repo-config core.autocrlf true &&
+       git read-tree --reset -u HEAD &&
+
+       if remove_cr dir/two >/dev/null
+       then
+               echo "Huh?"
+               false
+       else
+               : happy
+       fi &&
+
+       if remove_cr one >/dev/null
+       then
+               : happy
+       else
+               echo "Huh?"
+               false
+       fi
+'
+
 test_done