From 22d843e6719c025bf6d711bfdd3644e442ee8966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Mon, 6 Jul 2015 21:49:19 +0200 Subject: Warn when saving a file which has been changed outside the editor --- editor.c | 1 + editor.h | 1 + text.c | 9 ++++++++- text.h | 4 ++++ vis.c | 11 ++++++++++- 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/editor.c b/editor.c index 87072a3..ad9bd4e 100644 --- a/editor.c +++ b/editor.c @@ -293,6 +293,7 @@ static File *file_new_text(Editor *ed, Text *text) { if (!file) return NULL; file->text = text; + file->stat = text_stat(text); file->refcount++; if (ed->files) ed->files->prev = file; diff --git a/editor.h b/editor.h index 5192d31..36f2829 100644 --- a/editor.h +++ b/editor.h @@ -195,6 +195,7 @@ struct File { Text *text; const char *name; bool stdin; + struct stat stat; int refcount; Mark marks[MARK_LAST]; File *next, *prev; diff --git a/text.c b/text.c index 764d7cb..c5f3768 100644 --- a/text.c +++ b/text.c @@ -802,7 +802,7 @@ static bool preserve_selinux_context(int src, int dest) { * - SELinux security context can not be preserved (if enabled) */ static bool text_range_save_atomic(Text *txt, Filerange *range, const char *filename) { - struct stat meta; + struct stat meta = { 0 }; int fd = -1, oldfd = -1, saved_errno; char *tmpname = NULL; size_t size = text_range_size(range); @@ -877,6 +877,8 @@ static bool text_range_save_atomic(Text *txt, Filerange *range, const char *file if (rename(tmpname, filename) == -1) goto err; + if (meta.st_mtime) + txt->info = meta; free(tmpname); return true; err: @@ -955,6 +957,7 @@ bool text_range_save(Text *txt, Filerange *range, const char *filename) { goto err; if (close(fd) == -1) return false; + txt->info = meta; ok: txt->saved_action = txt->history; text_snapshot(txt); @@ -1043,6 +1046,10 @@ out: return NULL; } +struct stat text_stat(Text *txt) { + return txt->info; +} + /* A delete operation can either start/stop midway through a piece or at * a boundry. In the former case a new piece is created to represent the * remaining text before/after the modification point. diff --git a/text.h b/text.h index 725fa26..16b4a45 100644 --- a/text.h +++ b/text.h @@ -3,7 +3,9 @@ #include #include +#include #include +#include #define EPOS ((size_t)-1) /* invalid position */ @@ -35,6 +37,8 @@ typedef struct { text_iterator_next(&it)) Text *text_load(const char *file); +/* file information at time of load or last save */ +struct stat text_stat(Text*); bool text_insert(Text*, size_t pos, const char *data, size_t len); bool text_delete(Text*, size_t pos, size_t len); void text_snapshot(Text*); diff --git a/vis.c b/vis.c index 076f0c7..4520fe3 100644 --- a/vis.c +++ b/vis.c @@ -1683,12 +1683,20 @@ static bool cmd_write(Filerange *range, enum CmdOpt opt, const char *argv[]) { return false; } for (const char **name = &argv[1]; *name; name++) { + struct stat meta; + if (!(opt & CMD_OPT_FORCE) && file->stat.st_mtime && stat(*name, &meta) == 0 && + file->stat.st_mtime < meta.st_mtime) { + editor_info_show(vis, "WARNING: file has been changed since reading it"); + return false; + } if (!text_range_save(text, range, *name)) { editor_info_show(vis, "Can't write `%s'", *name); return false; } - if (!file->name) + if (!file->name) { editor_window_name(vis->win, *name); + file->stat = text_stat(text); + } } return true; } @@ -1696,6 +1704,7 @@ static bool cmd_write(Filerange *range, enum CmdOpt opt, const char *argv[]) { static bool cmd_saveas(Filerange *range, enum CmdOpt opt, const char *argv[]) { if (cmd_write(range, opt, argv)) { editor_window_name(vis->win, argv[1]); + vis->win->file->stat = text_stat(vis->win->file->text); return true; } return false; -- cgit v1.2.3