Re: [PATCH v3 3/4] cat-file --textconv/--filters: allow specifying the path separately

2016-09-10 Thread Johannes Schindelin
Hi Junio,

On Fri, 9 Sep 2016, Junio C Hamano wrote:

> Johannes Schindelin  writes:
> 
> > +test_expect_success 'path= complains without 
> > --textconv/--filters' '
> 
> I wonder where this "path" came from; it wasn't in v2 I queued,
> but somehow came back mysteriously.

No idea how it crept back in. Sorry.

> Will locally amend.

Thanks!
Dscho


Re: [PATCH v3 3/4] cat-file --textconv/--filters: allow specifying the path separately

2016-09-09 Thread Junio C Hamano
Johannes Schindelin  writes:

> +test_expect_success 'path= complains without --textconv/--filters' 
> '

I wonder where this "path" came from; it wasn't in v2 I queued,
but somehow came back mysteriously.

Will locally amend.

> + sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
> + test_must_fail git cat-file --path=hello.txt blob $sha1 >actual 2>err &&
> + test ! -s actual &&
> + grep "path.*needs.*filters" err
> +'
> +
>  test_done


[PATCH v3 3/4] cat-file --textconv/--filters: allow specifying the path separately

2016-09-09 Thread Johannes Schindelin
There are circumstances when it is relatively easy to figure out the
object name for a given path, but not the name of the containing tree.
For example, when looking at a diff generated by Git, the object names
are recorded, but not the revision. As a matter of fact, the revisions
from which the diff was generated may not even exist locally.

In such a case, the user would have to generate a fake revision just to
be able to use --textconv or --filters.

Let's simplify this dramatically, because we do not really need that
revision at all: all we care about is that we know the path. In the
scenario described above, we do know the path, and we just want to
specify it separately from the object name.

Example usage:

git cat-file --textconv --path=main.c 0f1937fd

Signed-off-by: Johannes Schindelin 
---
 Documentation/git-cat-file.txt |  7 ++-
 builtin/cat-file.c | 26 +-
 t/t8010-cat-file-filters.sh| 20 
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index 537d02c..4fa9041 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -9,7 +9,7 @@ git-cat-file - Provide content or type and size information for 
repository objec
 SYNOPSIS
 
 [verse]
-'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p 
|  | --textconv | --filters ) 
+'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p 
|  | --textconv | --filters ) [--path=] 
 'git cat-file' (--batch | --batch-check) [--follow-symlinks]
 
 DESCRIPTION
@@ -64,6 +64,11 @@ OPTIONS
end-of-line conversion, etc). In this case,  has to be of
the form :, or :.
 
+--path=::
+   For use with --textconv or --filters, to allow specifying an object
+   name and a path separately, e.g. when it is difficult to figure out
+   the revision from which the blob came.
+
 --batch::
 --batch=::
Print object information and contents for each object provided
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 0b74afa..b648056 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -20,6 +20,8 @@ struct batch_options {
const char *format;
 };
 
+static const char *force_path;
+
 static int filter_object(const char *path, unsigned mode,
 const unsigned char *sha1,
 char **buf, unsigned long *size)
@@ -58,6 +60,7 @@ static int cat_one_file(int opt, const char *exp_type, const 
char *obj_name,
struct object_info oi = {NULL};
struct strbuf sb = STRBUF_INIT;
unsigned flags = LOOKUP_REPLACE_OBJECT;
+   const char *path = force_path;
 
if (unknown_type)
flags |= LOOKUP_UNKNOWN_OBJECT;
@@ -65,6 +68,11 @@ static int cat_one_file(int opt, const char *exp_type, const 
char *obj_name,
if (get_sha1_with_context(obj_name, 0, sha1, _context))
die("Not a valid object name %s", obj_name);
 
+   if (!path)
+   path = obj_context.path;
+   if (obj_context.mode == S_IFINVALID)
+   obj_context.mode = 0100644;
+
buf = NULL;
switch (opt) {
case 't':
@@ -89,21 +97,22 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return !has_sha1_file(sha1);
 
case 'w':
-   if (!obj_context.path[0])
+   if (!path[0])
die("git cat-file --filters %s:  must be "
"", obj_name);
 
-   if (filter_object(obj_context.path, obj_context.mode,
+   if (filter_object(path, obj_context.mode,
  sha1, , ))
return -1;
break;
 
case 'c':
-   if (!obj_context.path[0])
+   if (!path[0])
die("git cat-file --textconv %s:  must be 
",
obj_name);
 
-   if (textconv_object(obj_context.path, obj_context.mode, sha1, 
1, , ))
+   if (textconv_object(path, obj_context.mode,
+   sha1, 1, , ))
break;
 
case 'p':
@@ -477,7 +486,7 @@ static int batch_objects(struct batch_options *opt)
 }
 
 static const char * const cat_file_usage[] = {
-   N_("git cat-file (-t [--allow-unknown-type]|-s 
[--allow-unknown-type]|-e|-p||--textconv|--filters) "),
+   N_("git cat-file (-t [--allow-unknown-type]|-s 
[--allow-unknown-type]|-e|-p||--textconv|--filters) [--path=] 
"),
N_("git cat-file (--batch | --batch-check) [--follow-symlinks]"),
NULL
 };
@@ -525,6 +534,8 @@ int cmd_cat_file(int argc, const char **argv, const char 
*prefix)
N_("for blob objects, run textconv on object's 
content"), 'c'),
OPT_CMDMODE(0, "filters",