{"thread":{"id":"637","subject":"[PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.","startedAt":"2005-05-15T21:23:12Z","lastAt":"2005-05-16T23:11:29Z","messageCount":5,"participants":["Junio C Hamano","Petr Baudis","Linus Torvalds"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"3394","messageId":"7vll6gqj3z.fsf@assigned-by-dhcp.cox.net","threadId":"637","inReplyTo":null,"subject":"[PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-15T21:23:12Z","receivedAt":"2005-05-15T21:23:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"With -u flag, git-checkout-cache picks up the stat information\nfrom newly created file and updates the cache.  This removes the\nneed to run git-update-cache --refresh immediately after running\ngit-checkout-cache.\n---\n\n*** The one I posted earlier failed to add a couple of files\n*** that the patch should have added.  Please discard it and\n*** replace it with this one.  Thanks.\n\nDocumentation/git-checkout-cache.txt |    6 +++\nMakefile                             |    2 -\ncache.h                              |    9 +++++\ncheckout-cache.c                     |   35 ++++++++++++++++++++++-\nindex.c                              |   53 +++++++++++++++++++++++++++++++++++\nread-cache.c                         |   20 +++++++++++++\nt/t2002-checkout-cache-u.sh          |   31 ++++++++++++++++++++\nupdate-cache.c                       |   48 ++-----------------------------\n8 files changed, 157 insertions(+), 47 deletions(-)\nindex.c (. --> 100644)\nt/t2002-checkout-cache-u.sh (. --> 100644)\n\n--- a/Documentation/git-checkout-cache.txt\n+++ b/Documentation/git-checkout-cache.txt\n@@ -9,7 +9,7 @@\n \n SYNOPSIS\n --------\n-'git-checkout-cache' [-q] [-a] [-f] [-n] [--prefix=<string>]\n+'git-checkout-cache' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]\n \t           [--] <file>...\n \n DESCRIPTION\n@@ -19,6 +19,10 @@\n \n OPTIONS\n -------\n+-u::\n+\tupdate stat information for the checked out entries in\n+\tthe cache file.\n+\n -q::\n \tbe quiet if files exist or are not in the cache\n \n--- a/Makefile\n+++ b/Makefile\n@@ -36,7 +36,7 @@\n \t$(INSTALL) $(PROG) $(SCRIPTS) $(dest)$(bin)\n \n LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \\\n-\t tag.o date.o\n+\t tag.o date.o index.o\n LIB_FILE=libgit.a\n LIB_H=cache.h object.h blob.h tree.h commit.h tag.h\n \n--- a/cache.h\n+++ b/cache.h\n@@ -127,6 +127,15 @@\n extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);\n extern int ce_match_stat(struct cache_entry *ce, struct stat *st);\n extern int index_fd(unsigned char *sha1, int fd, struct stat *st);\n+extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);\n+\n+struct cache_file {\n+\tstruct cache_file *next;\n+\tchar lockfile[PATH_MAX];\n+};\n+extern int hold_index_file_for_update(struct cache_file *, const char *path);\n+extern int commit_index_file(struct cache_file *);\n+extern void rollback_index_file(struct cache_file *);\n \n #define MTIME_CHANGED\t0x0001\n #define CTIME_CHANGED\t0x0002\n--- a/checkout-cache.c\n+++ b/checkout-cache.c\n@@ -36,7 +36,7 @@\n #include <dirent.h>\n #include \"cache.h\"\n \n-static int force = 0, quiet = 0, not_new = 0;\n+static int force = 0, quiet = 0, not_new = 0, refresh_cache = 0;\n \n static void create_directories(const char *path)\n {\n@@ -154,6 +154,12 @@\n \t\tfree(new);\n \t\treturn error(\"checkout-cache: unknown file mode for %s\", path);\n \t}\n+\n+\tif (refresh_cache) {\n+\t\tstruct stat st;\n+\t\tlstat(ce->name, &st);\n+\t\tfill_stat_cache_info(ce, &st);\n+\t}\n \treturn 0;\n }\n \n@@ -224,6 +230,8 @@\n {\n \tint i, force_filename = 0;\n \tconst char *base_dir = \"\";\n+\tstruct cache_file cache_file;\n+\tint newfd = -1;\n \n \tif (read_cache() < 0) {\n \t\tdie(\"invalid cache\");\n@@ -252,12 +260,37 @@\n \t\t\t\tnot_new = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"-u\")) {\n+\t\t\t\trefresh_cache = 1;\n+\t\t\t\tif (newfd < 0)\n+\t\t\t\t\tnewfd = hold_index_file_for_update\n+\t\t\t\t\t\t(&cache_file,\n+\t\t\t\t\t\t get_index_file());\n+\t\t\t\tif (newfd < 0)\n+\t\t\t\t\tdie(\"cannot open index.lock file.\");\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (!memcmp(arg, \"--prefix=\", 9)) {\n \t\t\t\tbase_dir = arg+9;\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t}\n+\t\tif (base_dir[0]) {\n+\t\t\t/* when --prefix is specified we do not\n+\t\t\t * want to update cache.\n+\t\t\t */\n+\t\t\tif (refresh_cache) {\n+\t\t\t\tclose(newfd); newfd = -1;\n+\t\t\t\trollback_index_file(&cache_file);\n+\t\t\t}\n+\t\t\trefresh_cache = 0;\n+\t\t}\n \t\tcheckout_file(arg, base_dir);\n \t}\n+\n+\tif (0 <= newfd &&\n+\t    (write_cache(newfd, active_cache, active_nr) ||\n+\t     commit_index_file(&cache_file)))\n+\t\tdie(\"Unable to write new cachefile\");\n \treturn 0;\n }\n--- a/index.c\n+++ b/index.c\n@@ -0,0 +1,53 @@\n+/*\n+ * Copyright (c) 2005, Junio C Hamano\n+ */\n+#include <signal.h>\n+#include \"cache.h\"\n+\n+static struct cache_file *cache_file_list;\n+\n+static void remove_lock_file(void)\n+{\n+\twhile (cache_file_list) {\n+\t\tif (cache_file_list->lockfile[0])\n+\t\t\tunlink(cache_file_list->lockfile);\n+\t\tcache_file_list = cache_file_list->next;\n+\t}\n+}\n+\n+static void remove_lock_file_on_signal(int signo)\n+{\n+\tremove_lock_file();\n+}\n+\n+int hold_index_file_for_update(struct cache_file *cf, const char *path)\n+{\n+\tsprintf(cf->lockfile, \"%s.lock\", path);\n+\tcf->next = cache_file_list;\n+\tcache_file_list = cf;\n+\tif (!cf->next) {\n+\t\tsignal(SIGINT, remove_lock_file_on_signal);\n+\t\tatexit(remove_lock_file);\n+\t}\n+\treturn open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);\n+}\n+\n+int commit_index_file(struct cache_file *cf)\n+{\n+\tchar indexfile[PATH_MAX];\n+\tint i;\n+\tstrcpy(indexfile, cf->lockfile);\n+\ti = strlen(indexfile) - 5; /* .lock */\n+\tindexfile[i] = 0;\n+\ti = rename(cf->lockfile, indexfile);\n+\tcf->lockfile[0] = 0;\n+\treturn i;\n+}\n+\n+void rollback_index_file(struct cache_file *cf)\n+{\n+\tif (cf->lockfile[0])\n+\t\tunlink(cf->lockfile);\n+\tcf->lockfile[0] = 0;\n+}\n+\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -9,6 +9,26 @@\n struct cache_entry **active_cache = NULL;\n unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;\n \n+/*\n+ * This only updates the \"non-critical\" parts of the directory\n+ * cache, ie the parts that aren't tracked by GIT, and only used\n+ * to validate the cache.\n+ */\n+void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)\n+{\n+\tce->ce_ctime.sec = htonl(st->st_ctime);\n+\tce->ce_mtime.sec = htonl(st->st_mtime);\n+#ifdef NSEC\n+\tce->ce_ctime.nsec = htonl(st->st_ctim.tv_nsec);\n+\tce->ce_mtime.nsec = htonl(st->st_mtim.tv_nsec);\n+#endif\n+\tce->ce_dev = htonl(st->st_dev);\n+\tce->ce_ino = htonl(st->st_ino);\n+\tce->ce_uid = htonl(st->st_uid);\n+\tce->ce_gid = htonl(st->st_gid);\n+\tce->ce_size = htonl(st->st_size);\n+}\n+\n int ce_match_stat(struct cache_entry *ce, struct stat *st)\n {\n \tunsigned int changed = 0;\n--- a/t/t2002-checkout-cache-u.sh\n+++ b/t/t2002-checkout-cache-u.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano\n+#\n+\n+test_description='git-checkout-cache -u test.\n+\n+With -u flag, git-checkout-cache internally runs the equivalent of\n+git-update-cache --refresh on the checked out entry.'\n+\n+. ./test-lib.sh\n+\n+test_expect_success \\\n+'preparation' '\n+echo frotz >path0 &&\n+git-update-cache --add path0 &&\n+t=$(git-write-tree)'\n+\n+test_expect_failure \\\n+'without -u, git-checkout-cache smudges stat information.' '\n+rm -f path0 &&\n+git-read-tree $t &&\n+git-checkout-cache -f -a &&\n+git-diff-files | diff - /dev/null'\n+\n+test_expect_success \\\n+'with -u, git-checkout-cache picks up stat information from new files.' '\n+rm -f path0 &&\n+git-read-tree $t &&\n+git-checkout-cache -u -f -a &&\n+git-diff-files | diff - /dev/null'\n--- a/update-cache.c\n+++ b/update-cache.c\n@@ -3,7 +3,6 @@\n  *\n  * Copyright (C) Linus Torvalds, 2005\n  */\n-#include <signal.h>\n #include \"cache.h\"\n \n /*\n@@ -31,26 +30,6 @@\n \treturn (unsigned long)ptr > (unsigned long)-1000L;\n }\n \n-/*\n- * This only updates the \"non-critical\" parts of the directory\n- * cache, ie the parts that aren't tracked by GIT, and only used\n- * to validate the cache.\n- */\n-static void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)\n-{\n-\tce->ce_ctime.sec = htonl(st->st_ctime);\n-\tce->ce_mtime.sec = htonl(st->st_mtime);\n-#ifdef NSEC\n-\tce->ce_ctime.nsec = htonl(st->st_ctim.tv_nsec);\n-\tce->ce_mtime.nsec = htonl(st->st_mtim.tv_nsec);\n-#endif\n-\tce->ce_dev = htonl(st->st_dev);\n-\tce->ce_ino = htonl(st->st_ino);\n-\tce->ce_uid = htonl(st->st_uid);\n-\tce->ce_gid = htonl(st->st_gid);\n-\tce->ce_size = htonl(st->st_size);\n-}\n-\n static int add_file_to_cache(char *path)\n {\n \tint size, namelen, option, status;\n@@ -313,36 +292,17 @@\n \treturn add_cache_entry(ce, option);\n }\n \n-static const char *lockfile_name = NULL;\n-\n-static void remove_lock_file(void)\n-{\n-\tif (lockfile_name)\n-\t\tunlink(lockfile_name);\n-}\n-\n-static void remove_lock_file_on_signal(int signo)\n-{\n-\tremove_lock_file();\n-}\n+struct cache_file cache_file;\n \n int main(int argc, char **argv)\n {\n \tint i, newfd, entries, has_errors = 0;\n \tint allow_options = 1;\n-\tstatic char lockfile[MAXPATHLEN+1];\n-\tconst char *indexfile = get_index_file();\n-\n-\tsnprintf(lockfile, sizeof(lockfile), \"%s.lock\", indexfile);\n \n-\tnewfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);\n+\tnewfd = hold_index_file_for_update(&cache_file, get_index_file());\n \tif (newfd < 0)\n \t\tdie(\"unable to create new cachefile\");\n \n-\tsignal(SIGINT, remove_lock_file_on_signal);\n-\tatexit(remove_lock_file);\n-\tlockfile_name = lockfile;\n-\n \tentries = read_cache();\n \tif (entries < 0)\n \t\tdie(\"cache corrupted\");\n@@ -401,9 +361,9 @@\n \t\tif (add_file_to_cache(path))\n \t\t\tdie(\"Unable to add %s to database\", path);\n \t}\n-\tif (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))\n+\tif (write_cache(newfd, active_cache, active_nr) ||\n+\t    commit_index_file(&cache_file))\n \t\tdie(\"Unable to write new cachefile\");\n \n-\tlockfile_name = NULL;\n \treturn has_errors ? 1 : 0;\n }\n\n\n"},{"id":"3419","messageId":"20050516220153.GA8609@pasky.ji.cz","threadId":"637","inReplyTo":"7vll6gqj3z.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-05-16T22:01:53Z","receivedAt":"2005-05-16T22:01:53Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Sun, May 15, 2005 at 11:23:12PM CEST, I got a letter\nwhere Junio C Hamano <junkio@cox.net> told me that...\n> With -u flag, git-checkout-cache picks up the stat information\n> from newly created file and updates the cache.  This removes the\n> need to run git-update-cache --refresh immediately after running\n> git-checkout-cache.\n\nI actually feel ok with this, but I wonder about Linus' opinion about\nit.  :-)\n\n> *** The one I posted earlier failed to add a couple of files\n> *** that the patch should have added.  Please discard it and\n> *** replace it with this one.  Thanks.\n\nThat reminds me, the patches would be a little easier for me to process\nif you followed the /dev/null convention. (You don't need to rediff your\nolder patches just because of that, or even bother about it if it's a\nproblem for you, though.)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"3425","messageId":"Pine.LNX.4.58.0505161530230.18337@ppc970.osdl.org","threadId":"637","inReplyTo":"20050516220153.GA8609@pasky.ji.cz","subject":"Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-16T22:32:24Z","receivedAt":"2005-05-16T22:32:24Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 17 May 2005, Petr Baudis wrote:\n>\n> Dear diary, on Sun, May 15, 2005 at 11:23:12PM CEST, I got a letter\n> where Junio C Hamano <junkio@cox.net> told me that...\n> > With -u flag, git-checkout-cache picks up the stat information\n> > from newly created file and updates the cache.  This removes the\n> > need to run git-update-cache --refresh immediately after running\n> > git-checkout-cache.\n> \n> I actually feel ok with this, but I wonder about Linus' opinion about\n> it.  :-)\n\nI don't think I mind any more.\n\nMy initial reluctance to do this was based on the fact that I wanted to \navoid having something that updates things \"both ways\" (ie updates both \nthe index file _and_ the checked-out stuff), and the largest reason for \nthat was just worrying about stability.\n\nHowever, it's not like we've been having major stability issues, afaik, \nand as long as the index file locking is honoured (which the patch seemed \nto do), I don't have any real issues with it.\n\n\t\tLinus\n"},{"id":"3423","messageId":"7v8y2eol4h.fsf@assigned-by-dhcp.cox.net","threadId":"637","inReplyTo":"20050516220153.GA8609@pasky.ji.cz","subject":"Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-16T22:34:54Z","receivedAt":"2005-05-16T22:34:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"PB\" == Petr Baudis <pasky@ucw.cz> writes:\n\nPB> That reminds me, the patches would be a little easier for me to process\nPB> if you followed the /dev/null convention.\n\nOops, thanks for spotting a bug in \"jit-log -p\" ;-).\n\n"},{"id":"3428","messageId":"7vk6lyn4v2.fsf@assigned-by-dhcp.cox.net","threadId":"637","inReplyTo":"Pine.LNX.4.58.0505161530230.18337@ppc970.osdl.org","subject":"Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-16T23:11:29Z","receivedAt":"2005-05-16T23:11:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> ... and as long as the index file locking is honoured\nLT> (which the patch seemed to do) ...\n\nYes, it does.  But that was one thing I was not very sure about\nthis patch.  I am reasonably sure this \"index.c\" conflicts with\nthe libification effort, and when the libification finishes, I\nfeel that what \"index.c\" does should be part of it.\n\n"}]}