dir: simplify untracked cache "ident" field

It is not a good idea to compare kernel versions and disable
the untracked cache if it changes, as people may upgrade and
still want the untracked cache to work. So let's just
compare work tree locations and kernel name to decide if we
should disable it.

Also storing many locations in the ident field and comparing
to any of them can be dangerous if GIT_WORK_TREE is used with
different values. So let's just store one location, the
location of the current work tree.

The downside is that untracked cache can only be used by one
type of OS for now. Exporting a git repo to different clients
via a network to e.g. Linux and Windows means that only one
can use the untracked cache.

If the location changed in the ident field and we still want
an untracked cache, let's delete the cache and recreate it.

Note that if an untracked cache has been created by a
previous Git version, then the kernel version is stored in
the ident field. As we now compare with just the kernel
name the comparison will fail and the untracked cache will
be disabled until it's recreated.

Helped-by: Torsten Bögershausen <tboegi@web.de>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Christian Couder 2016-01-24 16:28:21 +01:00 committed by Junio C Hamano
parent 07b29bfd8d
commit 0e0f761842
2 changed files with 24 additions and 16 deletions

39
dir.c
View File

@ -1913,28 +1913,31 @@ static const char *get_ident_string(void)
return sb.buf;
if (uname(&uts) < 0)
die_errno(_("failed to get kernel name and information"));
strbuf_addf(&sb, "Location %s, system %s %s %s", get_git_work_tree(),
uts.sysname, uts.release, uts.version);
strbuf_addf(&sb, "Location %s, system %s", get_git_work_tree(),
uts.sysname);
return sb.buf;
}
static int ident_in_untracked(const struct untracked_cache *uc)
{
const char *end = uc->ident.buf + uc->ident.len;
const char *p = uc->ident.buf;
/*
* Previous git versions may have saved many NUL separated
* strings in the "ident" field, but it is insane to manage
* many locations, so just take care of the first one.
*/
for (p = uc->ident.buf; p < end; p += strlen(p) + 1)
if (!strcmp(p, get_ident_string()))
return 1;
return 0;
return !strcmp(uc->ident.buf, get_ident_string());
}
void add_untracked_ident(struct untracked_cache *uc)
static void set_untracked_ident(struct untracked_cache *uc)
{
if (ident_in_untracked(uc))
return;
strbuf_reset(&uc->ident);
strbuf_addstr(&uc->ident, get_ident_string());
/* this strbuf contains a list of strings, save NUL too */
/*
* This strbuf used to contain a list of NUL separated
* strings, so save NUL too for backward compatibility.
*/
strbuf_addch(&uc->ident, 0);
}
@ -1945,15 +1948,21 @@ static void new_untracked_cache(struct index_state *istate)
uc->exclude_per_dir = ".gitignore";
/* should be the same flags used by git-status */
uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
set_untracked_ident(uc);
istate->untracked = uc;
istate->cache_changed |= UNTRACKED_CHANGED;
}
void add_untracked_cache(struct index_state *istate)
{
if (!istate->untracked) {
new_untracked_cache(istate);
add_untracked_ident(istate->untracked);
istate->cache_changed |= UNTRACKED_CHANGED;
} else {
if (!ident_in_untracked(istate->untracked)) {
free_untracked_cache(istate->untracked);
new_untracked_cache(istate);
}
}
}
void remove_untracked_cache(struct index_state *istate)
@ -2022,7 +2031,7 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
return NULL;
if (!ident_in_untracked(dir->untracked)) {
warning(_("Untracked cache is disabled on this system."));
warning(_("Untracked cache is disabled on this system or location."));
return NULL;
}

1
dir.h
View File

@ -307,7 +307,6 @@ void untracked_cache_add_to_index(struct index_state *, const char *);
void free_untracked_cache(struct untracked_cache *);
struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz);
void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked);
void add_untracked_ident(struct untracked_cache *);
void add_untracked_cache(struct index_state *istate);
void remove_untracked_cache(struct index_state *istate);
#endif