From: Torsten Bögershausen <[email protected]>
To compare a file in working tree with the index, convert_to_git() is used,
the the result is hashed and the hash value compared with ce->sha1.
Deep down would_convert_crlf_at_commit() is invoked, to check if CRLF
are converted or not: When a CRLF had been in the index before, CRLF in
the working tree are not converted.
While in a merge, a file name in the working tree has different blobs
in the index with different hash values.
Forwarding ce->sha1 from ce_compare_data() into crlf_to_git() makes sure
the would_convert_crlf_at_commit() looks at the appropriate blob.
---
cache.h | 1 +
convert.c | 30 ++++++++++++++++++++----------
convert.h | 23 +++++++++++++++++++----
read-cache.c | 4 +++-
sha1_file.c | 17 +++++++++++++----
t/t6038-merge-text-auto.sh | 12 ++++++------
6 files changed, 62 insertions(+), 25 deletions(-)
diff --git a/cache.h b/cache.h
index 28f23d7..43a4fd6 100644
--- a/cache.h
+++ b/cache.h
@@ -605,6 +605,7 @@ extern int ie_modified(const struct index_state *, const
struct cache_entry *, s
#define HASH_WRITE_OBJECT 1
#define HASH_FORMAT_CHECK 2
+#define HASH_CE_HAS_SHA1 4
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum
object_type type, const char *path, unsigned flags);
extern int index_path(unsigned char *sha1, const char *path, struct stat *st,
unsigned flags);
diff --git a/convert.c b/convert.c
index 8d4c42a..ccbd2e9 100644
--- a/convert.c
+++ b/convert.c
@@ -254,9 +254,8 @@ static int would_convert_lf_at_checkout(unsigned
convert_stats,
}
-static int would_convert_crlf_at_commit(const char * path,
+static int would_convert_crlf_at_commit(const unsigned char *sha1,
const struct text_stat *stats,
- size_t len,
enum crlf_action crlf_action)
{
unsigned stat_bits_index;
@@ -267,7 +266,7 @@ static int would_convert_crlf_at_commit(const char * path,
* If the file in the index has any CRLF in it, do not convert.
* This is the new safer autocrlf handling.
*/
- stat_bits_index = get_convert_stats_sha1(get_sha1_from_cache(path),
+ stat_bits_index = get_convert_stats_sha1(sha1,
CONVERT_STAT_BITS_TXT_CRLF);
if (stat_bits_index & CONVERT_STAT_BITS_TXT_CRLF)
return 0;
@@ -319,7 +318,8 @@ static void check_safe_crlf(const char *path, enum
crlf_action crlf_action,
}
}
-static int crlf_to_git(const char *path, const char *src, size_t len,
+static int crlf_to_git(const char *path, const unsigned char *sha1,
+ const char *src, size_t len,
struct strbuf *buf,
enum crlf_action crlf_action, enum safe_crlf checksafe)
{
@@ -350,7 +350,14 @@ static int crlf_to_git(const char *path, const char *src,
size_t len,
convert_crlf = 1;
checksafe = SAFE_CRLF_FALSE;
} else {
- convert_crlf = would_convert_crlf_at_commit(path, &stats, len,
+ /*
+ * If ce_compare_data() wants to check a specic blob,
+ * then sha1 != NULL and should be used
+ */
+ if (!sha1)
+ sha1 = get_sha1_from_cache(path);
+
+ convert_crlf = would_convert_crlf_at_commit(sha1, &stats,
crlf_action);
}
@@ -949,8 +956,9 @@ const char *get_convert_attr_ascii(const char *path)
return "";
}
-int convert_to_git(const char *path, const char *src, size_t len,
- struct strbuf *dst, enum safe_crlf checksafe)
+int convert_to_git_ce_sha1(const char *path, const unsigned char *sha1,
+ const char *src, size_t len,
+ struct strbuf *dst, enum safe_crlf checksafe)
{
int ret = 0;
const char *filter = NULL;
@@ -971,7 +979,7 @@ int convert_to_git(const char *path, const char *src,
size_t len,
src = dst->buf;
len = dst->len;
}
- ret |= crlf_to_git(path, src, len, dst, ca.crlf_action, checksafe);
+ ret |= crlf_to_git(path, sha1, src, len, dst, ca.crlf_action,
checksafe);
if (ret && dst) {
src = dst->buf;
len = dst->len;
@@ -979,7 +987,9 @@ int convert_to_git(const char *path, const char *src,
size_t len,
return ret | ident_to_git(path, src, len, dst, ca.ident);
}
-void convert_to_git_filter_fd(const char *path, int fd, struct strbuf *dst,
+void convert_to_git_filter_fd(const char *path,
+ const unsigned char *sha1,
+ int fd, struct strbuf *dst,
enum safe_crlf checksafe)
{
struct conv_attrs ca;
@@ -991,7 +1001,7 @@ void convert_to_git_filter_fd(const char *path, int fd,
struct strbuf *dst,
if (!apply_filter(path, NULL, 0, fd, dst, ca.drv->clean))
die("%s: clean filter '%s' failed", path, ca.drv->name);
- crlf_to_git(path, dst->buf, dst->len, dst, ca.crlf_action, checksafe);
+ crlf_to_git(path, sha1, dst->buf, dst->len, dst, ca.crlf_action,
checksafe);
ident_to_git(path, dst->buf, dst->len, dst, ca.ident);
}
diff --git a/convert.h b/convert.h
index 81b6cdf..769e9c9 100644
--- a/convert.h
+++ b/convert.h
@@ -38,8 +38,16 @@ extern const char *get_wt_convert_stats_ascii(const char
*path);
extern const char *get_convert_attr_ascii(const char *path);
/* returns 1 if *dst was used */
-extern int convert_to_git(const char *path, const char *src, size_t len,
- struct strbuf *dst, enum safe_crlf checksafe);
+extern int convert_to_git_ce_sha1(const char *path, const unsigned char *sha1,
+ const char *src, size_t len,
+ struct strbuf *dst, enum safe_crlf checksafe);
+
+static inline int convert_to_git(const char *path, const char *src, size_t len,
+ struct strbuf *dst, enum safe_crlf checksafe)
+{
+ return convert_to_git_ce_sha1(path, NULL, src, len, dst, checksafe);
+}
+
extern int convert_to_working_tree(const char *path, const char *src,
size_t len, struct strbuf *dst);
extern int renormalize_buffer(const char *path, const char *src, size_t len,
@@ -48,9 +56,16 @@ static inline int would_convert_to_git(const char *path)
{
return convert_to_git(path, NULL, 0, NULL, 0);
}
+static inline int would_convert_to_git_ce_sha1(const char *path,
+ const unsigned char *sha1)
+{
+ return convert_to_git_ce_sha1(path, sha1, NULL, 0, NULL, 0);
+}
+
/* Precondition: would_convert_to_git_filter_fd(path) == true */
-extern void convert_to_git_filter_fd(const char *path, int fd,
- struct strbuf *dst,
+extern void convert_to_git_filter_fd(const char *path,
+ const unsigned char *sha1,
+ int fd, struct strbuf *dst,
enum safe_crlf checksafe);
extern int would_convert_to_git_filter_fd(const char *path);
diff --git a/read-cache.c b/read-cache.c
index a3ef967..0ebc237 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -163,7 +163,9 @@ static int ce_compare_data(const struct cache_entry *ce,
struct stat *st)
if (fd >= 0) {
unsigned char sha1[20];
- if (!index_fd(sha1, fd, st, OBJ_BLOB, ce->name, 0))
+ unsigned flags = HASH_CE_HAS_SHA1;
+ memcpy(sha1, ce->sha1, sizeof(sha1));
+ if (!index_fd(sha1, fd, st, OBJ_BLOB, ce->name, flags))
match = hashcmp(sha1, ce->sha1);
/* index_fd() closed the file descriptor already */
}
diff --git a/sha1_file.c b/sha1_file.c
index d0f2aa0..dd013d5 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -3275,6 +3275,7 @@ static int index_mem(unsigned char *sha1, void *buf,
size_t size,
{
int ret, re_allocated = 0;
int write_object = flags & HASH_WRITE_OBJECT;
+ const int valid_sha1 = flags & HASH_CE_HAS_SHA1;
if (!type)
type = OBJ_BLOB;
@@ -3284,8 +3285,11 @@ static int index_mem(unsigned char *sha1, void *buf,
size_t size,
*/
if ((type == OBJ_BLOB) && path) {
struct strbuf nbuf = STRBUF_INIT;
- if (convert_to_git(path, buf, size, &nbuf,
- write_object ? safe_crlf : SAFE_CRLF_FALSE))
{
+ if (convert_to_git_ce_sha1(path,
+ valid_sha1 ? sha1 : NULL,
+ buf, size, &nbuf,
+ write_object ? safe_crlf :
SAFE_CRLF_FALSE)){
+
buf = strbuf_detach(&nbuf, &size);
re_allocated = 1;
}
@@ -3313,12 +3317,15 @@ static int index_stream_convert_blob(unsigned char
*sha1, int fd,
{
int ret;
const int write_object = flags & HASH_WRITE_OBJECT;
+ const int valid_sha1 = flags & HASH_CE_HAS_SHA1;
struct strbuf sbuf = STRBUF_INIT;
assert(path);
assert(would_convert_to_git_filter_fd(path));
- convert_to_git_filter_fd(path, fd, &sbuf,
+ convert_to_git_filter_fd(path,
+ valid_sha1 ? sha1 : NULL,
+ fd, &sbuf,
write_object ? safe_crlf : SAFE_CRLF_FALSE);
if (write_object)
@@ -3396,6 +3403,8 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st,
enum object_type type, const char *path, unsigned flags)
{
int ret;
+ const unsigned char *sha1_ce;
+ sha1_ce = flags & HASH_CE_HAS_SHA1 ? sha1 : NULL;
/*
* Call xsize_t() only when needed to avoid potentially unnecessary
@@ -3406,7 +3415,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st,
else if (!S_ISREG(st->st_mode))
ret = index_pipe(sha1, fd, type, path, flags);
else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
- (path && would_convert_to_git(path)))
+ (path && would_convert_to_git_ce_sha1(path,sha1_ce)))
ret = index_core(sha1, fd, xsize_t(st->st_size), type, path,
flags);
else
diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh
index 0108ead..5450cba 100755
--- a/t/t6038-merge-text-auto.sh
+++ b/t/t6038-merge-text-auto.sh
@@ -108,9 +108,9 @@ test_expect_success 'Merge addition of text=auto' '
test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
echo "<<<<<<<" >expected &&
- echo first line | append_cr >>expected &&
- echo same line | append_cr >>expected &&
- echo ======= | append_cr >>expected &&
+ echo first line >>expected &&
+ echo same line >>expected &&
+ echo ======= >>expected &&
echo first line | append_cr >>expected &&
echo same line | append_cr >>expected &&
echo ">>>>>>>" >>expected &&
@@ -126,9 +126,9 @@ test_expect_success 'Detect LF/CRLF conflict from addition
of text=auto' '
echo "<<<<<<<" >expected &&
echo first line | append_cr >>expected &&
echo same line | append_cr >>expected &&
- echo ======= | append_cr >>expected &&
- echo first line | append_cr >>expected &&
- echo same line | append_cr >>expected &&
+ echo ======= >>expected &&
+ echo first line >>expected &&
+ echo same line >>expected &&
echo ">>>>>>>" >>expected &&
git config merge.renormalize false &&
rm -f .gitattributes &&
--
2.0.0.rc1.6318.g0c2c796
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html