commit:     79ae531435cf37e50676c25e794f335a6587c7d3
Author:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Mon Mar 28 03:52:02 2016 +0000
Commit:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Mon Mar 28 03:52:02 2016 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=79ae5314

qlop: add --date option to filter output

Allow people to filter results by start & end dates.

URL: https://bugs.gentoo.org/192918
Reported-by: Laurento Frittella <laurento.frittella <AT> gmail.com>

 man/qlop.1             |   5 +-
 qlop.c                 | 131 ++++++++++++++++++++++++++++++++++++++++++++++---
 tests/qlop/dotest      |   5 ++
 tests/qlop/list06.good |   2 +
 tests/qlop/list07.good |   2 +
 tests/qlop/list08.good |   2 +
 6 files changed, 139 insertions(+), 8 deletions(-)

diff --git a/man/qlop.1 b/man/qlop.1
index 6e645a8..77cf5ef 100644
--- a/man/qlop.1
+++ b/man/qlop.1
@@ -1,4 +1,4 @@
-.TH qlop "1" "Feb 2016" "Gentoo Foundation" "qlop"
+.TH qlop "1" "Mar 2016" "Gentoo Foundation" "qlop"
 .SH NAME
 qlop \- emerge log analyzer
 .SH SYNOPSIS
@@ -29,6 +29,9 @@ Show sync history
 \fB\-c\fR, \fB\-\-current\fR
 Show current emerging packages
 .TP
+\fB\-d\fR \fI<arg>\fR, \fB\-\-date\fR \fI<arg>\fR
+Limit selection to this time (1st -d is start, 2nd -d is end)
+.TP
 \fB\-f\fR \fI<arg>\fR, \fB\-\-logfile\fR \fI<arg>\fR
 Read emerge logfile instead of $EMERGE_LOG_DIR/emerge.log
 .TP

diff --git a/qlop.c b/qlop.c
index 319d767..0da636a 100644
--- a/qlop.c
+++ b/qlop.c
@@ -10,7 +10,7 @@
 
 #define QLOP_DEFAULT_LOGFILE "emerge.log"
 
-#define QLOP_FLAGS "gtHluscf:" COMMON_FLAGS
+#define QLOP_FLAGS "gtHluscd:f:" COMMON_FLAGS
 static struct option const qlop_long_opts[] = {
        {"gauge",     no_argument, NULL, 'g'},
        {"time",      no_argument, NULL, 't'},
@@ -19,6 +19,7 @@ static struct option const qlop_long_opts[] = {
        {"unlist",    no_argument, NULL, 'u'},
        {"sync",      no_argument, NULL, 's'},
        {"current",   no_argument, NULL, 'c'},
+       {"date",       a_argument, NULL, 'd'},
        {"logfile",    a_argument, NULL, 'f'},
        COMMON_LONG_OPTS
 };
@@ -30,6 +31,7 @@ static const char * const qlop_opts_help[] = {
        "Show unmerge history",
        "Show sync history",
        "Show current emerging packages",
+       "Limit selection to this time (1st -d is start, 2nd -d is end)",
        "Read emerge logfile instead of $EMERGE_LOG_DIR/" QLOP_DEFAULT_LOGFILE,
        COMMON_OPTS_HELP
 };
@@ -64,7 +66,8 @@ chop_ctime(time_t t)
 }
 
 _q_static unsigned long
-show_merge_times(char *package, const char *logfile, int average, char 
human_readable)
+show_merge_times(char *package, const char *logfile, int average, char 
human_readable,
+                 time_t start_time, time_t end_time)
 {
        FILE *fp;
        char cat[126], buf[2][BUFSIZ];
@@ -103,6 +106,8 @@ show_merge_times(char *package, const char *logfile, int 
average, char human_rea
                        continue;
                *p = 0;
                t[0] = atol(buf[0]);
+               if (t[0] < start_time || t[0] > end_time)
+                       continue;
                strcpy(buf[1], p + 1);
                rmspace(buf[1]);
                if (strncmp(buf[1], ">>> emerge (", 12) == 0) {
@@ -216,7 +221,8 @@ show_merge_times(char *package, const char *logfile, int 
average, char human_rea
 }
 
 _q_static void
-show_emerge_history(int listflag, array_t *atoms, const char *logfile)
+show_emerge_history(int listflag, array_t *atoms, const char *logfile,
+                    time_t start_time, time_t end_time)
 {
        FILE *fp;
        size_t buflen, linelen;
@@ -247,6 +253,8 @@ show_emerge_history(int listflag, array_t *atoms, const 
char *logfile)
                        continue;
 
                t = (time_t) atol(buf);
+               if (t < start_time || t > end_time)
+                       continue;
 
                if ((listflag & QLOP_LIST) && !strncmp(q, "::: completed emerge 
(", 22)) {
                        merged = 1;
@@ -313,7 +321,7 @@ New format:
 1431764493:  *** terminating.
 */
 _q_static void
-show_sync_history(const char *logfile)
+show_sync_history(const char *logfile, time_t start_time, time_t end_time)
 {
        FILE *fp;
        size_t buflen, linelen;
@@ -344,6 +352,8 @@ show_sync_history(const char *logfile)
                rmspace_len(buf, linelen);
 
                t = (time_t)atol(buf);
+               if (t < start_time || t > end_time)
+                       continue;
 
                if (!strncmp(p, "with ", 5))
                        p += 5;
@@ -635,16 +645,112 @@ void show_current_emerge(void)
 }
 #endif
 
+_q_static
+bool parse_date(const char *sdate, time_t *t)
+{
+       struct tm tm;
+       const char *s;
+
+       memset(&tm, 0, sizeof(tm));
+
+       s = strchr(sdate, '|');
+       if (s) {
+               /* Handle custom format like "%Y|2012". */
+               size_t fmtlen = s - sdate;
+               char fmt[fmtlen + 1];
+               memcpy(fmt, sdate, fmtlen);
+               fmt[fmtlen] = '\0';
+               sdate = s + 1;
+               s = strptime(sdate, fmt, &tm);
+               if (s == NULL || s[0] != '\0')
+                       return false;
+       } else {
+               /* Handle automatic formats:
+                * - "12315128"   -> %s
+                * - "2015-12-24" -> %F (same as %Y-%m-%d
+                * - human readable format (see below)
+                */
+               size_t len = strspn(sdate, "0123456789-");
+               if (sdate[len] == '\0') {
+                       const char *fmt;
+                       if (strchr(sdate, '-') == NULL)
+                               fmt = "%s";
+                       else
+                               fmt = "%F";
+
+                       s = strptime(sdate, fmt, &tm);
+                       if (s == NULL || s[0] != '\0')
+                               return false;
+               } else {
+                       /* Handle the formats:
+                        * <#> <day|week|month|year>[s] [ago]
+                        */
+                       len = strlen(sdate);
+
+                       unsigned long num;
+                       char dur[len];
+                       char ago[len];
+                       int ret = sscanf(sdate, "%lu %s %s", &num, dur, ago);
+
+                       if (ret < 2)
+                               return false;
+                       if (ret == 3 && strcmp(ago, "ago") != 0)
+                               return false;
+
+                       if (time(t) == -1)
+                               return false;
+                       if (localtime_r(t, &tm) == NULL)
+                               return false;
+
+                       /* Chop and trailing "s" sizes. */
+                       len = strlen(dur);
+                       if (dur[len - 1] == 's')
+                               dur[len - 1] = '\0';
+
+                       /* Step down the current time. */
+                       if (!strcmp(dur, "year")) {
+                               tm.tm_year -= num;
+                       } else if (!strcmp(dur, "month")) {
+                               if (num >= 12) {
+                                       tm.tm_year -= (num / 12);
+                                       num %= 12;
+                               }
+                               tm.tm_mon -= num;
+                               if (tm.tm_mon < 0) {
+                                       tm.tm_mon += 12;
+                                       tm.tm_year -= 1;
+                               }
+                       } else if (!strcmp(dur, "week")) {
+                               num *= 7;
+                               goto days;
+                       } else if (!strcmp(dur, "day")) {
+ days:
+                               /* This is in seconds, so scale w/that.  */
+                               *t -= (num * 24 * 60 * 60);
+                               if (localtime_r(t, &tm) == NULL)
+                                       return false;
+                       } else
+                               return false;
+               }
+       }
+
+       *t = mktime(&tm);
+       return (*t == -1) ? false : true;
+}
+
 int qlop_main(int argc, char **argv)
 {
        size_t i;
        int average = 1;
+       time_t start_time, end_time;
        char do_time, do_list, do_unlist, do_sync, do_current, 
do_human_readable = 0;
        char *logfile = NULL;
        int flags;
        depend_atom *atom;
        DECLARE_ARRAY(atoms);
 
+       start_time = 0;
+       end_time = LONG_MAX;
        do_time = do_list = do_unlist = do_sync = do_current = 0;
 
        while ((i = GETOPT_LONG(QLOP, qlop, "")) != -1) {
@@ -658,6 +764,16 @@ int qlop_main(int argc, char **argv)
                        case 'c': do_current = 1; break;
                        case 'g': do_time = 1; average = 0; break;
                        case 'H': do_human_readable = 1; break;
+                       case 'd':
+                               if (start_time == 0) {
+                                       if (!parse_date(optarg, &start_time))
+                                               err("invalid date: %s", optarg);
+                               } else if (end_time == LONG_MAX) {
+                                       if (!parse_date(optarg, &end_time))
+                                               err("invalid date: %s", optarg);
+                               } else
+                                       err("too many -d options");
+                               break;
                        case 'f':
                                if (logfile) err("Only use -f once");
                                logfile = xstrdup(optarg);
@@ -685,16 +801,17 @@ int qlop_main(int argc, char **argv)
        if (do_unlist)
                flags |= QLOP_UNLIST;
        if (flags)
-               show_emerge_history(flags, atoms, logfile);
+               show_emerge_history(flags, atoms, logfile, start_time, 
end_time);
 
        if (do_current)
                show_current_emerge();
        if (do_sync)
-               show_sync_history(logfile);
+               show_sync_history(logfile, start_time, end_time);
 
        if (do_time) {
                for (i = 0; i < argc; ++i)
-                       show_merge_times(argv[i], logfile, average, 
do_human_readable);
+                       show_merge_times(argv[i], logfile, average, 
do_human_readable,
+                               start_time, end_time);
        }
 
        array_for_each(atoms, i, atom)

diff --git a/tests/qlop/dotest b/tests/qlop/dotest
index fad6011..0275d45 100755
--- a/tests/qlop/dotest
+++ b/tests/qlop/dotest
@@ -37,6 +37,11 @@ test 04 0 "qlop -l gcc -f ${as}/sync.log"
 # verify atom version parsing works
 test 05 0 "qlop -l '<gcc-5' -f ${as}/sync.log"
 
+# check date time parser
+test 06 0 "qlop -l -f ${as}/sync.log -d 2005-01-01"
+test 07 0 "qlop -l -f ${as}/sync.log -d '%d%Y%m|01200501'"
+test 08 0 "qlop -l -f ${as}/sync.log -d 1104898893"
+
 cleantmpdir
 
 end

diff --git a/tests/qlop/list06.good b/tests/qlop/list06.good
new file mode 100644
index 0000000..e9fccc3
--- /dev/null
+++ b/tests/qlop/list06.good
@@ -0,0 +1,2 @@
+Thu Jan 27 05:56:39 2005 >>> sys-devel/gcc-config-1.3.9
+Thu Jan 27 06:17:10 2005 >>> sys-devel/gcc-3.4.3-r1

diff --git a/tests/qlop/list07.good b/tests/qlop/list07.good
new file mode 100644
index 0000000..e9fccc3
--- /dev/null
+++ b/tests/qlop/list07.good
@@ -0,0 +1,2 @@
+Thu Jan 27 05:56:39 2005 >>> sys-devel/gcc-config-1.3.9
+Thu Jan 27 06:17:10 2005 >>> sys-devel/gcc-3.4.3-r1

diff --git a/tests/qlop/list08.good b/tests/qlop/list08.good
new file mode 100644
index 0000000..e9fccc3
--- /dev/null
+++ b/tests/qlop/list08.good
@@ -0,0 +1,2 @@
+Thu Jan 27 05:56:39 2005 >>> sys-devel/gcc-config-1.3.9
+Thu Jan 27 06:17:10 2005 >>> sys-devel/gcc-3.4.3-r1

Reply via email to