diff: handle sha1 abbreviations outside of repository

When generating diffs outside a repository (e.g., with "diff
--no-index"), we may write abbreviated sha1s as part of
"--raw" output or the "index" lines of "--patch" output.
Since we have no object database, we never find any
collisions, and these sha1s get whatever static abbreviation
length is configured (typically 7).

However, we do blindly look in ".git/objects" to see if any
objects exist, even though we know we are not in a
repository. This is usually harmless because such a
directory is unlikely to exist, but could be wrong in rare
circumstances.

Let's instead notice when we are not in a repository and
behave as if the object database is empty (i.e., just use
the default abbrev length). It would perhaps make sense to
be conservative and show full sha1s in that case, but
showing the default abbreviation is what we've always done
(and is certainly less ugly).

Note that this does mean that:

  cd /not/a/repo
  GIT_OBJECT_DIRECTORY=/some/real/objdir git diff --no-index ...

used to look for collisions in /some/real/objdir but now
does not. This could be considered either a bugfix (we do
not look at objects if we have no repository) or a
regression, but it seems unlikely that anybody would care
much either way.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2016-10-20 02:21:25 -04:00 committed by Junio C Hamano
parent d6cece51b8
commit 4f03666ac6

21
diff.c
View File

@ -3096,6 +3096,19 @@ static int similarity_index(struct diff_filepair *p)
return p->score * 100 / MAX_SCORE;
}
static const char *diff_abbrev_oid(const struct object_id *oid, int abbrev)
{
if (startup_info->have_repository)
return find_unique_abbrev(oid->hash, abbrev);
else {
char *hex = oid_to_hex(oid);
if (abbrev < 0 || abbrev > GIT_SHA1_HEXSZ)
die("BUG: oid abbreviation out of range: %d", abbrev);
hex[abbrev] = '\0';
return hex;
}
}
static void fill_metainfo(struct strbuf *msg,
const char *name,
const char *other,
@ -3154,9 +3167,9 @@ static void fill_metainfo(struct strbuf *msg,
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
abbrev = 40;
}
strbuf_addf(msg, "%s%sindex %s..", line_prefix, set,
find_unique_abbrev(one->oid.hash, abbrev));
strbuf_add_unique_abbrev(msg, two->oid.hash, abbrev);
strbuf_addf(msg, "%s%sindex %s..%s", line_prefix, set,
diff_abbrev_oid(&one->oid, abbrev),
diff_abbrev_oid(&two->oid, abbrev));
if (one->mode == two->mode)
strbuf_addf(msg, " %06o", one->mode);
strbuf_addf(msg, "%s\n", reset);
@ -4165,7 +4178,7 @@ const char *diff_aligned_abbrev(const struct object_id *oid, int len)
if (len == GIT_SHA1_HEXSZ)
return oid_to_hex(oid);
abbrev = find_unique_abbrev(oid->hash, len);
abbrev = diff_abbrev_oid(oid, len);
abblen = strlen(abbrev);
/*