Merge pull request #247 from rkta/hist
Do not override history file if it was changed
This commit is contained in:
73
history.c
73
history.c
@@ -2,6 +2,19 @@
|
|||||||
#include "fm.h"
|
#include "fm.h"
|
||||||
|
|
||||||
#ifdef USE_HISTORY
|
#ifdef USE_HISTORY
|
||||||
|
/* Merge entries from their history into ours */
|
||||||
|
static int
|
||||||
|
mergeHistory(Hist *ours, Hist *theirs)
|
||||||
|
{
|
||||||
|
HistItem *item;
|
||||||
|
|
||||||
|
for (item = theirs->list->first; item; item = item->next)
|
||||||
|
if (!getHashHist(ours, item->ptr))
|
||||||
|
pushHist(ours, (char *)item->ptr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Buffer *
|
Buffer *
|
||||||
historyBuffer(Hist *hist)
|
historyBuffer(Hist *hist)
|
||||||
{
|
{
|
||||||
@@ -31,16 +44,23 @@ historyBuffer(Hist *hist)
|
|||||||
return loadHTMLString(src);
|
return loadHTMLString(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
loadHistory(Hist *hist)
|
loadHistory(Hist *hist)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
Str line;
|
Str line;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
if (hist == NULL)
|
if (hist == NULL)
|
||||||
return;
|
return 1;
|
||||||
if ((f = fopen(rcFile(HISTORY_FILE), "rt")) == NULL)
|
if ((f = fopen(rcFile(HISTORY_FILE), "rt")) == NULL)
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
|
if (fstat(fileno(f), &st) == -1) {
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
hist->mtime = (long long)st.st_mtim.tv_sec;
|
||||||
|
|
||||||
while (!feof(f)) {
|
while (!feof(f)) {
|
||||||
line = Strfgets(f);
|
line = Strfgets(f);
|
||||||
@@ -52,42 +72,61 @@ loadHistory(Hist *hist)
|
|||||||
pushHist(hist, url_quote(line->ptr));
|
pushHist(hist, url_quote(line->ptr));
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
saveHistory(Hist *hist, size_t size)
|
saveHistory(Hist *hist, size_t size)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
Hist *fhist;
|
||||||
HistItem *item;
|
HistItem *item;
|
||||||
|
char *histf;
|
||||||
char *tmpf;
|
char *tmpf;
|
||||||
int rename_ret;
|
int rename_ret;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
if (hist == NULL || hist->list == NULL)
|
if (hist == NULL || hist->list == NULL)
|
||||||
return;
|
return;
|
||||||
tmpf = tmpfname(TMPF_HIST, NULL)->ptr;
|
|
||||||
if ((f = fopen(tmpf, "w")) == NULL) {
|
histf = rcFile(HISTORY_FILE);
|
||||||
/* FIXME: gettextize? */
|
if (stat(histf, &st) == -1)
|
||||||
disp_err_message("Can't open history", FALSE);
|
goto fail;
|
||||||
return;
|
if (hist->mtime != (long long)st.st_mtim.tv_sec) {
|
||||||
|
fhist = newHist();
|
||||||
|
if (loadHistory(fhist) || mergeHistory(fhist, hist))
|
||||||
|
disp_err_message("Can't merge history", FALSE);
|
||||||
|
else
|
||||||
|
hist = fhist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmpf = tmpfname(TMPF_HIST, NULL)->ptr;
|
||||||
|
if ((f = fopen(tmpf, "w")) == NULL)
|
||||||
|
goto fail;
|
||||||
for (item = hist->list->first; item && hist->list->nitem > size;
|
for (item = hist->list->first; item && hist->list->nitem > size;
|
||||||
item = item->next)
|
item = item->next)
|
||||||
size++;
|
size++;
|
||||||
for (; item; item = item->next)
|
for (; item; item = item->next)
|
||||||
fprintf(f, "%s\n", (char *)item->ptr);
|
fprintf(f, "%s\n", (char *)item->ptr);
|
||||||
if (fclose(f) == EOF) {
|
if (fclose(f) == EOF)
|
||||||
/* FIXME: gettextize? */
|
goto fail;
|
||||||
disp_err_message("Can't save history", FALSE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rename_ret = rename(tmpf, rcFile(HISTORY_FILE));
|
rename_ret = rename(tmpf, rcFile(HISTORY_FILE));
|
||||||
if (rename_ret != 0) {
|
if (rename_ret != 0)
|
||||||
disp_err_message("Can't save history", FALSE);
|
goto fail;
|
||||||
return;
|
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
disp_err_message("Can't open history", FALSE);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif /* USE_HISTORY */
|
#endif /* USE_HISTORY */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following functions are used for internal stuff, we need them regardless
|
||||||
|
* if history is used or not.
|
||||||
|
*/
|
||||||
|
|
||||||
Hist *
|
Hist *
|
||||||
newHist(void)
|
newHist(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ typedef struct {
|
|||||||
HistList *list;
|
HistList *list;
|
||||||
HistItem *current;
|
HistItem *current;
|
||||||
Hash_sv *hash;
|
Hash_sv *hash;
|
||||||
|
long long mtime;
|
||||||
} Hist;
|
} Hist;
|
||||||
|
|
||||||
extern Hist *newHist(void);
|
extern Hist *newHist(void);
|
||||||
@@ -28,4 +29,12 @@ extern char *lastHist(Hist *hist);
|
|||||||
extern char *nextHist(Hist *hist);
|
extern char *nextHist(Hist *hist);
|
||||||
extern char *prevHist(Hist *hist);
|
extern char *prevHist(Hist *hist);
|
||||||
|
|
||||||
|
#ifdef USE_HISTORY
|
||||||
|
extern int loadHistory(Hist *hist);
|
||||||
|
extern void saveHistory(Hist *hist, size_t size);
|
||||||
|
extern void ldHist(void);
|
||||||
|
#else /* not USE_HISTORY */
|
||||||
|
#define ldHist nulcmd
|
||||||
|
#endif /* not USE_HISTORY */
|
||||||
|
|
||||||
#endif /* HISTORY_H */
|
#endif /* HISTORY_H */
|
||||||
|
|||||||
5
proto.h
5
proto.h
@@ -391,11 +391,6 @@ extern char *inputLineHistSearch(char *prompt, char *def_str, int flag,
|
|||||||
extern Str unescape_spaces(Str s);
|
extern Str unescape_spaces(Str s);
|
||||||
#ifdef USE_HISTORY
|
#ifdef USE_HISTORY
|
||||||
extern Buffer *historyBuffer(Hist *hist);
|
extern Buffer *historyBuffer(Hist *hist);
|
||||||
extern void loadHistory(Hist *hist);
|
|
||||||
extern void saveHistory(Hist *hist, size_t size);
|
|
||||||
extern void ldHist(void);
|
|
||||||
#else /* not USE_HISTORY */
|
|
||||||
#define ldHist nulcmd
|
|
||||||
#endif /* not USE_HISTORY */
|
#endif /* not USE_HISTORY */
|
||||||
extern double log_like(int x);
|
extern double log_like(int x);
|
||||||
extern struct table *newTable(void);
|
extern struct table *newTable(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user