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