aboutsummaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2015-03-08 17:12:46 +0700
committerJunio C Hamano <gitster@pobox.com>2015-03-12 13:45:18 -0700
commit1e8fef609e78110e276df633c5ba1fb1f1589fa5 (patch)
treec7ccbe9baf7e7b557fbfe77f406198cc5ce20939 /dir.c
parent7b6aff0655c965959a59cc7fa3ed51c2a1fbcd44 (diff)
downloadgit-1e8fef609e78110e276df633c5ba1fb1f1589fa5.tar.gz
git-1e8fef609e78110e276df633c5ba1fb1f1589fa5.tar.xz
untracked cache: guard and disable on system changes
If the user enables untracked cache, then - move worktree to an unsupported filesystem - or simply upgrade OS - or move the whole (portable) disk from one machine to another - or access a shared fs from another machine there's no guarantee that untracked cache can still function properly. Record the worktree location and OS footprint in the cache. If it changes, err on the safe side and disable the cache. The user can 'update-index --untracked-cache' again to make sure all conditions are met. This adds a new requirement that setup_git_directory* must be called before read_cache() because we need worktree location by then, or the cache is dropped. This change does not cover all bases, you can fool it if you try hard. The point is to stop accidents. Helped-by: Eric Sunshine <sunshine@sunshineco.com> Helped-by: brian m. carlson <sandals@crustytoothpaste.net> Helped-by: Torsten Bögershausen <tboegi@web.de> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/dir.c b/dir.c
index 2cf8f35cc..e9eaf97ef 100644
--- a/dir.c
+++ b/dir.c
@@ -1794,6 +1794,40 @@ static int treat_leading_path(struct dir_struct *dir,
return rc;
}
+static const char *get_ident_string(void)
+{
+ static struct strbuf sb = STRBUF_INIT;
+ struct utsname uts;
+
+ if (sb.len)
+ return sb.buf;
+ if (uname(&uts))
+ 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);
+ 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;
+
+ for (p = uc->ident.buf; p < end; p += strlen(p) + 1)
+ if (!strcmp(p, get_ident_string()))
+ return 1;
+ return 0;
+}
+
+void add_untracked_ident(struct untracked_cache *uc)
+{
+ if (ident_in_untracked(uc))
+ return;
+ strbuf_addstr(&uc->ident, get_ident_string());
+ /* this strbuf contains a list of strings, save NUL too */
+ strbuf_addch(&uc->ident, 0);
+}
+
static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *dir,
int base_len,
const struct pathspec *pathspec)
@@ -1860,6 +1894,11 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
if (ce_skip_worktree(active_cache[i]))
return NULL;
+ if (!ident_in_untracked(dir->untracked)) {
+ warning(_("Untracked cache is disabled on this system."));
+ return NULL;
+ }
+
if (!dir->untracked->root) {
const int len = sizeof(*dir->untracked->root);
dir->untracked->root = xmalloc(len);
@@ -2268,6 +2307,11 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
hashcpy(ouc->excludes_file_sha1, untracked->ss_excludes_file.sha1);
ouc->dir_flags = htonl(untracked->dir_flags);
memcpy(ouc->exclude_per_dir, untracked->exclude_per_dir, len + 1);
+
+ varint_len = encode_varint(untracked->ident.len, varbuf);
+ strbuf_add(out, varbuf, varint_len);
+ strbuf_add(out, untracked->ident.buf, untracked->ident.len);
+
strbuf_add(out, ouc, ouc_size(len));
free(ouc);
ouc = NULL;
@@ -2453,17 +2497,26 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
struct untracked_cache *uc;
struct read_data rd;
const unsigned char *next = data, *end = (const unsigned char *)data + sz;
- int len;
+ const char *ident;
+ int ident_len, len;
if (sz <= 1 || end[-1] != '\0')
return NULL;
end--;
+ ident_len = decode_varint(&next);
+ if (next + ident_len > end)
+ return NULL;
+ ident = (const char *)next;
+ next += ident_len;
+
ouc = (const struct ondisk_untracked_cache *)next;
if (next + ouc_size(0) > end)
return NULL;
uc = xcalloc(1, sizeof(*uc));
+ strbuf_init(&uc->ident, ident_len);
+ strbuf_add(&uc->ident, ident, ident_len);
load_sha1_stat(&uc->ss_info_exclude, &ouc->info_exclude_stat,
ouc->info_exclude_sha1);
load_sha1_stat(&uc->ss_excludes_file, &ouc->excludes_file_stat,