4
4
5
5
static struct trace_key trace_serialize = TRACE_KEY_INIT (SERIALIZE );
6
6
7
+ /*
8
+ * Compute header record for exclude file using format:
9
+ * <key> SP <status_char> SP <variant> LF
10
+ */
11
+ void wt_serialize_compute_exclude_header (struct strbuf * sb ,
12
+ const char * key ,
13
+ const char * path )
14
+ {
15
+ struct stat st ;
16
+ struct stat_data sd ;
17
+
18
+ memset (& sd , 0 , sizeof (sd ));
19
+
20
+ strbuf_setlen (sb , 0 );
21
+
22
+ if (!path || !* path ) {
23
+ strbuf_addf (sb , "%s U (unset)" , key );
24
+ } else if (lstat (path , & st ) == -1 ) {
25
+ if (is_missing_file_error (errno ))
26
+ strbuf_addf (sb , "%s E (not-found) %s" , key , path );
27
+ else
28
+ strbuf_addf (sb , "%s E (other) %s" , key , path );
29
+ } else {
30
+ fill_stat_data (& sd , & st );
31
+ strbuf_addf (sb , "%s F %d %d %s" ,
32
+ key , sd .sd_mtime .sec , sd .sd_mtime .nsec , path );
33
+ }
34
+ }
35
+
36
+ static void append_exclude_info (int fd , const char * path , const char * key )
37
+ {
38
+ struct strbuf sb = STRBUF_INIT ;
39
+
40
+ wt_serialize_compute_exclude_header (& sb , key , path );
41
+
42
+ packet_write_fmt (fd , "%s\n" , sb .buf );
43
+
44
+ strbuf_release (& sb );
45
+ }
46
+
47
+ static void append_core_excludes_file_info (int fd )
48
+ {
49
+ /*
50
+ * Write pathname and mtime of the core/global excludes file to
51
+ * the status cache header. Since a change in the global excludes
52
+ * will/may change the results reported by status, the deserialize
53
+ * code should be able to reject the status cache if the excludes
54
+ * file changes since when the cache was written.
55
+ *
56
+ * The "core.excludefile" setting defaults to $XDG_HOME/git/ignore
57
+ * and uses a global variable which should have been set during
58
+ * wt_status_collect_untracked().
59
+ *
60
+ * See dir.c:setup_standard_excludes()
61
+ */
62
+ append_exclude_info (fd , excludes_file , "core_excludes" );
63
+ }
64
+
65
+ static void append_repo_excludes_file_info (int fd )
66
+ {
67
+ /*
68
+ * Likewise, there is a per-repo excludes file in .git/info/excludes
69
+ * that can change the results reported by status. And the deserialize
70
+ * code needs to be able to reject the status cache if this file
71
+ * changes.
72
+ *
73
+ * See dir.c:setup_standard_excludes() and git_path_info_excludes().
74
+ * We replicate the pathname construction here because of the static
75
+ * variables/functions used in dir.c.
76
+ */
77
+ char * path = git_pathdup ("info/exclude" );
78
+
79
+ append_exclude_info (fd , path , "repo_excludes" );
80
+
81
+ free (path );
82
+ }
83
+
84
+ /*
85
+ * WARNING: The status cache attempts to preserve the essential in-memory
86
+ * status data after a status scan into a "serialization" (aka "status cache")
87
+ * file. It allows later "git status --deserialize=<foo>" instances to
88
+ * just print the cached status results without scanning the workdir (and
89
+ * without reading the index).
90
+ *
91
+ * The status cache file is valid as long as:
92
+ * [1] the set of functional command line options are the same (think "-u").
93
+ * [2] repo-local and user-global configuration settings are compatible.
94
+ * [3] nothing in the workdir has changed.
95
+ *
96
+ * We rely on:
97
+ * [1.a] We remember the relevant (functional, non-display) command line
98
+ * arguments in the status cache header.
99
+ * [2.a] We use the mtime of the .git/index to detect staging changes.
100
+ * [2.b] We use the mtimes of the excludes files to detect changes that
101
+ * might affect untracked file reporting.
102
+ *
103
+ * But we need external help to verify [3].
104
+ * [] This includes changes to tracked files.
105
+ * [] This includes changes to tracked .gitignore files that might change
106
+ * untracked file reporting.
107
+ * [] This includes the creation of new, untracked per-directory .gitignore
108
+ * files that might change untracked file reporting.
109
+ *
110
+ * [3.a] On GVFS repos, we rely on the GVFS service (mount) daemon to
111
+ * watch the filesystem and invalidate (delete) the status cache
112
+ * when anything changes inside the workdir.
113
+ *
114
+ * [3.b] TODO This problem is not solved for non-GVFS repos.
115
+ * [] It is possible that the untracked-cache index extension
116
+ * could help with this but that requires status to read the
117
+ * index to load the extension.
118
+ * [] It is possible that the new fsmonitor facility could also
119
+ * provide this information, but that to requires reading the
120
+ * index.
121
+ */
122
+
7
123
/*
8
124
* Write V1 header fields.
9
125
*/
@@ -16,6 +132,8 @@ static void wt_serialize_v1_header(struct wt_status *s, int fd)
16
132
packet_write_fmt (fd , "index_mtime %d %d\n" ,
17
133
the_index .timestamp .sec ,
18
134
the_index .timestamp .nsec );
135
+ append_core_excludes_file_info (fd );
136
+ append_repo_excludes_file_info (fd );
19
137
20
138
/*
21
139
* Write data from wt_status to qualify this status report.
0 commit comments