From 573285e55265ccedab5507c47ebd4357f360093f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Poulain?= Date: Wed, 9 Jun 2010 19:02:06 +0200 Subject: [PATCH 1/4] sha1_name: add get_sha1_with_context() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Textconv is defined by the diff driver, which is associated with a pathname, not a blob. This fonction permits to know the context for the sha1 you're looking for, especially his pathname Signed-off-by: Clément Poulain Signed-off-by: Diane Gasselin Signed-off-by: Axel Bonnet Signed-off-by: Junio C Hamano --- cache.h | 11 +++++++++++ sha1_name.c | 31 ++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/cache.h b/cache.h index c96602305f..67030dbfca 100644 --- a/cache.h +++ b/cache.h @@ -730,12 +730,23 @@ static inline unsigned int hexval(unsigned char c) #define MINIMUM_ABBREV 4 #define DEFAULT_ABBREV 7 +struct object_context { + unsigned char tree[20]; + char path[PATH_MAX]; + unsigned mode; +}; + extern int get_sha1(const char *str, unsigned char *sha1); extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int gently, const char *prefix); static inline int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode) { return get_sha1_with_mode_1(str, sha1, mode, 1, NULL); } +extern int get_sha1_with_context_1(const char *name, unsigned char *sha1, struct object_context *orc, int gently, const char *prefix); +static inline int get_sha1_with_context(const char *str, unsigned char *sha1, struct object_context *orc) +{ + return get_sha1_with_context_1(str, sha1, orc, 1, NULL); +} extern int get_sha1_hex(const char *hex, unsigned char *sha1); extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */ extern int read_ref(const char *filename, unsigned char *sha1); diff --git a/sha1_name.c b/sha1_name.c index bf92417838..7fdb20277f 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -933,8 +933,8 @@ int interpret_branch_name(const char *name, struct strbuf *buf) */ int get_sha1(const char *name, unsigned char *sha1) { - unsigned unused; - return get_sha1_with_mode(name, sha1, &unused); + struct object_context unused; + return get_sha1_with_context(name, sha1, &unused); } /* Must be called only when object_name:filename doesn't exist. */ @@ -1031,12 +1031,24 @@ static void diagnose_invalid_index_path(int stage, int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode, int gently, const char *prefix) +{ + struct object_context oc; + int ret; + ret = get_sha1_with_context_1(name, sha1, &oc, gently, prefix); + *mode = oc.mode; + return ret; +} + +int get_sha1_with_context_1(const char *name, unsigned char *sha1, + struct object_context *oc, + int gently, const char *prefix) { int ret, bracket_depth; int namelen = strlen(name); const char *cp; - *mode = S_IFINVALID; + memset(oc, 0, sizeof(*oc)); + oc->mode = S_IFINVALID; ret = get_sha1_1(name, namelen, sha1); if (!ret) return ret; @@ -1059,6 +1071,11 @@ int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode, cp = name + 3; } namelen = namelen - (cp - name); + + strncpy(oc->path, cp, + sizeof(oc->path)); + oc->path[sizeof(oc->path)-1] = '\0'; + if (!active_cache) read_cache(); pos = cache_name_pos(cp, namelen); @@ -1071,7 +1088,6 @@ int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode, break; if (ce_stage(ce) == stage) { hashcpy(sha1, ce->sha1); - *mode = ce->ce_mode; return 0; } pos++; @@ -1098,12 +1114,17 @@ int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode, } if (!get_sha1_1(name, cp-name, tree_sha1)) { const char *filename = cp+1; - ret = get_tree_entry(tree_sha1, filename, sha1, mode); + ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode); if (!gently) { diagnose_invalid_sha1_path(prefix, filename, tree_sha1, object_name); free(object_name); } + hashcpy(oc->tree, tree_sha1); + strncpy(oc->path, filename, + sizeof(oc->path)); + oc->path[sizeof(oc->path)-1] = '\0'; + return ret; } else { if (!gently) From e5fba602e59292c8c383a7a587897b5f7cbd5c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Poulain?= Date: Tue, 15 Jun 2010 17:50:28 +0200 Subject: [PATCH 2/4] textconv: support for cat_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the textconv_object function public, and add --textconv option to cat-file to perform conversion on blob objects. Using --textconv implies that we are working on a blob. As files drivers need to be initialized, a new config is required in addition to git_default_config. Therefore git_cat_file_config() is introduced Signed-off-by: Clément Poulain Signed-off-by: Diane Gasselin Signed-off-by: Axel Bonnet Signed-off-by: Junio C Hamano --- builtin.h | 2 ++ builtin/blame.c | 8 ++++---- builtin/cat-file.c | 38 ++++++++++++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/builtin.h b/builtin.h index 5c887ef61b..5a1dba0069 100644 --- a/builtin.h +++ b/builtin.h @@ -36,6 +36,8 @@ void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c); extern int check_pager_config(const char *cmd); +extern int textconv_object(const char *path, const unsigned char *sha1, char **buf, unsigned long *buf_size); + extern int cmd_add(int argc, const char **argv, const char *prefix); extern int cmd_annotate(int argc, const char **argv, const char *prefix); extern int cmd_apply(int argc, const char **argv, const char *prefix); diff --git a/builtin/blame.c b/builtin/blame.c index 7bbe7612a1..2e63648ea0 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -91,10 +91,10 @@ struct origin { * 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, - unsigned long *buf_size) +int textconv_object(const char *path, + const unsigned char *sha1, + char **buf, + unsigned long *buf_size) { struct diff_filespec *df; struct userdiff_driver *textconv; diff --git a/builtin/cat-file.c b/builtin/cat-file.c index a933eaa043..cada5d2257 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -9,6 +9,8 @@ #include "tree.h" #include "builtin.h" #include "parse-options.h" +#include "diff.h" +#include "userdiff.h" #define BATCH 1 #define BATCH_CHECK 2 @@ -84,10 +86,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) { unsigned char sha1[20]; enum object_type type; - void *buf; + char *buf; unsigned long size; + struct object_context obj_context; - if (get_sha1(obj_name, sha1)) + if (get_sha1_with_context(obj_name, sha1, &obj_context)) die("Not a valid object name %s", obj_name); buf = NULL; @@ -132,6 +135,17 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) /* otherwise just spit out the data */ break; + + case 'c': + if (!obj_context.path[0]) + die("git cat-file --textconv %s: must be ", + obj_name); + + if (!textconv_object(obj_context.path, sha1, &buf, &size)) + die("git cat-file --textconv: unable to run textconv on %s", + obj_name); + break; + case 0: buf = read_object_with_reference(sha1, exp_type, &size, NULL); break; @@ -201,11 +215,25 @@ static int batch_objects(int print_contents) } static const char * const cat_file_usage[] = { - "git cat-file (-t|-s|-e|-p|) ", + "git cat-file (-t|-s|-e|-p||--textconv) ", "git cat-file (--batch|--batch-check) < ", NULL }; +static int git_cat_file_config(const char *var, const char *value, void *cb) +{ + switch (userdiff_config(var, value)) { + case 0: + break; + case -1: + return -1; + default: + return 0; + } + + return git_default_config(var, value, cb); +} + int cmd_cat_file(int argc, const char **argv, const char *prefix) { int opt = 0, batch = 0; @@ -218,6 +246,8 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) OPT_SET_INT('e', NULL, &opt, "exit with zero when there's no error", 'e'), OPT_SET_INT('p', NULL, &opt, "pretty-print object's content", 'p'), + OPT_SET_INT(0, "textconv", &opt, + "for blob objects, run textconv on object's content", 'c'), OPT_SET_INT(0, "batch", &batch, "show info and content of objects fed from the standard input", BATCH), @@ -227,7 +257,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) OPT_END() }; - git_config(git_default_config, NULL); + git_config(git_cat_file_config, NULL); if (argc != 3 && argc != 2) usage_with_options(cat_file_usage, options); From 34bb92eca4259b3db8cb9bfad5fcac4ff2be139b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Poulain?= Date: Wed, 9 Jun 2010 19:02:09 +0200 Subject: [PATCH 3/4] t/t8007: test textconv support for cat-file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test the correct functionning of textconv with cat-file and cat-file HEAD^ . Test the case when no driver is specified Signed-off-by: Clément Poulain Signed-off-by: Diane Gasselin Signed-off-by: Axel Bonnet Signed-off-by: Junio C Hamano --- t/t8007-cat-file-textconv.sh | 70 ++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100755 t/t8007-cat-file-textconv.sh diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh new file mode 100755 index 0000000000..38ac05e4a0 --- /dev/null +++ b/t/t8007-cat-file-textconv.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +test_description='git cat-file textconv support' +. ./test-lib.sh + +cat >helper <<'EOF' +#!/bin/sh +sed 's/^/converted: /' "$@" +EOF +chmod +x helper + +test_expect_success 'setup ' ' + echo test >one.bin && + git add . && + GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" && + echo test version 2 >one.bin && + GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00" +' + +cat >expected <result + test_cmp expected result +' + +test_expect_success 'setup textconv filters' ' + echo "*.bin diff=test" >.gitattributes && + git config diff.test.textconv ./helper && + git config diff.test.cachetextconv false +' + +cat >expected <result && + test_cmp expected result +' + +cat >expected <result && + test_cmp expected result +' + +cat >expected <result && + test_cmp expected result +' + +cat >expected <result && + test_cmp expected result +' +test_done From 9f77fe022425360dced8b1f19275852e89d2351c Mon Sep 17 00:00:00 2001 From: Michael J Gruber Date: Thu, 24 Jun 2010 14:56:55 +0200 Subject: [PATCH 4/4] git-cat-file.txt: Document --textconv Signed-off-by: Michael J Gruber Signed-off-by: Junio C Hamano --- Documentation/git-cat-file.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 58c8d65772..9ebbe9402b 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -9,14 +9,15 @@ git-cat-file - Provide content or type and size information for repository objec SYNOPSIS -------- [verse] -'git cat-file' (-t | -s | -e | -p | ) +'git cat-file' (-t | -s | -e | -p | | --textconv ) 'git cat-file' (--batch | --batch-check) < DESCRIPTION ----------- In its first form, the command provides the content or the type of an object in the repository. The type is required unless '-t' or '-p' is used to find the -object type, or '-s' is used to find the object size. +object type, or '-s' is used to find the object size, or '--textconv' is used +(which implies type "blob"). In the second form, a list of objects (separated by linefeeds) is provided on stdin, and the SHA1, type, and size of each object is printed on stdout. @@ -51,6 +52,11 @@ OPTIONS or to ask for a "blob" with being a tag object that points at it. +--textconv:: + Show the content as transformed by a textconv filter. In this case, + has be of the form :, or : in order + to apply the filter to the content recorded in the index at . + --batch:: Print the SHA1, type, size, and contents of each object provided on stdin. May not be combined with any other options or arguments.