git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
ABAxel Bonnet <axel.bonnet@ensimag.imag.fr>
Date
Jun 3, 2010, 10:47 UTC
Message-ID
<1275562038-7468-4-git-send-email-axel.bonnet@ensimag.imag.fr>
In-Reply-To
<1275562038-7468-3-git-send-email-axel.bonnet@ensimag.imag.fr>

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@ensimag.imag.fr>
Signed-off-by: Clément Poulain <clement.poulain@ensimag.imag.fr>
Signed-off-by: Axel Bonnet <axel.bonnet@ensimag.imag.fr>
---
 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
Previous: Axel BonnetNext: Axel Bonnet
Message 4 of 16 in “textconv support for blame”
  1. 0/4 textconv support for blameAxel Bonnet, Jun 3, 2010
  2. 1/4 textconv: make the API publicAxel Bonnet, Jun 3, 2010
  3. 2/4 textconv: make diff_options accessible from blameAxel Bonnet, Jun 3, 2010
  4. 3/4 textconv: support for blameAxel Bonnet, Jun 3, 2010
  5. 4/4 t/t8006: test textconv support for blameAxel Bonnet, Jun 3, 2010
  6. Johannes SixtJun 3, 2010
  7. Diane GasselinJun 4, 2010
  8. Matthieu MoyJun 4, 2010
  9. Matthieu MoyJun 4, 2010
  10. Junio C HamanoJun 4, 2010
  11. Diane GasselinJun 4, 2010
  12. Jeff KingJun 6, 2010
  13. Junio C HamanoJun 4, 2010
  14. Matthieu MoyJun 4, 2010
  15. bonnetaJun 4, 2010
  16. Matthieu MoyJun 4, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.