/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* Copyright 2013-2021 Stephan Beal (https://wanderinghorse.net). Derived heavily from previous work: Copyright (c) 2013 D. Richard Hipp (https://www.hwaci.com/drh/) This program is free software; you can redistribute it and/or modify it under the terms of the Simplified BSD License (also known as the "2-Clause License" or "FreeBSD License".) 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. ***************************************************************************** A test/demo app for doing mass parsing tests on all artifacts in a repository. */ #include "fossil-scm/fossil-cli.h" /* Fossil App mini-framework */ #include "fossil-scm/fossil-internal.h" #include #ifndef _WIN32 #include /*isatty()*/ #endif static struct App_{ int checkRCard; int failFast; int crosslink; int quiet; const char * eventTypes; } App = { 0/*checkRCard*/, 0/*failFast*/, 0/*crosslink*/, 0/*quiet*/, 0/*eventTypes*/ }; static int my_xlink_f(fsl_deck * d, void * state){ if(fcli.verbose){ FCLI_VN(1,("Crosslinking rid %"FSL_ID_T_PFMT", uuid %s ...\n", d->rid, d->uuid)); }else if(!App.quiet){ f_out("x"); } return 0; } static int test_parse_all(void){ fsl_buffer content = fsl_buffer_empty; fsl_deck mf = fsl_deck_empty; fsl_cx * const f = fcli.f; fsl_stmt q1 = fsl_stmt_empty; fsl_db * const db = fsl_cx_db_repo(f); int rc = 0; int counter = 0; int errCount = 0; int counters[FSL_SATYPE_count] = {0,0,0,0,0,0,0,0,0}; if(!db){ return fsl_cx_err_set(f, FSL_RC_MISUSE, "This app requires a repository db."); } if(App.crosslink){ rc = fsl_xlink_listener( f, "parseparty", my_xlink_f, 0 ); if(!rc) rc = fsl_crosslink_begin(f); if(rc) goto end; } #define RC if(rc) goto end if(App.eventTypes && *App.eventTypes){ fsl_buffer q = fsl_buffer_empty; const char * c = App.eventTypes; fsl_buffer_append(&q, "SELECT e.objid, b.uuid FROM event e, blob b " "WHERE e.objid=b.rid AND type in ", -1); for(; *c; ++c){ const char * eType = 0; switch(*c){ case 'c': eType = "ci"; break; case 'g': eType = "g"; break; case 't': eType = "t"; break; case 'n': eType = "e"; break; case 'w': eType = "w"; break; case 'f': eType = "f"; break; default: fsl_cx_err_set(f, FSL_RC_MISUSE, "Unknown --types value '%c'.", *c); fsl_buffer_clear(&q); goto end; } fsl_buffer_append(&q, (c==App.eventTypes ? "(" : ","), 1); fsl_buffer_appendf(&q, "%Q", eType); } fsl_buffer_append(&q, ") ORDER BY mtime", -1); FCLI_V(("Query=%b\n", &q)); rc = fsl_db_prepare(db, &q1, fsl_buffer_cstr(&q)); fsl_buffer_clear(&q); }else{ rc = fsl_db_prepare(db, &q1, "SELECT e.objid, b.uuid FROM event e, blob b " "WHERE e.objid=b.rid ORDER BY RANDOM()"); } if(rc){ fsl_cx_uplift_db_error(f, db); goto end; } f_out("Here we go...\n"); mf.f = f; while(FSL_RC_STEP_ROW==fsl_stmt_step(&q1)){ fsl_id_t const rid = fsl_stmt_g_id(&q1, 0); const char * zUuid = fsl_stmt_g_text(&q1, 1, 0); const char * lineBreak = !fcli.verbose ? "\n" : ""; assert(rid>0); fsl_buffer_reset(&content); rc = fsl_content_get(f, rid, &content); RC; fsl_deck_clean(&mf); assert(mf.f); rc = fsl_deck_parse(&mf, &content); if(!fcli.verbose && !App.quiet){ f_out("."); fflush(stdout); } if(rc){ ++errCount; f_out("%sparse-offending artifact: %d / %s\n", lineBreak, (int)rid, zUuid); if(App.failFast){ goto end; } fcli_err_report(1); continue; } assert(mf.rid); assert(mf.uuid); assert(mf.type>=0 && mf.type