From: Axel Bonnet <axel.bonnet@ensimag.imag.fr>
To: git@vger.kernel.org
Cc: "Axel Bonnet" <axel.bonnet@ensimag.imag.fr>,
"Clément Poulain" <clement.poulain@ensimag.imag.fr>,
"Diane Gasselin" <diane.gasselin@ensimag.imag.fr>
Subject: [PATCH v2 2/3] textconv: support for blame
Date: Mon, 7 Jun 2010 17:23:37 +0200 [thread overview]
Message-ID: <1275924218-20154-2-git-send-email-axel.bonnet@ensimag.imag.fr> (raw)
In-Reply-To: <1275924218-20154-1-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.
Only regular files are converted, so the mode of diff_filespec is faked.
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 declarations of several functions are modified to give access to a
diff_options, in order to know whether the textconv option is activated or not.
Signed-off-by: Axel Bonnet <axel.bonnet@ensimag.imag.fr>
Signed-off-by: Clément Poulain <clement.poulain@ensimag.imag.fr>
Signed-off-by: Diane Gasselin <diane.gasselin@ensimag.imag.fr>
---
builtin/blame.c | 82 +++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 68 insertions(+), 14 deletions(-)
diff --git a/builtin/blame.c b/builtin/blame.c
index fc15863..f831e3a 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,16 +87,49 @@ 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,
+ char **buf,
+ size_t *buf_size)
+{
+ struct diff_filespec *df;
+ struct userdiff_driver *textconv;
+
+ df = alloc_filespec(path);
+ fill_filespec(df, sha1, S_IFREG | 0664);
+ textconv = get_textconv(df);
+ if (!textconv) {
+ free_filespec(df);
+ return 0;
+ }
+
+ *buf_size = fill_textconv(textconv, df, buf);
+ 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 origin *o, mmfile_t *file)
+static void fill_origin_blob(struct diff_options *opt,
+ struct origin *o, mmfile_t *file)
{
if (!o->file.ptr) {
enum object_type type;
num_read_blob++;
- file->ptr = read_sha1_file(o->blob_sha1, &type,
- (unsigned long *)(&(file->size)));
+
+ if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
+ textconv_object(o->path, o->blob_sha1, &file->ptr,
+ (size_t *) &file->size))
+ ;
+ else
+ file->ptr = read_sha1_file(o->blob_sha1, &type,
+ (unsigned long *)(&(file->size)));
if (!file->ptr)
die("Cannot read blob %s for path %s",
sha1_to_hex(o->blob_sha1),
@@ -282,7 +316,6 @@ static struct origin *get_origin(struct scoreboard *sb,
static int fill_blob_sha1(struct origin *origin)
{
unsigned mode;
-
if (!is_null_sha1(origin->blob_sha1))
return 0;
if (get_tree_entry(origin->commit->object.sha1,
@@ -741,8 +774,8 @@ static int pass_blame_to_parent(struct scoreboard *sb,
if (last_in_target < 0)
return 1; /* nothing remains for this target */
- fill_origin_blob(parent, &file_p);
- fill_origin_blob(target, &file_o);
+ fill_origin_blob(&sb->revs->diffopt, parent, &file_p);
+ fill_origin_blob(&sb->revs->diffopt, target, &file_o);
num_get_patch++;
memset(&xpp, 0, sizeof(xpp));
@@ -922,7 +955,7 @@ static int find_move_in_parent(struct scoreboard *sb,
if (last_in_target < 0)
return 1; /* nothing remains for this target */
- fill_origin_blob(parent, &file_p);
+ fill_origin_blob(&sb->revs->diffopt, parent, &file_p);
if (!file_p.ptr)
return 0;
@@ -1063,7 +1096,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
norigin = get_origin(sb, parent, p->one->path);
hashcpy(norigin->blob_sha1, p->one->sha1);
- fill_origin_blob(norigin, &file_p);
+ fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
if (!file_p.ptr)
continue;
@@ -1983,6 +2016,13 @@ static int git_blame_config(const char *var, const char *value, void *cb)
blame_date_mode = parse_date_format(value);
return 0;
}
+
+ switch (userdiff_config(var, value)) {
+ case 0: break;
+ case -1: return -1;
+ default: return 0;
+ }
+
return git_default_config(var, value, cb);
}
@@ -1990,7 +2030,9 @@ static int git_blame_config(const char *var, const char *value, void *cb)
* Prepare a dummy commit that represents the work tree (or staged) item.
* Note that annotating work tree item never works in the reverse.
*/
-static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)
+static struct commit *fake_working_tree_commit(struct diff_options *opt,
+ const char *path,
+ const char *contents_from)
{
struct commit *commit;
struct origin *origin;
@@ -2030,10 +2072,14 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
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, &buf.buf, &buf.len))
+ ;
+ else 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)
@@ -2248,6 +2294,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
git_config(git_blame_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;
@@ -2384,7 +2431,8 @@ parse_done:
* or "--contents".
*/
setup_work_tree();
- sb.final = fake_working_tree_commit(path, contents_from);
+ sb.final = fake_working_tree_commit(&sb.revs->diffopt,
+ path, contents_from);
add_pending_object(&revs, &(sb.final->object), ":");
}
else if (contents_from)
@@ -2411,8 +2459,14 @@ parse_done:
if (fill_blob_sha1(o))
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, (char **) &sb.final_buf,
+ (size_t *) &sb.final_buf_size))
+ ;
+ else
+ sb.final_buf = read_sha1_file(o->blob_sha1, &type,
+ &sb.final_buf_size);
+
if (!sb.final_buf)
die("Cannot read blob %s for path %s",
sha1_to_hex(o->blob_sha1),
--
1.6.6.7.ga5fe3
next prev parent reply other threads:[~2010-06-07 15:24 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-07 14:41 [PATCH v2 0/3] textconv support for blame Axel Bonnet
2010-06-07 15:23 ` [PATCH v2 1/3] textconv: make the API public Axel Bonnet
2010-06-07 15:23 ` Axel Bonnet [this message]
2010-06-07 15:23 ` [PATCH v2 3/3] t/t8006: test textconv support for blame Axel Bonnet
2010-06-11 23:52 ` Junio C Hamano
2010-06-14 7:52 ` Diane Gasselin
2010-06-11 23:52 ` [PATCH v2 2/3] textconv: " Junio C Hamano
2010-06-12 4:11 ` Jeff King
2010-06-14 20:40 ` Junio C Hamano
2010-06-15 9:29 ` Clément Poulain
2010-06-15 9:54 ` Jeff King
2010-06-15 10:32 ` bonneta
2010-06-15 10:51 ` Matthieu Moy
[not found] ` <aad13a73928536f87879ef7284d6cc75@ensimag.fr>
2010-06-15 11:07 ` Jeff King
2010-06-15 12:13 ` bonneta
2010-06-15 15:00 ` Junio C Hamano
2010-06-15 13:58 ` Axel Bonnet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1275924218-20154-2-git-send-email-axel.bonnet@ensimag.imag.fr \
--to=axel.bonnet@ensimag.imag.fr \
--cc=clement.poulain@ensimag.imag.fr \
--cc=diane.gasselin@ensimag.imag.fr \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).