| | @@ -1143,10 +1143,40 @@ |
| 1143 | 1143 | case CFTYPE_CONTROL: zType = "Tag-change"; break; |
| 1144 | 1144 | default: break; |
| 1145 | 1145 | } |
| 1146 | 1146 | return zType; |
| 1147 | 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 | +} |
| 1148 | 1178 | |
| 1149 | 1179 | /* |
| 1150 | 1180 | ** Flag values for whatis_rid(). |
| 1151 | 1181 | */ |
| 1152 | 1182 | #if INTERFACE |
| | @@ -1153,18 +1183,25 @@ |
| 1153 | 1183 | #define WHATIS_VERBOSE 0x01 /* Extra output */ |
| 1154 | 1184 | #define WHATIS_BRIEF 0x02 /* Omit unnecessary output */ |
| 1155 | 1185 | #define WHATIS_REPO 0x04 /* Show repository name */ |
| 1156 | 1186 | #define WHATIS_OMIT_UNK 0x08 /* Do not show "unknown" lines */ |
| 1157 | 1187 | #define WHATIS_HASHONLY 0x10 /* Show only the hash */ |
| 1188 | +#define WHATIS_JSON 0x20 /* Render as JSON */ |
| 1158 | 1189 | #endif |
| 1159 | 1190 | |
| 1160 | 1191 | /* |
| 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. |
| 1162 | 1197 | */ |
| 1163 | | -void whatis_rid(int rid, int flags){ |
| 1198 | +void whatis_rid(int rid, int flags, sqlite3_str *pOut){ |
| 1164 | 1199 | Stmt q; |
| 1165 | 1200 | int cnt; |
| 1201 | + |
| 1202 | + if( pOut ) sqlite3_str_appendf(pOut, "{\"rid\":%d", rid); |
| 1166 | 1203 | |
| 1167 | 1204 | /* Basic information about the object. */ |
| 1168 | 1205 | db_prepare(&q, |
| 1169 | 1206 | "SELECT uuid, size, datetime(mtime,toLocal()), ipaddr" |
| 1170 | 1207 | " FROM blob, rcvfrom" |
| | @@ -1173,19 +1210,21 @@ |
| 1173 | 1210 | rid); |
| 1174 | 1211 | if( db_step(&q)==SQLITE_ROW ){ |
| 1175 | 1212 | if( flags & WHATIS_HASHONLY ){ |
| 1176 | 1213 | fossil_print("%s\n", db_column_text(&q,0)); |
| 1177 | 1214 | }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", |
| 1181 | 1218 | db_column_text(&q, 2), |
| 1182 | 1219 | db_column_text(&q, 3)); |
| 1183 | 1220 | }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)); |
| 1186 | 1223 | } |
| 1224 | + }else if( pOut ){ |
| 1225 | + sqlite3_str_appendf(pOut, ",\"artifact\":null"); |
| 1187 | 1226 | } |
| 1188 | 1227 | db_finalize(&q); |
| 1189 | 1228 | if( flags & WHATIS_HASHONLY ) return; |
| 1190 | 1229 | |
| 1191 | 1230 | /* Report any symbolic tags on this artifact */ |
| | @@ -1198,14 +1237,27 @@ |
| 1198 | 1237 | " ORDER BY 1", |
| 1199 | 1238 | rid |
| 1200 | 1239 | ); |
| 1201 | 1240 | cnt = 0; |
| 1202 | 1241 | while( db_step(&q)==SQLITE_ROW ){ |
| 1203 | | - const char *zPrefix = cnt++ ? ", " : "tags: "; |
| 1204 | | - fossil_print("%s%s", zPrefix, db_column_text(&q,0)); |
| 1242 | + const char *zTag = (const char*)db_column_text(&q,0); |
| 1243 | + if( pOut ){ |
| 1244 | + const char *zSep = cnt==0 ? ",tags:[" : ","; |
| 1245 | + sqlite3_str_appendf(pOut, "%s%J", zSep, zTag); |
| 1246 | + }else{ |
| 1247 | + const char *zPrefix = cnt ? ", " : "tags: "; |
| 1248 | + fossil_print("%s%s", zPrefix, db_column_text(&q,0)); |
| 1249 | + } |
| 1250 | + cnt++; |
| 1205 | 1251 | } |
| 1206 | | - if( cnt ) fossil_print("\n"); |
| 1252 | + if( cnt ){ |
| 1253 | + if( pOut ){ |
| 1254 | + sqlite3_str_append(pOut, "]", 1); |
| 1255 | + }else{ |
| 1256 | + fossil_print("\n"); |
| 1257 | + } |
| 1258 | + } |
| 1207 | 1259 | db_finalize(&q); |
| 1208 | 1260 | |
| 1209 | 1261 | /* Report any HIDDEN, PRIVATE, CLUSTER, or CLOSED tags on this artifact */ |
| 1210 | 1262 | db_prepare(&q, |
| 1211 | 1263 | "SELECT tagname" |
| | @@ -1215,14 +1267,27 @@ |
| 1215 | 1267 | " ORDER BY 1", |
| 1216 | 1268 | rid |
| 1217 | 1269 | ); |
| 1218 | 1270 | cnt = 0; |
| 1219 | 1271 | while( db_step(&q)==SQLITE_ROW ){ |
| 1220 | | - const char *zPrefix = cnt++ ? ", " : "raw-tags: "; |
| 1221 | | - fossil_print("%s%s", zPrefix, db_column_text(&q,0)); |
| 1272 | + const char *zTag = (const char*)db_column_text(&q,0); |
| 1273 | + if( pOut ){ |
| 1274 | + const char *zSep = cnt==0 ? ",\"raw-tags\":[" : ","; |
| 1275 | + sqlite3_str_appendf(pOut, "%s%J", zSep, zTag); |
| 1276 | + }else{ |
| 1277 | + const char *zPrefix = cnt ? ", " : "raw-tags: "; |
| 1278 | + fossil_print("%s%s", zPrefix, db_column_text(&q,0)); |
| 1279 | + } |
| 1280 | + cnt++; |
| 1222 | 1281 | } |
| 1223 | | - if( cnt ) fossil_print("\n"); |
| 1282 | + if( cnt ){ |
| 1283 | + if( pOut ){ |
| 1284 | + sqlite3_str_append(pOut, "]", 1); |
| 1285 | + }else{ |
| 1286 | + fossil_print("\n"); |
| 1287 | + } |
| 1288 | + } |
| 1224 | 1289 | db_finalize(&q); |
| 1225 | 1290 | |
| 1226 | 1291 | /* Check for entries on the timeline that reference this object */ |
| 1227 | 1292 | db_prepare(&q, |
| 1228 | 1293 | "SELECT" |
| | @@ -1244,17 +1309,21 @@ |
| 1244 | 1309 | case 'f': zType = "Forum-post"; break; |
| 1245 | 1310 | case 't': zType = "Ticket-change"; break; |
| 1246 | 1311 | case 'g': zType = "Tag-change"; break; |
| 1247 | 1312 | default: zType = "Unknown"; break; |
| 1248 | 1313 | } |
| 1249 | | - fossil_print("type: %s by %s on %s\n", zType, db_column_text(&q,2), |
| 1314 | + whatis_line(pOut, "type", "%s by %s on %s", zType, db_column_text(&q,2), |
| 1250 | 1315 | db_column_text(&q, 1)); |
| 1251 | 1316 | if( eType=='t' && db_column_type(&q,4)==SQLITE_TEXT ){ |
| 1252 | | - fossil_print("ticket-id: %s\n", db_column_text(&q,4)); |
| 1317 | + whatis_line(pOut, "ticket-id", "%s", db_column_text(&q,4)); |
| 1253 | 1318 | } |
| 1254 | | - fossil_print("comment: "); |
| 1255 | | - comment_print(db_column_text(&q,3), 0, 12, -1, get_comment_format()); |
| 1319 | + if( pOut ){ |
| 1320 | + sqlite3_str_appendf(pOut, ",\"comment\":%J", db_column_text(&q,3)); |
| 1321 | + }else{ |
| 1322 | + fossil_print("comment: "); |
| 1323 | + comment_print(db_column_text(&q,3), 0, 12, -1, get_comment_format()); |
| 1324 | + } |
| 1256 | 1325 | cnt++; |
| 1257 | 1326 | } |
| 1258 | 1327 | db_finalize(&q); |
| 1259 | 1328 | |
| 1260 | 1329 | /* Check to see if this object is used as a file in a check-in */ |
| | @@ -1271,20 +1340,25 @@ |
| 1271 | 1340 | " ORDER BY event.mtime %s /*sort*/", |
| 1272 | 1341 | TAG_BRANCH, rid, |
| 1273 | 1342 | (flags & WHATIS_BRIEF) ? "LIMIT 1" : "DESC"); |
| 1274 | 1343 | while( db_step(&q)==SQLITE_ROW ){ |
| 1275 | 1344 | 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()); |
| 1345 | + whatis_line(pOut, "mtime","%s", db_column_text(&q,2)); |
| 1346 | + } |
| 1347 | + if( pOut ){ |
| 1348 | + whatis_line(pOut,"file","%s", db_column_text(&q,0)); |
| 1349 | + whatis_line(pOut,"part-of","%s", db_column_text(&q,1)); |
| 1350 | + }else{ |
| 1351 | + fossil_print("file: %s\n", db_column_text(&q,0)); |
| 1352 | + fossil_print(" part of [%S] on branch %s by %s on %s\n", |
| 1353 | + db_column_text(&q, 1), |
| 1354 | + db_column_text(&q, 5), |
| 1355 | + db_column_text(&q, 3), |
| 1356 | + db_column_text(&q, 2)); |
| 1357 | + fossil_print(" "); |
| 1358 | + comment_print(db_column_text(&q,4), 0, 12, -1, get_comment_format()); |
| 1359 | + } |
| 1286 | 1360 | cnt++; |
| 1287 | 1361 | } |
| 1288 | 1362 | db_finalize(&q); |
| 1289 | 1363 | |
| 1290 | 1364 | /* Check to see if this object is used as an attachment */ |
| | @@ -1303,30 +1377,36 @@ |
| 1303 | 1377 | " FROM attachment JOIN blob ON attachment.src=blob.uuid" |
| 1304 | 1378 | " WHERE blob.rid=%d", |
| 1305 | 1379 | rid |
| 1306 | 1380 | ); |
| 1307 | 1381 | 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)); |
| 1382 | + if( pOut ){ |
| 1383 | + whatis_line(pOut, "attachment", "%s", db_column_text(&q,0)); |
| 1384 | + whatis_line(pOut, "attached-to", "%s %s", |
| 1385 | + db_column_text(&q,5), db_column_text(&q,4)); |
| 1314 | 1386 | }else{ |
| 1315 | | - fossil_print(" via %s\n", |
| 1316 | | - db_column_text(&q,7)); |
| 1387 | + fossil_print("attachment: %s\n", db_column_text(&q,0)); |
| 1388 | + fossil_print(" attached to %s %s\n", |
| 1389 | + db_column_text(&q,5), db_column_text(&q,4)); |
| 1390 | + if( flags & WHATIS_VERBOSE ){ |
| 1391 | + fossil_print(" via %s (%d)\n", |
| 1392 | + db_column_text(&q,7), db_column_int(&q,6)); |
| 1393 | + }else{ |
| 1394 | + fossil_print(" via %s\n", |
| 1395 | + db_column_text(&q,7)); |
| 1396 | + } |
| 1397 | + fossil_print(" by user %s on %s\n", |
| 1398 | + db_column_text(&q,2), db_column_text(&q,3)); |
| 1399 | + fossil_print(" "); |
| 1400 | + comment_print(db_column_text(&q,1), 0, 12, -1, get_comment_format()); |
| 1317 | 1401 | } |
| 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 | 1402 | cnt++; |
| 1323 | 1403 | } |
| 1324 | 1404 | db_finalize(&q); |
| 1325 | 1405 | |
| 1326 | 1406 | /* If other information available, try to describe the object */ |
| 1327 | | - if( cnt==0 ){ |
| 1407 | + if( cnt==0 && pOut==0 ){ |
| 1328 | 1408 | char *zWhere = mprintf("=%d", rid); |
| 1329 | 1409 | char *zDesc; |
| 1330 | 1410 | describe_artifacts(zWhere); |
| 1331 | 1411 | free(zWhere); |
| 1332 | 1412 | zDesc = db_text(0, |
| | @@ -1333,25 +1413,33 @@ |
| 1333 | 1413 | "SELECT printf('%%-12s%%s %%s',type||':',summary,substr(ref,1,16))" |
| 1334 | 1414 | " FROM description WHERE rid=%d", rid); |
| 1335 | 1415 | fossil_print("%s\n", zDesc); |
| 1336 | 1416 | fossil_free(zDesc); |
| 1337 | 1417 | } |
| 1418 | + |
| 1419 | + if( pOut ) sqlite3_str_append(pOut, "}", 1); |
| 1338 | 1420 | } |
| 1339 | 1421 | |
| 1340 | 1422 | /* |
| 1341 | 1423 | ** Generate a description of artifact from it symbolic name. |
| 1342 | 1424 | */ |
| 1343 | 1425 | 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 */ |
| 1426 | + const char *zName, /* Symbolic name or full hash */ |
| 1427 | + const char *zFileName,/* Optional: original filename (in file mode) */ |
| 1428 | + const char *zType, /* Artifact type filter */ |
| 1429 | + int mFlags, /* WHATIS_* flags */ |
| 1430 | + sqlite3_str *pOut /* Write JSON here, if not NULL */ |
| 1348 | 1431 | ){ |
| 1349 | 1432 | int rid = symbolic_name_to_rid(zName, zType); |
| 1350 | 1433 | size_t nName; |
| 1351 | 1434 | char *zC = 0; |
| 1352 | 1435 | int nTkt = 0; |
| 1436 | + |
| 1437 | + if( pOut ){ |
| 1438 | + mFlags &= ~(WHATIS_HASHONLY|WHATIS_REPO); |
| 1439 | + zFileName = 0; |
| 1440 | + } |
| 1353 | 1441 | if( (nName = strlen(zName))>=4 && validate16(zName,nName) ){ |
| 1354 | 1442 | zC = fossil_strdup(zName); |
| 1355 | 1443 | canonical16(zC, nName); |
| 1356 | 1444 | nTkt = db_int(0,"SELECT count(*) FROM tag WHERE tagname GLOB 'tkt-%q*'",zC); |
| 1357 | 1445 | if( nTkt>0 ){ |
| | @@ -1376,18 +1464,28 @@ |
| 1376 | 1464 | fossil_print("\nrepository: %s\n", g.zRepositoryName); |
| 1377 | 1465 | } |
| 1378 | 1466 | if( zFileName ){ |
| 1379 | 1467 | fossil_print("%-12s%s\n", "name:", zFileName); |
| 1380 | 1468 | } |
| 1381 | | - fossil_print("%-12s%s (ambiguous)\n", "hash:", zName); |
| 1469 | + if( pOut ){ |
| 1470 | + sqlite3_str_appendall(pOut, "{\"ambiguous\":["); |
| 1471 | + }else{ |
| 1472 | + fossil_print("%-12s%s (ambiguous)\n", "hash:", zName); |
| 1473 | + } |
| 1382 | 1474 | db_prepare(&q, |
| 1383 | 1475 | "SELECT rid FROM blob WHERE uuid>=lower(%Q) AND uuid<(lower(%Q)||'z')", |
| 1384 | 1476 | zName, zName |
| 1385 | 1477 | ); |
| 1386 | 1478 | 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); |
| 1479 | + if( cnt++ ){ |
| 1480 | + if( pOut ){ |
| 1481 | + sqlite3_str_append(pOut, ",", 1); |
| 1482 | + }else{ |
| 1483 | + fossil_print("%12s---- meaning #%d ----\n", " ", cnt); |
| 1484 | + } |
| 1485 | + } |
| 1486 | + whatis_rid(db_column_int(&q, 0), mFlags, pOut); |
| 1389 | 1487 | } |
| 1390 | 1488 | db_finalize(&q); |
| 1391 | 1489 | if( nTkt>0 ){ |
| 1392 | 1490 | db_prepare(&q, |
| 1393 | 1491 | "SELECT (SELECT srcid FROM tagxref" |
| | @@ -1396,34 +1494,41 @@ |
| 1396 | 1494 | " ORDER BY mtime LIMIT 1)" |
| 1397 | 1495 | " FROM tag WHERE tagname GLOB 'tkt-%q*'", |
| 1398 | 1496 | zC |
| 1399 | 1497 | ); |
| 1400 | 1498 | 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); |
| 1499 | + if( pOut ){ |
| 1500 | + sqlite3_str_append(pOut, ",", 1); |
| 1501 | + }else{ |
| 1502 | + fossil_print("%12s---- meaning #%d ----\n", " ", cnt); |
| 1503 | + } |
| 1504 | + whatis_rid(db_column_int(&q, 0), mFlags, pOut); |
| 1403 | 1505 | } |
| 1404 | 1506 | db_finalize(&q); |
| 1405 | 1507 | } |
| 1508 | + if( pOut ) sqlite3_str_append(pOut, "]}", 2); |
| 1406 | 1509 | }else if( rid==0 ){ |
| 1407 | 1510 | if( (mFlags & (WHATIS_OMIT_UNK|WHATIS_HASHONLY))==0 ){ |
| 1408 | 1511 | /* 0123456789 12 */ |
| 1409 | 1512 | if( zFileName ){ |
| 1410 | 1513 | fossil_print("%-12s%s\n", "name:", zFileName); |
| 1411 | 1514 | } |
| 1412 | | - fossil_print("unknown: %s\n", zName); |
| 1515 | + if( pOut ) sqlite3_str_append(pOut, "{", 1); |
| 1516 | + whatis_line(pOut, "unknown", "%s", zName); |
| 1517 | + if( pOut ) sqlite3_str_append(pOut, "}", 1); |
| 1413 | 1518 | } |
| 1414 | 1519 | }else{ |
| 1415 | 1520 | if( mFlags & WHATIS_REPO ){ |
| 1416 | 1521 | fossil_print("\nrepository: %s\n", g.zRepositoryName); |
| 1417 | 1522 | } |
| 1418 | 1523 | if( zFileName ){ |
| 1419 | 1524 | zName = zFileName; |
| 1420 | 1525 | } |
| 1421 | | - if( (mFlags & WHATIS_HASHONLY)==0 ){ |
| 1422 | | - fossil_print("%-12s%s\n", "name:", zName); |
| 1526 | + if( (mFlags & WHATIS_HASHONLY)==0 && pOut==0 ){ |
| 1527 | + whatis_line(pOut, "name", "%s", zName); |
| 1423 | 1528 | } |
| 1424 | | - whatis_rid(rid, mFlags); |
| 1529 | + whatis_rid(rid, mFlags, pOut); |
| 1425 | 1530 | } |
| 1426 | 1531 | fossil_free(zC); |
| 1427 | 1532 | } |
| 1428 | 1533 | |
| 1429 | 1534 | /* |
| | @@ -1449,10 +1554,11 @@ |
| 1449 | 1554 | void whatis_cmd(void){ |
| 1450 | 1555 | int mFlags = 0; |
| 1451 | 1556 | int fileFlag; |
| 1452 | 1557 | int i; |
| 1453 | 1558 | const char *zType = 0; |
| 1559 | + sqlite3_str *pOut = 0; |
| 1454 | 1560 | db_find_and_open_repository(0,0); |
| 1455 | 1561 | if( find_option("verbose","v",0)!=0 ){ |
| 1456 | 1562 | mFlags |= WHATIS_VERBOSE; |
| 1457 | 1563 | } |
| 1458 | 1564 | if( find_option("hash","h",0)!=0 ){ |
| | @@ -1461,10 +1567,14 @@ |
| 1461 | 1567 | if( g.fQuiet ){ |
| 1462 | 1568 | mFlags |= WHATIS_OMIT_UNK | WHATIS_REPO; |
| 1463 | 1569 | } |
| 1464 | 1570 | fileFlag = find_option("file","f",0)!=0; |
| 1465 | 1571 | zType = find_option("type",0,1); |
| 1572 | + |
| 1573 | + if( find_option("json",0,0)!=0 ){ /* undocumented test option */ |
| 1574 | + pOut = sqlite3_str_new(0); |
| 1575 | + } |
| 1466 | 1576 | |
| 1467 | 1577 | /* We should be done with options.. */ |
| 1468 | 1578 | verify_all_options(); |
| 1469 | 1579 | |
| 1470 | 1580 | if( g.argc<3 ) usage("NAME ..."); |
| | @@ -1487,17 +1597,52 @@ |
| 1487 | 1597 | ** the primary hash name. */ |
| 1488 | 1598 | blob_reset(&hash); |
| 1489 | 1599 | hname_hash(&in, 0, &hash); |
| 1490 | 1600 | zHash = (const char*)blob_str(&hash); |
| 1491 | 1601 | } |
| 1492 | | - whatis_artifact(zHash, zName, zType, mFlags); |
| 1602 | + whatis_artifact(zHash, zName, zType, mFlags, pOut); |
| 1493 | 1603 | blob_reset(&hash); |
| 1494 | 1604 | }else{ |
| 1495 | | - whatis_artifact(zName, 0, zType, mFlags); |
| 1605 | + whatis_artifact(zName, 0, zType, mFlags, pOut); |
| 1606 | + } |
| 1607 | + if( pOut ){ |
| 1608 | + fossil_print("%s\n", sqlite3_str_value(pOut)); |
| 1609 | + sqlite3_str_truncate(pOut, 0); |
| 1496 | 1610 | } |
| 1497 | 1611 | } |
| 1612 | + if( pOut ) sqlite3_str_free(pOut); |
| 1613 | +} |
| 1614 | + |
| 1615 | +/* |
| 1616 | +** This is an SQL function that does the rough equivalent of the |
| 1617 | +** "whatis" command. The argument can be a text identifier, or a |
| 1618 | +** integer RID. |
| 1619 | +*/ |
| 1620 | +void whatis_sql_function( |
| 1621 | + sqlite3_context *context, |
| 1622 | + int argc, |
| 1623 | + sqlite3_value **argv |
| 1624 | +){ |
| 1625 | + sqlite3_str *pOut = sqlite3_str_new(0); |
| 1626 | + int n; |
| 1627 | + assert( argc==1 ); |
| 1628 | + if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ |
| 1629 | + int rid = sqlite3_value_int(argv[0]); |
| 1630 | + whatis_rid(rid, 0, pOut); |
| 1631 | + }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){ |
| 1632 | + const char *zName = (const char*)sqlite3_value_text(argv[0]); |
| 1633 | + whatis_artifact(zName, 0, 0, 0, pOut); |
| 1634 | + }else{ |
| 1635 | + sqlite3_str_free(pOut); |
| 1636 | + return; |
| 1637 | + } |
| 1638 | + n = sqlite3_str_length(pOut); |
| 1639 | + sqlite3_result_text64(context, sqlite3_str_finish(pOut), n, |
| 1640 | + sqlite3_free, SQLITE_UTF8); |
| 1641 | + sqlite3_result_subtype(context, 'J'); |
| 1498 | 1642 | } |
| 1643 | + |
| 1499 | 1644 | |
| 1500 | 1645 | /* |
| 1501 | 1646 | ** COMMAND: test-whatis-all |
| 1502 | 1647 | ** |
| 1503 | 1648 | ** Usage: %fossil test-whatis-all |
| | @@ -1509,11 +1654,11 @@ |
| 1509 | 1654 | int cnt = 0; |
| 1510 | 1655 | db_find_and_open_repository(0,0); |
| 1511 | 1656 | db_prepare(&q, "SELECT rid FROM blob ORDER BY rid"); |
| 1512 | 1657 | while( db_step(&q)==SQLITE_ROW ){ |
| 1513 | 1658 | if( cnt++ ) fossil_print("%.79c\n", '-'); |
| 1514 | | - whatis_rid(db_column_int(&q,0), 1); |
| 1659 | + whatis_rid(db_column_int(&q,0), 1, 0); |
| 1515 | 1660 | } |
| 1516 | 1661 | db_finalize(&q); |
| 1517 | 1662 | } |
| 1518 | 1663 | |
| 1519 | 1664 | |
| 1520 | 1665 | |