From cacd81cd1065cf9a145bb2fbe66c383ad3c90206 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Orsini Date: Sun, 22 May 2011 22:12:31 +0000 Subject: [PATCH] ppa stats graph --- src/Makefile.am | 1 + src/Makefile.in | 8 ++-- src/chart.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/chart.h | 31 +++++++++++++++ src/html.c | 47 ++++++++++++++++++++--- src/html.h | 3 +- src/list.c | 28 ++++++++++++-- src/list.h | 1 + src/lp_ws.c | 22 ----------- src/main.c | 9 +++-- src/ppastats.c | 58 ++++++++++++++++++++++++++++ src/ppastats.h | 2 +- 12 files changed, 288 insertions(+), 39 deletions(-) create mode 100644 src/chart.c create mode 100644 src/chart.h diff --git a/src/Makefile.am b/src/Makefile.am index a662a5f..9fc8b01 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ LIBS += $(CURL_LIBS) $(JSON_LIBS) bin_PROGRAMS = ppastats ppastats_SOURCES = \ cache.h cache.c\ + chart.h chart.c\ html.h html.c\ list.h list.c\ lp.h lp.c\ diff --git a/src/Makefile.in b/src/Makefile.in index 12908ec..d63cb70 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -46,9 +46,9 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) -am_ppastats_OBJECTS = cache.$(OBJEXT) html.$(OBJEXT) list.$(OBJEXT) \ - lp.$(OBJEXT) lp_json.$(OBJEXT) lp_ws.$(OBJEXT) main.$(OBJEXT) \ - ppastats.$(OBJEXT) +am_ppastats_OBJECTS = cache.$(OBJEXT) chart.$(OBJEXT) html.$(OBJEXT) \ + list.$(OBJEXT) lp.$(OBJEXT) lp_json.$(OBJEXT) lp_ws.$(OBJEXT) \ + main.$(OBJEXT) ppastats.$(OBJEXT) ppastats_OBJECTS = $(am_ppastats_OBJECTS) ppastats_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) @@ -189,6 +189,7 @@ AM_CPPFLAGS = -Wall -std=gnu99 -Werror \ ppastats_SOURCES = \ cache.h cache.c\ + chart.h chart.c\ html.h html.c\ list.h list.c\ lp.h lp.c\ @@ -280,6 +281,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chart.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/html.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lp.Po@am__quote@ diff --git a/src/chart.c b/src/chart.c new file mode 100644 index 0000000..f11feb8 --- /dev/null +++ b/src/chart.c @@ -0,0 +1,117 @@ +/* + Copyright (C) 2011 jeanfi@gmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include +#include + +#include + +#include "chart.h" + +#define HTML_TEMPLATE \ +"\n\ + \n\ + \n\ + \n\ + \n\ +\n\ + \n\ +
\n\ + \n\ +\n" + +char *tm_to_str(struct tm *date) +{ + char *str = malloc(10+1); + + sprintf(str, "%d-%02d-%02d", + date->tm_year+1900, + date->tm_mon+1, + date->tm_mday); + + return str; +} + +void +generate_chart(const char *path, + const char *title, + const char *name, + struct daily_download_total **totals) +{ + FILE *f; + struct daily_download_total **cur; + struct daily_download_total *total; + char *str_date; + json_object *arr, *item; + + if (!totals) { + fprintf(stderr, "ERROR: no totals\n"); + return ; + } + + f = fopen(path, "w"); + + if (!f) { + fprintf(stderr, "ERROR: failed to open: %s\n", path); + return ; + } + + arr = json_object_new_array(); + cur = totals; + while(*cur) { + total = *cur; + + str_date = tm_to_str(&(total->date)); + + item = json_object_new_array(); + + json_object_array_add(item, json_object_new_string(str_date)); + json_object_array_add(item, + json_object_new_int(total->count)); + + json_object_array_add(arr, item); + + free(str_date); + + cur++; + } + + fprintf(f, + HTML_TEMPLATE, + json_object_to_json_string(arr)); + + json_object_put(arr); + + fclose(f); +} diff --git a/src/chart.h b/src/chart.h new file mode 100644 index 0000000..0791a91 --- /dev/null +++ b/src/chart.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2011 jeanfi@gmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#ifndef _PPASTATS_CHART_H_ +#define _PPASTATS_CHART_H_ + +#include "lp.h" + +void +generate_chart(const char *path, + const char *title, + const char *name, + struct daily_download_total **totals); + +#endif diff --git a/src/html.c b/src/html.c index 28fe195..aa4c6f1 100644 --- a/src/html.c +++ b/src/html.c @@ -19,9 +19,11 @@ #include +#include "chart.h" #include "html.h" #include "list.h" #include "lp_ws.h" +#include "ppastats.h" #include @@ -188,28 +190,61 @@ build_data_str(struct binary_package_publishing_history **list) return str; } -void ppa_to_html(const char *owner, const char *ppa, const char *package_status) +static char *get_path(const char *dir, const char *file) +{ + char *path = malloc(strlen(dir)+1+strlen(file)+1); + + strcpy(path, dir); + strcat(path, "/"); + strcat(path, file); + + return path; +} + +void +ppa_to_html(const char *owner, + const char *ppa, + const char *package_status, + const char *output_dir) { struct binary_package_publishing_history **list; - char *archive_url = get_archive_url(owner, ppa); - char *addcolumns_str; - char *data_str; + char *archive_url, *addcolumns_str, *data_str, *path; + FILE *f; + struct ppa_stats *ppastats; + struct daily_download_total **totals; + + ppastats = create_ppa_stats(owner, ppa, package_status); + totals = ppastats->daily_download_totals; + path = get_path(output_dir, "ppa.html"); + generate_chart(path, "PPA Statistics", ppa, totals); + free(path); + + archive_url = get_archive_url(owner, ppa); list = get_binary_package_publishing_history_list(archive_url, package_status); free(archive_url); if (!list) { - fprintf(stderr, "Failed to retrieve PPA information\n"); + fprintf(stderr, "ERROR: Failed to retrieve PPA information\n"); exit(EXIT_FAILURE); } addcolumns_str = build_addcolums_str(list); data_str = build_data_str(list); - printf(HTML_TEMPLATE, addcolumns_str, data_str); + path = get_path(output_dir, "index.html"); + f = fopen(path, "w"); + if (f) { + fprintf(f, HTML_TEMPLATE, addcolumns_str, data_str); + fclose(f); + } else { + fprintf(stderr, "ERROR: failed to write %s\n", path); + } + free(path); free(addcolumns_str); free(data_str); binary_package_publishing_history_list_free(list); + ppa_stats_free(ppastats); } diff --git a/src/html.h b/src/html.h index 79ed705..b165f78 100644 --- a/src/html.h +++ b/src/html.h @@ -24,6 +24,7 @@ void ppa_to_html(const char *owner, const char *ppa, - const char *package_status); + const char *package_status, + const char *output_dir); #endif diff --git a/src/list.c b/src/list.c index ceb4efa..76a37e6 100644 --- a/src/list.c +++ b/src/list.c @@ -44,14 +44,36 @@ void **list_add(void **list, void *new_item) new_list = malloc(sizeof(void *)*(n+2)); - if (n) + if (n) { memcpy(new_list, list, sizeof(void *)*n); + free(list); + } new_list[n] = new_item; new_list[n+1] = NULL; - free(list); - return new_list; } +void **list_add_list(void **list1, void **list2) +{ + int n1, n2, n; + void **list; + + n1 = list_length(list1); + n2 = list_length(list2); + + n = n1 + n2 + 1; + + list = malloc(sizeof(void *)*(n+1)); + + memcpy(list, list1, n1*sizeof(void *)); + memcpy(list+n1, list2, n2*sizeof(void *)); + + list[n1+n2] = NULL; + + free(list1); + + return list; +} + diff --git a/src/list.h b/src/list.h index f2115c8..69b7b25 100644 --- a/src/list.h +++ b/src/list.h @@ -22,5 +22,6 @@ int list_length(void **list); void **list_add(void **list, void *new_item); +void **list_add_list(void **list1, void **list2); #endif diff --git a/src/lp_ws.c b/src/lp_ws.c index 2370d36..6c2e299 100644 --- a/src/lp_ws.c +++ b/src/lp_ws.c @@ -116,28 +116,6 @@ static json_object *get_json_object(const char *url) return NULL; } -static void **list_add_list(void **list1, void **list2) -{ - int n1, n2, n; - void **list; - - n1 = list_length(list1); - n2 = list_length(list2); - - n = n1 + n2 + 1; - - list = malloc(sizeof(void *)*(n+1)); - - memcpy(list, list1, n1*sizeof(void *)); - memcpy(list+n1, list2, n2*sizeof(void *)); - - list[n1+n2] = NULL; - - free(list1); - - return list; -} - #define json_object_to_bpph_list \ json_object_to_binary_package_publishing_history_list diff --git a/src/main.c b/src/main.c index 1997551..1629053 100644 --- a/src/main.c +++ b/src/main.c @@ -86,7 +86,7 @@ static void display_published_binaries(const char *owner, static struct option long_options[] = { {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, - {"html", no_argument, 0, 't'}, + {"html", required_argument, 0, 't'}, {"debug", no_argument, 0, 'd'}, {"status", required_argument, 0, 's'}, {0, 0, 0, 0} @@ -140,14 +140,16 @@ int main(int argc, char **argv) int output_html = 0; char *package_status = NULL; int cmdok = 1; + char *output_dir = NULL; program_name = argv[0]; - while ((optc = getopt_long(argc, argv, "vhtds:", long_options, + while ((optc = getopt_long(argc, argv, "vht:ds:", long_options, NULL)) != -1) { switch (optc) { case 't': output_html = 1; + output_dir = strdup(optarg); break; case 'd': debug = 1; @@ -178,12 +180,13 @@ int main(int argc, char **argv) ppa = argv[optind+1]; if (output_html) - ppa_to_html(owner, ppa, package_status); + ppa_to_html(owner, ppa, package_status, output_dir); else display_published_binaries(owner, ppa, package_status); /* for valgrind.... */ free(package_status); + free(output_dir); lp_ws_cleanup(); cache_cleanup(); diff --git a/src/ppastats.c b/src/ppastats.c index 56a8942..70f6c6f 100644 --- a/src/ppastats.c +++ b/src/ppastats.c @@ -137,6 +137,55 @@ static struct arch_stats *get_arch_stats(struct distro_stats *distro, } +static struct daily_download_total ** +add_total(struct daily_download_total **totals, + struct daily_download_total *total) +{ + struct daily_download_total **cur; + struct daily_download_total *item; + + cur = totals; + while (*cur) { + item = *cur; + + if (item->date.tm_year == total->date.tm_year && + item->date.tm_mon == total->date.tm_mon && + item->date.tm_mday == total->date.tm_mday) { + item->count += total->count; + return totals; + } + + cur++; + } + + item = malloc(sizeof(struct daily_download_total)); + memcpy(item, total, sizeof(struct daily_download_total)); + + return (struct daily_download_total **) + list_add((void **)totals, (void *)item); +} + +struct daily_download_total ** +add_totals(struct daily_download_total **total1, + struct daily_download_total **total2) +{ + struct daily_download_total **cur; + struct daily_download_total **result; + + if (!total1) + return total2; + + result = total1; + cur = total2; + while (*cur) { + result = add_total(result, *cur); + + cur++; + } + + return result; +} + struct ppa_stats * create_ppa_stats(const char *owner, const char *ppa, @@ -154,6 +203,7 @@ create_ppa_stats(const char *owner, struct distro_stats *distro; struct arch_stats *arch; int count; + struct daily_download_total **totals; ppa_url = get_archive_url(owner, ppa); history = get_binary_package_publishing_history_list(ppa_url, @@ -198,6 +248,14 @@ create_ppa_stats(const char *owner, ppastats->download_count += count; + totals = get_daily_download_totals(h->self_link); + ppastats->daily_download_totals + = add_totals(ppastats->daily_download_totals, + totals); + + if (ppastats->daily_download_totals != totals) + daily_download_total_list_free(totals); + h_cur++; } diff --git a/src/ppastats.h b/src/ppastats.h index 1f8ea61..019c5d4 100644 --- a/src/ppastats.h +++ b/src/ppastats.h @@ -61,7 +61,7 @@ struct ppa_stats { struct package_stats **packages; int download_count; - struct daily_download_total *daily_download_totals; + struct daily_download_total **daily_download_totals; }; struct ppa_stats *create_ppa_stats(const char *owner, -- 2.7.4