@@ -57,6 +57,23 @@ static int index_fd(const char *path, int namelen, struct cache_entry *ce, int f
57
57
return write_sha1_buffer (ce -> sha1 , out , stream .total_out );
58
58
}
59
59
60
+ /*
61
+ * This only updates the "non-critical" parts of the directory
62
+ * cache, ie the parts that aren't tracked by GIT, and only used
63
+ * to validate the cache.
64
+ */
65
+ static void fill_stat_cache_info (struct cache_entry * ce , struct stat * st )
66
+ {
67
+ ce -> ctime .sec = st -> st_ctime ;
68
+ ce -> ctime .nsec = st -> st_ctim .tv_nsec ;
69
+ ce -> mtime .sec = st -> st_mtime ;
70
+ ce -> mtime .nsec = st -> st_mtim .tv_nsec ;
71
+ ce -> st_dev = st -> st_dev ;
72
+ ce -> st_ino = st -> st_ino ;
73
+ ce -> st_uid = st -> st_uid ;
74
+ ce -> st_gid = st -> st_gid ;
75
+ }
76
+
60
77
static int add_file_to_cache (char * path )
61
78
{
62
79
int size , namelen ;
@@ -81,15 +98,8 @@ static int add_file_to_cache(char *path)
81
98
ce = malloc (size );
82
99
memset (ce , 0 , size );
83
100
memcpy (ce -> name , path , namelen );
84
- ce -> ctime .sec = st .st_ctime ;
85
- ce -> ctime .nsec = st .st_ctim .tv_nsec ;
86
- ce -> mtime .sec = st .st_mtime ;
87
- ce -> mtime .nsec = st .st_mtim .tv_nsec ;
88
- ce -> st_dev = st .st_dev ;
89
- ce -> st_ino = st .st_ino ;
101
+ fill_stat_cache_info (ce , & st );
90
102
ce -> st_mode = st .st_mode ;
91
- ce -> st_uid = st .st_uid ;
92
- ce -> st_gid = st .st_gid ;
93
103
ce -> st_size = st .st_size ;
94
104
ce -> namelen = namelen ;
95
105
@@ -99,26 +109,96 @@ static int add_file_to_cache(char *path)
99
109
return add_cache_entry (ce , allow_add );
100
110
}
101
111
102
- static void refresh_entry (struct cache_entry * ce )
112
+ static int match_data (int fd , void * buffer , unsigned long size )
113
+ {
114
+ while (size ) {
115
+ char compare [1024 ];
116
+ int ret = read (fd , compare , sizeof (compare ));
117
+
118
+ if (ret <= 0 || ret > size || memcmp (buffer , compare , ret ))
119
+ return -1 ;
120
+ size -= ret ;
121
+ buffer += ret ;
122
+ }
123
+ return 0 ;
124
+ }
125
+
126
+ static int compare_data (struct cache_entry * ce )
127
+ {
128
+ int match = -1 ;
129
+ int fd = open (ce -> name , O_RDONLY );
130
+
131
+ if (fd >= 0 ) {
132
+ void * buffer ;
133
+ unsigned long size ;
134
+ char type [10 ];
135
+
136
+ buffer = read_sha1_file (ce -> sha1 , type , & size );
137
+ if (buffer ) {
138
+ if (size == ce -> st_size && !strcmp (type , "blob" ))
139
+ match = match_data (fd , buffer , size );
140
+ free (buffer );
141
+ }
142
+ close (fd );
143
+ }
144
+ return match ;
145
+ }
146
+
147
+ /*
148
+ * "refresh" does not calculate a new sha1 file or bring the
149
+ * cache up-to-date for mode/content changes. But what it
150
+ * _does_ do is to "re-match" the stat information of a file
151
+ * with the cache, so that you can refresh the cache for a
152
+ * file that hasn't been changed but where the stat entry is
153
+ * out of date.
154
+ *
155
+ * For example, you'd want to do this after doing a "read-tree",
156
+ * to link up the stat cache details with the proper files.
157
+ */
158
+ static struct cache_entry * refresh_entry (struct cache_entry * ce )
103
159
{
160
+ struct stat st ;
161
+ struct cache_entry * updated ;
162
+ int changed , size ;
163
+
164
+ if (stat (ce -> name , & st ) < 0 )
165
+ return NULL ;
166
+
167
+ changed = cache_match_stat (ce , & st );
168
+ if (!changed )
169
+ return ce ;
170
+
104
171
/*
105
- * This is really not the right way to do it, but
106
- * add_file_to_cache() does do the right thing.
107
- *
108
- * We should really just update the cache
109
- * entry in-place, I think. With this approach we
110
- * end up allocating a new one, searching for where
111
- * to insert it etc etc crud.
172
+ * If the length has changed, there's no point in trying
173
+ * to refresh the entry - it's not going to match
112
174
*/
113
- add_file_to_cache (ce -> name );
175
+ if (changed & (DATA_CHANGED | MODE_CHANGED ))
176
+ return NULL ;
177
+
178
+ if (compare_data (ce ))
179
+ return NULL ;
180
+
181
+ size = ce_size (ce );
182
+ updated = malloc (size );
183
+ memcpy (updated , ce , size );
184
+ fill_stat_cache_info (updated , & st );
185
+ return updated ;
114
186
}
115
187
116
188
static void refresh_cache (void )
117
189
{
118
190
int i ;
119
191
120
- for (i = 0 ; i < active_nr ; i ++ )
121
- refresh_entry (active_cache [i ]);
192
+ for (i = 0 ; i < active_nr ; i ++ ) {
193
+ struct cache_entry * ce = active_cache [i ];
194
+ struct cache_entry * new = refresh_entry (ce );
195
+
196
+ if (!new ) {
197
+ printf ("%s: needs update\n" , ce -> name );
198
+ continue ;
199
+ }
200
+ active_cache [i ] = new ;
201
+ }
122
202
}
123
203
124
204
/*
0 commit comments