git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.
@ 2005-05-15 21:23 Junio C Hamano
  2005-05-16 22:01 ` Petr Baudis
  0 siblings, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2005-05-15 21:23 UTC (permalink / raw)
  To: pasky; +Cc: git, torvalds

With -u flag, git-checkout-cache picks up the stat information
from newly created file and updates the cache.  This removes the
need to run git-update-cache --refresh immediately after running
git-checkout-cache.
---

*** The one I posted earlier failed to add a couple of files
*** that the patch should have added.  Please discard it and
*** replace it with this one.  Thanks.

Documentation/git-checkout-cache.txt |    6 +++
Makefile                             |    2 -
cache.h                              |    9 +++++
checkout-cache.c                     |   35 ++++++++++++++++++++++-
index.c                              |   53 +++++++++++++++++++++++++++++++++++
read-cache.c                         |   20 +++++++++++++
t/t2002-checkout-cache-u.sh          |   31 ++++++++++++++++++++
update-cache.c                       |   48 ++-----------------------------
8 files changed, 157 insertions(+), 47 deletions(-)
index.c (. --> 100644)
t/t2002-checkout-cache-u.sh (. --> 100644)

--- a/Documentation/git-checkout-cache.txt
+++ b/Documentation/git-checkout-cache.txt
@@ -9,7 +9,7 @@
 
 SYNOPSIS
 --------
-'git-checkout-cache' [-q] [-a] [-f] [-n] [--prefix=<string>]
+'git-checkout-cache' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
 	           [--] <file>...
 
 DESCRIPTION
@@ -19,6 +19,10 @@
 
 OPTIONS
 -------
+-u::
+	update stat information for the checked out entries in
+	the cache file.
+
 -q::
 	be quiet if files exist or are not in the cache
 
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,7 @@
 	$(INSTALL) $(PROG) $(SCRIPTS) $(dest)$(bin)
 
 LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \
-	 tag.o date.o
+	 tag.o date.o index.o
 LIB_FILE=libgit.a
 LIB_H=cache.h object.h blob.h tree.h commit.h tag.h
 
--- a/cache.h
+++ b/cache.h
@@ -127,6 +127,15 @@
 extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
 extern int ce_match_stat(struct cache_entry *ce, struct stat *st);
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st);
+extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
+
+struct cache_file {
+	struct cache_file *next;
+	char lockfile[PATH_MAX];
+};
+extern int hold_index_file_for_update(struct cache_file *, const char *path);
+extern int commit_index_file(struct cache_file *);
+extern void rollback_index_file(struct cache_file *);
 
 #define MTIME_CHANGED	0x0001
 #define CTIME_CHANGED	0x0002
--- a/checkout-cache.c
+++ b/checkout-cache.c
@@ -36,7 +36,7 @@
 #include <dirent.h>
 #include "cache.h"
 
-static int force = 0, quiet = 0, not_new = 0;
+static int force = 0, quiet = 0, not_new = 0, refresh_cache = 0;
 
 static void create_directories(const char *path)
 {
@@ -154,6 +154,12 @@
 		free(new);
 		return error("checkout-cache: unknown file mode for %s", path);
 	}
+
+	if (refresh_cache) {
+		struct stat st;
+		lstat(ce->name, &st);
+		fill_stat_cache_info(ce, &st);
+	}
 	return 0;
 }
 
@@ -224,6 +230,8 @@
 {
 	int i, force_filename = 0;
 	const char *base_dir = "";
+	struct cache_file cache_file;
+	int newfd = -1;
 
 	if (read_cache() < 0) {
 		die("invalid cache");
@@ -252,12 +260,37 @@
 				not_new = 1;
 				continue;
 			}
+			if (!strcmp(arg, "-u")) {
+				refresh_cache = 1;
+				if (newfd < 0)
+					newfd = hold_index_file_for_update
+						(&cache_file,
+						 get_index_file());
+				if (newfd < 0)
+					die("cannot open index.lock file.");
+				continue;
+			}
 			if (!memcmp(arg, "--prefix=", 9)) {
 				base_dir = arg+9;
 				continue;
 			}
 		}
+		if (base_dir[0]) {
+			/* when --prefix is specified we do not
+			 * want to update cache.
+			 */
+			if (refresh_cache) {
+				close(newfd); newfd = -1;
+				rollback_index_file(&cache_file);
+			}
+			refresh_cache = 0;
+		}
 		checkout_file(arg, base_dir);
 	}
+
+	if (0 <= newfd &&
+	    (write_cache(newfd, active_cache, active_nr) ||
+	     commit_index_file(&cache_file)))
+		die("Unable to write new cachefile");
 	return 0;
 }
--- a/index.c
+++ b/index.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005, Junio C Hamano
+ */
+#include <signal.h>
+#include "cache.h"
+
+static struct cache_file *cache_file_list;
+
+static void remove_lock_file(void)
+{
+	while (cache_file_list) {
+		if (cache_file_list->lockfile[0])
+			unlink(cache_file_list->lockfile);
+		cache_file_list = cache_file_list->next;
+	}
+}
+
+static void remove_lock_file_on_signal(int signo)
+{
+	remove_lock_file();
+}
+
+int hold_index_file_for_update(struct cache_file *cf, const char *path)
+{
+	sprintf(cf->lockfile, "%s.lock", path);
+	cf->next = cache_file_list;
+	cache_file_list = cf;
+	if (!cf->next) {
+		signal(SIGINT, remove_lock_file_on_signal);
+		atexit(remove_lock_file);
+	}
+	return open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);
+}
+
+int commit_index_file(struct cache_file *cf)
+{
+	char indexfile[PATH_MAX];
+	int i;
+	strcpy(indexfile, cf->lockfile);
+	i = strlen(indexfile) - 5; /* .lock */
+	indexfile[i] = 0;
+	i = rename(cf->lockfile, indexfile);
+	cf->lockfile[0] = 0;
+	return i;
+}
+
+void rollback_index_file(struct cache_file *cf)
+{
+	if (cf->lockfile[0])
+		unlink(cf->lockfile);
+	cf->lockfile[0] = 0;
+}
+
--- a/read-cache.c
+++ b/read-cache.c
@@ -9,6 +9,26 @@
 struct cache_entry **active_cache = NULL;
 unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
 
+/*
+ * This only updates the "non-critical" parts of the directory
+ * cache, ie the parts that aren't tracked by GIT, and only used
+ * to validate the cache.
+ */
+void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
+{
+	ce->ce_ctime.sec = htonl(st->st_ctime);
+	ce->ce_mtime.sec = htonl(st->st_mtime);
+#ifdef NSEC
+	ce->ce_ctime.nsec = htonl(st->st_ctim.tv_nsec);
+	ce->ce_mtime.nsec = htonl(st->st_mtim.tv_nsec);
+#endif
+	ce->ce_dev = htonl(st->st_dev);
+	ce->ce_ino = htonl(st->st_ino);
+	ce->ce_uid = htonl(st->st_uid);
+	ce->ce_gid = htonl(st->st_gid);
+	ce->ce_size = htonl(st->st_size);
+}
+
 int ce_match_stat(struct cache_entry *ce, struct stat *st)
 {
 	unsigned int changed = 0;
--- a/t/t2002-checkout-cache-u.sh
+++ b/t/t2002-checkout-cache-u.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+test_description='git-checkout-cache -u test.
+
+With -u flag, git-checkout-cache internally runs the equivalent of
+git-update-cache --refresh on the checked out entry.'
+
+. ./test-lib.sh
+
+test_expect_success \
+'preparation' '
+echo frotz >path0 &&
+git-update-cache --add path0 &&
+t=$(git-write-tree)'
+
+test_expect_failure \
+'without -u, git-checkout-cache smudges stat information.' '
+rm -f path0 &&
+git-read-tree $t &&
+git-checkout-cache -f -a &&
+git-diff-files | diff - /dev/null'
+
+test_expect_success \
+'with -u, git-checkout-cache picks up stat information from new files.' '
+rm -f path0 &&
+git-read-tree $t &&
+git-checkout-cache -u -f -a &&
+git-diff-files | diff - /dev/null'
--- a/update-cache.c
+++ b/update-cache.c
@@ -3,7 +3,6 @@
  *
  * Copyright (C) Linus Torvalds, 2005
  */
-#include <signal.h>
 #include "cache.h"
 
 /*
@@ -31,26 +30,6 @@
 	return (unsigned long)ptr > (unsigned long)-1000L;
 }
 
-/*
- * This only updates the "non-critical" parts of the directory
- * cache, ie the parts that aren't tracked by GIT, and only used
- * to validate the cache.
- */
-static void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
-{
-	ce->ce_ctime.sec = htonl(st->st_ctime);
-	ce->ce_mtime.sec = htonl(st->st_mtime);
-#ifdef NSEC
-	ce->ce_ctime.nsec = htonl(st->st_ctim.tv_nsec);
-	ce->ce_mtime.nsec = htonl(st->st_mtim.tv_nsec);
-#endif
-	ce->ce_dev = htonl(st->st_dev);
-	ce->ce_ino = htonl(st->st_ino);
-	ce->ce_uid = htonl(st->st_uid);
-	ce->ce_gid = htonl(st->st_gid);
-	ce->ce_size = htonl(st->st_size);
-}
-
 static int add_file_to_cache(char *path)
 {
 	int size, namelen, option, status;
@@ -313,36 +292,17 @@
 	return add_cache_entry(ce, option);
 }
 
-static const char *lockfile_name = NULL;
-
-static void remove_lock_file(void)
-{
-	if (lockfile_name)
-		unlink(lockfile_name);
-}
-
-static void remove_lock_file_on_signal(int signo)
-{
-	remove_lock_file();
-}
+struct cache_file cache_file;
 
 int main(int argc, char **argv)
 {
 	int i, newfd, entries, has_errors = 0;
 	int allow_options = 1;
-	static char lockfile[MAXPATHLEN+1];
-	const char *indexfile = get_index_file();
-
-	snprintf(lockfile, sizeof(lockfile), "%s.lock", indexfile);
 
-	newfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);
+	newfd = hold_index_file_for_update(&cache_file, get_index_file());
 	if (newfd < 0)
 		die("unable to create new cachefile");
 
-	signal(SIGINT, remove_lock_file_on_signal);
-	atexit(remove_lock_file);
-	lockfile_name = lockfile;
-
 	entries = read_cache();
 	if (entries < 0)
 		die("cache corrupted");
@@ -401,9 +361,9 @@
 		if (add_file_to_cache(path))
 			die("Unable to add %s to database", path);
 	}
-	if (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile))
+	if (write_cache(newfd, active_cache, active_nr) ||
+	    commit_index_file(&cache_file))
 		die("Unable to write new cachefile");
 
-	lockfile_name = NULL;
 	return has_errors ? 1 : 0;
 }



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.
  2005-05-15 21:23 [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache Junio C Hamano
@ 2005-05-16 22:01 ` Petr Baudis
  2005-05-16 22:32   ` Linus Torvalds
  2005-05-16 22:34   ` Junio C Hamano
  0 siblings, 2 replies; 5+ messages in thread
From: Petr Baudis @ 2005-05-16 22:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, torvalds

Dear diary, on Sun, May 15, 2005 at 11:23:12PM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> told me that...
> With -u flag, git-checkout-cache picks up the stat information
> from newly created file and updates the cache.  This removes the
> need to run git-update-cache --refresh immediately after running
> git-checkout-cache.

I actually feel ok with this, but I wonder about Linus' opinion about
it.  :-)

> *** The one I posted earlier failed to add a couple of files
> *** that the patch should have added.  Please discard it and
> *** replace it with this one.  Thanks.

That reminds me, the patches would be a little easier for me to process
if you followed the /dev/null convention. (You don't need to rediff your
older patches just because of that, or even bother about it if it's a
problem for you, though.)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.
  2005-05-16 22:01 ` Petr Baudis
@ 2005-05-16 22:32   ` Linus Torvalds
  2005-05-16 23:11     ` Junio C Hamano
  2005-05-16 22:34   ` Junio C Hamano
  1 sibling, 1 reply; 5+ messages in thread
From: Linus Torvalds @ 2005-05-16 22:32 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Junio C Hamano, git



On Tue, 17 May 2005, Petr Baudis wrote:
>
> Dear diary, on Sun, May 15, 2005 at 11:23:12PM CEST, I got a letter
> where Junio C Hamano <junkio@cox.net> told me that...
> > With -u flag, git-checkout-cache picks up the stat information
> > from newly created file and updates the cache.  This removes the
> > need to run git-update-cache --refresh immediately after running
> > git-checkout-cache.
> 
> I actually feel ok with this, but I wonder about Linus' opinion about
> it.  :-)

I don't think I mind any more.

My initial reluctance to do this was based on the fact that I wanted to 
avoid having something that updates things "both ways" (ie updates both 
the index file _and_ the checked-out stuff), and the largest reason for 
that was just worrying about stability.

However, it's not like we've been having major stability issues, afaik, 
and as long as the index file locking is honoured (which the patch seemed 
to do), I don't have any real issues with it.

		Linus

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.
  2005-05-16 22:01 ` Petr Baudis
  2005-05-16 22:32   ` Linus Torvalds
@ 2005-05-16 22:34   ` Junio C Hamano
  1 sibling, 0 replies; 5+ messages in thread
From: Junio C Hamano @ 2005-05-16 22:34 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git, torvalds

>>>>> "PB" == Petr Baudis <pasky@ucw.cz> writes:

PB> That reminds me, the patches would be a little easier for me to process
PB> if you followed the /dev/null convention.

Oops, thanks for spotting a bug in "jit-log -p" ;-).


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache.
  2005-05-16 22:32   ` Linus Torvalds
@ 2005-05-16 23:11     ` Junio C Hamano
  0 siblings, 0 replies; 5+ messages in thread
From: Junio C Hamano @ 2005-05-16 23:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> ... and as long as the index file locking is honoured
LT> (which the patch seemed to do) ...

Yes, it does.  But that was one thing I was not very sure about
this patch.  I am reasonably sure this "index.c" conflicts with
the libification effort, and when the libification finishes, I
feel that what "index.c" does should be part of it.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-05-16 23:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-15 21:23 [PATCH 3/4] Implement git-checkout-cache -u to update stat information in the cache Junio C Hamano
2005-05-16 22:01 ` Petr Baudis
2005-05-16 22:32   ` Linus Torvalds
2005-05-16 23:11     ` Junio C Hamano
2005-05-16 22:34   ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).