Merge branch 'jk/diff-blob'

The result from "git diff" that compares two blobs, e.g. "git diff
$commit1:$path $commit2:$path", used to be shown with the full
object name as given on the command line, but it is more natural to
use the $path in the output and use it to look up .gitattributes.

* jk/diff-blob:
  diff: use blob path for blob/file diffs
  diff: use pending "path" if it is available
  diff: use the word "path" instead of "name" for blobs
  diff: pass whole pending entry in blobinfo
  handle_revision_arg: record paths for pending objects
  handle_revision_arg: record modes for "a..b" endpoints
  t4063: add tests of direct blob diffs
  get_sha1_with_context: dynamically allocate oc->path
  get_sha1_with_context: always initialize oc->symlink_path
  sha1_name: consistently refer to object_context as "oc"
  handle_revision_arg: add handle_dotdot() helper
  handle_revision_arg: hoist ".." check out of range parsing
  handle_revision_arg: stop using "dotdot" as a generic pointer
  handle_revision_arg: simplify commit reference lookups
  handle_revision_arg: reset "dotdot" consistently
This commit is contained in:
Junio C Hamano
2017-06-02 15:06:05 +09:00
10 changed files with 301 additions and 147 deletions

View File

@ -20,23 +20,22 @@
#define DIFF_NO_INDEX_EXPLICIT 1
#define DIFF_NO_INDEX_IMPLICIT 2
struct blobinfo {
struct object_id oid;
const char *name;
unsigned mode;
};
static const char builtin_diff_usage[] =
"git diff [<options>] [<commit> [<commit>]] [--] [<path>...]";
static const char *blob_path(struct object_array_entry *entry)
{
return entry->path ? entry->path : entry->name;
}
static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
const struct object_id *old_oid,
const struct object_id *new_oid,
int old_oid_valid,
int new_oid_valid,
const char *old_name,
const char *new_name)
const char *old_path,
const char *new_path)
{
struct diff_filespec *one, *two;
@ -47,16 +46,16 @@ static void stuff_change(struct diff_options *opt,
if (DIFF_OPT_TST(opt, REVERSE_DIFF)) {
SWAP(old_mode, new_mode);
SWAP(old_oid, new_oid);
SWAP(old_name, new_name);
SWAP(old_path, new_path);
}
if (opt->prefix &&
(strncmp(old_name, opt->prefix, opt->prefix_length) ||
strncmp(new_name, opt->prefix, opt->prefix_length)))
(strncmp(old_path, opt->prefix, opt->prefix_length) ||
strncmp(new_path, opt->prefix, opt->prefix_length)))
return;
one = alloc_filespec(old_name);
two = alloc_filespec(new_name);
one = alloc_filespec(old_path);
two = alloc_filespec(new_path);
fill_filespec(one, old_oid->hash, old_oid_valid, old_mode);
fill_filespec(two, new_oid->hash, new_oid_valid, new_mode);
@ -65,7 +64,7 @@ static void stuff_change(struct diff_options *opt,
static int builtin_diff_b_f(struct rev_info *revs,
int argc, const char **argv,
struct blobinfo *blob)
struct object_array_entry **blob)
{
/* Blob vs file in the working tree*/
struct stat st;
@ -84,14 +83,15 @@ static int builtin_diff_b_f(struct rev_info *revs,
diff_set_mnemonic_prefix(&revs->diffopt, "o/", "w/");
if (blob[0].mode == S_IFINVALID)
blob[0].mode = canon_mode(st.st_mode);
if (blob[0]->mode == S_IFINVALID)
blob[0]->mode = canon_mode(st.st_mode);
stuff_change(&revs->diffopt,
blob[0].mode, canon_mode(st.st_mode),
&blob[0].oid, &null_oid,
blob[0]->mode, canon_mode(st.st_mode),
&blob[0]->item->oid, &null_oid,
1, 0,
path, path);
blob[0]->path ? blob[0]->path : path,
path);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
@ -99,24 +99,24 @@ static int builtin_diff_b_f(struct rev_info *revs,
static int builtin_diff_blobs(struct rev_info *revs,
int argc, const char **argv,
struct blobinfo *blob)
struct object_array_entry **blob)
{
unsigned mode = canon_mode(S_IFREG | 0644);
if (argc > 1)
usage(builtin_diff_usage);
if (blob[0].mode == S_IFINVALID)
blob[0].mode = mode;
if (blob[0]->mode == S_IFINVALID)
blob[0]->mode = mode;
if (blob[1].mode == S_IFINVALID)
blob[1].mode = mode;
if (blob[1]->mode == S_IFINVALID)
blob[1]->mode = mode;
stuff_change(&revs->diffopt,
blob[0].mode, blob[1].mode,
&blob[0].oid, &blob[1].oid,
blob[0]->mode, blob[1]->mode,
&blob[0]->item->oid, &blob[1]->item->oid,
1, 1,
blob[0].name, blob[1].name);
blob_path(blob[0]), blob_path(blob[1]));
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
@ -259,7 +259,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
struct rev_info rev;
struct object_array ent = OBJECT_ARRAY_INIT;
int blobs = 0, paths = 0;
struct blobinfo blob[2];
struct object_array_entry *blob[2];
int nongit = 0, no_index = 0;
int result = 0;
@ -408,9 +408,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
} else if (obj->type == OBJ_BLOB) {
if (2 <= blobs)
die(_("more than two blobs given: '%s'"), name);
oidcpy(&blob[blobs].oid, &obj->oid);
blob[blobs].name = name;
blob[blobs].mode = entry->mode;
blob[blobs] = entry;
blobs++;
} else {