Fossil SCM

Add the whatis() SQL function for use in debugging.

drh 2026-05-26 18:13 UTC pinned-forum-posts
Commit db8c6f909d43c5df9ccdbb15dff6cf3799704fb06725d55f27b50805e3afa5f8
+1 -1
--- src/bundle.c
+++ src/bundle.c
@@ -660,11 +660,11 @@
660660
int n = 0;
661661
db_prepare(&q,
662662
"SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
663663
);
664664
while( db_step(&q)==SQLITE_ROW ){
665
- whatis_rid(db_column_int(&q,0),0);
665
+ whatis_rid(db_column_int(&q,0),0,0);
666666
fossil_print("%.78c\n", '-');
667667
n++;
668668
}
669669
db_finalize(&q);
670670
if( n>0 ){
671671
--- src/bundle.c
+++ src/bundle.c
@@ -660,11 +660,11 @@
660 int n = 0;
661 db_prepare(&q,
662 "SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
663 );
664 while( db_step(&q)==SQLITE_ROW ){
665 whatis_rid(db_column_int(&q,0),0);
666 fossil_print("%.78c\n", '-');
667 n++;
668 }
669 db_finalize(&q);
670 if( n>0 ){
671
--- src/bundle.c
+++ src/bundle.c
@@ -660,11 +660,11 @@
660 int n = 0;
661 db_prepare(&q,
662 "SELECT cid FROM plink WHERE pid IN ok AND cid NOT IN ok"
663 );
664 while( db_step(&q)==SQLITE_ROW ){
665 whatis_rid(db_column_int(&q,0),0,0);
666 fossil_print("%.78c\n", '-');
667 n++;
668 }
669 db_finalize(&q);
670 if( n>0 ){
671
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -164,11 +164,11 @@
164164
zRevision, &fname, filename_collation());
165165
if( rid==0 ) {
166166
fossil_fatal("file not found for revision %s: %s",
167167
zRevision, blob_str(&fname));
168168
}
169
- whatis_rid(rid,whatisFlags);
169
+ whatis_rid(rid,whatisFlags,0);
170170
blob_reset(&fname);
171171
}else{
172172
Blob line;
173173
Stmt q;
174174
Blob fname;
175175
--- src/finfo.c
+++ src/finfo.c
@@ -164,11 +164,11 @@
164 zRevision, &fname, filename_collation());
165 if( rid==0 ) {
166 fossil_fatal("file not found for revision %s: %s",
167 zRevision, blob_str(&fname));
168 }
169 whatis_rid(rid,whatisFlags);
170 blob_reset(&fname);
171 }else{
172 Blob line;
173 Stmt q;
174 Blob fname;
175
--- src/finfo.c
+++ src/finfo.c
@@ -164,11 +164,11 @@
164 zRevision, &fname, filename_collation());
165 if( rid==0 ) {
166 fossil_fatal("file not found for revision %s: %s",
167 zRevision, blob_str(&fname));
168 }
169 whatis_rid(rid,whatisFlags,0);
170 blob_reset(&fname);
171 }else{
172 Blob line;
173 Stmt q;
174 Blob fname;
175
+197 -56
--- src/name.c
+++ src/name.c
@@ -1143,10 +1143,40 @@
11431143
case CFTYPE_CONTROL: zType = "Tag-change"; break;
11441144
default: break;
11451145
}
11461146
return zType;
11471147
}
1148
+
1149
+/*
1150
+** This is the output routine for whatis_rid(). If pOut is NULL
1151
+** then write zKey and zValue on fossil_print(). But if pOut is
1152
+** not NULL, append the key and value as a term of a JSON object.
1153
+*/
1154
+static void whatis_line(
1155
+ sqlite3_str *pOut,
1156
+ const char *zKey,
1157
+ const char *zValue,
1158
+ ...
1159
+){
1160
+ char *zArg;
1161
+ va_list ap;
1162
+ va_start(ap, zValue);
1163
+ zArg = sqlite3_vmprintf(zValue,ap);
1164
+ va_end(ap);
1165
+ if( pOut ){
1166
+ int n = sqlite3_str_length(pOut);
1167
+ if( n>1 && sqlite3_str_value(pOut)[n-1]!='{' ){
1168
+ sqlite3_str_append(pOut, ",", 1);
1169
+ }
1170
+ sqlite3_str_appendf(pOut, "%J:%J", zKey, zArg);
1171
+ }else{
1172
+ int n = 11 - (int)strlen(zKey);
1173
+ if( n<=0 ) n = 0;
1174
+ fossil_print("%s:%*s%s\n",zKey,n,"",zArg);
1175
+ }
1176
+ sqlite3_free(zArg);
1177
+}
11481178
11491179
/*
11501180
** Flag values for whatis_rid().
11511181
*/
11521182
#if INTERFACE
@@ -1153,18 +1183,25 @@
11531183
#define WHATIS_VERBOSE 0x01 /* Extra output */
11541184
#define WHATIS_BRIEF 0x02 /* Omit unnecessary output */
11551185
#define WHATIS_REPO 0x04 /* Show repository name */
11561186
#define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */
11571187
#define WHATIS_HASHONLY 0x10 /* Show only the hash */
1188
+#define WHATIS_JSON 0x20 /* Render as JSON */
11581189
#endif
11591190
11601191
/*
1161
-** Generate a description of artifact "rid"
1192
+** Generate a description of artifact "rid".
1193
+**
1194
+** Send results to stdout using fossil_print() if pOut==0 or if
1195
+** WHATIS_HASHONLY is set. But without WHATIS_HASHONLY and if
1196
+** pOut!=0, then write a JSON description of the object into pOut.
11621197
*/
1163
-void whatis_rid(int rid, int flags){
1198
+void whatis_rid(int rid, int flags, sqlite3_str *pOut){
11641199
Stmt q;
11651200
int cnt;
1201
+
1202
+ if( pOut ) sqlite3_str_append(pOut, "{", 1);
11661203
11671204
/* Basic information about the object. */
11681205
db_prepare(&q,
11691206
"SELECT uuid, size, datetime(mtime,toLocal()), ipaddr"
11701207
" FROM blob, rcvfrom"
@@ -1173,18 +1210,18 @@
11731210
rid);
11741211
if( db_step(&q)==SQLITE_ROW ){
11751212
if( flags & WHATIS_HASHONLY ){
11761213
fossil_print("%s\n", db_column_text(&q,0));
11771214
}else if( flags & WHATIS_VERBOSE ){
1178
- fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
1179
- fossil_print("size: %d bytes\n", db_column_int(&q,1));
1180
- fossil_print("received: %s from %s\n",
1215
+ whatis_line(pOut, "artifact", "%s (%d)", db_column_text(&q,0), rid);
1216
+ whatis_line(pOut, "size", "%d bytes", db_column_int(&q,1));
1217
+ whatis_line(pOut, "received", "%s from %s",
11811218
db_column_text(&q, 2),
11821219
db_column_text(&q, 3));
11831220
}else{
1184
- fossil_print("artifact: %s\n", db_column_text(&q,0));
1185
- fossil_print("size: %d bytes\n", db_column_int(&q,1));
1221
+ whatis_line(pOut, "artifact","%s", db_column_text(&q,0));
1222
+ whatis_line(pOut, "size", "%d bytes", db_column_int(&q,1));
11861223
}
11871224
}
11881225
db_finalize(&q);
11891226
if( flags & WHATIS_HASHONLY ) return;
11901227
@@ -1198,14 +1235,27 @@
11981235
" ORDER BY 1",
11991236
rid
12001237
);
12011238
cnt = 0;
12021239
while( db_step(&q)==SQLITE_ROW ){
1203
- const char *zPrefix = cnt++ ? ", " : "tags: ";
1204
- fossil_print("%s%s", zPrefix, db_column_text(&q,0));
1240
+ const char *zTag = (const char*)db_column_text(&q,0);
1241
+ if( pOut ){
1242
+ const char *zSep = cnt==0 ? ",tags:[" : ",";
1243
+ sqlite3_str_appendf(pOut, "%s%J", zSep, zTag);
1244
+ }else{
1245
+ const char *zPrefix = cnt++ ? ", " : "tags: ";
1246
+ fossil_print("%s%s", zPrefix, db_column_text(&q,0));
1247
+ }
1248
+ cnt++;
12051249
}
1206
- if( cnt ) fossil_print("\n");
1250
+ if( cnt ){
1251
+ if( pOut ){
1252
+ sqlite3_str_append(pOut, "]", 1);
1253
+ }else{
1254
+ fossil_print("\n");
1255
+ }
1256
+ }
12071257
db_finalize(&q);
12081258
12091259
/* Report any HIDDEN, PRIVATE, CLUSTER, or CLOSED tags on this artifact */
12101260
db_prepare(&q,
12111261
"SELECT tagname"
@@ -1215,14 +1265,27 @@
12151265
" ORDER BY 1",
12161266
rid
12171267
);
12181268
cnt = 0;
12191269
while( db_step(&q)==SQLITE_ROW ){
1220
- const char *zPrefix = cnt++ ? ", " : "raw-tags: ";
1221
- fossil_print("%s%s", zPrefix, db_column_text(&q,0));
1270
+ const char *zTag = (const char*)db_column_text(&q,0);
1271
+ if( pOut ){
1272
+ const char *zSep = cnt==0 ? ",\"raw-tags\":[" : ",";
1273
+ sqlite3_str_appendf(pOut, "%s%J", zSep, zTag);
1274
+ }else{
1275
+ const char *zPrefix = cnt++ ? ", " : "raw-tags: ";
1276
+ fossil_print("%s%s", zPrefix, db_column_text(&q,0));
1277
+ }
1278
+ cnt++;
12221279
}
1223
- if( cnt ) fossil_print("\n");
1280
+ if( cnt ){
1281
+ if( pOut ){
1282
+ sqlite3_str_append(pOut, "]", 1);
1283
+ }else{
1284
+ fossil_print("\n");
1285
+ }
1286
+ }
12241287
db_finalize(&q);
12251288
12261289
/* Check for entries on the timeline that reference this object */
12271290
db_prepare(&q,
12281291
"SELECT"
@@ -1244,17 +1307,21 @@
12441307
case 'f': zType = "Forum-post"; break;
12451308
case 't': zType = "Ticket-change"; break;
12461309
case 'g': zType = "Tag-change"; break;
12471310
default: zType = "Unknown"; break;
12481311
}
1249
- fossil_print("type: %s by %s on %s\n", zType, db_column_text(&q,2),
1312
+ whatis_line(pOut, "type", "%s by %s on %s", zType, db_column_text(&q,2),
12501313
db_column_text(&q, 1));
12511314
if( eType=='t' && db_column_type(&q,4)==SQLITE_TEXT ){
1252
- fossil_print("ticket-id: %s\n", db_column_text(&q,4));
1315
+ whatis_line(pOut, "ticket-id", "%s", db_column_text(&q,4));
12531316
}
1254
- fossil_print("comment: ");
1255
- comment_print(db_column_text(&q,3), 0, 12, -1, get_comment_format());
1317
+ if( pOut ){
1318
+ sqlite3_str_appendf(pOut, ",\"comment\":%J", db_column_text(&q,3));
1319
+ }else{
1320
+ fossil_print("comment: ");
1321
+ comment_print(db_column_text(&q,3), 0, 12, -1, get_comment_format());
1322
+ }
12561323
cnt++;
12571324
}
12581325
db_finalize(&q);
12591326
12601327
/* Check to see if this object is used as a file in a check-in */
@@ -1271,20 +1338,25 @@
12711338
" ORDER BY event.mtime %s /*sort*/",
12721339
TAG_BRANCH, rid,
12731340
(flags & WHATIS_BRIEF) ? "LIMIT 1" : "DESC");
12741341
while( db_step(&q)==SQLITE_ROW ){
12751342
if( flags & WHATIS_BRIEF ){
1276
- fossil_print("mtime: %s\n", db_column_text(&q,2));
1277
- }
1278
- fossil_print("file: %s\n", db_column_text(&q,0));
1279
- fossil_print(" part of [%S] on branch %s by %s on %s\n",
1280
- db_column_text(&q, 1),
1281
- db_column_text(&q, 5),
1282
- db_column_text(&q, 3),
1283
- db_column_text(&q, 2));
1284
- fossil_print(" ");
1285
- comment_print(db_column_text(&q,4), 0, 12, -1, get_comment_format());
1343
+ whatis_line(pOut, "mtime","%s", db_column_text(&q,2));
1344
+ }
1345
+ if( pOut ){
1346
+ whatis_line(pOut,"file","%s", db_column_text(&q,0));
1347
+ whatis_line(pOut,"part-of","%s", db_column_text(&q,1));
1348
+ }else{
1349
+ fossil_print("file: %s\n", db_column_text(&q,0));
1350
+ fossil_print(" part of [%S] on branch %s by %s on %s\n",
1351
+ db_column_text(&q, 1),
1352
+ db_column_text(&q, 5),
1353
+ db_column_text(&q, 3),
1354
+ db_column_text(&q, 2));
1355
+ fossil_print(" ");
1356
+ comment_print(db_column_text(&q,4), 0, 12, -1, get_comment_format());
1357
+ }
12861358
cnt++;
12871359
}
12881360
db_finalize(&q);
12891361
12901362
/* Check to see if this object is used as an attachment */
@@ -1303,30 +1375,36 @@
13031375
" FROM attachment JOIN blob ON attachment.src=blob.uuid"
13041376
" WHERE blob.rid=%d",
13051377
rid
13061378
);
13071379
while( db_step(&q)==SQLITE_ROW ){
1308
- fossil_print("attachment: %s\n", db_column_text(&q,0));
1309
- fossil_print(" attached to %s %s\n",
1310
- db_column_text(&q,5), db_column_text(&q,4));
1311
- if( flags & WHATIS_VERBOSE ){
1312
- fossil_print(" via %s (%d)\n",
1313
- db_column_text(&q,7), db_column_int(&q,6));
1380
+ if( pOut ){
1381
+ whatis_line(pOut, "attachment", "%s", db_column_text(&q,0));
1382
+ whatis_line(pOut, "attached-to", "%s %s",
1383
+ db_column_text(&q,5), db_column_text(&q,4));
13141384
}else{
1315
- fossil_print(" via %s\n",
1316
- db_column_text(&q,7));
1385
+ fossil_print("attachment: %s\n", db_column_text(&q,0));
1386
+ fossil_print(" attached to %s %s\n",
1387
+ db_column_text(&q,5), db_column_text(&q,4));
1388
+ if( flags & WHATIS_VERBOSE ){
1389
+ fossil_print(" via %s (%d)\n",
1390
+ db_column_text(&q,7), db_column_int(&q,6));
1391
+ }else{
1392
+ fossil_print(" via %s\n",
1393
+ db_column_text(&q,7));
1394
+ }
1395
+ fossil_print(" by user %s on %s\n",
1396
+ db_column_text(&q,2), db_column_text(&q,3));
1397
+ fossil_print(" ");
1398
+ comment_print(db_column_text(&q,1), 0, 12, -1, get_comment_format());
13171399
}
1318
- fossil_print(" by user %s on %s\n",
1319
- db_column_text(&q,2), db_column_text(&q,3));
1320
- fossil_print(" ");
1321
- comment_print(db_column_text(&q,1), 0, 12, -1, get_comment_format());
13221400
cnt++;
13231401
}
13241402
db_finalize(&q);
13251403
13261404
/* If other information available, try to describe the object */
1327
- if( cnt==0 ){
1405
+ if( cnt==0 && pOut==0 ){
13281406
char *zWhere = mprintf("=%d", rid);
13291407
char *zDesc;
13301408
describe_artifacts(zWhere);
13311409
free(zWhere);
13321410
zDesc = db_text(0,
@@ -1339,19 +1417,25 @@
13391417
13401418
/*
13411419
** Generate a description of artifact from it symbolic name.
13421420
*/
13431421
void whatis_artifact(
1344
- const char *zName, /* Symbolic name or full hash */
1345
- const char *zFileName,/* Optional: original filename (in file mode) */
1346
- const char *zType, /* Artifact type filter */
1347
- int mFlags /* WHATIS_* flags */
1422
+ const char *zName, /* Symbolic name or full hash */
1423
+ const char *zFileName,/* Optional: original filename (in file mode) */
1424
+ const char *zType, /* Artifact type filter */
1425
+ int mFlags, /* WHATIS_* flags */
1426
+ sqlite3_str *pOut /* Write JSON here, if not NULL */
13481427
){
13491428
int rid = symbolic_name_to_rid(zName, zType);
13501429
size_t nName;
13511430
char *zC = 0;
13521431
int nTkt = 0;
1432
+
1433
+ if( pOut ){
1434
+ mFlags &= ~(WHATIS_HASHONLY|WHATIS_REPO);
1435
+ zFileName = 0;
1436
+ }
13531437
if( (nName = strlen(zName))>=4 && validate16(zName,nName) ){
13541438
zC = fossil_strdup(zName);
13551439
canonical16(zC, nName);
13561440
nTkt = db_int(0,"SELECT count(*) FROM tag WHERE tagname GLOB 'tkt-%q*'",zC);
13571441
if( nTkt>0 ){
@@ -1376,18 +1460,28 @@
13761460
fossil_print("\nrepository: %s\n", g.zRepositoryName);
13771461
}
13781462
if( zFileName ){
13791463
fossil_print("%-12s%s\n", "name:", zFileName);
13801464
}
1381
- fossil_print("%-12s%s (ambiguous)\n", "hash:", zName);
1465
+ if( pOut ){
1466
+ sqlite3_str_appendall(pOut, "{\"ambiguous\":[");
1467
+ }else{
1468
+ fossil_print("%-12s%s (ambiguous)\n", "hash:", zName);
1469
+ }
13821470
db_prepare(&q,
13831471
"SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')",
13841472
zName, zName
13851473
);
13861474
while( db_step(&q)==SQLITE_ROW ){
1387
- if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1388
- whatis_rid(db_column_int(&q, 0), mFlags);
1475
+ if( cnt++ ){
1476
+ if( pOut ){
1477
+ sqlite3_str_append(pOut, ",", 1);
1478
+ }else{
1479
+ fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1480
+ }
1481
+ }
1482
+ whatis_rid(db_column_int(&q, 0), mFlags, pOut);
13891483
}
13901484
db_finalize(&q);
13911485
if( nTkt>0 ){
13921486
db_prepare(&q,
13931487
"SELECT (SELECT srcid FROM tagxref"
@@ -1396,34 +1490,41 @@
13961490
" ORDER BY mtime LIMIT 1)"
13971491
" FROM tag WHERE tagname GLOB 'tkt-%q*'",
13981492
zC
13991493
);
14001494
while( db_step(&q)==SQLITE_ROW ){
1401
- if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1402
- whatis_rid(db_column_int(&q, 0), mFlags);
1495
+ if( pOut ){
1496
+ sqlite3_str_append(pOut, ",", 1);
1497
+ }else{
1498
+ fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1499
+ }
1500
+ whatis_rid(db_column_int(&q, 0), mFlags, pOut);
14031501
}
14041502
db_finalize(&q);
14051503
}
1504
+ if( pOut ) sqlite3_str_append(pOut, "]", 1);
14061505
}else if( rid==0 ){
14071506
if( (mFlags & (WHATIS_OMIT_UNK|WHATIS_HASHONLY))==0 ){
14081507
/* 0123456789 12 */
14091508
if( zFileName ){
14101509
fossil_print("%-12s%s\n", "name:", zFileName);
14111510
}
1412
- fossil_print("unknown: %s\n", zName);
1511
+ if( pOut ) sqlite3_str_append(pOut, "{", 1);
1512
+ whatis_line(pOut, "unknown", "%s", zName);
1513
+ if( pOut ) sqlite3_str_append(pOut, "}", 1);
14131514
}
14141515
}else{
14151516
if( mFlags & WHATIS_REPO ){
14161517
fossil_print("\nrepository: %s\n", g.zRepositoryName);
14171518
}
14181519
if( zFileName ){
14191520
zName = zFileName;
14201521
}
1421
- if( (mFlags & WHATIS_HASHONLY)==0 ){
1422
- fossil_print("%-12s%s\n", "name:", zName);
1522
+ if( (mFlags & WHATIS_HASHONLY)==0 && pOut==0 ){
1523
+ whatis_line(pOut, "name", "%s", zName);
14231524
}
1424
- whatis_rid(rid, mFlags);
1525
+ whatis_rid(rid, mFlags, pOut);
14251526
}
14261527
fossil_free(zC);
14271528
}
14281529
14291530
/*
@@ -1449,10 +1550,11 @@
14491550
void whatis_cmd(void){
14501551
int mFlags = 0;
14511552
int fileFlag;
14521553
int i;
14531554
const char *zType = 0;
1555
+ sqlite3_str *pOut = 0;
14541556
db_find_and_open_repository(0,0);
14551557
if( find_option("verbose","v",0)!=0 ){
14561558
mFlags |= WHATIS_VERBOSE;
14571559
}
14581560
if( find_option("hash","h",0)!=0 ){
@@ -1461,10 +1563,14 @@
14611563
if( g.fQuiet ){
14621564
mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO;
14631565
}
14641566
fileFlag = find_option("file","f",0)!=0;
14651567
zType = find_option("type",0,1);
1568
+
1569
+ if( find_option("json",0,0)!=0 ){ /* undocumented test option */
1570
+ pOut = sqlite3_str_new(0);
1571
+ }
14661572
14671573
/* We should be done with options.. */
14681574
verify_all_options();
14691575
14701576
if( g.argc<3 ) usage("NAME ...");
@@ -1487,17 +1593,52 @@
14871593
** the primary hash name. */
14881594
blob_reset(&hash);
14891595
hname_hash(&in, 0, &hash);
14901596
zHash = (const char*)blob_str(&hash);
14911597
}
1492
- whatis_artifact(zHash, zName, zType, mFlags);
1598
+ whatis_artifact(zHash, zName, zType, mFlags, pOut);
14931599
blob_reset(&hash);
14941600
}else{
1495
- whatis_artifact(zName, 0, zType, mFlags);
1601
+ whatis_artifact(zName, 0, zType, mFlags, pOut);
1602
+ }
1603
+ if( pOut ){
1604
+ fossil_print("%s\n", sqlite3_str_value(pOut));
1605
+ sqlite3_str_truncate(pOut, 0);
14961606
}
14971607
}
1608
+ if( pOut ) sqlite3_str_free(pOut);
1609
+}
1610
+
1611
+/*
1612
+** This is an SQL function that does the rough equivalent of the
1613
+** "whatis" command. The argument can be a text identifier, or a
1614
+** integer RID.
1615
+*/
1616
+void whatis_sql_function(
1617
+ sqlite3_context *context,
1618
+ int argc,
1619
+ sqlite3_value **argv
1620
+){
1621
+ sqlite3_str *pOut = sqlite3_str_new(0);
1622
+ int n;
1623
+ assert( argc==1 );
1624
+ if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
1625
+ int rid = sqlite3_value_int(argv[0]);
1626
+ whatis_rid(rid, 0, pOut);
1627
+ }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
1628
+ const char *zName = (const char*)sqlite3_value_text(argv[0]);
1629
+ whatis_artifact(zName, 0, 0, 0, pOut);
1630
+ }else{
1631
+ sqlite3_str_free(pOut);
1632
+ return;
1633
+ }
1634
+ n = sqlite3_str_length(pOut);
1635
+ sqlite3_result_text64(context, sqlite3_str_finish(pOut), n,
1636
+ sqlite3_free, SQLITE_UTF8);
1637
+ sqlite3_result_subtype(context, 'J');
14981638
}
1639
+
14991640
15001641
/*
15011642
** COMMAND: test-whatis-all
15021643
**
15031644
** Usage: %fossil test-whatis-all
@@ -1509,11 +1650,11 @@
15091650
int cnt = 0;
15101651
db_find_and_open_repository(0,0);
15111652
db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
15121653
while( db_step(&q)==SQLITE_ROW ){
15131654
if( cnt++ ) fossil_print("%.79c\n", '-');
1514
- whatis_rid(db_column_int(&q,0), 1);
1655
+ whatis_rid(db_column_int(&q,0), 1, 0);
15151656
}
15161657
db_finalize(&q);
15171658
}
15181659
15191660
15201661
--- src/name.c
+++ src/name.c
@@ -1143,10 +1143,40 @@
1143 case CFTYPE_CONTROL: zType = "Tag-change"; break;
1144 default: break;
1145 }
1146 return zType;
1147 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1148
1149 /*
1150 ** Flag values for whatis_rid().
1151 */
1152 #if INTERFACE
@@ -1153,18 +1183,25 @@
1153 #define WHATIS_VERBOSE 0x01 /* Extra output */
1154 #define WHATIS_BRIEF 0x02 /* Omit unnecessary output */
1155 #define WHATIS_REPO 0x04 /* Show repository name */
1156 #define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */
1157 #define WHATIS_HASHONLY 0x10 /* Show only the hash */
 
1158 #endif
1159
1160 /*
1161 ** Generate a description of artifact "rid"
 
 
 
 
1162 */
1163 void whatis_rid(int rid, int flags){
1164 Stmt q;
1165 int cnt;
 
 
1166
1167 /* Basic information about the object. */
1168 db_prepare(&q,
1169 "SELECT uuid, size, datetime(mtime,toLocal()), ipaddr"
1170 " FROM blob, rcvfrom"
@@ -1173,18 +1210,18 @@
1173 rid);
1174 if( db_step(&q)==SQLITE_ROW ){
1175 if( flags & WHATIS_HASHONLY ){
1176 fossil_print("%s\n", db_column_text(&q,0));
1177 }else if( flags & WHATIS_VERBOSE ){
1178 fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
1179 fossil_print("size: %d bytes\n", db_column_int(&q,1));
1180 fossil_print("received: %s from %s\n",
1181 db_column_text(&q, 2),
1182 db_column_text(&q, 3));
1183 }else{
1184 fossil_print("artifact: %s\n", db_column_text(&q,0));
1185 fossil_print("size: %d bytes\n", db_column_int(&q,1));
1186 }
1187 }
1188 db_finalize(&q);
1189 if( flags & WHATIS_HASHONLY ) return;
1190
@@ -1198,14 +1235,27 @@
1198 " ORDER BY 1",
1199 rid
1200 );
1201 cnt = 0;
1202 while( db_step(&q)==SQLITE_ROW ){
1203 const char *zPrefix = cnt++ ? ", " : "tags: ";
1204 fossil_print("%s%s", zPrefix, db_column_text(&q,0));
 
 
 
 
 
 
 
1205 }
1206 if( cnt ) fossil_print("\n");
 
 
 
 
 
 
1207 db_finalize(&q);
1208
1209 /* Report any HIDDEN, PRIVATE, CLUSTER, or CLOSED tags on this artifact */
1210 db_prepare(&q,
1211 "SELECT tagname"
@@ -1215,14 +1265,27 @@
1215 " ORDER BY 1",
1216 rid
1217 );
1218 cnt = 0;
1219 while( db_step(&q)==SQLITE_ROW ){
1220 const char *zPrefix = cnt++ ? ", " : "raw-tags: ";
1221 fossil_print("%s%s", zPrefix, db_column_text(&q,0));
 
 
 
 
 
 
 
1222 }
1223 if( cnt ) fossil_print("\n");
 
 
 
 
 
 
1224 db_finalize(&q);
1225
1226 /* Check for entries on the timeline that reference this object */
1227 db_prepare(&q,
1228 "SELECT"
@@ -1244,17 +1307,21 @@
1244 case 'f': zType = "Forum-post"; break;
1245 case 't': zType = "Ticket-change"; break;
1246 case 'g': zType = "Tag-change"; break;
1247 default: zType = "Unknown"; break;
1248 }
1249 fossil_print("type: %s by %s on %s\n", zType, db_column_text(&q,2),
1250 db_column_text(&q, 1));
1251 if( eType=='t' && db_column_type(&q,4)==SQLITE_TEXT ){
1252 fossil_print("ticket-id: %s\n", db_column_text(&q,4));
1253 }
1254 fossil_print("comment: ");
1255 comment_print(db_column_text(&q,3), 0, 12, -1, get_comment_format());
 
 
 
 
1256 cnt++;
1257 }
1258 db_finalize(&q);
1259
1260 /* Check to see if this object is used as a file in a check-in */
@@ -1271,20 +1338,25 @@
1271 " ORDER BY event.mtime %s /*sort*/",
1272 TAG_BRANCH, rid,
1273 (flags & WHATIS_BRIEF) ? "LIMIT 1" : "DESC");
1274 while( db_step(&q)==SQLITE_ROW ){
1275 if( flags & WHATIS_BRIEF ){
1276 fossil_print("mtime: %s\n", db_column_text(&q,2));
1277 }
1278 fossil_print("file: %s\n", db_column_text(&q,0));
1279 fossil_print(" part of [%S] on branch %s by %s on %s\n",
1280 db_column_text(&q, 1),
1281 db_column_text(&q, 5),
1282 db_column_text(&q, 3),
1283 db_column_text(&q, 2));
1284 fossil_print(" ");
1285 comment_print(db_column_text(&q,4), 0, 12, -1, get_comment_format());
 
 
 
 
 
1286 cnt++;
1287 }
1288 db_finalize(&q);
1289
1290 /* Check to see if this object is used as an attachment */
@@ -1303,30 +1375,36 @@
1303 " FROM attachment JOIN blob ON attachment.src=blob.uuid"
1304 " WHERE blob.rid=%d",
1305 rid
1306 );
1307 while( db_step(&q)==SQLITE_ROW ){
1308 fossil_print("attachment: %s\n", db_column_text(&q,0));
1309 fossil_print(" attached to %s %s\n",
1310 db_column_text(&q,5), db_column_text(&q,4));
1311 if( flags & WHATIS_VERBOSE ){
1312 fossil_print(" via %s (%d)\n",
1313 db_column_text(&q,7), db_column_int(&q,6));
1314 }else{
1315 fossil_print(" via %s\n",
1316 db_column_text(&q,7));
 
 
 
 
 
 
 
 
 
 
 
 
1317 }
1318 fossil_print(" by user %s on %s\n",
1319 db_column_text(&q,2), db_column_text(&q,3));
1320 fossil_print(" ");
1321 comment_print(db_column_text(&q,1), 0, 12, -1, get_comment_format());
1322 cnt++;
1323 }
1324 db_finalize(&q);
1325
1326 /* If other information available, try to describe the object */
1327 if( cnt==0 ){
1328 char *zWhere = mprintf("=%d", rid);
1329 char *zDesc;
1330 describe_artifacts(zWhere);
1331 free(zWhere);
1332 zDesc = db_text(0,
@@ -1339,19 +1417,25 @@
1339
1340 /*
1341 ** Generate a description of artifact from it symbolic name.
1342 */
1343 void whatis_artifact(
1344 const char *zName, /* Symbolic name or full hash */
1345 const char *zFileName,/* Optional: original filename (in file mode) */
1346 const char *zType, /* Artifact type filter */
1347 int mFlags /* WHATIS_* flags */
 
1348 ){
1349 int rid = symbolic_name_to_rid(zName, zType);
1350 size_t nName;
1351 char *zC = 0;
1352 int nTkt = 0;
 
 
 
 
 
1353 if( (nName = strlen(zName))>=4 && validate16(zName,nName) ){
1354 zC = fossil_strdup(zName);
1355 canonical16(zC, nName);
1356 nTkt = db_int(0,"SELECT count(*) FROM tag WHERE tagname GLOB 'tkt-%q*'",zC);
1357 if( nTkt>0 ){
@@ -1376,18 +1460,28 @@
1376 fossil_print("\nrepository: %s\n", g.zRepositoryName);
1377 }
1378 if( zFileName ){
1379 fossil_print("%-12s%s\n", "name:", zFileName);
1380 }
1381 fossil_print("%-12s%s (ambiguous)\n", "hash:", zName);
 
 
 
 
1382 db_prepare(&q,
1383 "SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')",
1384 zName, zName
1385 );
1386 while( db_step(&q)==SQLITE_ROW ){
1387 if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1388 whatis_rid(db_column_int(&q, 0), mFlags);
 
 
 
 
 
 
1389 }
1390 db_finalize(&q);
1391 if( nTkt>0 ){
1392 db_prepare(&q,
1393 "SELECT (SELECT srcid FROM tagxref"
@@ -1396,34 +1490,41 @@
1396 " ORDER BY mtime LIMIT 1)"
1397 " FROM tag WHERE tagname GLOB 'tkt-%q*'",
1398 zC
1399 );
1400 while( db_step(&q)==SQLITE_ROW ){
1401 if( cnt++ ) fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1402 whatis_rid(db_column_int(&q, 0), mFlags);
 
 
 
 
1403 }
1404 db_finalize(&q);
1405 }
 
1406 }else if( rid==0 ){
1407 if( (mFlags & (WHATIS_OMIT_UNK|WHATIS_HASHONLY))==0 ){
1408 /* 0123456789 12 */
1409 if( zFileName ){
1410 fossil_print("%-12s%s\n", "name:", zFileName);
1411 }
1412 fossil_print("unknown: %s\n", zName);
 
 
1413 }
1414 }else{
1415 if( mFlags & WHATIS_REPO ){
1416 fossil_print("\nrepository: %s\n", g.zRepositoryName);
1417 }
1418 if( zFileName ){
1419 zName = zFileName;
1420 }
1421 if( (mFlags & WHATIS_HASHONLY)==0 ){
1422 fossil_print("%-12s%s\n", "name:", zName);
1423 }
1424 whatis_rid(rid, mFlags);
1425 }
1426 fossil_free(zC);
1427 }
1428
1429 /*
@@ -1449,10 +1550,11 @@
1449 void whatis_cmd(void){
1450 int mFlags = 0;
1451 int fileFlag;
1452 int i;
1453 const char *zType = 0;
 
1454 db_find_and_open_repository(0,0);
1455 if( find_option("verbose","v",0)!=0 ){
1456 mFlags |= WHATIS_VERBOSE;
1457 }
1458 if( find_option("hash","h",0)!=0 ){
@@ -1461,10 +1563,14 @@
1461 if( g.fQuiet ){
1462 mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO;
1463 }
1464 fileFlag = find_option("file","f",0)!=0;
1465 zType = find_option("type",0,1);
 
 
 
 
1466
1467 /* We should be done with options.. */
1468 verify_all_options();
1469
1470 if( g.argc<3 ) usage("NAME ...");
@@ -1487,17 +1593,52 @@
1487 ** the primary hash name. */
1488 blob_reset(&hash);
1489 hname_hash(&in, 0, &hash);
1490 zHash = (const char*)blob_str(&hash);
1491 }
1492 whatis_artifact(zHash, zName, zType, mFlags);
1493 blob_reset(&hash);
1494 }else{
1495 whatis_artifact(zName, 0, zType, mFlags);
 
 
 
 
1496 }
1497 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1498 }
 
1499
1500 /*
1501 ** COMMAND: test-whatis-all
1502 **
1503 ** Usage: %fossil test-whatis-all
@@ -1509,11 +1650,11 @@
1509 int cnt = 0;
1510 db_find_and_open_repository(0,0);
1511 db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
1512 while( db_step(&q)==SQLITE_ROW ){
1513 if( cnt++ ) fossil_print("%.79c\n", '-');
1514 whatis_rid(db_column_int(&q,0), 1);
1515 }
1516 db_finalize(&q);
1517 }
1518
1519
1520
--- src/name.c
+++ src/name.c
@@ -1143,10 +1143,40 @@
1143 case CFTYPE_CONTROL: zType = "Tag-change"; break;
1144 default: break;
1145 }
1146 return zType;
1147 }
1148
1149 /*
1150 ** This is the output routine for whatis_rid(). If pOut is NULL
1151 ** then write zKey and zValue on fossil_print(). But if pOut is
1152 ** not NULL, append the key and value as a term of a JSON object.
1153 */
1154 static void whatis_line(
1155 sqlite3_str *pOut,
1156 const char *zKey,
1157 const char *zValue,
1158 ...
1159 ){
1160 char *zArg;
1161 va_list ap;
1162 va_start(ap, zValue);
1163 zArg = sqlite3_vmprintf(zValue,ap);
1164 va_end(ap);
1165 if( pOut ){
1166 int n = sqlite3_str_length(pOut);
1167 if( n>1 && sqlite3_str_value(pOut)[n-1]!='{' ){
1168 sqlite3_str_append(pOut, ",", 1);
1169 }
1170 sqlite3_str_appendf(pOut, "%J:%J", zKey, zArg);
1171 }else{
1172 int n = 11 - (int)strlen(zKey);
1173 if( n<=0 ) n = 0;
1174 fossil_print("%s:%*s%s\n",zKey,n,"",zArg);
1175 }
1176 sqlite3_free(zArg);
1177 }
1178
1179 /*
1180 ** Flag values for whatis_rid().
1181 */
1182 #if INTERFACE
@@ -1153,18 +1183,25 @@
1183 #define WHATIS_VERBOSE 0x01 /* Extra output */
1184 #define WHATIS_BRIEF 0x02 /* Omit unnecessary output */
1185 #define WHATIS_REPO 0x04 /* Show repository name */
1186 #define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */
1187 #define WHATIS_HASHONLY 0x10 /* Show only the hash */
1188 #define WHATIS_JSON 0x20 /* Render as JSON */
1189 #endif
1190
1191 /*
1192 ** Generate a description of artifact "rid".
1193 **
1194 ** Send results to stdout using fossil_print() if pOut==0 or if
1195 ** WHATIS_HASHONLY is set. But without WHATIS_HASHONLY and if
1196 ** pOut!=0, then write a JSON description of the object into pOut.
1197 */
1198 void whatis_rid(int rid, int flags, sqlite3_str *pOut){
1199 Stmt q;
1200 int cnt;
1201
1202 if( pOut ) sqlite3_str_append(pOut, "{", 1);
1203
1204 /* Basic information about the object. */
1205 db_prepare(&q,
1206 "SELECT uuid, size, datetime(mtime,toLocal()), ipaddr"
1207 " FROM blob, rcvfrom"
@@ -1173,18 +1210,18 @@
1210 rid);
1211 if( db_step(&q)==SQLITE_ROW ){
1212 if( flags & WHATIS_HASHONLY ){
1213 fossil_print("%s\n", db_column_text(&q,0));
1214 }else if( flags & WHATIS_VERBOSE ){
1215 whatis_line(pOut, "artifact", "%s (%d)", db_column_text(&q,0), rid);
1216 whatis_line(pOut, "size", "%d bytes", db_column_int(&q,1));
1217 whatis_line(pOut, "received", "%s from %s",
1218 db_column_text(&q, 2),
1219 db_column_text(&q, 3));
1220 }else{
1221 whatis_line(pOut, "artifact","%s", db_column_text(&q,0));
1222 whatis_line(pOut, "size", "%d bytes", db_column_int(&q,1));
1223 }
1224 }
1225 db_finalize(&q);
1226 if( flags & WHATIS_HASHONLY ) return;
1227
@@ -1198,14 +1235,27 @@
1235 " ORDER BY 1",
1236 rid
1237 );
1238 cnt = 0;
1239 while( db_step(&q)==SQLITE_ROW ){
1240 const char *zTag = (const char*)db_column_text(&q,0);
1241 if( pOut ){
1242 const char *zSep = cnt==0 ? ",tags:[" : ",";
1243 sqlite3_str_appendf(pOut, "%s%J", zSep, zTag);
1244 }else{
1245 const char *zPrefix = cnt++ ? ", " : "tags: ";
1246 fossil_print("%s%s", zPrefix, db_column_text(&q,0));
1247 }
1248 cnt++;
1249 }
1250 if( cnt ){
1251 if( pOut ){
1252 sqlite3_str_append(pOut, "]", 1);
1253 }else{
1254 fossil_print("\n");
1255 }
1256 }
1257 db_finalize(&q);
1258
1259 /* Report any HIDDEN, PRIVATE, CLUSTER, or CLOSED tags on this artifact */
1260 db_prepare(&q,
1261 "SELECT tagname"
@@ -1215,14 +1265,27 @@
1265 " ORDER BY 1",
1266 rid
1267 );
1268 cnt = 0;
1269 while( db_step(&q)==SQLITE_ROW ){
1270 const char *zTag = (const char*)db_column_text(&q,0);
1271 if( pOut ){
1272 const char *zSep = cnt==0 ? ",\"raw-tags\":[" : ",";
1273 sqlite3_str_appendf(pOut, "%s%J", zSep, zTag);
1274 }else{
1275 const char *zPrefix = cnt++ ? ", " : "raw-tags: ";
1276 fossil_print("%s%s", zPrefix, db_column_text(&q,0));
1277 }
1278 cnt++;
1279 }
1280 if( cnt ){
1281 if( pOut ){
1282 sqlite3_str_append(pOut, "]", 1);
1283 }else{
1284 fossil_print("\n");
1285 }
1286 }
1287 db_finalize(&q);
1288
1289 /* Check for entries on the timeline that reference this object */
1290 db_prepare(&q,
1291 "SELECT"
@@ -1244,17 +1307,21 @@
1307 case 'f': zType = "Forum-post"; break;
1308 case 't': zType = "Ticket-change"; break;
1309 case 'g': zType = "Tag-change"; break;
1310 default: zType = "Unknown"; break;
1311 }
1312 whatis_line(pOut, "type", "%s by %s on %s", zType, db_column_text(&q,2),
1313 db_column_text(&q, 1));
1314 if( eType=='t' && db_column_type(&q,4)==SQLITE_TEXT ){
1315 whatis_line(pOut, "ticket-id", "%s", db_column_text(&q,4));
1316 }
1317 if( pOut ){
1318 sqlite3_str_appendf(pOut, ",\"comment\":%J", db_column_text(&q,3));
1319 }else{
1320 fossil_print("comment: ");
1321 comment_print(db_column_text(&q,3), 0, 12, -1, get_comment_format());
1322 }
1323 cnt++;
1324 }
1325 db_finalize(&q);
1326
1327 /* Check to see if this object is used as a file in a check-in */
@@ -1271,20 +1338,25 @@
1338 " ORDER BY event.mtime %s /*sort*/",
1339 TAG_BRANCH, rid,
1340 (flags & WHATIS_BRIEF) ? "LIMIT 1" : "DESC");
1341 while( db_step(&q)==SQLITE_ROW ){
1342 if( flags & WHATIS_BRIEF ){
1343 whatis_line(pOut, "mtime","%s", db_column_text(&q,2));
1344 }
1345 if( pOut ){
1346 whatis_line(pOut,"file","%s", db_column_text(&q,0));
1347 whatis_line(pOut,"part-of","%s", db_column_text(&q,1));
1348 }else{
1349 fossil_print("file: %s\n", db_column_text(&q,0));
1350 fossil_print(" part of [%S] on branch %s by %s on %s\n",
1351 db_column_text(&q, 1),
1352 db_column_text(&q, 5),
1353 db_column_text(&q, 3),
1354 db_column_text(&q, 2));
1355 fossil_print(" ");
1356 comment_print(db_column_text(&q,4), 0, 12, -1, get_comment_format());
1357 }
1358 cnt++;
1359 }
1360 db_finalize(&q);
1361
1362 /* Check to see if this object is used as an attachment */
@@ -1303,30 +1375,36 @@
1375 " FROM attachment JOIN blob ON attachment.src=blob.uuid"
1376 " WHERE blob.rid=%d",
1377 rid
1378 );
1379 while( db_step(&q)==SQLITE_ROW ){
1380 if( pOut ){
1381 whatis_line(pOut, "attachment", "%s", db_column_text(&q,0));
1382 whatis_line(pOut, "attached-to", "%s %s",
1383 db_column_text(&q,5), db_column_text(&q,4));
 
 
1384 }else{
1385 fossil_print("attachment: %s\n", db_column_text(&q,0));
1386 fossil_print(" attached to %s %s\n",
1387 db_column_text(&q,5), db_column_text(&q,4));
1388 if( flags & WHATIS_VERBOSE ){
1389 fossil_print(" via %s (%d)\n",
1390 db_column_text(&q,7), db_column_int(&q,6));
1391 }else{
1392 fossil_print(" via %s\n",
1393 db_column_text(&q,7));
1394 }
1395 fossil_print(" by user %s on %s\n",
1396 db_column_text(&q,2), db_column_text(&q,3));
1397 fossil_print(" ");
1398 comment_print(db_column_text(&q,1), 0, 12, -1, get_comment_format());
1399 }
 
 
 
 
1400 cnt++;
1401 }
1402 db_finalize(&q);
1403
1404 /* If other information available, try to describe the object */
1405 if( cnt==0 && pOut==0 ){
1406 char *zWhere = mprintf("=%d", rid);
1407 char *zDesc;
1408 describe_artifacts(zWhere);
1409 free(zWhere);
1410 zDesc = db_text(0,
@@ -1339,19 +1417,25 @@
1417
1418 /*
1419 ** Generate a description of artifact from it symbolic name.
1420 */
1421 void whatis_artifact(
1422 const char *zName, /* Symbolic name or full hash */
1423 const char *zFileName,/* Optional: original filename (in file mode) */
1424 const char *zType, /* Artifact type filter */
1425 int mFlags, /* WHATIS_* flags */
1426 sqlite3_str *pOut /* Write JSON here, if not NULL */
1427 ){
1428 int rid = symbolic_name_to_rid(zName, zType);
1429 size_t nName;
1430 char *zC = 0;
1431 int nTkt = 0;
1432
1433 if( pOut ){
1434 mFlags &= ~(WHATIS_HASHONLY|WHATIS_REPO);
1435 zFileName = 0;
1436 }
1437 if( (nName = strlen(zName))>=4 && validate16(zName,nName) ){
1438 zC = fossil_strdup(zName);
1439 canonical16(zC, nName);
1440 nTkt = db_int(0,"SELECT count(*) FROM tag WHERE tagname GLOB 'tkt-%q*'",zC);
1441 if( nTkt>0 ){
@@ -1376,18 +1460,28 @@
1460 fossil_print("\nrepository: %s\n", g.zRepositoryName);
1461 }
1462 if( zFileName ){
1463 fossil_print("%-12s%s\n", "name:", zFileName);
1464 }
1465 if( pOut ){
1466 sqlite3_str_appendall(pOut, "{\"ambiguous\":[");
1467 }else{
1468 fossil_print("%-12s%s (ambiguous)\n", "hash:", zName);
1469 }
1470 db_prepare(&q,
1471 "SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')",
1472 zName, zName
1473 );
1474 while( db_step(&q)==SQLITE_ROW ){
1475 if( cnt++ ){
1476 if( pOut ){
1477 sqlite3_str_append(pOut, ",", 1);
1478 }else{
1479 fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1480 }
1481 }
1482 whatis_rid(db_column_int(&q, 0), mFlags, pOut);
1483 }
1484 db_finalize(&q);
1485 if( nTkt>0 ){
1486 db_prepare(&q,
1487 "SELECT (SELECT srcid FROM tagxref"
@@ -1396,34 +1490,41 @@
1490 " ORDER BY mtime LIMIT 1)"
1491 " FROM tag WHERE tagname GLOB 'tkt-%q*'",
1492 zC
1493 );
1494 while( db_step(&q)==SQLITE_ROW ){
1495 if( pOut ){
1496 sqlite3_str_append(pOut, ",", 1);
1497 }else{
1498 fossil_print("%12s---- meaning #%d ----\n", " ", cnt);
1499 }
1500 whatis_rid(db_column_int(&q, 0), mFlags, pOut);
1501 }
1502 db_finalize(&q);
1503 }
1504 if( pOut ) sqlite3_str_append(pOut, "]", 1);
1505 }else if( rid==0 ){
1506 if( (mFlags & (WHATIS_OMIT_UNK|WHATIS_HASHONLY))==0 ){
1507 /* 0123456789 12 */
1508 if( zFileName ){
1509 fossil_print("%-12s%s\n", "name:", zFileName);
1510 }
1511 if( pOut ) sqlite3_str_append(pOut, "{", 1);
1512 whatis_line(pOut, "unknown", "%s", zName);
1513 if( pOut ) sqlite3_str_append(pOut, "}", 1);
1514 }
1515 }else{
1516 if( mFlags & WHATIS_REPO ){
1517 fossil_print("\nrepository: %s\n", g.zRepositoryName);
1518 }
1519 if( zFileName ){
1520 zName = zFileName;
1521 }
1522 if( (mFlags & WHATIS_HASHONLY)==0 && pOut==0 ){
1523 whatis_line(pOut, "name", "%s", zName);
1524 }
1525 whatis_rid(rid, mFlags, pOut);
1526 }
1527 fossil_free(zC);
1528 }
1529
1530 /*
@@ -1449,10 +1550,11 @@
1550 void whatis_cmd(void){
1551 int mFlags = 0;
1552 int fileFlag;
1553 int i;
1554 const char *zType = 0;
1555 sqlite3_str *pOut = 0;
1556 db_find_and_open_repository(0,0);
1557 if( find_option("verbose","v",0)!=0 ){
1558 mFlags |= WHATIS_VERBOSE;
1559 }
1560 if( find_option("hash","h",0)!=0 ){
@@ -1461,10 +1563,14 @@
1563 if( g.fQuiet ){
1564 mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO;
1565 }
1566 fileFlag = find_option("file","f",0)!=0;
1567 zType = find_option("type",0,1);
1568
1569 if( find_option("json",0,0)!=0 ){ /* undocumented test option */
1570 pOut = sqlite3_str_new(0);
1571 }
1572
1573 /* We should be done with options.. */
1574 verify_all_options();
1575
1576 if( g.argc<3 ) usage("NAME ...");
@@ -1487,17 +1593,52 @@
1593 ** the primary hash name. */
1594 blob_reset(&hash);
1595 hname_hash(&in, 0, &hash);
1596 zHash = (const char*)blob_str(&hash);
1597 }
1598 whatis_artifact(zHash, zName, zType, mFlags, pOut);
1599 blob_reset(&hash);
1600 }else{
1601 whatis_artifact(zName, 0, zType, mFlags, pOut);
1602 }
1603 if( pOut ){
1604 fossil_print("%s\n", sqlite3_str_value(pOut));
1605 sqlite3_str_truncate(pOut, 0);
1606 }
1607 }
1608 if( pOut ) sqlite3_str_free(pOut);
1609 }
1610
1611 /*
1612 ** This is an SQL function that does the rough equivalent of the
1613 ** "whatis" command. The argument can be a text identifier, or a
1614 ** integer RID.
1615 */
1616 void whatis_sql_function(
1617 sqlite3_context *context,
1618 int argc,
1619 sqlite3_value **argv
1620 ){
1621 sqlite3_str *pOut = sqlite3_str_new(0);
1622 int n;
1623 assert( argc==1 );
1624 if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
1625 int rid = sqlite3_value_int(argv[0]);
1626 whatis_rid(rid, 0, pOut);
1627 }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
1628 const char *zName = (const char*)sqlite3_value_text(argv[0]);
1629 whatis_artifact(zName, 0, 0, 0, pOut);
1630 }else{
1631 sqlite3_str_free(pOut);
1632 return;
1633 }
1634 n = sqlite3_str_length(pOut);
1635 sqlite3_result_text64(context, sqlite3_str_finish(pOut), n,
1636 sqlite3_free, SQLITE_UTF8);
1637 sqlite3_result_subtype(context, 'J');
1638 }
1639
1640
1641 /*
1642 ** COMMAND: test-whatis-all
1643 **
1644 ** Usage: %fossil test-whatis-all
@@ -1509,11 +1650,11 @@
1650 int cnt = 0;
1651 db_find_and_open_repository(0,0);
1652 db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
1653 while( db_step(&q)==SQLITE_ROW ){
1654 if( cnt++ ) fossil_print("%.79c\n", '-');
1655 whatis_rid(db_column_int(&q,0), 1, 0);
1656 }
1657 db_finalize(&q);
1658 }
1659
1660
1661
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -142,10 +142,12 @@
142142
}
143143
144144
/*
145145
** Add the content(), compress(), decompress(), and
146146
** gather_artifact_stats() SQL functions to database connection db.
147
+**
148
+** Also add whatis().
147149
*/
148150
int add_content_sql_commands(sqlite3 *db){
149151
sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
150152
sqlcmd_content, 0, 0);
151153
sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
@@ -152,10 +154,12 @@
152154
sqlcmd_compress, 0, 0);
153155
sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0,
154156
sqlcmd_decompress, 0, 0);
155157
sqlite3_create_function(db, "gather_artifact_stats", 0, SQLITE_UTF8, 0,
156158
sqlcmd_gather_artifact_stats, 0, 0);
159
+ sqlite3_create_function(db, "whatis", 1, SQLITE_UTF8|SQLITE_RESULT_SUBTYPE, 0,
160
+ whatis_sql_function, 0, 0);
157161
return SQLITE_OK;
158162
}
159163
160164
/*
161165
** Undocumented test SQL functions:
162166
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -142,10 +142,12 @@
142 }
143
144 /*
145 ** Add the content(), compress(), decompress(), and
146 ** gather_artifact_stats() SQL functions to database connection db.
 
 
147 */
148 int add_content_sql_commands(sqlite3 *db){
149 sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
150 sqlcmd_content, 0, 0);
151 sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
@@ -152,10 +154,12 @@
152 sqlcmd_compress, 0, 0);
153 sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0,
154 sqlcmd_decompress, 0, 0);
155 sqlite3_create_function(db, "gather_artifact_stats", 0, SQLITE_UTF8, 0,
156 sqlcmd_gather_artifact_stats, 0, 0);
 
 
157 return SQLITE_OK;
158 }
159
160 /*
161 ** Undocumented test SQL functions:
162
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -142,10 +142,12 @@
142 }
143
144 /*
145 ** Add the content(), compress(), decompress(), and
146 ** gather_artifact_stats() SQL functions to database connection db.
147 **
148 ** Also add whatis().
149 */
150 int add_content_sql_commands(sqlite3 *db){
151 sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
152 sqlcmd_content, 0, 0);
153 sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
@@ -152,10 +154,12 @@
154 sqlcmd_compress, 0, 0);
155 sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0,
156 sqlcmd_decompress, 0, 0);
157 sqlite3_create_function(db, "gather_artifact_stats", 0, SQLITE_UTF8, 0,
158 sqlcmd_gather_artifact_stats, 0, 0);
159 sqlite3_create_function(db, "whatis", 1, SQLITE_UTF8|SQLITE_RESULT_SUBTYPE, 0,
160 whatis_sql_function, 0, 0);
161 return SQLITE_OK;
162 }
163
164 /*
165 ** Undocumented test SQL functions:
166

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button