#include #include #include #include "packages.h" #include "swabber.h" #include "wandering.h" #define MAX_WANDERING_LISTS 10 struct top_not_found_node { char basename[FILENAME_LENGTH]; unsigned int wandering_type; char found_path[FILENAME_LENGTH]; struct not_found_node * not_found_base; struct top_not_found_node * next; }; struct not_found_node { struct error_file_node * error_file; unsigned int count; struct not_found_node * next; }; static void not_found_free(struct top_not_found_node * top_node) { struct not_found_node * t, *next; for (t = top_node->not_found_base; next; t = next) { next = t->next; free(t); } free(top_node); } static char * basename(const char * filename) { return strrchr(filename, '/')+1; } static int in_project(const char * path, const char * project) { unsigned int len = FILENAME_LENGTH; if (strlen(path) < len) len = strlen(path); if (strlen(project) < len) len = strlen(project); return memcmp(path, project, len); } void wandering_process(struct top_tag_node *tag, const char * project) { struct not_found_node * nfn; struct top_not_found_node * tnfn; unsigned int first = 0; /* Go through all the wandering entries and calculate type */ for (tnfn = tag->wandering_problems_base; tnfn; tnfn = tnfn->next) { for (nfn = tnfn->not_found_base; nfn; nfn = nfn->next) { if (in_project(nfn->error_file->filename, project)) { switch (first) { case WANDERING_ONLY_HOST: first = WANDERING_HOST_THEN_PROJECT; goto done; case 0: first = WANDERING_ONLY_PROJECT; case WANDERING_ONLY_PROJECT: case WANDERING_HOST_THEN_PROJECT: case WANDERING_PROJECT_THEN_HOST: /* should never happen */ break; } } else { switch (first) { case WANDERING_ONLY_PROJECT: first = WANDERING_PROJECT_THEN_HOST; goto done; case 0: first = WANDERING_ONLY_HOST; case WANDERING_ONLY_HOST: case WANDERING_PROJECT_THEN_HOST: case WANDERING_HOST_THEN_PROJECT: /* should never happen */ break; } } } done: tnfn->wandering_type = first; first = 0; } } void wandering_print_report(FILE * f, struct top_tag_node *tag, unsigned int wandering_type) { struct not_found_node * nfn; struct top_not_found_node * tnfn; fprintf(f, "Wandering search errors\n"); for (tnfn = tag->wandering_problems_base; tnfn; tnfn = tnfn->next) { if (tnfn->wandering_type!=wandering_type) continue; shrink_path_dirname(tnfn->found_path); fprintf(f, " - %s found in %s\n", tnfn->basename, tnfn->found_path); for (nfn = tnfn->not_found_base; nfn; nfn = nfn->next) { shrink_path_dirname(nfn->error_file->filename); fprintf(f, " %s (%d)\n", nfn->error_file->filename, nfn->count); } } } void wandering_found(struct top_tag_node *tag, const char * filename) { struct top_not_found_node * tnfn, *prev = NULL; char *b = basename(filename); char * p; for (tnfn = tag->wandering_base; tnfn; tnfn = tnfn->next) { if (strcmp(b, tnfn->basename) == 0) { /* * Here, we need to move the tree over to the * list of wandering problems found */ /* Copy just the dirname where we found it*/ if ((p = strrchr(filename, '/'))) { memset(tnfn->found_path, '\0', FILENAME_LENGTH); memcpy(tnfn->found_path, filename, p-filename); } if (prev) { prev->next = tnfn->next; } else { tag->wandering_base = tnfn->next; } tnfn->next = tag->wandering_problems_base; tag->wandering_problems_base = tnfn; return; } prev = tnfn; } } void wandering_add_error(struct top_tag_node * tag, struct error_file_node * tf) { unsigned int count = 0; struct top_not_found_node * tnfn, *prev = NULL, * next; struct not_found_node * nfn; char * b; b = basename(tf->filename); /* First, see if we have the basename somewhere */ for (tnfn = tag->wandering_base; tnfn; tnfn = tnfn->next) { if (strncmp(tnfn->basename, b, FILENAME_LENGTH) == 0) goto found_basename; count++; prev = tnfn; } tnfn = malloc(sizeof(*tnfn)); memset(tnfn, 0, sizeof(*tnfn)); strncpy(tnfn->basename, b, FILENAME_LENGTH); tnfn->next = NULL; if (prev) { prev->next = tnfn; } else { tag->wandering_base = tnfn; } if (count > MAX_WANDERING_LISTS) { next = ((struct top_not_found_node *)(tag->wandering_base))->next; not_found_free(tag->wandering_base); tag->wandering_base = next; } found_basename: /* now see if we have a reference for the full path name */ for (nfn = tnfn->not_found_base; nfn; nfn = nfn->next) { if (nfn->error_file == tf) { goto found_node; } } nfn = malloc(sizeof(*nfn)); memset(nfn, 0, sizeof(*nfn)); nfn->error_file = tf; nfn->next = tnfn->not_found_base; tnfn->not_found_base = nfn; found_node: nfn->count++; return; }