Improve ical import logging

The log file is not deleted if items were skipped (adresses Github issue #269).
The log file includes the import file name and time.
The import line numbers have been corrected (and tests amended).

Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk>
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
Lars Henriksen 2020-03-10 00:12:50 +01:00 committed by Lukas Fleischer
parent 80b60d63cb
commit 467815d465
12 changed files with 49 additions and 40 deletions

View File

@ -425,7 +425,8 @@ int parse_args(int argc, char **argv)
int dump_imported = 0, export_uid = 0; int dump_imported = 0, export_uid = 0;
/* Data file locations */ /* Data file locations */
const char *datadir = NULL; const char *datadir = NULL;
const char *cfile = NULL, *ifile = NULL, *confdir = NULL; const char *cfile = NULL, *confdir = NULL;
char *ifile = NULL;
int non_interactive = 1; int non_interactive = 1;
int ch, cpid, type; int ch, cpid, type;

View File

@ -876,9 +876,9 @@ int display_help(const char *);
int run_hook(const char *); int run_hook(const char *);
/* ical.c */ /* ical.c */
void ical_import_data(FILE *, FILE *, unsigned *, unsigned *, unsigned *, void ical_import_data(const char *, FILE *, FILE *, unsigned *, unsigned *,
unsigned *, unsigned *, const char *, const char *, unsigned *, unsigned *, unsigned *, const char *,
const char *, const char *, const char *); const char *, const char *, const char *, const char *);
void ical_export_data(FILE *, int); void ical_export_data(FILE *, int);
/* io.c */ /* io.c */
@ -903,7 +903,7 @@ int io_check_file(const char *);
int io_check_data_files(void); int io_check_data_files(void);
void io_startup_screen(int); void io_startup_screen(int);
void io_export_data(enum export_type, int); void io_export_data(enum export_type, int);
void io_import_data(enum import_type, const char *, const char *, const char *, void io_import_data(enum import_type, char *, const char *, const char *,
const char *, const char *, const char *); const char *, const char *, const char *);
struct io_file *io_log_init(void); struct io_file *io_log_init(void);
void io_log_print(struct io_file *, int, const char *); void io_log_print(struct io_file *, int, const char *);

View File

@ -305,26 +305,35 @@ static void ical_export_todo(FILE * stream, int export_uid)
} }
/* Print a header to describe import log report format. */ /* Print a header to describe import log report format. */
static void ical_log_init(FILE * log, int major, int minor) static void ical_log_init(const char *file, FILE * log, int major, int minor)
{ {
const char *header = const char *header =
"+-------------------------------------------------------------------+\n" "+-------------------------------------------------------------------+\n"
"| Calcurse icalendar import log. |\n" "| Calcurse icalendar import log. |\n"
"| |\n" "| |\n"
"| Items imported from icalendar file, version %d.%d |\n" "| Import from icalendar file |\n"
"| Some items could not be imported, they are described hereafter. |\n" "| %-60s|\n"
"| version %d.%d at %s. |\n"
"| |\n"
"| Items which could not be imported are described below. |\n"
"| The log line format is as follows: |\n" "| The log line format is as follows: |\n"
"| |\n" "| |\n"
"| TYPE [LINE]: DESCRIPTION |\n" "| TYPE [LINE]: DESCRIPTION |\n"
"| |\n" "| |\n"
"| where: |\n" "| where: |\n"
"| * TYPE represents the item type ('VEVENT' or 'VTODO') |\n" "| * TYPE is the item type, 'VEVENT' or 'VTODO' |\n"
"| * LINE is the line in the input stream at which this item begins |\n" "| * LINE is the line in the import file where the item begins |\n"
"| * DESCRIPTION indicates why the item could not be imported |\n" "| * DESCRIPTION explains why the item could not be imported |\n"
"+-------------------------------------------------------------------+\n\n"; "+-------------------------------------------------------------------+\n\n";
char *date, *fmt;
asprintf(&fmt, "%s %s", DATEFMT(conf.input_datefmt), "%H:%M");
date = date_sec2date_str(now(), fmt);
if (log) if (log)
fprintf(log, header, major, minor); fprintf(log, header, file, major, minor, date);
mem_free(fmt);
mem_free(date);
} }
/* /*
@ -479,13 +488,13 @@ ical_readline_init(FILE * fdi, char *buf, char *lstore, unsigned *ln)
*buf = *lstore = '\0'; *buf = *lstore = '\0';
if (fgets(lstore, BUFSIZ, fdi)) { if (fgets(lstore, BUFSIZ, fdi)) {
(*ln)++;
if ((eol = strchr(lstore, '\n')) != NULL) { if ((eol = strchr(lstore, '\n')) != NULL) {
if (*(eol - 1) == '\r') if (*(eol - 1) == '\r')
*(eol - 1) = '\0'; *(eol - 1) = '\0';
else else
*eol = '\0'; *eol = '\0';
} }
(*ln)++;
} }
} }
@ -494,9 +503,9 @@ static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln)
char *eol; char *eol;
strncpy(buf, lstore, BUFSIZ); strncpy(buf, lstore, BUFSIZ);
(*ln)++;
while (fgets(lstore, BUFSIZ, fdi) != NULL) { while (fgets(lstore, BUFSIZ, fdi) != NULL) {
(*ln)++;
if ((eol = strchr(lstore, '\n')) != NULL) { if ((eol = strchr(lstore, '\n')) != NULL) {
if (*(eol - 1) == '\r') if (*(eol - 1) == '\r')
*(eol - 1) = '\0'; *(eol - 1) = '\0';
@ -506,7 +515,6 @@ static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln)
if (*lstore != SPACE && *lstore != TAB) if (*lstore != SPACE && *lstore != TAB)
break; break;
strncat(buf, lstore + 1, BUFSIZ - strlen(buf) - 1); strncat(buf, lstore + 1, BUFSIZ - strlen(buf) - 1);
(*ln)++;
} }
if (feof(fdi)) { if (feof(fdi)) {
@ -919,7 +927,7 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
char *lstore, unsigned *lineno, const char *fmt_ev, char *lstore, unsigned *lineno, const char *fmt_ev,
const char *fmt_rev, const char *fmt_apt, const char *fmt_rapt) const char *fmt_rev, const char *fmt_apt, const char *fmt_rapt)
{ {
const int ITEMLINE = *lineno; const int ITEMLINE = *lineno - !feof(fdi);
ical_vevent_e vevent_type; ical_vevent_e vevent_type;
char *p; char *p;
struct { struct {
@ -1073,7 +1081,7 @@ static void
ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped, ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
char *buf, char *lstore, unsigned *lineno, const char *fmt_todo) char *buf, char *lstore, unsigned *lineno, const char *fmt_todo)
{ {
const int ITEMLINE = *lineno; const int ITEMLINE = *lineno - !feof(fdi);
struct { struct {
char *mesg, *note; char *mesg, *note;
int priority; int priority;
@ -1140,7 +1148,7 @@ cleanup:
/* Import calcurse data. */ /* Import calcurse data. */
void void
ical_import_data(FILE * stream, FILE * log, unsigned *events, ical_import_data(const char *file, FILE * stream, FILE * log, unsigned *events,
unsigned *apoints, unsigned *todos, unsigned *lines, unsigned *apoints, unsigned *todos, unsigned *lines,
unsigned *skipped, const char *fmt_ev, const char *fmt_rev, unsigned *skipped, const char *fmt_ev, const char *fmt_rev,
const char *fmt_apt, const char *fmt_rapt, const char *fmt_apt, const char *fmt_rapt,
@ -1155,10 +1163,9 @@ ical_import_data(FILE * stream, FILE * log, unsigned *events,
_("Warning: ical header malformed or wrong version number. " _("Warning: ical header malformed or wrong version number. "
"Aborting...")); "Aborting..."));
ical_log_init(log, major, minor); ical_log_init(file, log, major, minor);
while (ical_readline(stream, buf, lstore, lines)) { while (ical_readline(stream, buf, lstore, lines)) {
(*lines)++;
if (starts_with_ci(buf, "BEGIN:VEVENT")) { if (starts_with_ci(buf, "BEGIN:VEVENT")) {
ical_read_event(stream, log, events, apoints, ical_read_event(stream, log, events, apoints,
skipped, buf, lstore, lines, fmt_ev, skipped, buf, lstore, lines, fmt_ev,

View File

@ -1247,31 +1247,29 @@ void io_export_data(enum export_type type, int export_uid)
} }
} }
static FILE *get_import_stream(enum import_type type) static FILE *get_import_stream(enum import_type type, char **stream_name)
{ {
FILE *stream = NULL; FILE *stream = NULL;
char *stream_name;
const char *ask_fname = const char *ask_fname =
_("Enter the file name to import data from:"); _("Enter the file name to import data from:");
const char *wrong_file = const char *wrong_file =
_("The file cannot be accessed, please enter another file name."); _("The file cannot be accessed, please enter another file name.");
const char *press_enter = _("Press [ENTER] to continue."); const char *press_enter = _("Press [ENTER] to continue.");
stream_name = mem_malloc(BUFSIZ); *stream_name = mem_malloc(BUFSIZ);
memset(stream_name, 0, BUFSIZ); memset(*stream_name, 0, BUFSIZ);
while (stream == NULL) { while (stream == NULL) {
status_mesg(ask_fname, ""); status_mesg(ask_fname, "");
if (updatestring(win[STA].p, &stream_name, 0, 1)) { if (updatestring(win[STA].p, stream_name, 0, 1)) {
mem_free(stream_name); mem_free(*stream_name);
return NULL; return NULL;
} }
stream = fopen(stream_name, "r"); stream = fopen(*stream_name, "r");
if (stream == NULL) { if (stream == NULL) {
status_mesg(wrong_file, press_enter); status_mesg(wrong_file, press_enter);
keys_wait_for_any_key(win[KEY].p); keys_wait_for_any_key(win[KEY].p);
} }
} }
mem_free(stream_name);
return stream; return stream;
} }
@ -1282,7 +1280,7 @@ static FILE *get_import_stream(enum import_type type)
* A temporary log file is created in /tmp to store the import process report, * A temporary log file is created in /tmp to store the import process report,
* and is cleared at the end. * and is cleared at the end.
*/ */
void io_import_data(enum import_type type, const char *stream_name, void io_import_data(enum import_type type, char *stream_name,
const char *fmt_ev, const char *fmt_rev, const char *fmt_ev, const char *fmt_rev,
const char *fmt_apt, const char *fmt_rapt, const char *fmt_apt, const char *fmt_rapt,
const char *fmt_todo) const char *fmt_todo)
@ -1309,7 +1307,7 @@ void io_import_data(enum import_type type, const char *stream_name,
"Aborting...")); "Aborting..."));
break; break;
case UI_CURSES: case UI_CURSES:
stream = get_import_stream(type); stream = get_import_stream(type, &stream_name);
break; break;
default: default:
EXIT(_("FATAL ERROR: wrong import mode")); EXIT(_("FATAL ERROR: wrong import mode"));
@ -1329,7 +1327,7 @@ void io_import_data(enum import_type type, const char *stream_name,
} }
if (type == IO_IMPORT_ICAL) if (type == IO_IMPORT_ICAL)
ical_import_data(stream, log->fd, &stats.events, ical_import_data(stream_name, stream, log->fd, &stats.events,
&stats.apoints, &stats.todos, &stats.apoints, &stats.todos,
&stats.lines, &stats.skipped, fmt_ev, fmt_rev, &stats.lines, &stats.skipped, fmt_ev, fmt_rev,
fmt_apt, fmt_rapt, fmt_todo); fmt_apt, fmt_rapt, fmt_todo);
@ -1380,6 +1378,9 @@ void io_import_data(enum import_type type, const char *stream_name,
mem_free(stats_str[1]); mem_free(stats_str[1]);
mem_free(stats_str[2]); mem_free(stats_str[2]);
mem_free(stats_str[3]); mem_free(stats_str[3]);
if (ui_mode == UI_CURSES)
mem_free(stream_name);
if (!stats.skipped)
io_log_free(log); io_log_free(log);
} }

View File

@ -11,7 +11,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0017 lines read Import process report: 0012 lines read
1 app / 0 events / 1 todo / 0 skipped 1 app / 0 events / 1 todo / 0 skipped
01/01/80: 01/01/80:
- 00:01 -> ..:.. - 00:01 -> ..:..

View File

@ -10,7 +10,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0036 lines read Import process report: 0028 lines read
5 apps / 0 events / 0 todos / 0 skipped 5 apps / 0 events / 0 todos / 0 skipped
01/01/00: 01/01/00:
- 00:00 -> 00:00 - 00:00 -> 00:00

View File

@ -10,7 +10,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0031 lines read Import process report: 0025 lines read
3 apps / 0 events / 0 todos / 0 skipped 3 apps / 0 events / 0 todos / 0 skipped
01/01/00: 01/01/00:
- 00:00 -> 01:30 - 00:00 -> 01:30

View File

@ -11,7 +11,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0017 lines read Import process report: 0012 lines read
1 app / 0 events / 1 todo / 0 skipped 1 app / 0 events / 1 todo / 0 skipped
01/01/80: 01/01/80:
- 00:01 -> ..:.. - 00:01 -> ..:..

View File

@ -10,7 +10,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0030 lines read Import process report: 0023 lines read
0 apps / 4 events / 0 todos / 0 skipped 0 apps / 4 events / 0 todos / 0 skipped
10/03/13: 10/03/13:
* All day * All day

View File

@ -10,7 +10,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0078 lines read Import process report: 0063 lines read
12 apps / 0 events / 0 todos / 0 skipped 12 apps / 0 events / 0 todos / 0 skipped
06/01/12: 06/01/12:
- 15:00 -> 15:30 - 15:00 -> 15:30

View File

@ -11,7 +11,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0018 lines read Import process report: 0013 lines read
2 apps / 0 events / 0 todos / 0 skipped 2 apps / 0 events / 0 todos / 0 skipped
02/23/15: 02/23/15:
- 06:00 -> 07:00 - 06:00 -> 07:00

View File

@ -11,7 +11,7 @@ if [ "$1" = 'actual' ]; then
rm -rf .calcurse || exit 1 rm -rf .calcurse || exit 1
elif [ "$1" = 'expected' ]; then elif [ "$1" = 'expected' ]; then
cat <<EOD cat <<EOD
Import process report: 0017 lines read Import process report: 0012 lines read
1 app / 0 events / 1 todo / 0 skipped 1 app / 0 events / 1 todo / 0 skipped
01/01/80: 01/01/80:
- 00:01 -> ..:.. - 00:01 -> ..:..