1 /* Copyright (c) 2006-2014 Jonas Fonseca <jonas.fonseca@gmail.com>
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
16 #include "tig/refdb.h"
18 #include "tig/options.h"
19 #include "tig/watch.h"
21 static struct watch
*watches
;
24 watch_register(struct watch
*watch
, enum watch_trigger triggers
)
26 watch_unregister(watch
);
28 watch
->next
= watches
;
31 watch
->triggers
= triggers
;
36 watch_unregister(struct watch
*watch
)
38 struct watch
*pos
, *prev
= NULL
;
40 for (pos
= watches
; pos
; prev
= pos
, pos
= pos
->next
) {
44 watches
= watch
->next
;
46 prev
->next
= watch
->next
;
50 memset(watch
, 0, sizeof(*watch
));
53 struct watch_handler
{
54 enum watch_trigger (*check
)(struct watch_handler
*handler
, enum watch_event event
, enum watch_trigger check
);
55 enum watch_trigger triggers
;
57 enum watch_trigger last_check
;
61 check_file_mtime(time_t *last_modified
, const char *path_fmt
, ...)
63 char path
[SIZEOF_STR
];
67 FORMAT_BUFFER(path
, sizeof(path
), path_fmt
, retval
, FALSE
);
70 lstat(path
, &stat
) < 0 ||
71 stat
.st_mtime
<= *last_modified
)
74 *last_modified
= stat
.st_mtime
;
78 static enum watch_trigger
79 watch_head_handler(struct watch_handler
*handler
, enum watch_event event
, enum watch_trigger check
)
84 check_file_mtime(&handler
->last_modified
, "%s/HEAD", repo
.git_dir
))
87 // FIXME: check branch
88 if ((head
= get_ref_head()) &&
89 check_file_mtime(&handler
->last_modified
, "%s/refs/head/%s", repo
.git_dir
, head
->name
))
95 static enum watch_trigger
96 watch_stash_handler(struct watch_handler
*handler
, enum watch_event event
, enum watch_trigger check
)
99 check_file_mtime(&handler
->last_modified
, "%s/refs/stash", repo
.git_dir
))
105 static enum watch_trigger
106 watch_index_handler(struct watch_handler
*handler
, enum watch_event event
, enum watch_trigger check
)
108 enum watch_trigger changed
= WATCH_NONE
;
109 enum watch_trigger diff
= WATCH_NONE
;
114 if (event
== WATCH_EVENT_AFTER_EXTERNAL
)
115 return check_file_mtime(&handler
->last_modified
, "%s/index", repo
.git_dir
)
116 ? check
: WATCH_NONE
;
118 if (!check_file_mtime(&handler
->last_modified
, "%s/index", repo
.git_dir
) ||
122 if (check
& WATCH_INDEX_STAGED
) {
123 if (index_diff_staged())
124 changed
|= WATCH_INDEX_STAGED
;
125 else if (handler
->last_check
& WATCH_INDEX_STAGED
)
126 diff
|= WATCH_INDEX_STAGED
;
129 if (check
& WATCH_INDEX_UNSTAGED
) {
130 if (index_diff_unstaged())
131 changed
|= WATCH_INDEX_UNSTAGED
;
132 else if (handler
->last_check
& WATCH_INDEX_UNSTAGED
)
133 diff
|= WATCH_INDEX_UNSTAGED
;
136 handler
->last_check
= changed
;
140 handler
->last_modified
= time(NULL
);
145 static struct watch_handler watch_handlers
[] = {
146 { watch_index_handler
, WATCH_INDEX_STAGED
| WATCH_INDEX_UNSTAGED
},
147 { watch_head_handler
, WATCH_HEAD
},
148 { watch_stash_handler
, WATCH_STASH
},
152 watch_update(enum watch_event event
)
154 enum watch_trigger trigger
= WATCH_NONE
;
155 enum watch_trigger changed
= WATCH_NONE
;
159 if (opt_refresh_mode
== REFRESH_MODE_MANUEL
)
162 /* Collect triggers to check. Skkipping watches that are already
163 * marked dirty to avoid unnecessary checks. */
164 for (watch
= watches
; watch
; watch
= watch
->next
)
166 trigger
|= watch
->triggers
;
168 for (i
= 0; trigger
&& i
< ARRAY_SIZE(watch_handlers
); i
++) {
169 struct watch_handler
*handler
= &watch_handlers
[i
];
171 if (trigger
& handler
->triggers
)
172 changed
|= handler
->check(handler
, event
, trigger
);
175 for (watch
= watches
; watch
; watch
= watch
->next
)
176 if (changed
& watch
->triggers
)
183 watch_periodic(int interval
)
185 static time_t last_update
;
188 if (watches
&& interval
> 0) {
189 time_t now
= time(NULL
);
193 if (last_update
+ interval
<= now
) {
194 watch_update(WATCH_EVENT_PERIODIC
);
198 delay
= (now
- last_update
+ interval
) * 1000;
205 watch_dirty(struct watch
*watch
)
210 dirty
= watch
->dirty
;
211 watch
->dirty
= FALSE
;
217 /* vim: set ts=8 sw=8 noexpandtab: */