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 <sunsh...@sunshineco.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 Documentation/technical/index-format.txt |  3 +++
 dir.c                                    | 28 ++++++++++++++++++++++++++++
 git-compat-util.h                        |  1 +
 test-dump-untracked-cache.c              |  1 +
 4 files changed, 33 insertions(+)

diff --git a/Documentation/technical/index-format.txt 
b/Documentation/technical/index-format.txt
index b97ac8d..5dc2bee 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -242,6 +242,9 @@ Git index format
 
   The extension starts with
 
+  - A NUL-terminated string describing the environment when the cache
+    is created.
+
   - Stat data of $GIT_DIR/info/exclude. See "Index entry" section from
     ctime field until "file size".
 
diff --git a/dir.c b/dir.c
index 916f1ed..ef58547 100644
--- a/dir.c
+++ b/dir.c
@@ -2246,10 +2246,21 @@ static void write_one_dir(struct untracked_cache_dir 
*untracked,
                        write_one_dir(untracked->dirs[i], wd);
 }
 
+static void get_ident_string(struct strbuf *sb)
+{
+       struct utsname uts;
+
+       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);
+}
+
 void write_untracked_extension(struct strbuf *out, struct untracked_cache 
*untracked)
 {
        struct ondisk_untracked_cache *ouc;
        struct write_data wd;
+       struct strbuf sb = STRBUF_INIT;
        unsigned char varbuf[16];
        int len = 0, varint_len;
        if (untracked->exclude_per_dir)
@@ -2261,6 +2272,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);
+
+       get_ident_string(&sb);
+       strbuf_add(out, sb.buf, sb.len + 1);
+       strbuf_release(&sb);
+
        strbuf_add(out, ouc, sizeof(*ouc) + len);
        if (!untracked->root) {
                varint_len = encode_varint(0, varbuf);
@@ -2444,12 +2460,24 @@ 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 = data + sz;
+       struct strbuf sb = STRBUF_INIT;
        int len;
 
        if (sz <= 1 || end[-1] != '\0')
                return NULL;
        end--;
 
+       get_ident_string(&sb);
+       if (strcmp(sb.buf, (const char *)next)) {
+               warning(_("system identification does not match, untracked 
cache disabled.\n"
+                         "Stored: %s\nCurrent: %s\n"),
+                       next, sb.buf);
+               strbuf_release(&sb);
+               return NULL;
+       }
+       next += sb.len + 1;
+       strbuf_release(&sb);
+
        ouc = (const struct ondisk_untracked_cache *)next;
        if (next + sizeof(*ouc) > end)
                return NULL;
diff --git a/git-compat-util.h b/git-compat-util.h
index f587749..e9502a1 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -132,6 +132,7 @@
 #elif defined(_MSC_VER)
 #include "compat/msvc.h"
 #else
+#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
diff --git a/test-dump-untracked-cache.c b/test-dump-untracked-cache.c
index 710441e..25d855d 100644
--- a/test-dump-untracked-cache.c
+++ b/test-dump-untracked-cache.c
@@ -44,6 +44,7 @@ int main(int ac, char **av)
 {
        struct untracked_cache *uc;
        struct strbuf base = STRBUF_INIT;
+       setup_git_directory();
        if (read_cache() < 0)
                die("unable to read index file");
        uc = the_index.untracked;
-- 
2.2.0.60.gb7b3c64

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to