Skip to content

Commit

Permalink
Merge branch 'lt/abbrev-auto'
Browse files Browse the repository at this point in the history
Allow the default abbreviation length, which has historically been
7, to scale as the repository grows.  The logic suggests to use 12
hexdigits for the Linux kernel, and 9 to 10 for Git itself.

* lt/abbrev-auto:
  abbrev: auto size the default abbreviation
  abbrev: prepare for new world order
  abbrev: add FALLBACK_DEFAULT_ABBREV to prepare for auto sizing
  • Loading branch information
gitster committed Oct 27, 2016
2 parents 2cc2e70 + e6c587c commit 580d820
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 7 deletions.
3 changes: 3 additions & 0 deletions builtin/fetch.c
Expand Up @@ -17,6 +17,9 @@
#include "argv-array.h"
#include "utf8.h"

#define TRANSPORT_SUMMARY(x) \
(int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)

static const char * const builtin_fetch_usage[] = {
N_("git fetch [<options>] [<repository> [<refspec>...]]"),
N_("git fetch [<options>] <group>"),
Expand Down
5 changes: 3 additions & 2 deletions builtin/rev-parse.c
Expand Up @@ -671,8 +671,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
filter &= ~(DO_FLAGS|DO_NOREV);
verify = 1;
abbrev = DEFAULT_ABBREV;
if (arg[7] == '=')
abbrev = strtoul(arg + 8, NULL, 10);
if (!arg[7])
continue;
abbrev = strtoul(arg + 8, NULL, 10);
if (abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (40 <= abbrev)
Expand Down
4 changes: 4 additions & 0 deletions cache.h
Expand Up @@ -1190,6 +1190,9 @@ static inline int hex2chr(const char *s)
#define MINIMUM_ABBREV minimum_abbrev
#define DEFAULT_ABBREV default_abbrev

/* used when the code does not know or care what the default abbrev is */
#define FALLBACK_DEFAULT_ABBREV 7

struct object_context {
unsigned char tree[20];
char path[PATH_MAX];
Expand All @@ -1208,6 +1211,7 @@ struct object_context {
#define GET_SHA1_TREEISH 020
#define GET_SHA1_BLOB 040
#define GET_SHA1_FOLLOW_SYMLINKS 0100
#define GET_SHA1_AUTOMATIC 0200
#define GET_SHA1_ONLY_TO_DIE 04000

#define GET_SHA1_DISAMBIGUATORS \
Expand Down
2 changes: 1 addition & 1 deletion diff.c
Expand Up @@ -3468,7 +3468,7 @@ void diff_setup_done(struct diff_options *options)
*/
read_cache();
}
if (options->abbrev <= 0 || 40 < options->abbrev)
if (40 < options->abbrev)
options->abbrev = 40; /* full */

/*
Expand Down
2 changes: 1 addition & 1 deletion environment.c
Expand Up @@ -16,7 +16,7 @@ int trust_executable_bit = 1;
int trust_ctime = 1;
int check_stat = 1;
int has_symlinks = 1;
int minimum_abbrev = 4, default_abbrev = 7;
int minimum_abbrev = 4, default_abbrev = -1;
int ignore_case;
int assume_unchanged;
int prefer_symlink_refs;
Expand Down
28 changes: 27 additions & 1 deletion sha1_name.c
Expand Up @@ -15,6 +15,7 @@ typedef int (*disambiguate_hint_fn)(const unsigned char *, void *);

struct disambiguate_state {
int len; /* length of prefix in hex chars */
unsigned int nrobjects;
char hex_pfx[GIT_SHA1_HEXSZ + 1];
unsigned char bin_pfx[GIT_SHA1_RAWSZ];

Expand Down Expand Up @@ -111,6 +112,14 @@ static void find_short_object_filename(struct disambiguate_state *ds)

if (strlen(de->d_name) != 38)
continue;

/*
* We only look at the one subdirectory, and we assume
* each subdirectory is roughly similar, so each
* object we find probably has 255 other objects in
* the other fan-out directories.
*/
ds->nrobjects += 256;
if (memcmp(de->d_name, ds->hex_pfx + 2, ds->len - 2))
continue;
memcpy(hex + 2, de->d_name, 38);
Expand Down Expand Up @@ -144,6 +153,7 @@ static void unique_in_pack(struct packed_git *p,

open_pack_index(p);
num = p->num_objects;
ds->nrobjects += num;
last = num;
while (first < last) {
uint32_t mid = (first + last) / 2;
Expand Down Expand Up @@ -373,6 +383,9 @@ static int show_ambiguous_object(const unsigned char *sha1, void *data)
return 0;
}

/* start from our historical default before the automatic abbreviation */
static int default_automatic_abbrev = FALLBACK_DEFAULT_ABBREV;

static int get_short_sha1(const char *name, int len, unsigned char *sha1,
unsigned flags)
{
Expand Down Expand Up @@ -419,6 +432,14 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
for_each_abbrev(ds.hex_pfx, show_ambiguous_object, &ds);
}

if (len < 16 && !status && (flags & GET_SHA1_AUTOMATIC)) {
unsigned int expect_collision = 1 << (len * 2);
if (ds.nrobjects > expect_collision) {
default_automatic_abbrev = len+1;
return SHORT_NAME_AMBIGUOUS;
}
}

return status;
}

Expand Down Expand Up @@ -451,14 +472,19 @@ int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len)
{
int status, exists;
int flags = GET_SHA1_QUIETLY;

if (len < 0) {
flags |= GET_SHA1_AUTOMATIC;
len = default_automatic_abbrev;
}
sha1_to_hex_r(hex, sha1);
if (len == 40 || !len)
return 40;
exists = has_sha1_file(sha1);
while (len < 40) {
unsigned char sha1_ret[20];
status = get_short_sha1(hex, len, sha1_ret, GET_SHA1_QUIETLY);
status = get_short_sha1(hex, len, sha1_ret, flags);
if (exists
? !status
: status == SHORT_NAME_NOT_FOUND) {
Expand Down
3 changes: 1 addition & 2 deletions transport.h
Expand Up @@ -147,8 +147,7 @@ struct transport {
#define TRANSPORT_PUSH_ATOMIC 8192
#define TRANSPORT_PUSH_OPTIONS 16384

#define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
#define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)
#define TRANSPORT_SUMMARY_WIDTH (2 * FALLBACK_DEFAULT_ABBREV + 3)

/* Returns a transport suitable for the url */
struct transport *transport_get(struct remote *, const char *);
Expand Down

0 comments on commit 580d820

Please sign in to comment.