[RFC/PATCH 3/4] textconv: support for blame

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patches enables to perform textconv with blame if a textconv driver
is available for the file.

The main task is performed by the textconv_object function which
prepares diff_filespec and if possible converts the file using diff
textconv API.

Textconv conversion is enabled by default (equivalent to the option
--textconv), since blaming binary files is useless in most cases.
The option --no-textconv is used to disable textconv conversion.

The declaration of fill_blob_sha1 declaration is modified to get back
the mode the function was getting.

Signed-off-by: Diane Gasselin <diane.gasselin@xxxxxxxxxxxxxxx>
Signed-off-by: Clément Poulain <clement.poulain@xxxxxxxxxxxxxxx>
Signed-off-by: Axel Bonnet <axel.bonnet@xxxxxxxxxxxxxxx>
---
 builtin/blame.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index 63b497c..4679fd9 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -20,6 +20,7 @@
 #include "mailmap.h"
 #include "parse-options.h"
 #include "utf8.h"
+#include "userdiff.h"
 
 static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
 
@@ -86,17 +87,57 @@ struct origin {
 };
 
 /*
+ * Prepare diff_filespec and convert it using diff textconv API
+ * if the textconv driver exists.
+ * Return 1 if the conversion succeeds, 0 otherwise.
+ */
+static int textconv_object(const char *path,
+			   const unsigned char *sha1,
+			   unsigned short mode,
+			   struct strbuf *buf)
+{
+	struct diff_filespec *df;
+
+	df = alloc_filespec(path);
+	fill_filespec(df, sha1, mode);
+	get_textconv(df);
+
+	if (!df->driver|| !df->driver->textconv) {
+		free_filespec(df);
+		return 0;
+	}
+
+	buf->len = fill_textconv(df->driver, df, &buf->buf);
+	buf->alloc = 1;
+	free_filespec(df);
+	return 1;
+}
+
+/*
  * Given an origin, prepare mmfile_t structure to be used by the
  * diff machinery
  */
 static void fill_origin_blob(struct diff_options opt,
 			     struct origin *o, mmfile_t *file)
 {
+	unsigned mode;
+
 	if (!o->file.ptr) {
+		struct strbuf buf = STRBUF_INIT;
 		enum object_type type;
 		num_read_blob++;
-		file->ptr = read_sha1_file(o->blob_sha1, &type,
-					   (unsigned long *)(&(file->size)));
+
+		get_tree_entry(o->commit->object.sha1,
+			       o->path,
+			       o->blob_sha1, &mode);
+		if (DIFF_OPT_TST(&opt, ALLOW_TEXTCONV) &&
+		    textconv_object(o->path, o->blob_sha1, mode, &buf))
+			file->ptr = strbuf_detach(&buf, (size_t *) &file->size);
+		else
+			file->ptr = read_sha1_file(o->blob_sha1, &type,
+						   (unsigned long *)(&(file->size)));
+		strbuf_release(&buf);
+
 		if (!file->ptr)
 			die("Cannot read blob %s for path %s",
 			    sha1_to_hex(o->blob_sha1),
@@ -280,15 +321,13 @@ static struct origin *get_origin(struct scoreboard *sb,
  * the parent to detect the case where a child's blob is identical to
  * that of its parent's.
  */
-static int fill_blob_sha1(struct origin *origin)
+static int fill_blob_sha1(struct origin *origin, unsigned *mode)
 {
-	unsigned mode;
-
 	if (!is_null_sha1(origin->blob_sha1))
 		return 0;
 	if (get_tree_entry(origin->commit->object.sha1,
 			   origin->path,
-			   origin->blob_sha1, &mode))
+			   origin->blob_sha1, mode))
 		goto error_out;
 	if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)
 		goto error_out;
@@ -2033,10 +2072,13 @@ static struct commit *fake_working_tree_commit(struct diff_options opt,
 			read_from = path;
 		}
 		mode = canon_mode(st.st_mode);
+
 		switch (st.st_mode & S_IFMT) {
 		case S_IFREG:
-			if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
-				die_errno("cannot open or read '%s'", read_from);
+			if (!DIFF_OPT_TST(&opt, ALLOW_TEXTCONV) ||
+			    !textconv_object(read_from, null_sha1, mode, &buf))
+				if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
+					die_errno("cannot open or read '%s'", read_from);
 			break;
 		case S_IFLNK:
 			if (strbuf_readlink(&buf, read_from, st.st_size) < 0)
@@ -2249,8 +2291,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	int cmd_is_annotate = !strcmp(argv[0], "annotate");
 
 	git_config(git_blame_config, NULL);
+	git_config(git_diff_ui_config, NULL);
 	init_revisions(&revs, NULL);
 	revs.date_mode = blame_date_mode;
+	DIFF_OPT_SET(&revs.diffopt, ALLOW_TEXTCONV);
 
 	save_commit_buffer = 0;
 	dashdash_pos = 0;
@@ -2411,12 +2455,20 @@ parse_done:
 		sb.final_buf_size = o->file.size;
 	}
 	else {
+		struct strbuf buf = STRBUF_INIT;
+		unsigned mode;
 		o = get_origin(&sb, sb.final, path);
-		if (fill_blob_sha1(o))
+		if (fill_blob_sha1(o, &mode))
 			die("no such path %s in %s", path, final_commit_name);
 
-		sb.final_buf = read_sha1_file(o->blob_sha1, &type,
-					      &sb.final_buf_size);
+		if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
+		    textconv_object(path, o->blob_sha1, mode, &buf))
+			sb.final_buf= strbuf_detach(&buf, (size_t *) &sb.final_buf_size);
+		else
+			sb.final_buf = read_sha1_file(o->blob_sha1, &type,
+						      &sb.final_buf_size);
+
+		strbuf_release(&buf);
 		if (!sb.final_buf)
 			die("Cannot read blob %s for path %s",
 			    sha1_to_hex(o->blob_sha1),
-- 
1.6.6.7.ga5fe3

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]