From 467815d465195ac7fe05449e074963585c4eaf9f Mon Sep 17 00:00:00 2001
From: Lars Henriksen <LarsHenriksen@get2net.dk>
Date: Tue, 10 Mar 2020 00:12:50 +0100
Subject: 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>
---
 src/args.c     |  3 ++-
 src/calcurse.h |  8 ++++----
 src/ical.c     | 37 ++++++++++++++++++++++---------------
 src/io.c       | 25 +++++++++++++------------
 4 files changed, 41 insertions(+), 32 deletions(-)

(limited to 'src')

diff --git a/src/args.c b/src/args.c
index bd58960..b2ccb0a 100644
--- a/src/args.c
+++ b/src/args.c
@@ -425,7 +425,8 @@ int parse_args(int argc, char **argv)
 	int dump_imported = 0, export_uid = 0;
 	/* Data file locations */
 	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 ch, cpid, type;
diff --git a/src/calcurse.h b/src/calcurse.h
index 419915e..d65d088 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -876,9 +876,9 @@ int display_help(const char *);
 int run_hook(const char *);
 
 /* ical.c */
-void ical_import_data(FILE *, FILE *, unsigned *, unsigned *, unsigned *,
-		      unsigned *, unsigned *, const char *, const char *,
-		      const char *, const char *, const char *);
+void ical_import_data(const char *, FILE *, FILE *, unsigned *, unsigned *,
+		      unsigned *, unsigned *, unsigned *, const char *,
+		      const char *, const char *, const char *, const char *);
 void ical_export_data(FILE *, int);
 
 /* io.c */
@@ -903,7 +903,7 @@ int io_check_file(const char *);
 int io_check_data_files(void);
 void io_startup_screen(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 *);
 struct io_file *io_log_init(void);
 void io_log_print(struct io_file *, int, const char *);
diff --git a/src/ical.c b/src/ical.c
index 2438351..f6936ec 100644
--- a/src/ical.c
+++ b/src/ical.c
@@ -305,26 +305,35 @@ static void ical_export_todo(FILE * stream, int export_uid)
 }
 
 /* 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 =
 	    "+-------------------------------------------------------------------+\n"
 	    "| Calcurse icalendar import log.                                    |\n"
 	    "|                                                                   |\n"
-	    "| Items imported from icalendar file, version %d.%d                   |\n"
-	    "| Some items could not be imported, they are described hereafter.   |\n"
+	    "| Import from icalendar file                                        |\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"
 	    "|                                                                   |\n"
 	    "|       TYPE [LINE]: DESCRIPTION                                    |\n"
 	    "|                                                                   |\n"
 	    "| where:                                                            |\n"
-	    "|  * TYPE represents the item type ('VEVENT' or 'VTODO')            |\n"
-	    "|  * LINE is the line in the input stream at which this item begins |\n"
-	    "|  * DESCRIPTION indicates why the item could not be imported       |\n"
+	    "|  * TYPE is the item type, 'VEVENT' or 'VTODO'                     |\n"
+	    "|  * LINE is the line in the import file where the item begins      |\n"
+	    "|  * DESCRIPTION explains why the item could not be imported        |\n"
 	    "+-------------------------------------------------------------------+\n\n";
 
+	char *date, *fmt;
+
+	asprintf(&fmt, "%s %s", DATEFMT(conf.input_datefmt), "%H:%M");
+	date = date_sec2date_str(now(), fmt);
 	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';
 	if (fgets(lstore, BUFSIZ, fdi)) {
+		(*ln)++;
 		if ((eol = strchr(lstore, '\n')) != NULL) {
 			if (*(eol - 1) == '\r')
 				*(eol - 1) = '\0';
 			else
 				*eol = '\0';
 		}
-		(*ln)++;
 	}
 }
 
@@ -494,9 +503,9 @@ static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln)
 	char *eol;
 
 	strncpy(buf, lstore, BUFSIZ);
-	(*ln)++;
 
 	while (fgets(lstore, BUFSIZ, fdi) != NULL) {
+		(*ln)++;
 		if ((eol = strchr(lstore, '\n')) != NULL) {
 			if (*(eol - 1) == '\r')
 				*(eol - 1) = '\0';
@@ -506,7 +515,6 @@ static int ical_readline(FILE * fdi, char *buf, char *lstore, unsigned *ln)
 		if (*lstore != SPACE && *lstore != TAB)
 			break;
 		strncat(buf, lstore + 1, BUFSIZ - strlen(buf) - 1);
-		(*ln)++;
 	}
 
 	if (feof(fdi)) {
@@ -919,7 +927,7 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
 		char *lstore, unsigned *lineno, const char *fmt_ev,
 		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;
 	char *p;
 	struct {
@@ -1073,7 +1081,7 @@ static void
 ical_read_todo(FILE * fdi, FILE * log, unsigned *notodos, unsigned *noskipped,
 	       char *buf, char *lstore, unsigned *lineno, const char *fmt_todo)
 {
-	const int ITEMLINE = *lineno;
+	const int ITEMLINE = *lineno - !feof(fdi);
 	struct {
 		char *mesg, *note;
 		int priority;
@@ -1140,7 +1148,7 @@ cleanup:
 
 /* Import calcurse data. */
 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 *skipped, const char *fmt_ev, const char *fmt_rev,
 		 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. "
 		   "Aborting..."));
 
-	ical_log_init(log, major, minor);
+	ical_log_init(file, log, major, minor);
 
 	while (ical_readline(stream, buf, lstore, lines)) {
-		(*lines)++;
 		if (starts_with_ci(buf, "BEGIN:VEVENT")) {
 			ical_read_event(stream, log, events, apoints,
 					skipped, buf, lstore, lines, fmt_ev,
diff --git a/src/io.c b/src/io.c
index 49892c5..1782105 100644
--- a/src/io.c
+++ b/src/io.c
@@ -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;
-	char *stream_name;
 	const char *ask_fname =
 	    _("Enter the file name to import data from:");
 	const char *wrong_file =
 	    _("The file cannot be accessed, please enter another file name.");
 	const char *press_enter = _("Press [ENTER] to continue.");
 
-	stream_name = mem_malloc(BUFSIZ);
-	memset(stream_name, 0, BUFSIZ);
+	*stream_name = mem_malloc(BUFSIZ);
+	memset(*stream_name, 0, BUFSIZ);
 	while (stream == NULL) {
 		status_mesg(ask_fname, "");
-		if (updatestring(win[STA].p, &stream_name, 0, 1)) {
-			mem_free(stream_name);
+		if (updatestring(win[STA].p, stream_name, 0, 1)) {
+			mem_free(*stream_name);
 			return NULL;
 		}
-		stream = fopen(stream_name, "r");
+		stream = fopen(*stream_name, "r");
 		if (stream == NULL) {
 			status_mesg(wrong_file, press_enter);
 			keys_wait_for_any_key(win[KEY].p);
 		}
 	}
-	mem_free(stream_name);
 
 	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,
  * 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_apt, const char *fmt_rapt,
 		    const char *fmt_todo)
@@ -1309,7 +1307,7 @@ void io_import_data(enum import_type type, const char *stream_name,
 			 "Aborting..."));
 		break;
 	case UI_CURSES:
-		stream = get_import_stream(type);
+		stream = get_import_stream(type, &stream_name);
 		break;
 	default:
 		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)
-		ical_import_data(stream, log->fd, &stats.events,
+		ical_import_data(stream_name, stream, log->fd, &stats.events,
 				 &stats.apoints, &stats.todos,
 				 &stats.lines, &stats.skipped, fmt_ev, fmt_rev,
 				 fmt_apt, fmt_rapt, fmt_todo);
@@ -1380,7 +1378,10 @@ void io_import_data(enum import_type type, const char *stream_name,
 	mem_free(stats_str[1]);
 	mem_free(stats_str[2]);
 	mem_free(stats_str[3]);
-	io_log_free(log);
+	if (ui_mode == UI_CURSES)
+		mem_free(stream_name);
+	if (!stats.skipped)
+		io_log_free(log);
 }
 
 struct io_file *io_log_init(void)
-- 
cgit v1.2.3-70-g09d2