{"thread":{"id":"625","subject":"[PATCH] Implement git-checkout-cache -u to update stat information in the cache.","startedAt":"2005-05-15T08:36:59Z","lastAt":"2005-05-15T21:23:37Z","messageCount":2,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"3348","messageId":"7vis1kvqac.fsf@assigned-by-dhcp.cox.net","threadId":"625","inReplyTo":null,"subject":"[PATCH] Implement git-checkout-cache -u to update stat information in the cache.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-15T08:36:59Z","receivedAt":"2005-05-15T08:36:59Z","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 files and updates the cache.  This removes the\nneed to run git-update-cache --refresh immediately after running\ngit-checkout-cache.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\nDocumentation/git-checkout-cache.txt |    6 +++\nMakefile                             |    2 -\ncache.h                              |    9 +++++\ncheckout-cache.c                     |   35 ++++++++++++++++++++-\nindex.c                              |   58 +++++++++++++++++++++++++++++++++++\nread-cache.c                         |   20 ++++++++++++\nt/t2002-checkout-cache-u.sh          |   35 +++++++++++++++++++++\nupdate-cache.c                       |   48 ++--------------------------\n8 files changed, 166 insertions(+), 47 deletions(-)\nindex.c (. --> 100644)\nt/t0110-environment-names-old.sh (100644 --> 100755)\nt/t1000-read-tree-m-3way.sh (100644 --> 100755)\nt/t2002-checkout-cache-u.sh (. --> 100755)\nt/t4000-diff-format.sh (100644 --> 100755)\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@@ -131,6 +131,15 @@\n extern int same_name(struct cache_entry *a, struct cache_entry *b);\n extern int cache_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,58 @@\n+/*\n+ * GIT - The information manager from hell\n+ * Cache-file locking management.\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 = NULL;\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 commit_index_file(struct cache_file *cf)\n+{\n+\tint i;\n+\tchar indexfile[PATH_MAX];\n+\n+\tstrcpy(indexfile, cf->lockfile);\n+\ti = strlen(indexfile);\n+\tindexfile[i - 5] = 0; /* .lock */\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+\tunlink(cf->lockfile);\n+\tcf->lockfile[0] = 0;\n+}\n+\n+int hold_index_file_for_update(struct cache_file *cf, const char *path)\n+{\n+\tint newfd;\n+\n+\tsprintf(cf->lockfile, \"%s.lock\", path);\n+\tcf->next = cache_file_list;\n+\tcache_file_list = cf;\n+\tnewfd = open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);\n+\tif (!cf->next) {\n+\t\tsignal(SIGINT, remove_lock_file_on_signal);\n+\t\tatexit(remove_lock_file);\n+\t}\n+\treturn newfd;\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 cache_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,35 @@\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+\n+\n+\n+\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":"3395","messageId":"7vk6m0qj3a.fsf@assigned-by-dhcp.cox.net","threadId":"625","inReplyTo":"7vis1kvqac.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH 0/4] Rediffed against the tip of git-pb tree","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-05-15T21:23:37Z","receivedAt":"2005-05-15T21:23:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr, I am sending rediff against the tip of git-pb tree.  One\nof the patches is not just rediff---the earlier version I failed\nto add a couple of newly created files.\n\n [1/4] Add --author and --committer match to git-rev-list and git-rev-tree.\n [2/4] Tweak diff output further to make it a bit less distracting.\n [3/4] Implement git-checkout-cache -u to update stat information in the cache.\n [4/4] Trivial test harness fixes.\n\n"}]}