/* ** Load the record ID rid and up to N-1 closest descendants into ** the "ok" table. */ void compute_descendants(int rid, int N){ Bag seen; PQueue queue; Stmt ins; Stmt q; bag_init(&seen); pqueuex_init(&queue); bag_insert(&seen, rid); pqueuex_insert(&queue, rid, 0.0, 0); db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid"); while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){ db_bind_int(&ins, ":rid", rid); db_step(&ins); db_reset(&ins); db_bind_int(&q, ":rid", rid); while( db_step(&q)==SQLITE_ROW ){ int pid = db_column_int(&q, 0); double mtime = db_column_double(&q, 1); if( bag_insert(&seen, pid) ){ pqueuex_insert(&queue, pid, mtime, 0); } } db_reset(&q); } bag_clear(&seen); pqueuex_clear(&queue); db_finalize(&ins); db_finalize(&q); }
/* Find or create a record the value of a column and return the id */ DBint64 id_of_with_insert(DB *db, const char *table, const char *column, const char *value, int *inserted) { DBStatement *select, *insert; DBint64 id; char sql[256]; snprintf(sql, sizeof(sql), "select id from %s where %s = ?;", table, column); select = db_prep(db, sql); db_bind_text(select, 1, value); if (db_step(select) == DB_DONE) { snprintf(sql, sizeof(sql), "insert into %s (%s) values (?);", table, column); insert = db_prep(db, sql); db_bind_text(insert, 1, value); db_step(insert); id = db_last_insert_rowid(db); db_finalize(insert); *inserted = TRUE; } else { id = db_column_int64(select, 0); *inserted = FALSE; } db_finalize(select); return id; }
/* ** Compute up to N direct ancestors (merge ancestors do not count) ** for the check-in rid and put them in a table named "ancestor". ** Label each generation with consecutive integers going backwards ** in time such that rid has the smallest generation number and the oldest ** direct ancestor as the largest generation number. */ void compute_direct_ancestors(int rid, int N){ Stmt ins; Stmt q; int gen = 0; db_multi_exec( "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER UNIQUE NOT NULL," " generation INTEGER PRIMARY KEY);" "DELETE FROM ancestor;" "INSERT INTO ancestor VALUES(%d, 0);", rid ); db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)"); db_prepare(&q, "SELECT pid FROM plink" " WHERE cid=:rid AND isprim" ); while( (N--)>0 ){ db_bind_int(&q, ":rid", rid); if( db_step(&q)!=SQLITE_ROW ) break; rid = db_column_int(&q, 0); db_reset(&q); gen++; db_bind_int(&ins, ":rid", rid); db_bind_int(&ins, ":gen", gen); db_step(&ins); db_reset(&ins); } db_finalize(&ins); db_finalize(&q); }
/* ** Load the record ID rid and up to N-1 closest ancestors into ** the "ok" table. */ void compute_ancestors(int rid, int N, int directOnly){ Bag seen; PQueue queue; Stmt ins; Stmt q; bag_init(&seen); pqueuex_init(&queue); bag_insert(&seen, rid); pqueuex_insert(&queue, rid, 0.0, 0); db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); db_prepare(&q, "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid" " WHERE a.cid=:rid %s", directOnly ? " AND a.isprim" : "" ); while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){ db_bind_int(&ins, ":rid", rid); db_step(&ins); db_reset(&ins); db_bind_int(&q, ":rid", rid); while( db_step(&q)==SQLITE_ROW ){ int pid = db_column_int(&q, 0); double mtime = db_column_double(&q, 1); if( bag_insert(&seen, pid) ){ pqueuex_insert(&queue, pid, -mtime, 0); } } db_reset(&q); } bag_clear(&seen); pqueuex_clear(&queue); db_finalize(&ins); db_finalize(&q); }
/* ** Check to see if checkin "rid" is a leaf and either add it to the LEAF ** table if it is, or remove it if it is not. */ void leaf_check(int rid){ static Stmt checkIfLeaf; static Stmt addLeaf; static Stmt removeLeaf; int rc; db_static_prepare(&checkIfLeaf, "SELECT 1 FROM plink" " WHERE pid=:rid" " AND coalesce((SELECT value FROM tagxref" " WHERE tagid=%d AND rid=:rid),'trunk')" " == coalesce((SELECT value FROM tagxref" " WHERE tagid=%d AND rid=plink.cid),'trunk');", TAG_BRANCH, TAG_BRANCH ); db_bind_int(&checkIfLeaf, ":rid", rid); rc = db_step(&checkIfLeaf); db_reset(&checkIfLeaf); if( rc==SQLITE_ROW ){ db_static_prepare(&removeLeaf, "DELETE FROM leaf WHERE rid=:rid"); db_bind_int(&removeLeaf, ":rid", rid); db_step(&removeLeaf); db_reset(&removeLeaf); }else{ db_static_prepare(&addLeaf, "INSERT OR IGNORE INTO leaf VALUES(:rid)"); db_bind_int(&addLeaf, ":rid", rid); db_step(&addLeaf); db_reset(&addLeaf); } }
static void artist_query(bmdb_t *b, void *db) { sqlite3_stmt *stmt; int rc; int artist_id = atoi(b->b_query); rc = db_prepare(db, &stmt, "SELECT title " "FROM artist " "WHERE ds_id = 1 " "AND id = ?1"); if(rc != SQLITE_OK) return; sqlite3_bind_int(stmt, 1, artist_id); if(db_step(stmt) == SQLITE_ROW) { rstr_t *artist = db_rstr(stmt, 0); prop_set(b->b_metadata, "title", PROP_SET_RSTRING, artist); prop_t *p = prop_create_r(b->b_metadata, "artist_images"); metadata_bind_artistpics(p, artist); prop_ref_dec(p); rstr_release(artist); } sqlite3_finalize(stmt); rc = db_prepare(db, &stmt, "SELECT id,title " "FROM album " "WHERE ds_id = 1 " "AND artist_id = ?1"); if(rc != SQLITE_OK) return; sqlite3_bind_int(stmt, 1, artist_id); rstr_t *ct = rstr_alloc("album"); while((rc = db_step(stmt)) == SQLITE_ROW) { char url[PATH_MAX]; snprintf(url, sizeof(url), "library:album:%d", sqlite3_column_int(stmt, 0)); add_item(b, url, NULL, ct, (const char *)sqlite3_column_text(stmt, 1), 0, NULL, 0); } rstr_release(ct); sqlite3_finalize(stmt); }
/* ** Attempt to convert more full-text blobs into delta-blobs for ** storage efficiency. */ static void extra_deltification(void){ Stmt q; int topid, previd, rid; int prevfnid, fnid; db_begin_transaction(); db_prepare(&q, "SELECT rid FROM event, blob" " WHERE blob.rid=event.objid" " AND event.type='ci'" " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" " ORDER BY event.mtime DESC" ); topid = previd = 0; while( db_step(&q)==SQLITE_ROW ){ rid = db_column_int(&q, 0); if( topid==0 ){ topid = previd = rid; }else{ if( content_deltify(rid, previd, 0)==0 && previd!=topid ){ content_deltify(rid, topid, 0); } previd = rid; } } db_finalize(&q); db_prepare(&q, "SELECT blob.rid, mlink.fnid FROM blob, mlink, plink" " WHERE NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" " AND mlink.fid=blob.rid" " AND mlink.mid=plink.cid" " AND plink.cid=mlink.mid" " ORDER BY mlink.fnid, plink.mtime DESC" ); prevfnid = 0; while( db_step(&q)==SQLITE_ROW ){ rid = db_column_int(&q, 0); fnid = db_column_int(&q, 1); if( prevfnid!=fnid ){ prevfnid = fnid; topid = previd = rid; }else{ if( content_deltify(rid, previd, 0)==0 && previd!=topid ){ content_deltify(rid, topid, 0); } previd = rid; } } db_finalize(&q); db_end_transaction(0); }
/* ** Load a vfile from a record ID. */ void load_vfile_from_rid(int vid){ int rid, size; Stmt ins, ridq; Manifest *p; ManifestFile *pFile; if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){ return; } db_begin_transaction(); p = manifest_get(vid, CFTYPE_MANIFEST, 0); if( p==0 ) { db_end_transaction(1); return; } db_prepare(&ins, "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname) " " VALUES(:vid,:isexe,:islink,:id,:id,:name)"); db_prepare(&ridq, "SELECT rid,size FROM blob WHERE uuid=:uuid"); db_bind_int(&ins, ":vid", vid); manifest_file_rewind(p); while( (pFile = manifest_file_next(p,0))!=0 ){ if( pFile->zUuid==0 || uuid_is_shunned(pFile->zUuid) ) continue; db_bind_text(&ridq, ":uuid", pFile->zUuid); if( db_step(&ridq)==SQLITE_ROW ){ rid = db_column_int(&ridq, 0); size = db_column_int(&ridq, 1); }else{ rid = 0; size = 0; } db_reset(&ridq); if( rid==0 || size<0 ){ fossil_warning("content missing for %s", pFile->zName); continue; } db_bind_int(&ins, ":isexe", ( manifest_file_mperm(pFile)==PERM_EXE )); db_bind_int(&ins, ":id", rid); db_bind_text(&ins, ":name", pFile->zName); db_bind_int(&ins, ":islink", ( manifest_file_mperm(pFile)==PERM_LNK )); db_step(&ins); db_reset(&ins); } db_finalize(&ridq); db_finalize(&ins); manifest_destroy(p); db_end_transaction(0); }
/* ** fossil bundle ls BUNDLE ?OPTIONS? ** ** Display the content of a bundle in human-readable form. */ static void bundle_ls_cmd(void){ Stmt q; sqlite3_int64 sumSz = 0; sqlite3_int64 sumLen = 0; int bDetails = find_option("details","l",0)!=0; verify_all_options(); if( g.argc!=4 ) usage("ls BUNDLE ?OPTIONS?"); bundle_attach_file(g.argv[3], "b1", 0); db_prepare(&q, "SELECT bcname, bcvalue FROM bconfig" " WHERE typeof(bcvalue)='text'" " AND bcvalue NOT GLOB char(0x2a,0x0a,0x2a);" ); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%s: %s\n", db_column_text(&q,0), db_column_text(&q,1)); } db_finalize(&q); fossil_print("%.78c\n",'-'); if( bDetails ){ db_prepare(&q, "SELECT blobid, substr(uuid,1,10), coalesce(substr(delta,1,10),'')," " sz, length(data), notes" " FROM bblob" ); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%4d %10s %10s %8d %8d %s\n", db_column_int(&q,0), db_column_text(&q,1), db_column_text(&q,2), db_column_int(&q,3), db_column_int(&q,4), db_column_text(&q,5)); sumSz += db_column_int(&q,3); sumLen += db_column_int(&q,4); } db_finalize(&q); fossil_print("%27s %8lld %8lld\n", "Total:", sumSz, sumLen); }else{ db_prepare(&q, "SELECT substr(uuid,1,16), notes FROM bblob" ); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%16s %s\n", db_column_text(&q,0), db_column_text(&q,1)); } db_finalize(&q); } }
/* ** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them ** in sorted order in aField[]. ** ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and ** TICKETCHANGE tables exist, respectively. */ static void getAllTicketFields(void){ Stmt q; int i; static int once = 0; if( once ) return; once = 1; db_prepare(&q, "PRAGMA table_info(ticket)"); while( db_step(&q)==SQLITE_ROW ){ const char *zFieldName = db_column_text(&q, 1); haveTicket = 1; if( memcmp(zFieldName,"tkt_",4)==0 ){ if( strcmp(zFieldName, "tkt_ctime")==0 ) haveTicketCTime = 1; continue; } if( nField%10==0 ){ aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) ); } aField[nField].zName = mprintf("%s", zFieldName); aField[nField].mUsed = USEDBY_TICKET; nField++; } db_finalize(&q); db_prepare(&q, "PRAGMA table_info(ticketchng)"); while( db_step(&q)==SQLITE_ROW ){ const char *zFieldName = db_column_text(&q, 1); haveTicketChng = 1; if( memcmp(zFieldName,"tkt_",4)==0 ){ if( strcmp(zFieldName,"tkt_rid")==0 ) haveTicketChngRid = 1; continue; } if( (i = fieldId(zFieldName))>=0 ){ aField[i].mUsed |= USEDBY_TICKETCHNG; continue; } if( nField%10==0 ){ aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) ); } aField[nField].zName = mprintf("%s", zFieldName); aField[nField].mUsed = USEDBY_TICKETCHNG; nField++; } db_finalize(&q); qsort(aField, nField, sizeof(aField[0]), nameCmpr); for(i=0; i<nField; i++){ aField[i].zValue = ""; aField[i].zAppend = 0; } }
/* ** Query the database for all TICKET fields for the specific ** ticket whose name is given by the "name" CGI parameter. ** Load the values for all fields into the interpreter. ** ** Only load those fields which do not already exist as ** variables. ** ** Fields of the TICKET table that begin with "private_" are ** expanded using the db_reveal() function. If g.perm.RdAddr is ** true, then the db_reveal() function will decode the content ** using the CONCEALED table so that the content legable. ** Otherwise, db_reveal() is a no-op and the content remains ** obscured. */ static void initializeVariablesFromDb(void){ const char *zName; Stmt q; int i, n, size, j; zName = PD("name","-none-"); db_prepare(&q, "SELECT datetime(tkt_mtime,'localtime') AS tkt_datetime, *" " FROM ticket WHERE tkt_uuid GLOB '%q*'", zName); if( db_step(&q)==SQLITE_ROW ){ n = db_column_count(&q); for(i=0; i<n; i++){ const char *zVal = db_column_text(&q, i); const char *zName = db_column_name(&q, i); char *zRevealed = 0; if( zVal==0 ){ zVal = ""; }else if( strncmp(zName, "private_", 8)==0 ){ zVal = zRevealed = db_reveal(zVal); } for(j=0; j<nField; j++){ if( fossil_strcmp(azField[j],zName)==0 ){ azValue[j] = mprintf("%s", zVal); break; } } if( Th_Fetch(zName, &size)==0 ){ Th_Store(zName, zVal); } free(zRevealed); } }else{ db_finalize(&q); db_prepare(&q, "PRAGMA table_info(ticket)"); if( Th_Fetch("tkt_uuid",&size)==0 ){ Th_Store("tkt_uuid",zName); } while( db_step(&q)==SQLITE_ROW ){ const char *zField = db_column_text(&q, 1); if( Th_Fetch(zField, &size)==0 ){ Th_Store(zField, ""); } } if( Th_Fetch("tkt_datetime",&size)==0 ){ Th_Store("tkt_datetime",""); } } db_finalize(&q); }
/* ** Compute an aggregate MD5 checksum over the repository image of every ** file in vid. The file names are part of the checksum. The resulting ** checksum is suitable for the R-card of a manifest. ** ** Return the resulting checksum in blob pOut. */ void vfile_aggregate_checksum_repository(int vid, Blob *pOut){ Blob file; Stmt q; char zBuf[100]; db_must_be_within_tree(); db_prepare(&q, "SELECT pathname, origname, rid, file_is_selected(id)" " FROM vfile" " WHERE (NOT deleted OR NOT file_is_selected(id))" " AND rid>0 AND vid=%d" " ORDER BY pathname /*scan*/", vid); blob_zero(&file); md5sum_init(); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); const char *zOrigName = db_column_text(&q, 1); int rid = db_column_int(&q, 2); int isSelected = db_column_int(&q, 3); if( zOrigName && !isSelected ) zName = zOrigName; md5sum_step_text(zName, -1); content_get(rid, &file); sqlite3_snprintf(sizeof(zBuf), zBuf, " %d\n", blob_size(&file)); md5sum_step_text(zBuf, -1); /*printf("%s %s %s",md5sum_current_state(),zName,zBuf); fflush(stdout);*/ md5sum_step_blob(&file); blob_reset(&file); } db_finalize(&q); md5sum_finish(pOut); }
/* ** Query the database for all TICKET fields for the specific ** ticket whose name is given by the "name" CGI parameter. ** Load the values for all fields into the interpreter. ** ** Only load those fields which do not already exist as ** variables. ** ** Fields of the TICKET table that begin with "private_" are ** expanded using the db_reveal() function. If g.perm.RdAddr is ** true, then the db_reveal() function will decode the content ** using the CONCEALED table so that the content legible. ** Otherwise, db_reveal() is a no-op and the content remains ** obscured. */ static void initializeVariablesFromDb(void){ const char *zName; Stmt q; int i, n, size, j; zName = PD("name","-none-"); db_prepare(&q, "SELECT datetime(tkt_mtime%s) AS tkt_datetime, *" " FROM ticket WHERE tkt_uuid GLOB '%q*'", timeline_utc(), zName); if( db_step(&q)==SQLITE_ROW ){ n = db_column_count(&q); for(i=0; i<n; i++){ const char *zVal = db_column_text(&q, i); const char *zName = db_column_name(&q, i); char *zRevealed = 0; if( zVal==0 ){ zVal = ""; }else if( strncmp(zName, "private_", 8)==0 ){ zVal = zRevealed = db_reveal(zVal); } if( (j = fieldId(zName))>=0 ){ aField[j].zValue = mprintf("%s", zVal); }else if( memcmp(zName, "tkt_", 4)==0 && Th_Fetch(zName, &size)==0 ){ Th_Store(zName, zVal); } free(zRevealed); } } db_finalize(&q); for(i=0; i<nField; i++){ if( Th_Fetch(aField[i].zName, &size)==0 ){ Th_Store(aField[i].zName, aField[i].zValue); } } }
/* ** Implement the "fossil bundle append BUNDLE FILE..." command. Add ** the named files into the BUNDLE. Create the BUNDLE if it does not ** alraedy exist. */ static void bundle_append_cmd(void){ Blob content, hash; int i; Stmt q; verify_all_options(); bundle_attach_file(g.argv[3], "b1", 1); db_prepare(&q, "INSERT INTO bblob(blobid, uuid, sz, delta, data, notes) " "VALUES(NULL, $uuid, $sz, NULL, $data, $filename)"); db_begin_transaction(); for(i=4; i<g.argc; i++){ int sz; blob_read_from_file(&content, g.argv[i]); sz = blob_size(&content); sha1sum_blob(&content, &hash); blob_compress(&content, &content); db_bind_text(&q, "$uuid", blob_str(&hash)); db_bind_int(&q, "$sz", sz); db_bind_blob(&q, "$data", &content); db_bind_text(&q, "$filename", g.argv[i]); db_step(&q); db_reset(&q); blob_reset(&content); blob_reset(&hash); } db_end_transaction(0); db_finalize(&q); }
static void artists_query(bmdb_t *b, void *db) { sqlite3_stmt *stmt; int rc = db_prepare(db, &stmt, "SELECT artist.id, artist.title " "FROM artist,item,audioitem " "WHERE audioitem.item_id = item.id " "AND audioitem.artist_id = artist.id " "AND item.url like ?1 " "AND audioitem.ds_id = 1 " "GROUP by artist_id"); if(rc != SQLITE_OK) return; char q[PATH_MAX]; db_escape_path_query(q, sizeof(q), b->b_query); sqlite3_bind_text(stmt, 1, q, -1, SQLITE_STATIC); rstr_t *ct = rstr_alloc("artist"); while((rc = db_step(stmt)) == SQLITE_ROW) { char url[PATH_MAX]; snprintf(url, sizeof(url), "library:artist:%d", sqlite3_column_int(stmt, 0)); add_item(b, url, NULL, ct, (const char *)sqlite3_column_text(stmt, 1), 0, NULL, 0); } rstr_release(ct); sqlite3_finalize(stmt); }
/* ** Print information about a particular check-in. */ void print_checkin_description(int rid, int indent, const char *zLabel){ Stmt q; db_prepare(&q, "SELECT datetime(mtime%s)," " coalesce(euser,user), coalesce(ecomment,comment)," " (SELECT uuid FROM blob WHERE rid=%d)," " (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref" " WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid" " AND tagxref.rid=%d AND tagxref.tagtype>0)" " FROM event WHERE objid=%d", timeline_utc(), rid, rid, rid); if( db_step(&q)==SQLITE_ROW ){ const char *zTagList = db_column_text(&q, 4); char *zCom; if( zTagList && zTagList[0] ){ zCom = mprintf("%s (%s)", db_column_text(&q, 2), zTagList); }else{ zCom = mprintf("%s", db_column_text(&q,2)); } fossil_print("%-*s [%S] by %s on %s\n%*s", indent-1, zLabel, db_column_text(&q, 3), db_column_text(&q, 1), db_column_text(&q, 0), indent, ""); comment_print(zCom, db_column_text(&q,2), indent, -1, g.comFmtFlags); fossil_free(zCom); } db_finalize(&q); }
static void video_query(bmdb_t *b, void *db) { sqlite3_stmt *stmt; int rc = db_prepare(db, &stmt, "SELECT i.url, p.url, i.contenttype " "FROM item AS i, item AS p " "WHERE i.url LIKE ?1 " "AND (i.contenttype == 5 OR i.contenttype == 7) " "AND i.parent = p.id" ); if(rc != SQLITE_OK) return; char q[PATH_MAX]; db_escape_path_query(q, sizeof(q), b->b_query); sqlite3_bind_text(stmt, 1, q, -1, SQLITE_STATIC); while((rc = db_step(stmt)) == SQLITE_ROW) { const char *url = (const char *)sqlite3_column_text(stmt, 0); const char *parent = (const char *)sqlite3_column_text(stmt, 1); rstr_t *ct = rstr_alloc(content2type(sqlite3_column_int(stmt, 2))); add_item(b, url, parent, ct, NULL, 0, NULL, 0); rstr_release(ct); } sqlite3_finalize(stmt); }
/* ** Check content that was received with rcvid and return true if any ** fork was created. */ int fossil_any_has_fork(int rcvid){ static Stmt q; int fForkSeen = 0; if( rcvid==0 ) return 0; db_static_prepare(&q, " SELECT pid FROM plink WHERE pid>0 AND isprim" " AND cid IN (SELECT blob.rid FROM blob" " WHERE rcvid=:rcvid)"); db_bind_int(&q, ":rcvid", rcvid); while( !fForkSeen && db_step(&q)==SQLITE_ROW ){ int pid = db_column_int(&q, 0); if( count_nonbranch_children(pid)>1 ){ compute_leaves(pid,1); if( db_int(0, "SELECT count(*) FROM leaves")>1 ){ int rid = db_int(0, "SELECT rid FROM leaves, event" " WHERE event.objid=leaves.rid" " ORDER BY event.mtime DESC LIMIT 1"); fForkSeen = fossil_find_nearest_fork(rid, db_open_local(0))!=0; } } } db_finalize(&q); return fForkSeen; }
/* ** COMMAND: branch ** ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS? ** ** Run various subcommands to manage branches of the open repository or ** of the repository identified by the -R or --repository option. ** ** %fossil branch new BRANCH-NAME BASIS ?--bgcolor COLOR? ?--private? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** You can optionally give the branch a default color. The ** --private option makes the branch private. ** ** %fossil branch list ?-all | --closed? ** %fossil branch ls ?-all | --closed? ** ** List all branches. Use --all or --closed to list all branches ** or closed branches. The default is to show only open branches. ** ** Options: ** -R|--repository FILE Run commands on repository FILE */ void branch_cmd(void){ int n; const char *zCmd = "list"; db_find_and_open_repository(0, 0); if( g.argc<2 ){ usage("new|list|ls ..."); } if( g.argc>=3 ) zCmd = g.argv[2]; n = strlen(zCmd); if( strncmp(zCmd,"new",n)==0 ){ branch_new(); }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ Stmt q; int vid; char *zCurrent = 0; int showAll = find_option("all",0,0)!=0; int showClosed = find_option("closed",0,0)!=0; if( g.localOpen ){ vid = db_lget_int("checkout", 0); zCurrent = db_text(0, "SELECT value FROM tagxref" " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); } branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); while( db_step(&q)==SQLITE_ROW ){ const char *zBr = db_column_text(&q, 0); int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); } db_finalize(&q); }else{ fossil_panic("branch subcommand should be one of: " "new list ls"); } }
/* ** WEBPAGE: /taglist */ void taglist_page(void){ Stmt q; login_check_credentials(); if( !g.perm.Read ){ login_needed(); } login_anonymous_available(); style_header("Tags"); style_submenu_element("Timeline", "Timeline", "tagtimeline"); cgi_printf("<h2>Non-propagating tags:</h2>\n"); db_prepare(&q, "SELECT substr(tagname,5)" " FROM tag" " WHERE EXISTS(SELECT 1 FROM tagxref" " WHERE tagid=tag.tagid" " AND tagtype=1)" " AND tagname GLOB 'sym-*'" " ORDER BY tagname" ); cgi_printf("<ul>\n"); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); if( g.perm.Hyperlink ){ cgi_printf("<li>%z\n" "%h</a></li>\n",(xhref("class='taglink'","%R/timeline?t=%T",zName)),(zName)); }else{ cgi_printf("<li><span class=\"tagDsp\">%h</span></li>\n",(zName)); } } cgi_printf("</ul>\n"); db_finalize(&q); style_footer(); }
void deserialize_pms_fe(sqlite3* db, FeatureExtractionParams & pms_fe, int64_t & id) { sqlite3_stmt *read; db_prepare(db, read, boost::format( "select detector_type, extractor_type, descriptor_type, " "threshold, min_features, max_features, n_features, scale_factor, octaves " "from pms_fe where id=%d;") % id); db_step(read, SQLITE_ROW); int c = 0; pms_fe.detector_type = string((const char*) sqlite3_column_text(read, c++)); pms_fe.extractor_type = string((const char*) sqlite3_column_text(read, c++)); pms_fe.descriptor_type = string((const char*) sqlite3_column_text(read, c++)); pms_fe.detector_params["threshold"] = sqlite3_column_double(read, c++); pms_fe.detector_params["min_features"] = sqlite3_column_int(read, c++); pms_fe.detector_params["max_features"] = sqlite3_column_int(read, c++); pms_fe.detector_params["n_features"] = sqlite3_column_int(read, c++); pms_fe.extractor_params["scale_factor"] = sqlite3_column_double(read, c++); pms_fe.extractor_params["octaves"] = sqlite3_column_int(read, c++); // Workaround for issue with feature_extraction.cpp in tod_training pms_fe.extractor_params["n_features"] = pms_fe.detector_params["n_features"]; pms_fe.detector_params["scale_factor"] = pms_fe.extractor_params["scale_factor"]; pms_fe.detector_params["octaves"] = pms_fe.extractor_params["octaves"]; sqlite3_finalize(read); }
/* ** Obtain a list of all fields of the TICKET table. Put them ** in sorted order in azField[]. ** ** Also allocate space for azValue[] and azAppend[] and initialize ** all the values there to zero. */ static void getAllTicketFields(void){ Stmt q; int i; if( nField>0 ) return; db_prepare(&q, "PRAGMA table_info(ticket)"); while( db_step(&q)==SQLITE_ROW ){ const char *zField = db_column_text(&q, 1); if( strncmp(zField,"tkt_",4)==0 ) continue; if( nField%10==0 ){ azField = realloc(azField, sizeof(azField)*3*(nField+10) ); if( azField==0 ){ fossil_fatal("out of memory"); } } azField[nField] = mprintf("%s", zField); nField++; } db_finalize(&q); qsort(azField, nField, sizeof(azField[0]), nameCmpr); azAppend = &azField[nField]; memset(azAppend, 0, sizeof(azAppend[0])*nField); azValue = &azAppend[nField]; for(i=0; i<nField; i++){ azValue[i] = ""; } }
/* ** Rebuild an entire entry in the TICKET table */ void ticket_rebuild_entry(const char *zTktUuid){ char *zTag = mprintf("tkt-%s", zTktUuid); int tagid = tag_findid(zTag, 1); Stmt q; Manifest *pTicket; int tktid; int createFlag = 1; fossil_free(zTag); getAllTicketFields(); if( haveTicket==0 ) return; tktid = db_int(0, "SELECT tkt_id FROM ticket WHERE tkt_uuid=%Q", zTktUuid); if( haveTicketChng ){ db_multi_exec("DELETE FROM ticketchng WHERE tkt_id=%d;", tktid); } db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid); tktid = 0; db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid); while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ tktid = ticket_insert(pTicket, rid, tktid); manifest_ticket_event(rid, pTicket, createFlag, tagid); manifest_destroy(pTicket); } createFlag = 0; } db_finalize(&q); }
/* ** Return the RID that is the "root" of the branch that contains ** check-in "rid" if inBranch==0 or the first check-in in the branch ** if inBranch==1. */ int start_of_branch(int rid, int inBranch){ Stmt q; int rc; char *zBr; zBr = db_text("trunk","SELECT value FROM tagxref" " WHERE rid=%d AND tagid=%d" " AND tagtype>0", rid, TAG_BRANCH); db_prepare(&q, "SELECT pid, EXISTS(SELECT 1 FROM tagxref" " WHERE tagid=%d AND tagtype>0" " AND value=%Q AND rid=plink.pid)" " FROM plink" " WHERE cid=:cid AND isprim", TAG_BRANCH, zBr ); fossil_free(zBr); do{ db_reset(&q); db_bind_int(&q, ":cid", rid); rc = db_step(&q); if( rc!=SQLITE_ROW ) break; if( inBranch && db_column_int(&q,1)==0 ) break; rid = db_column_int(&q, 0); }while( db_column_int(&q, 1)==1 && rid>0 ); db_finalize(&q); return rid; }
/* ** Compute the "mtime" of the file given whose blob.rid is "fid" that ** is part of check-in "vid". The mtime will be the mtime on vid or ** some ancestor of vid where fid first appears. */ int mtime_of_manifest_file( int vid, /* The check-in that contains fid */ int fid, /* The id of the file whose check-in time is sought */ i64 *pMTime /* Write result here */ ){ static int prevVid = -1; static Stmt q; if( prevVid!=vid ){ prevVid = vid; db_multi_exec("DROP TABLE IF EXISTS temp.ok;" "CREATE TEMP TABLE ok(x INTEGER PRIMARY KEY);"); compute_ancestors(vid, 100000000, 1); } db_static_prepare(&q, "SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event" " WHERE mlink.mid=event.objid" " AND +mlink.mid IN ok" " AND mlink.fid=:fid"); db_bind_int(&q, ":fid", fid); if( db_step(&q)!=SQLITE_ROW ){ db_reset(&q); return 1; } *pMTime = db_column_int64(&q, 0); db_reset(&q); return 0; }
/* ** WEBPAGE: ambiguous ** URL: /ambiguous?name=UUID&src=WEBPAGE ** ** The UUID given by the name parameter is ambiguous. Display a page ** that shows all possible choices and let the user select between them. */ void ambiguous_page(void){ Stmt q; const char *zName = P("name"); const char *zSrc = P("src"); char *z; if( zName==0 || zName[0]==0 || zSrc==0 || zSrc[0]==0 ){ fossil_redirect_home(); } style_header("Ambiguous Artifact ID"); cgi_printf("<p>The artifact id <b>%h</b> is ambiguous and might\n" "mean any of the following:\n" "<ol>\n",(zName)); z = mprintf("%s", zName); canonical16(z, strlen(z)); db_prepare(&q, "SELECT uuid, rid FROM blob WHERE uuid GLOB '%q*'", z); while( db_step(&q)==SQLITE_ROW ){ const char *zUuid = db_column_text(&q, 0); int rid = db_column_int(&q, 1); cgi_printf("<li><p><a href=\"%s/%T/%S\">\n" "%S</a> -\n",(g.zTop),(zSrc),(zUuid),(zUuid)); object_description(rid, 0, 0); cgi_printf("</p></li>\n"); } cgi_printf("</ol>\n"); style_footer(); }
void Paramset::deserialize(sqlite3* db) { sqlite3_stmt *read; db_prepare(db, read, boost::format( "select train_pms_fe_id, recog_pms_fe_id, " "detect_pms_match_id, detect_pms_guess_id, " "refine_pms_match_id, refine_pms_guess_id, " "recog_pms_clutseg_id from paramset where id=%d;") % id); db_step(read, SQLITE_ROW); int c = 0; train_pms_fe_id = sqlite3_column_int64(read, c++); recog_pms_fe_id = sqlite3_column_int64(read, c++); detect_pms_match_id = sqlite3_column_int64(read, c++); detect_pms_guess_id = sqlite3_column_int64(read, c++); refine_pms_match_id = sqlite3_column_int64(read, c++); refine_pms_guess_id = sqlite3_column_int64(read, c++); pms_clutseg.id = sqlite3_column_int64(read, c++); sqlite3_finalize(read); deserialize_pms_fe(db, train_pms_fe, train_pms_fe_id); deserialize_pms_fe(db, recog_pms_fe, recog_pms_fe_id); deserialize_pms_match(db, detect_pms_match, detect_pms_match_id); deserialize_pms_guess(db, detect_pms_guess, detect_pms_guess_id); deserialize_pms_match(db, refine_pms_match, refine_pms_match_id); deserialize_pms_guess(db, refine_pms_guess, refine_pms_guess_id); pms_clutseg.deserialize(db); }
/* ** COMMAND: test-orphans ** ** Search the repository for orphaned artifacts */ void test_orphans(void){ Stmt q; int cnt = 0; db_find_and_open_repository(0, 0); db_multi_exec( "CREATE TEMP TABLE used(id INTEGER PRIMARY KEY ON CONFLICT IGNORE);" "INSERT INTO used SELECT mid FROM mlink;" /* Manifests */ "INSERT INTO used SELECT fid FROM mlink;" /* Files */ "INSERT INTO used SELECT srcid FROM tagxref WHERE srcid>0;" /* Tags */ "INSERT INTO used SELECT rid FROM tagxref;" /* Wiki & tickets */ "INSERT INTO used SELECT rid FROM attachment JOIN blob ON src=uuid;" "INSERT INTO used SELECT attachid FROM attachment;" "INSERT INTO used SELECT objid FROM event;" ); db_prepare(&q, "SELECT rid, uuid, size FROM blob WHERE rid NOT IN used"); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%7d %s size: %d\n", db_column_int(&q, 0), db_column_text(&q, 1), db_column_int(&q,2)); cnt++; } db_finalize(&q); fossil_print("%d orphans\n", cnt); }
/* This is a helper routine for test-artifacts. ** ** Check to see that artifact zUuid exists in the repository. If it does, ** return 0. If it does not, generate an error message and return 1. */ static int check_exists( const char *zUuid, /* The artifact we are checking for */ unsigned flags, /* Flags */ Manifest *p, /* The control artifact that references zUuid */ const char *zRole, /* Role of zUuid in p */ const char *zDetail /* Additional information, such as a filename */ ){ static Stmt q; int rc = 0; db_static_prepare(&q, "SELECT size FROM blob WHERE uuid=:uuid"); if( zUuid==0 || zUuid[0]==0 ) return 0; db_bind_text(&q, ":uuid", zUuid); if( db_step(&q)==SQLITE_ROW ){ int size = db_column_int(&q, 0); if( size<0 ) rc = 2; }else{ rc = 1; } db_reset(&q); if( rc ){ const char *zCFType = "control artifact"; char *zSrc; char *zDate; char *zErrType = "MISSING"; if( db_exists("SELECT 1 FROM shun WHERE uuid=%Q", zUuid) ){ if( flags & MISSING_SHUNNED ) return 0; zErrType = "SHUNNED"; } switch( p->type ){ case CFTYPE_MANIFEST: zCFType = "check-in"; break; case CFTYPE_CLUSTER: zCFType = "cluster"; break; case CFTYPE_CONTROL: zCFType = "tag"; break; case CFTYPE_WIKI: zCFType = "wiki"; break; case CFTYPE_TICKET: zCFType = "ticket"; break; case CFTYPE_ATTACHMENT: zCFType = "attachment"; break; case CFTYPE_EVENT: zCFType = "event"; break; } zSrc = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid); if( p->rDate>0.0 ){ zDate = db_text(0, "SELECT datetime(%.17g)", p->rDate); }else{ zDate = db_text(0, "SELECT datetime(rcvfrom.mtime)" " FROM blob, rcvfrom" " WHERE blob.rcvid=rcvfrom.rcvid" " AND blob.rid=%d", p->rid); } fossil_print("%s: %s\n %s %s %S (%d) %s\n", zErrType, zUuid, zRole, zCFType, zSrc, p->rid, zDate); if( zDetail && zDetail[0] ){ fossil_print(" %s\n", zDetail); } fossil_free(zSrc); fossil_free(zDate); rc = 1; } return rc; }
void ClutsegParams::deserialize(sqlite3* db) { sqlite3_stmt *read; db_prepare(db, read, boost::format("select accept_threshold, ranking from pms_clutseg where id=%d;") % id); db_step(read, SQLITE_ROW); accept_threshold = sqlite3_column_double(read, 0); ranking = string((const char*) sqlite3_column_text(read, 1)); sqlite3_finalize(read); }