Fossil SCM
Merge trunk
Commit
99af4d2a1264cd99cb5f90d3b78e2dc002162a71
Parent
0c1a1167911131f…
7 files changed
+36
-39
+36
-39
+46
+69
+69
+3
-2
+35
+36
-39
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -386,24 +386,10 @@ | ||
| 386 | 386 | pNew->isLast = 1; |
| 387 | 387 | while( zPath[i]=='/' ){ i++; } |
| 388 | 388 | pParent = pNew; |
| 389 | 389 | } |
| 390 | 390 | } |
| 391 | - | |
| 392 | -/* | |
| 393 | -** Render parent lines for pNode | |
| 394 | -*/ | |
| 395 | -static void tree_indentation(FileTreeNode *p){ | |
| 396 | - if( p==0 ) return; | |
| 397 | - tree_indentation(p->pParent); | |
| 398 | - if( p->isLast ){ | |
| 399 | - cgi_append_content(" ", 4); | |
| 400 | - }else{ | |
| 401 | - cgi_append_content("│ ", 11); | |
| 402 | - } | |
| 403 | -} | |
| 404 | - | |
| 405 | 391 | |
| 406 | 392 | /* |
| 407 | 393 | ** WEBPAGE: tree |
| 408 | 394 | ** |
| 409 | 395 | ** Query parameters: |
| @@ -422,16 +408,16 @@ | ||
| 422 | 408 | Manifest *pM = 0; |
| 423 | 409 | int nFile = 0; /* Number of files */ |
| 424 | 410 | int linkTrunk = 1; /* include link to "trunk" */ |
| 425 | 411 | int linkTip = 1; /* include link to "tip" */ |
| 426 | 412 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 427 | - char *zPrefix; /* Prefix on all filenames */ | |
| 428 | 413 | char *zREx = ""; /* Extra parameters for path hyperlinks */ |
| 429 | 414 | ReCompiled *pRE = 0; /* Compiled regular expression */ |
| 430 | 415 | FileTreeNode *p; /* One line of the tree */ |
| 431 | 416 | FileTree sTree; /* The complete tree of files */ |
| 432 | 417 | HQuery sURI; /* Hyperlink */ |
| 418 | + char *zProjectName = db_get("project-name", 0); | |
| 433 | 419 | |
| 434 | 420 | if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } |
| 435 | 421 | memset(&sTree, 0, sizeof(sTree)); |
| 436 | 422 | login_check_credentials(); |
| 437 | 423 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -474,18 +460,16 @@ | ||
| 474 | 460 | if( zD ){ |
| 475 | 461 | url_add_parameter(&sURI, "name", zD); |
| 476 | 462 | blob_append(&dirname, "within directory ", -1); |
| 477 | 463 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 478 | 464 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 479 | - zPrefix = mprintf("%T/", zD); | |
| 480 | 465 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 481 | 466 | url_render(&sURI, "name", 0, 0, 0)); |
| 482 | 467 | }else{ |
| 483 | 468 | if( zRE ){ |
| 484 | 469 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 485 | 470 | } |
| 486 | - zPrefix = ""; | |
| 487 | 471 | } |
| 488 | 472 | if( zCI ){ |
| 489 | 473 | style_submenu_element("All", "All", "%s", |
| 490 | 474 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | 475 | } |
| @@ -519,11 +503,11 @@ | ||
| 519 | 503 | || pFile->zName[nD-1]!='/') |
| 520 | 504 | ){ |
| 521 | 505 | continue; |
| 522 | 506 | } |
| 523 | 507 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 524 | - db_bind_text(&ins, ":f", &pFile->zName[nD]); | |
| 508 | + db_bind_text(&ins, ":f", pFile->zName); | |
| 525 | 509 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 526 | 510 | db_step(&ins); |
| 527 | 511 | db_reset(&ins); |
| 528 | 512 | } |
| 529 | 513 | db_finalize(&ins); |
| @@ -540,11 +524,11 @@ | ||
| 540 | 524 | const char *z = db_column_text(&q, 0); |
| 541 | 525 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 542 | 526 | continue; |
| 543 | 527 | } |
| 544 | 528 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 545 | - tree_add_node(&sTree, z+nD, 0); | |
| 529 | + tree_add_node(&sTree, z, 0); | |
| 546 | 530 | nFile++; |
| 547 | 531 | } |
| 548 | 532 | db_finalize(&q); |
| 549 | 533 | } |
| 550 | 534 | |
| @@ -560,39 +544,52 @@ | ||
| 560 | 544 | |
| 561 | 545 | |
| 562 | 546 | /* Generate a multi-column table listing the contents of zD[] |
| 563 | 547 | ** directory. |
| 564 | 548 | */ |
| 565 | - @ <pre> | |
| 549 | + @ <div class="filetree"><ul> | |
| 566 | 550 | if( nD ){ |
| 567 | - cgi_printf("%.*h\n", nD, zD); | |
| 568 | - }else{ | |
| 569 | - @ . | |
| 570 | - } | |
| 571 | - for(p=sTree.pFirst; p; p=p->pNext){ | |
| 572 | - tree_indentation(p->pParent); | |
| 573 | - if( p->isLast ){ | |
| 574 | - cgi_append_content("└── ", 25); | |
| 575 | - }else{ | |
| 576 | - cgi_append_content("├── ", 25); | |
| 577 | - } | |
| 551 | + char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0)); | |
| 552 | + @ <li class="dir"> | |
| 553 | + @ %z(zLink)%h(zProjectName)</a> | |
| 554 | + }else{ | |
| 555 | + @ <li class="dir subdir"> | |
| 556 | + @ <a>%h(zProjectName)</a> | |
| 557 | + } | |
| 558 | + @ <ul> | |
| 559 | + for(p=sTree.pFirst; p; p=p->pNext){ | |
| 578 | 560 | if( p->isDir ){ |
| 579 | - char *zName = mprintf("%s%T", zPrefix, p->zFullName); | |
| 580 | - char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0)); | |
| 581 | - fossil_free(zName); | |
| 582 | - @ %z(zLink)%h(p->zName)</a> | |
| 561 | + if( nD && strlen(p->zFullName)==nD-1 ){ | |
| 562 | + @ <li class="dir subdir"> | |
| 563 | + }else{ | |
| 564 | + @ <li class="dir"> | |
| 565 | + } | |
| 566 | + if( fossil_strcmp(p->zFullName, zD)==0 ){ | |
| 567 | + @ <a>%h(p->zName)</a> | |
| 568 | + }else{ | |
| 569 | + char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0)); | |
| 570 | + @ %z(zLink)%h(p->zName)</a> | |
| 571 | + } | |
| 572 | + @ <ul> | |
| 583 | 573 | }else{ |
| 584 | 574 | char *zLink; |
| 585 | 575 | if( zCI ){ |
| 586 | 576 | zLink = href("%R/artifact/%s",p->zUuid); |
| 587 | 577 | }else{ |
| 588 | - zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName); | |
| 578 | + zLink = href("%R/finfo?name=%T",p->zFullName); | |
| 589 | 579 | } |
| 590 | - @ %z(zLink)%h(p->zName)</a> | |
| 580 | + @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a> | |
| 581 | + } | |
| 582 | + if( p->isLast ){ | |
| 583 | + int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); | |
| 584 | + while( nClose-- > 0 ){ | |
| 585 | + @ </ul> | |
| 586 | + } | |
| 591 | 587 | } |
| 592 | 588 | } |
| 593 | - @ </pre> | |
| 589 | + @ </ul> | |
| 590 | + @ </ul></div> | |
| 594 | 591 | style_footer(); |
| 595 | 592 | |
| 596 | 593 | /* We could free memory used by sTree here if we needed to. But |
| 597 | 594 | ** the process is about to exit, so doing so would not really accomplish |
| 598 | 595 | ** anything useful. */ |
| @@ -607,11 +604,11 @@ | ||
| 607 | 604 | const char *zExt = strrchr(zFilename, '.'); |
| 608 | 605 | int isExt = zExt && zExt!=zFilename && zExt[1]; |
| 609 | 606 | int i; |
| 610 | 607 | for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]); |
| 611 | 608 | if( isExt ){ |
| 612 | - zClass = mprintf("file-%s", zExt+1); | |
| 609 | + zClass = mprintf("file file-%s", zExt+1); | |
| 613 | 610 | for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]); |
| 614 | 611 | }else{ |
| 615 | 612 | zClass = mprintf("file"); |
| 616 | 613 | } |
| 617 | 614 | return zClass; |
| 618 | 615 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -386,24 +386,10 @@ | |
| 386 | pNew->isLast = 1; |
| 387 | while( zPath[i]=='/' ){ i++; } |
| 388 | pParent = pNew; |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | ** Render parent lines for pNode |
| 394 | */ |
| 395 | static void tree_indentation(FileTreeNode *p){ |
| 396 | if( p==0 ) return; |
| 397 | tree_indentation(p->pParent); |
| 398 | if( p->isLast ){ |
| 399 | cgi_append_content(" ", 4); |
| 400 | }else{ |
| 401 | cgi_append_content("│ ", 11); |
| 402 | } |
| 403 | } |
| 404 | |
| 405 | |
| 406 | /* |
| 407 | ** WEBPAGE: tree |
| 408 | ** |
| 409 | ** Query parameters: |
| @@ -422,16 +408,16 @@ | |
| 422 | Manifest *pM = 0; |
| 423 | int nFile = 0; /* Number of files */ |
| 424 | int linkTrunk = 1; /* include link to "trunk" */ |
| 425 | int linkTip = 1; /* include link to "tip" */ |
| 426 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 427 | char *zPrefix; /* Prefix on all filenames */ |
| 428 | char *zREx = ""; /* Extra parameters for path hyperlinks */ |
| 429 | ReCompiled *pRE = 0; /* Compiled regular expression */ |
| 430 | FileTreeNode *p; /* One line of the tree */ |
| 431 | FileTree sTree; /* The complete tree of files */ |
| 432 | HQuery sURI; /* Hyperlink */ |
| 433 | |
| 434 | if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } |
| 435 | memset(&sTree, 0, sizeof(sTree)); |
| 436 | login_check_credentials(); |
| 437 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -474,18 +460,16 @@ | |
| 474 | if( zD ){ |
| 475 | url_add_parameter(&sURI, "name", zD); |
| 476 | blob_append(&dirname, "within directory ", -1); |
| 477 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 478 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 479 | zPrefix = mprintf("%T/", zD); |
| 480 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 481 | url_render(&sURI, "name", 0, 0, 0)); |
| 482 | }else{ |
| 483 | if( zRE ){ |
| 484 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 485 | } |
| 486 | zPrefix = ""; |
| 487 | } |
| 488 | if( zCI ){ |
| 489 | style_submenu_element("All", "All", "%s", |
| 490 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | } |
| @@ -519,11 +503,11 @@ | |
| 519 | || pFile->zName[nD-1]!='/') |
| 520 | ){ |
| 521 | continue; |
| 522 | } |
| 523 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 524 | db_bind_text(&ins, ":f", &pFile->zName[nD]); |
| 525 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 526 | db_step(&ins); |
| 527 | db_reset(&ins); |
| 528 | } |
| 529 | db_finalize(&ins); |
| @@ -540,11 +524,11 @@ | |
| 540 | const char *z = db_column_text(&q, 0); |
| 541 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 542 | continue; |
| 543 | } |
| 544 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 545 | tree_add_node(&sTree, z+nD, 0); |
| 546 | nFile++; |
| 547 | } |
| 548 | db_finalize(&q); |
| 549 | } |
| 550 | |
| @@ -560,39 +544,52 @@ | |
| 560 | |
| 561 | |
| 562 | /* Generate a multi-column table listing the contents of zD[] |
| 563 | ** directory. |
| 564 | */ |
| 565 | @ <pre> |
| 566 | if( nD ){ |
| 567 | cgi_printf("%.*h\n", nD, zD); |
| 568 | }else{ |
| 569 | @ . |
| 570 | } |
| 571 | for(p=sTree.pFirst; p; p=p->pNext){ |
| 572 | tree_indentation(p->pParent); |
| 573 | if( p->isLast ){ |
| 574 | cgi_append_content("└── ", 25); |
| 575 | }else{ |
| 576 | cgi_append_content("├── ", 25); |
| 577 | } |
| 578 | if( p->isDir ){ |
| 579 | char *zName = mprintf("%s%T", zPrefix, p->zFullName); |
| 580 | char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0)); |
| 581 | fossil_free(zName); |
| 582 | @ %z(zLink)%h(p->zName)</a> |
| 583 | }else{ |
| 584 | char *zLink; |
| 585 | if( zCI ){ |
| 586 | zLink = href("%R/artifact/%s",p->zUuid); |
| 587 | }else{ |
| 588 | zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName); |
| 589 | } |
| 590 | @ %z(zLink)%h(p->zName)</a> |
| 591 | } |
| 592 | } |
| 593 | @ </pre> |
| 594 | style_footer(); |
| 595 | |
| 596 | /* We could free memory used by sTree here if we needed to. But |
| 597 | ** the process is about to exit, so doing so would not really accomplish |
| 598 | ** anything useful. */ |
| @@ -607,11 +604,11 @@ | |
| 607 | const char *zExt = strrchr(zFilename, '.'); |
| 608 | int isExt = zExt && zExt!=zFilename && zExt[1]; |
| 609 | int i; |
| 610 | for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]); |
| 611 | if( isExt ){ |
| 612 | zClass = mprintf("file-%s", zExt+1); |
| 613 | for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]); |
| 614 | }else{ |
| 615 | zClass = mprintf("file"); |
| 616 | } |
| 617 | return zClass; |
| 618 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -386,24 +386,10 @@ | |
| 386 | pNew->isLast = 1; |
| 387 | while( zPath[i]=='/' ){ i++; } |
| 388 | pParent = pNew; |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | ** WEBPAGE: tree |
| 394 | ** |
| 395 | ** Query parameters: |
| @@ -422,16 +408,16 @@ | |
| 408 | Manifest *pM = 0; |
| 409 | int nFile = 0; /* Number of files */ |
| 410 | int linkTrunk = 1; /* include link to "trunk" */ |
| 411 | int linkTip = 1; /* include link to "tip" */ |
| 412 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 413 | char *zREx = ""; /* Extra parameters for path hyperlinks */ |
| 414 | ReCompiled *pRE = 0; /* Compiled regular expression */ |
| 415 | FileTreeNode *p; /* One line of the tree */ |
| 416 | FileTree sTree; /* The complete tree of files */ |
| 417 | HQuery sURI; /* Hyperlink */ |
| 418 | char *zProjectName = db_get("project-name", 0); |
| 419 | |
| 420 | if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } |
| 421 | memset(&sTree, 0, sizeof(sTree)); |
| 422 | login_check_credentials(); |
| 423 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -474,18 +460,16 @@ | |
| 460 | if( zD ){ |
| 461 | url_add_parameter(&sURI, "name", zD); |
| 462 | blob_append(&dirname, "within directory ", -1); |
| 463 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 464 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 465 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 466 | url_render(&sURI, "name", 0, 0, 0)); |
| 467 | }else{ |
| 468 | if( zRE ){ |
| 469 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 470 | } |
| 471 | } |
| 472 | if( zCI ){ |
| 473 | style_submenu_element("All", "All", "%s", |
| 474 | url_render(&sURI, "ci", 0, 0, 0)); |
| 475 | } |
| @@ -519,11 +503,11 @@ | |
| 503 | || pFile->zName[nD-1]!='/') |
| 504 | ){ |
| 505 | continue; |
| 506 | } |
| 507 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 508 | db_bind_text(&ins, ":f", pFile->zName); |
| 509 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 510 | db_step(&ins); |
| 511 | db_reset(&ins); |
| 512 | } |
| 513 | db_finalize(&ins); |
| @@ -540,11 +524,11 @@ | |
| 524 | const char *z = db_column_text(&q, 0); |
| 525 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 526 | continue; |
| 527 | } |
| 528 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 529 | tree_add_node(&sTree, z, 0); |
| 530 | nFile++; |
| 531 | } |
| 532 | db_finalize(&q); |
| 533 | } |
| 534 | |
| @@ -560,39 +544,52 @@ | |
| 544 | |
| 545 | |
| 546 | /* Generate a multi-column table listing the contents of zD[] |
| 547 | ** directory. |
| 548 | */ |
| 549 | @ <div class="filetree"><ul> |
| 550 | if( nD ){ |
| 551 | char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0)); |
| 552 | @ <li class="dir"> |
| 553 | @ %z(zLink)%h(zProjectName)</a> |
| 554 | }else{ |
| 555 | @ <li class="dir subdir"> |
| 556 | @ <a>%h(zProjectName)</a> |
| 557 | } |
| 558 | @ <ul> |
| 559 | for(p=sTree.pFirst; p; p=p->pNext){ |
| 560 | if( p->isDir ){ |
| 561 | if( nD && strlen(p->zFullName)==nD-1 ){ |
| 562 | @ <li class="dir subdir"> |
| 563 | }else{ |
| 564 | @ <li class="dir"> |
| 565 | } |
| 566 | if( fossil_strcmp(p->zFullName, zD)==0 ){ |
| 567 | @ <a>%h(p->zName)</a> |
| 568 | }else{ |
| 569 | char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0)); |
| 570 | @ %z(zLink)%h(p->zName)</a> |
| 571 | } |
| 572 | @ <ul> |
| 573 | }else{ |
| 574 | char *zLink; |
| 575 | if( zCI ){ |
| 576 | zLink = href("%R/artifact/%s",p->zUuid); |
| 577 | }else{ |
| 578 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 579 | } |
| 580 | @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a> |
| 581 | } |
| 582 | if( p->isLast ){ |
| 583 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 584 | while( nClose-- > 0 ){ |
| 585 | @ </ul> |
| 586 | } |
| 587 | } |
| 588 | } |
| 589 | @ </ul> |
| 590 | @ </ul></div> |
| 591 | style_footer(); |
| 592 | |
| 593 | /* We could free memory used by sTree here if we needed to. But |
| 594 | ** the process is about to exit, so doing so would not really accomplish |
| 595 | ** anything useful. */ |
| @@ -607,11 +604,11 @@ | |
| 604 | const char *zExt = strrchr(zFilename, '.'); |
| 605 | int isExt = zExt && zExt!=zFilename && zExt[1]; |
| 606 | int i; |
| 607 | for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]); |
| 608 | if( isExt ){ |
| 609 | zClass = mprintf("file file-%s", zExt+1); |
| 610 | for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]); |
| 611 | }else{ |
| 612 | zClass = mprintf("file"); |
| 613 | } |
| 614 | return zClass; |
| 615 |
+36
-39
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -386,24 +386,10 @@ | ||
| 386 | 386 | pNew->isLast = 1; |
| 387 | 387 | while( zPath[i]=='/' ){ i++; } |
| 388 | 388 | pParent = pNew; |
| 389 | 389 | } |
| 390 | 390 | } |
| 391 | - | |
| 392 | -/* | |
| 393 | -** Render parent lines for pNode | |
| 394 | -*/ | |
| 395 | -static void tree_indentation(FileTreeNode *p){ | |
| 396 | - if( p==0 ) return; | |
| 397 | - tree_indentation(p->pParent); | |
| 398 | - if( p->isLast ){ | |
| 399 | - cgi_append_content(" ", 4); | |
| 400 | - }else{ | |
| 401 | - cgi_append_content("│ ", 11); | |
| 402 | - } | |
| 403 | -} | |
| 404 | - | |
| 405 | 391 | |
| 406 | 392 | /* |
| 407 | 393 | ** WEBPAGE: tree |
| 408 | 394 | ** |
| 409 | 395 | ** Query parameters: |
| @@ -422,16 +408,16 @@ | ||
| 422 | 408 | Manifest *pM = 0; |
| 423 | 409 | int nFile = 0; /* Number of files */ |
| 424 | 410 | int linkTrunk = 1; /* include link to "trunk" */ |
| 425 | 411 | int linkTip = 1; /* include link to "tip" */ |
| 426 | 412 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 427 | - char *zPrefix; /* Prefix on all filenames */ | |
| 428 | 413 | char *zREx = ""; /* Extra parameters for path hyperlinks */ |
| 429 | 414 | ReCompiled *pRE = 0; /* Compiled regular expression */ |
| 430 | 415 | FileTreeNode *p; /* One line of the tree */ |
| 431 | 416 | FileTree sTree; /* The complete tree of files */ |
| 432 | 417 | HQuery sURI; /* Hyperlink */ |
| 418 | + char *zProjectName = db_get("project-name", 0); | |
| 433 | 419 | |
| 434 | 420 | if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } |
| 435 | 421 | memset(&sTree, 0, sizeof(sTree)); |
| 436 | 422 | login_check_credentials(); |
| 437 | 423 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -474,18 +460,16 @@ | ||
| 474 | 460 | if( zD ){ |
| 475 | 461 | url_add_parameter(&sURI, "name", zD); |
| 476 | 462 | blob_append(&dirname, "within directory ", -1); |
| 477 | 463 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 478 | 464 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 479 | - zPrefix = mprintf("%T/", zD); | |
| 480 | 465 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 481 | 466 | url_render(&sURI, "name", 0, 0, 0)); |
| 482 | 467 | }else{ |
| 483 | 468 | if( zRE ){ |
| 484 | 469 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 485 | 470 | } |
| 486 | - zPrefix = ""; | |
| 487 | 471 | } |
| 488 | 472 | if( zCI ){ |
| 489 | 473 | style_submenu_element("All", "All", "%s", |
| 490 | 474 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | 475 | } |
| @@ -519,11 +503,11 @@ | ||
| 519 | 503 | || pFile->zName[nD-1]!='/') |
| 520 | 504 | ){ |
| 521 | 505 | continue; |
| 522 | 506 | } |
| 523 | 507 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 524 | - db_bind_text(&ins, ":f", &pFile->zName[nD]); | |
| 508 | + db_bind_text(&ins, ":f", pFile->zName); | |
| 525 | 509 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 526 | 510 | db_step(&ins); |
| 527 | 511 | db_reset(&ins); |
| 528 | 512 | } |
| 529 | 513 | db_finalize(&ins); |
| @@ -540,11 +524,11 @@ | ||
| 540 | 524 | const char *z = db_column_text(&q, 0); |
| 541 | 525 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 542 | 526 | continue; |
| 543 | 527 | } |
| 544 | 528 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 545 | - tree_add_node(&sTree, z+nD, 0); | |
| 529 | + tree_add_node(&sTree, z, 0); | |
| 546 | 530 | nFile++; |
| 547 | 531 | } |
| 548 | 532 | db_finalize(&q); |
| 549 | 533 | } |
| 550 | 534 | |
| @@ -560,39 +544,52 @@ | ||
| 560 | 544 | |
| 561 | 545 | |
| 562 | 546 | /* Generate a multi-column table listing the contents of zD[] |
| 563 | 547 | ** directory. |
| 564 | 548 | */ |
| 565 | - @ <pre> | |
| 549 | + @ <div class="filetree"><ul> | |
| 566 | 550 | if( nD ){ |
| 567 | - cgi_printf("%.*h\n", nD, zD); | |
| 568 | - }else{ | |
| 569 | - @ . | |
| 570 | - } | |
| 571 | - for(p=sTree.pFirst; p; p=p->pNext){ | |
| 572 | - tree_indentation(p->pParent); | |
| 573 | - if( p->isLast ){ | |
| 574 | - cgi_append_content("└── ", 25); | |
| 575 | - }else{ | |
| 576 | - cgi_append_content("├── ", 25); | |
| 577 | - } | |
| 551 | + char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0)); | |
| 552 | + @ <li class="dir"> | |
| 553 | + @ %z(zLink)%h(zProjectName)</a> | |
| 554 | + }else{ | |
| 555 | + @ <li class="dir subdir"> | |
| 556 | + @ <a>%h(zProjectName)</a> | |
| 557 | + } | |
| 558 | + @ <ul> | |
| 559 | + for(p=sTree.pFirst; p; p=p->pNext){ | |
| 578 | 560 | if( p->isDir ){ |
| 579 | - char *zName = mprintf("%s%T", zPrefix, p->zFullName); | |
| 580 | - char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0)); | |
| 581 | - fossil_free(zName); | |
| 582 | - @ %z(zLink)%h(p->zName)</a> | |
| 561 | + if( nD && strlen(p->zFullName)==nD-1 ){ | |
| 562 | + @ <li class="dir subdir"> | |
| 563 | + }else{ | |
| 564 | + @ <li class="dir"> | |
| 565 | + } | |
| 566 | + if( fossil_strcmp(p->zFullName, zD)==0 ){ | |
| 567 | + @ <a>%h(p->zName)</a> | |
| 568 | + }else{ | |
| 569 | + char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0)); | |
| 570 | + @ %z(zLink)%h(p->zName)</a> | |
| 571 | + } | |
| 572 | + @ <ul> | |
| 583 | 573 | }else{ |
| 584 | 574 | char *zLink; |
| 585 | 575 | if( zCI ){ |
| 586 | 576 | zLink = href("%R/artifact/%s",p->zUuid); |
| 587 | 577 | }else{ |
| 588 | - zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName); | |
| 578 | + zLink = href("%R/finfo?name=%T",p->zFullName); | |
| 589 | 579 | } |
| 590 | - @ %z(zLink)%h(p->zName)</a> | |
| 580 | + @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a> | |
| 581 | + } | |
| 582 | + if( p->isLast ){ | |
| 583 | + int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); | |
| 584 | + while( nClose-- > 0 ){ | |
| 585 | + @ </ul> | |
| 586 | + } | |
| 591 | 587 | } |
| 592 | 588 | } |
| 593 | - @ </pre> | |
| 589 | + @ </ul> | |
| 590 | + @ </ul></div> | |
| 594 | 591 | style_footer(); |
| 595 | 592 | |
| 596 | 593 | /* We could free memory used by sTree here if we needed to. But |
| 597 | 594 | ** the process is about to exit, so doing so would not really accomplish |
| 598 | 595 | ** anything useful. */ |
| @@ -607,11 +604,11 @@ | ||
| 607 | 604 | const char *zExt = strrchr(zFilename, '.'); |
| 608 | 605 | int isExt = zExt && zExt!=zFilename && zExt[1]; |
| 609 | 606 | int i; |
| 610 | 607 | for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]); |
| 611 | 608 | if( isExt ){ |
| 612 | - zClass = mprintf("file-%s", zExt+1); | |
| 609 | + zClass = mprintf("file file-%s", zExt+1); | |
| 613 | 610 | for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]); |
| 614 | 611 | }else{ |
| 615 | 612 | zClass = mprintf("file"); |
| 616 | 613 | } |
| 617 | 614 | return zClass; |
| 618 | 615 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -386,24 +386,10 @@ | |
| 386 | pNew->isLast = 1; |
| 387 | while( zPath[i]=='/' ){ i++; } |
| 388 | pParent = pNew; |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | ** Render parent lines for pNode |
| 394 | */ |
| 395 | static void tree_indentation(FileTreeNode *p){ |
| 396 | if( p==0 ) return; |
| 397 | tree_indentation(p->pParent); |
| 398 | if( p->isLast ){ |
| 399 | cgi_append_content(" ", 4); |
| 400 | }else{ |
| 401 | cgi_append_content("│ ", 11); |
| 402 | } |
| 403 | } |
| 404 | |
| 405 | |
| 406 | /* |
| 407 | ** WEBPAGE: tree |
| 408 | ** |
| 409 | ** Query parameters: |
| @@ -422,16 +408,16 @@ | |
| 422 | Manifest *pM = 0; |
| 423 | int nFile = 0; /* Number of files */ |
| 424 | int linkTrunk = 1; /* include link to "trunk" */ |
| 425 | int linkTip = 1; /* include link to "tip" */ |
| 426 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 427 | char *zPrefix; /* Prefix on all filenames */ |
| 428 | char *zREx = ""; /* Extra parameters for path hyperlinks */ |
| 429 | ReCompiled *pRE = 0; /* Compiled regular expression */ |
| 430 | FileTreeNode *p; /* One line of the tree */ |
| 431 | FileTree sTree; /* The complete tree of files */ |
| 432 | HQuery sURI; /* Hyperlink */ |
| 433 | |
| 434 | if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } |
| 435 | memset(&sTree, 0, sizeof(sTree)); |
| 436 | login_check_credentials(); |
| 437 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -474,18 +460,16 @@ | |
| 474 | if( zD ){ |
| 475 | url_add_parameter(&sURI, "name", zD); |
| 476 | blob_append(&dirname, "within directory ", -1); |
| 477 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 478 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 479 | zPrefix = mprintf("%T/", zD); |
| 480 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 481 | url_render(&sURI, "name", 0, 0, 0)); |
| 482 | }else{ |
| 483 | if( zRE ){ |
| 484 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 485 | } |
| 486 | zPrefix = ""; |
| 487 | } |
| 488 | if( zCI ){ |
| 489 | style_submenu_element("All", "All", "%s", |
| 490 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | } |
| @@ -519,11 +503,11 @@ | |
| 519 | || pFile->zName[nD-1]!='/') |
| 520 | ){ |
| 521 | continue; |
| 522 | } |
| 523 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 524 | db_bind_text(&ins, ":f", &pFile->zName[nD]); |
| 525 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 526 | db_step(&ins); |
| 527 | db_reset(&ins); |
| 528 | } |
| 529 | db_finalize(&ins); |
| @@ -540,11 +524,11 @@ | |
| 540 | const char *z = db_column_text(&q, 0); |
| 541 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 542 | continue; |
| 543 | } |
| 544 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 545 | tree_add_node(&sTree, z+nD, 0); |
| 546 | nFile++; |
| 547 | } |
| 548 | db_finalize(&q); |
| 549 | } |
| 550 | |
| @@ -560,39 +544,52 @@ | |
| 560 | |
| 561 | |
| 562 | /* Generate a multi-column table listing the contents of zD[] |
| 563 | ** directory. |
| 564 | */ |
| 565 | @ <pre> |
| 566 | if( nD ){ |
| 567 | cgi_printf("%.*h\n", nD, zD); |
| 568 | }else{ |
| 569 | @ . |
| 570 | } |
| 571 | for(p=sTree.pFirst; p; p=p->pNext){ |
| 572 | tree_indentation(p->pParent); |
| 573 | if( p->isLast ){ |
| 574 | cgi_append_content("└── ", 25); |
| 575 | }else{ |
| 576 | cgi_append_content("├── ", 25); |
| 577 | } |
| 578 | if( p->isDir ){ |
| 579 | char *zName = mprintf("%s%T", zPrefix, p->zFullName); |
| 580 | char *zLink = href("%s", url_render(&sURI, "name", zName, 0, 0)); |
| 581 | fossil_free(zName); |
| 582 | @ %z(zLink)%h(p->zName)</a> |
| 583 | }else{ |
| 584 | char *zLink; |
| 585 | if( zCI ){ |
| 586 | zLink = href("%R/artifact/%s",p->zUuid); |
| 587 | }else{ |
| 588 | zLink = href("%R/finfo?name=%s%T",zPrefix,p->zFullName); |
| 589 | } |
| 590 | @ %z(zLink)%h(p->zName)</a> |
| 591 | } |
| 592 | } |
| 593 | @ </pre> |
| 594 | style_footer(); |
| 595 | |
| 596 | /* We could free memory used by sTree here if we needed to. But |
| 597 | ** the process is about to exit, so doing so would not really accomplish |
| 598 | ** anything useful. */ |
| @@ -607,11 +604,11 @@ | |
| 607 | const char *zExt = strrchr(zFilename, '.'); |
| 608 | int isExt = zExt && zExt!=zFilename && zExt[1]; |
| 609 | int i; |
| 610 | for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]); |
| 611 | if( isExt ){ |
| 612 | zClass = mprintf("file-%s", zExt+1); |
| 613 | for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]); |
| 614 | }else{ |
| 615 | zClass = mprintf("file"); |
| 616 | } |
| 617 | return zClass; |
| 618 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -386,24 +386,10 @@ | |
| 386 | pNew->isLast = 1; |
| 387 | while( zPath[i]=='/' ){ i++; } |
| 388 | pParent = pNew; |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | /* |
| 393 | ** WEBPAGE: tree |
| 394 | ** |
| 395 | ** Query parameters: |
| @@ -422,16 +408,16 @@ | |
| 408 | Manifest *pM = 0; |
| 409 | int nFile = 0; /* Number of files */ |
| 410 | int linkTrunk = 1; /* include link to "trunk" */ |
| 411 | int linkTip = 1; /* include link to "tip" */ |
| 412 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 413 | char *zREx = ""; /* Extra parameters for path hyperlinks */ |
| 414 | ReCompiled *pRE = 0; /* Compiled regular expression */ |
| 415 | FileTreeNode *p; /* One line of the tree */ |
| 416 | FileTree sTree; /* The complete tree of files */ |
| 417 | HQuery sURI; /* Hyperlink */ |
| 418 | char *zProjectName = db_get("project-name", 0); |
| 419 | |
| 420 | if( strcmp(PD("type",""),"flat")==0 ){ page_dir(); return; } |
| 421 | memset(&sTree, 0, sizeof(sTree)); |
| 422 | login_check_credentials(); |
| 423 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -474,18 +460,16 @@ | |
| 460 | if( zD ){ |
| 461 | url_add_parameter(&sURI, "name", zD); |
| 462 | blob_append(&dirname, "within directory ", -1); |
| 463 | hyperlinked_path(zD, &dirname, zCI, "tree", zREx); |
| 464 | if( zRE ) blob_appendf(&dirname, " matching \"%s\"", zRE); |
| 465 | style_submenu_element("Top-Level", "Top-Level", "%s", |
| 466 | url_render(&sURI, "name", 0, 0, 0)); |
| 467 | }else{ |
| 468 | if( zRE ){ |
| 469 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 470 | } |
| 471 | } |
| 472 | if( zCI ){ |
| 473 | style_submenu_element("All", "All", "%s", |
| 474 | url_render(&sURI, "ci", 0, 0, 0)); |
| 475 | } |
| @@ -519,11 +503,11 @@ | |
| 503 | || pFile->zName[nD-1]!='/') |
| 504 | ){ |
| 505 | continue; |
| 506 | } |
| 507 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 508 | db_bind_text(&ins, ":f", pFile->zName); |
| 509 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 510 | db_step(&ins); |
| 511 | db_reset(&ins); |
| 512 | } |
| 513 | db_finalize(&ins); |
| @@ -540,11 +524,11 @@ | |
| 524 | const char *z = db_column_text(&q, 0); |
| 525 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 526 | continue; |
| 527 | } |
| 528 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 529 | tree_add_node(&sTree, z, 0); |
| 530 | nFile++; |
| 531 | } |
| 532 | db_finalize(&q); |
| 533 | } |
| 534 | |
| @@ -560,39 +544,52 @@ | |
| 544 | |
| 545 | |
| 546 | /* Generate a multi-column table listing the contents of zD[] |
| 547 | ** directory. |
| 548 | */ |
| 549 | @ <div class="filetree"><ul> |
| 550 | if( nD ){ |
| 551 | char *zLink = href("%s", url_render(&sURI, "name", 0, 0, 0)); |
| 552 | @ <li class="dir"> |
| 553 | @ %z(zLink)%h(zProjectName)</a> |
| 554 | }else{ |
| 555 | @ <li class="dir subdir"> |
| 556 | @ <a>%h(zProjectName)</a> |
| 557 | } |
| 558 | @ <ul> |
| 559 | for(p=sTree.pFirst; p; p=p->pNext){ |
| 560 | if( p->isDir ){ |
| 561 | if( nD && strlen(p->zFullName)==nD-1 ){ |
| 562 | @ <li class="dir subdir"> |
| 563 | }else{ |
| 564 | @ <li class="dir"> |
| 565 | } |
| 566 | if( fossil_strcmp(p->zFullName, zD)==0 ){ |
| 567 | @ <a>%h(p->zName)</a> |
| 568 | }else{ |
| 569 | char *zLink = href("%s", url_render(&sURI, "name", p->zFullName, 0, 0)); |
| 570 | @ %z(zLink)%h(p->zName)</a> |
| 571 | } |
| 572 | @ <ul> |
| 573 | }else{ |
| 574 | char *zLink; |
| 575 | if( zCI ){ |
| 576 | zLink = href("%R/artifact/%s",p->zUuid); |
| 577 | }else{ |
| 578 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 579 | } |
| 580 | @ <li class="%z(fileext_class(p->zName))">%z(zLink)%h(p->zName)</a> |
| 581 | } |
| 582 | if( p->isLast ){ |
| 583 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 584 | while( nClose-- > 0 ){ |
| 585 | @ </ul> |
| 586 | } |
| 587 | } |
| 588 | } |
| 589 | @ </ul> |
| 590 | @ </ul></div> |
| 591 | style_footer(); |
| 592 | |
| 593 | /* We could free memory used by sTree here if we needed to. But |
| 594 | ** the process is about to exit, so doing so would not really accomplish |
| 595 | ** anything useful. */ |
| @@ -607,11 +604,11 @@ | |
| 604 | const char *zExt = strrchr(zFilename, '.'); |
| 605 | int isExt = zExt && zExt!=zFilename && zExt[1]; |
| 606 | int i; |
| 607 | for( i=1; isExt && zExt[i]; i++ ) isExt &= fossil_isalnum(zExt[i]); |
| 608 | if( isExt ){ |
| 609 | zClass = mprintf("file file-%s", zExt+1); |
| 610 | for ( i=5; zClass[i]; i++ ) zClass[i] = fossil_tolower(zClass[i]); |
| 611 | }else{ |
| 612 | zClass = mprintf("file"); |
| 613 | } |
| 614 | return zClass; |
| 615 |
M
src/db.c
+46
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -852,10 +852,32 @@ | ||
| 852 | 852 | g.zConfigDbType = "configdb"; |
| 853 | 853 | } |
| 854 | 854 | g.zConfigDbName = zDbName; |
| 855 | 855 | } |
| 856 | 856 | |
| 857 | + | |
| 858 | +/* | |
| 859 | +** Returns TRUE if zTable exists in the local database but lacks column | |
| 860 | +** zColumn | |
| 861 | +*/ | |
| 862 | +static int db_local_table_exists_but_lacks_column( | |
| 863 | + const char *zTable, | |
| 864 | + const char *zColumn | |
| 865 | +){ | |
| 866 | + char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" | |
| 867 | + " WHERE name=='%s' /*scan*/", | |
| 868 | + db_name("localdb"), zTable); | |
| 869 | + int rc = 0; | |
| 870 | + if( zDef ){ | |
| 871 | + char *zPattern = mprintf("* %s *", zColumn); | |
| 872 | + rc = strglob(zPattern, zDef)==0; | |
| 873 | + fossil_free(zPattern); | |
| 874 | + fossil_free(zDef); | |
| 875 | + } | |
| 876 | + return rc; | |
| 877 | +} | |
| 878 | + | |
| 857 | 879 | /* |
| 858 | 880 | ** If zDbName is a valid local database file, open it and return |
| 859 | 881 | ** true. If it is not a valid local database file, return 0. |
| 860 | 882 | */ |
| 861 | 883 | static int isValidLocalDb(const char *zDbName){ |
| @@ -868,10 +890,34 @@ | ||
| 868 | 890 | db_open_or_attach(zDbName, "localdb", 0); |
| 869 | 891 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 870 | 892 | " WHERE name=='vfile'", db_name("localdb")); |
| 871 | 893 | if( zVFileDef==0 ) return 0; |
| 872 | 894 | |
| 895 | + /* If the "isexe" column is missing from the vfile table, then | |
| 896 | + ** add it now. This code added on 2010-03-06. After all users have | |
| 897 | + ** upgraded, this code can be safely deleted. | |
| 898 | + */ | |
| 899 | + if( !strglob("* isexe *", zVFileDef) ){ | |
| 900 | + db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0"); | |
| 901 | + } | |
| 902 | + | |
| 903 | + /* If "islink"/"isLink" columns are missing from tables, then | |
| 904 | + ** add them now. This code added on 2011-01-17 and 2011-08-27. | |
| 905 | + ** After all users have upgraded, this code can be safely deleted. | |
| 906 | + */ | |
| 907 | + if( !strglob("* islink *", zVFileDef) ){ | |
| 908 | + db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0"); | |
| 909 | + if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){ | |
| 910 | + db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0"); | |
| 911 | + } | |
| 912 | + if( db_local_table_exists_but_lacks_column("undo", "isLink") ){ | |
| 913 | + db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0"); | |
| 914 | + } | |
| 915 | + if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ | |
| 916 | + db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); | |
| 917 | + } | |
| 918 | + } | |
| 873 | 919 | return 1; |
| 874 | 920 | } |
| 875 | 921 | |
| 876 | 922 | /* |
| 877 | 923 | ** Locate the root directory of the local repository tree. The root |
| 878 | 924 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -852,10 +852,32 @@ | |
| 852 | g.zConfigDbType = "configdb"; |
| 853 | } |
| 854 | g.zConfigDbName = zDbName; |
| 855 | } |
| 856 | |
| 857 | /* |
| 858 | ** If zDbName is a valid local database file, open it and return |
| 859 | ** true. If it is not a valid local database file, return 0. |
| 860 | */ |
| 861 | static int isValidLocalDb(const char *zDbName){ |
| @@ -868,10 +890,34 @@ | |
| 868 | db_open_or_attach(zDbName, "localdb", 0); |
| 869 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 870 | " WHERE name=='vfile'", db_name("localdb")); |
| 871 | if( zVFileDef==0 ) return 0; |
| 872 | |
| 873 | return 1; |
| 874 | } |
| 875 | |
| 876 | /* |
| 877 | ** Locate the root directory of the local repository tree. The root |
| 878 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -852,10 +852,32 @@ | |
| 852 | g.zConfigDbType = "configdb"; |
| 853 | } |
| 854 | g.zConfigDbName = zDbName; |
| 855 | } |
| 856 | |
| 857 | |
| 858 | /* |
| 859 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 860 | ** zColumn |
| 861 | */ |
| 862 | static int db_local_table_exists_but_lacks_column( |
| 863 | const char *zTable, |
| 864 | const char *zColumn |
| 865 | ){ |
| 866 | char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 867 | " WHERE name=='%s' /*scan*/", |
| 868 | db_name("localdb"), zTable); |
| 869 | int rc = 0; |
| 870 | if( zDef ){ |
| 871 | char *zPattern = mprintf("* %s *", zColumn); |
| 872 | rc = strglob(zPattern, zDef)==0; |
| 873 | fossil_free(zPattern); |
| 874 | fossil_free(zDef); |
| 875 | } |
| 876 | return rc; |
| 877 | } |
| 878 | |
| 879 | /* |
| 880 | ** If zDbName is a valid local database file, open it and return |
| 881 | ** true. If it is not a valid local database file, return 0. |
| 882 | */ |
| 883 | static int isValidLocalDb(const char *zDbName){ |
| @@ -868,10 +890,34 @@ | |
| 890 | db_open_or_attach(zDbName, "localdb", 0); |
| 891 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 892 | " WHERE name=='vfile'", db_name("localdb")); |
| 893 | if( zVFileDef==0 ) return 0; |
| 894 | |
| 895 | /* If the "isexe" column is missing from the vfile table, then |
| 896 | ** add it now. This code added on 2010-03-06. After all users have |
| 897 | ** upgraded, this code can be safely deleted. |
| 898 | */ |
| 899 | if( !strglob("* isexe *", zVFileDef) ){ |
| 900 | db_multi_exec("ALTER TABLE vfile ADD COLUMN isexe BOOLEAN DEFAULT 0"); |
| 901 | } |
| 902 | |
| 903 | /* If "islink"/"isLink" columns are missing from tables, then |
| 904 | ** add them now. This code added on 2011-01-17 and 2011-08-27. |
| 905 | ** After all users have upgraded, this code can be safely deleted. |
| 906 | */ |
| 907 | if( !strglob("* islink *", zVFileDef) ){ |
| 908 | db_multi_exec("ALTER TABLE vfile ADD COLUMN islink BOOLEAN DEFAULT 0"); |
| 909 | if( db_local_table_exists_but_lacks_column("stashfile", "isLink") ){ |
| 910 | db_multi_exec("ALTER TABLE stashfile ADD COLUMN isLink BOOL DEFAULT 0"); |
| 911 | } |
| 912 | if( db_local_table_exists_but_lacks_column("undo", "isLink") ){ |
| 913 | db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0"); |
| 914 | } |
| 915 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 916 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 917 | } |
| 918 | } |
| 919 | return 1; |
| 920 | } |
| 921 | |
| 922 | /* |
| 923 | ** Locate the root directory of the local repository tree. The root |
| 924 |
+69
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -771,10 +771,79 @@ | ||
| 771 | 771 | "format for the list in the file browser", |
| 772 | 772 | @ margin-left: 0.5em; |
| 773 | 773 | @ padding-left: 0.5em; |
| 774 | 774 | @ white-space: nowrap; |
| 775 | 775 | }, |
| 776 | + { ".filetree", | |
| 777 | + "tree-view file browser", | |
| 778 | + @ margin: 1em 0; | |
| 779 | + @ line-height: 1.5; | |
| 780 | + }, | |
| 781 | + { ".filetree ul", | |
| 782 | + "tree-view lists", | |
| 783 | + @ display: inline; | |
| 784 | + @ margin: 0; | |
| 785 | + @ padding: 0; | |
| 786 | + }, | |
| 787 | + { ".filetree li", | |
| 788 | + "tree-view list items", | |
| 789 | + @ display: inline; | |
| 790 | + }, | |
| 791 | + { ".filetree .subdir ul", | |
| 792 | + "tree-view lists below subdir", | |
| 793 | + @ position: relative; | |
| 794 | + @ display: block; | |
| 795 | + @ margin: 0 0 0 21px; | |
| 796 | + @ padding: 0; | |
| 797 | + }, | |
| 798 | + { ".filetree .subdir li", | |
| 799 | + "tree-view lists items below subdir", | |
| 800 | + @ position: relative; | |
| 801 | + @ display: block; | |
| 802 | + @ margin: 0; | |
| 803 | + @ padding: 0; | |
| 804 | + }, | |
| 805 | + { ".filetree .subdir li:before", | |
| 806 | + "tree-view node lines", | |
| 807 | + @ content: ''; | |
| 808 | + @ position: absolute; | |
| 809 | + @ top: -.8em; | |
| 810 | + @ left: -14px; | |
| 811 | + @ width: 14px; | |
| 812 | + @ height: 1.5em; | |
| 813 | + @ border-left: 2px solid #aaa; | |
| 814 | + @ border-bottom: 2px solid #aaa; | |
| 815 | + }, | |
| 816 | + { ".filetree .subdir > ul ul:before", | |
| 817 | + "tree-view directory lines", | |
| 818 | + @ content: ''; | |
| 819 | + @ position: absolute; | |
| 820 | + @ top: -1.5em; | |
| 821 | + @ bottom: 0; | |
| 822 | + @ left: -35px; | |
| 823 | + @ border-left: 2px solid #aaa; | |
| 824 | + }, | |
| 825 | + { ".filetree .subdir li:last-child > ul:before", | |
| 826 | + "hide lines for last-child directories", | |
| 827 | + @ display: none; | |
| 828 | + }, | |
| 829 | + { ".filetree a", | |
| 830 | + "tree-view links", | |
| 831 | + @ position: relative; | |
| 832 | + @ z-index: 1; | |
| 833 | + @ display: inline-block; | |
| 834 | + @ min-height: 16px; | |
| 835 | + @ margin-right: .5em; | |
| 836 | + @ padding-left: 21px; | |
| 837 | + @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); | |
| 838 | + @ background-position: center left; | |
| 839 | + @ background-repeat: no-repeat; | |
| 840 | + }, | |
| 841 | + { ".filetree .dir > a", | |
| 842 | + "tree-view directory links", | |
| 843 | + @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); | |
| 844 | + }, | |
| 776 | 845 | { "table.login_out", |
| 777 | 846 | "table format for login/out label/input table", |
| 778 | 847 | @ text-align: left; |
| 779 | 848 | @ margin-right: 10px; |
| 780 | 849 | @ margin-left: 10px; |
| 781 | 850 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -771,10 +771,79 @@ | |
| 771 | "format for the list in the file browser", |
| 772 | @ margin-left: 0.5em; |
| 773 | @ padding-left: 0.5em; |
| 774 | @ white-space: nowrap; |
| 775 | }, |
| 776 | { "table.login_out", |
| 777 | "table format for login/out label/input table", |
| 778 | @ text-align: left; |
| 779 | @ margin-right: 10px; |
| 780 | @ margin-left: 10px; |
| 781 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -771,10 +771,79 @@ | |
| 771 | "format for the list in the file browser", |
| 772 | @ margin-left: 0.5em; |
| 773 | @ padding-left: 0.5em; |
| 774 | @ white-space: nowrap; |
| 775 | }, |
| 776 | { ".filetree", |
| 777 | "tree-view file browser", |
| 778 | @ margin: 1em 0; |
| 779 | @ line-height: 1.5; |
| 780 | }, |
| 781 | { ".filetree ul", |
| 782 | "tree-view lists", |
| 783 | @ display: inline; |
| 784 | @ margin: 0; |
| 785 | @ padding: 0; |
| 786 | }, |
| 787 | { ".filetree li", |
| 788 | "tree-view list items", |
| 789 | @ display: inline; |
| 790 | }, |
| 791 | { ".filetree .subdir ul", |
| 792 | "tree-view lists below subdir", |
| 793 | @ position: relative; |
| 794 | @ display: block; |
| 795 | @ margin: 0 0 0 21px; |
| 796 | @ padding: 0; |
| 797 | }, |
| 798 | { ".filetree .subdir li", |
| 799 | "tree-view lists items below subdir", |
| 800 | @ position: relative; |
| 801 | @ display: block; |
| 802 | @ margin: 0; |
| 803 | @ padding: 0; |
| 804 | }, |
| 805 | { ".filetree .subdir li:before", |
| 806 | "tree-view node lines", |
| 807 | @ content: ''; |
| 808 | @ position: absolute; |
| 809 | @ top: -.8em; |
| 810 | @ left: -14px; |
| 811 | @ width: 14px; |
| 812 | @ height: 1.5em; |
| 813 | @ border-left: 2px solid #aaa; |
| 814 | @ border-bottom: 2px solid #aaa; |
| 815 | }, |
| 816 | { ".filetree .subdir > ul ul:before", |
| 817 | "tree-view directory lines", |
| 818 | @ content: ''; |
| 819 | @ position: absolute; |
| 820 | @ top: -1.5em; |
| 821 | @ bottom: 0; |
| 822 | @ left: -35px; |
| 823 | @ border-left: 2px solid #aaa; |
| 824 | }, |
| 825 | { ".filetree .subdir li:last-child > ul:before", |
| 826 | "hide lines for last-child directories", |
| 827 | @ display: none; |
| 828 | }, |
| 829 | { ".filetree a", |
| 830 | "tree-view links", |
| 831 | @ position: relative; |
| 832 | @ z-index: 1; |
| 833 | @ display: inline-block; |
| 834 | @ min-height: 16px; |
| 835 | @ margin-right: .5em; |
| 836 | @ padding-left: 21px; |
| 837 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 838 | @ background-position: center left; |
| 839 | @ background-repeat: no-repeat; |
| 840 | }, |
| 841 | { ".filetree .dir > a", |
| 842 | "tree-view directory links", |
| 843 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 844 | }, |
| 845 | { "table.login_out", |
| 846 | "table format for login/out label/input table", |
| 847 | @ text-align: left; |
| 848 | @ margin-right: 10px; |
| 849 | @ margin-left: 10px; |
| 850 |
+69
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -771,10 +771,79 @@ | ||
| 771 | 771 | "format for the list in the file browser", |
| 772 | 772 | @ margin-left: 0.5em; |
| 773 | 773 | @ padding-left: 0.5em; |
| 774 | 774 | @ white-space: nowrap; |
| 775 | 775 | }, |
| 776 | + { ".filetree", | |
| 777 | + "tree-view file browser", | |
| 778 | + @ margin: 1em 0; | |
| 779 | + @ line-height: 1.5; | |
| 780 | + }, | |
| 781 | + { ".filetree ul", | |
| 782 | + "tree-view lists", | |
| 783 | + @ display: inline; | |
| 784 | + @ margin: 0; | |
| 785 | + @ padding: 0; | |
| 786 | + }, | |
| 787 | + { ".filetree li", | |
| 788 | + "tree-view list items", | |
| 789 | + @ display: inline; | |
| 790 | + }, | |
| 791 | + { ".filetree .subdir ul", | |
| 792 | + "tree-view lists below subdir", | |
| 793 | + @ position: relative; | |
| 794 | + @ display: block; | |
| 795 | + @ margin: 0 0 0 21px; | |
| 796 | + @ padding: 0; | |
| 797 | + }, | |
| 798 | + { ".filetree .subdir li", | |
| 799 | + "tree-view lists items below subdir", | |
| 800 | + @ position: relative; | |
| 801 | + @ display: block; | |
| 802 | + @ margin: 0; | |
| 803 | + @ padding: 0; | |
| 804 | + }, | |
| 805 | + { ".filetree .subdir li:before", | |
| 806 | + "tree-view node lines", | |
| 807 | + @ content: ''; | |
| 808 | + @ position: absolute; | |
| 809 | + @ top: -.8em; | |
| 810 | + @ left: -14px; | |
| 811 | + @ width: 14px; | |
| 812 | + @ height: 1.5em; | |
| 813 | + @ border-left: 2px solid #aaa; | |
| 814 | + @ border-bottom: 2px solid #aaa; | |
| 815 | + }, | |
| 816 | + { ".filetree .subdir > ul ul:before", | |
| 817 | + "tree-view directory lines", | |
| 818 | + @ content: ''; | |
| 819 | + @ position: absolute; | |
| 820 | + @ top: -1.5em; | |
| 821 | + @ bottom: 0; | |
| 822 | + @ left: -35px; | |
| 823 | + @ border-left: 2px solid #aaa; | |
| 824 | + }, | |
| 825 | + { ".filetree .subdir li:last-child > ul:before", | |
| 826 | + "hide lines for last-child directories", | |
| 827 | + @ display: none; | |
| 828 | + }, | |
| 829 | + { ".filetree a", | |
| 830 | + "tree-view links", | |
| 831 | + @ position: relative; | |
| 832 | + @ z-index: 1; | |
| 833 | + @ display: inline-block; | |
| 834 | + @ min-height: 16px; | |
| 835 | + @ margin-right: .5em; | |
| 836 | + @ padding-left: 21px; | |
| 837 | + @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); | |
| 838 | + @ background-position: center left; | |
| 839 | + @ background-repeat: no-repeat; | |
| 840 | + }, | |
| 841 | + { ".filetree .dir > a", | |
| 842 | + "tree-view directory links", | |
| 843 | + @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); | |
| 844 | + }, | |
| 776 | 845 | { "table.login_out", |
| 777 | 846 | "table format for login/out label/input table", |
| 778 | 847 | @ text-align: left; |
| 779 | 848 | @ margin-right: 10px; |
| 780 | 849 | @ margin-left: 10px; |
| 781 | 850 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -771,10 +771,79 @@ | |
| 771 | "format for the list in the file browser", |
| 772 | @ margin-left: 0.5em; |
| 773 | @ padding-left: 0.5em; |
| 774 | @ white-space: nowrap; |
| 775 | }, |
| 776 | { "table.login_out", |
| 777 | "table format for login/out label/input table", |
| 778 | @ text-align: left; |
| 779 | @ margin-right: 10px; |
| 780 | @ margin-left: 10px; |
| 781 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -771,10 +771,79 @@ | |
| 771 | "format for the list in the file browser", |
| 772 | @ margin-left: 0.5em; |
| 773 | @ padding-left: 0.5em; |
| 774 | @ white-space: nowrap; |
| 775 | }, |
| 776 | { ".filetree", |
| 777 | "tree-view file browser", |
| 778 | @ margin: 1em 0; |
| 779 | @ line-height: 1.5; |
| 780 | }, |
| 781 | { ".filetree ul", |
| 782 | "tree-view lists", |
| 783 | @ display: inline; |
| 784 | @ margin: 0; |
| 785 | @ padding: 0; |
| 786 | }, |
| 787 | { ".filetree li", |
| 788 | "tree-view list items", |
| 789 | @ display: inline; |
| 790 | }, |
| 791 | { ".filetree .subdir ul", |
| 792 | "tree-view lists below subdir", |
| 793 | @ position: relative; |
| 794 | @ display: block; |
| 795 | @ margin: 0 0 0 21px; |
| 796 | @ padding: 0; |
| 797 | }, |
| 798 | { ".filetree .subdir li", |
| 799 | "tree-view lists items below subdir", |
| 800 | @ position: relative; |
| 801 | @ display: block; |
| 802 | @ margin: 0; |
| 803 | @ padding: 0; |
| 804 | }, |
| 805 | { ".filetree .subdir li:before", |
| 806 | "tree-view node lines", |
| 807 | @ content: ''; |
| 808 | @ position: absolute; |
| 809 | @ top: -.8em; |
| 810 | @ left: -14px; |
| 811 | @ width: 14px; |
| 812 | @ height: 1.5em; |
| 813 | @ border-left: 2px solid #aaa; |
| 814 | @ border-bottom: 2px solid #aaa; |
| 815 | }, |
| 816 | { ".filetree .subdir > ul ul:before", |
| 817 | "tree-view directory lines", |
| 818 | @ content: ''; |
| 819 | @ position: absolute; |
| 820 | @ top: -1.5em; |
| 821 | @ bottom: 0; |
| 822 | @ left: -35px; |
| 823 | @ border-left: 2px solid #aaa; |
| 824 | }, |
| 825 | { ".filetree .subdir li:last-child > ul:before", |
| 826 | "hide lines for last-child directories", |
| 827 | @ display: none; |
| 828 | }, |
| 829 | { ".filetree a", |
| 830 | "tree-view links", |
| 831 | @ position: relative; |
| 832 | @ z-index: 1; |
| 833 | @ display: inline-block; |
| 834 | @ min-height: 16px; |
| 835 | @ margin-right: .5em; |
| 836 | @ padding-left: 21px; |
| 837 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 838 | @ background-position: center left; |
| 839 | @ background-repeat: no-repeat; |
| 840 | }, |
| 841 | { ".filetree .dir > a", |
| 842 | "tree-view directory links", |
| 843 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 844 | }, |
| 845 | { "table.login_out", |
| 846 | "table format for login/out label/input table", |
| 847 | @ text-align: left; |
| 848 | @ margin-right: 10px; |
| 849 | @ margin-left: 10px; |
| 850 |
M
src/th.c
+3
-2
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -1154,11 +1154,12 @@ | ||
| 1154 | 1154 | |
| 1155 | 1155 | /* |
| 1156 | 1156 | ** Return true if variable (zVar, nVar) exists. |
| 1157 | 1157 | */ |
| 1158 | 1158 | int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){ |
| 1159 | - return thFindValue(interp, zVar, nVar, 0, 0)!=0; | |
| 1159 | + Th_Variable *pValue = thFindValue(interp, zVar, nVar, 0, 0); | |
| 1160 | + return pValue && pValue->zData; | |
| 1160 | 1161 | } |
| 1161 | 1162 | |
| 1162 | 1163 | /* |
| 1163 | 1164 | ** String (zVar, nVar) must contain the name of a scalar variable or |
| 1164 | 1165 | ** array member. If the variable does not exist it is created. The |
| @@ -1240,11 +1241,11 @@ | ||
| 1240 | 1241 | ** in the interpreter result and TH_ERROR is returned. |
| 1241 | 1242 | */ |
| 1242 | 1243 | int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){ |
| 1243 | 1244 | Th_Variable *pValue; |
| 1244 | 1245 | |
| 1245 | - pValue = thFindValue(interp, zVar, nVar, 1, 1); | |
| 1246 | + pValue = thFindValue(interp, zVar, nVar, 0, 1); | |
| 1246 | 1247 | if( !pValue ){ |
| 1247 | 1248 | return TH_ERROR; |
| 1248 | 1249 | } |
| 1249 | 1250 | |
| 1250 | 1251 | Th_Free(interp, pValue->zData); |
| 1251 | 1252 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -1154,11 +1154,12 @@ | |
| 1154 | |
| 1155 | /* |
| 1156 | ** Return true if variable (zVar, nVar) exists. |
| 1157 | */ |
| 1158 | int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){ |
| 1159 | return thFindValue(interp, zVar, nVar, 0, 0)!=0; |
| 1160 | } |
| 1161 | |
| 1162 | /* |
| 1163 | ** String (zVar, nVar) must contain the name of a scalar variable or |
| 1164 | ** array member. If the variable does not exist it is created. The |
| @@ -1240,11 +1241,11 @@ | |
| 1240 | ** in the interpreter result and TH_ERROR is returned. |
| 1241 | */ |
| 1242 | int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){ |
| 1243 | Th_Variable *pValue; |
| 1244 | |
| 1245 | pValue = thFindValue(interp, zVar, nVar, 1, 1); |
| 1246 | if( !pValue ){ |
| 1247 | return TH_ERROR; |
| 1248 | } |
| 1249 | |
| 1250 | Th_Free(interp, pValue->zData); |
| 1251 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -1154,11 +1154,12 @@ | |
| 1154 | |
| 1155 | /* |
| 1156 | ** Return true if variable (zVar, nVar) exists. |
| 1157 | */ |
| 1158 | int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){ |
| 1159 | Th_Variable *pValue = thFindValue(interp, zVar, nVar, 0, 0); |
| 1160 | return pValue && pValue->zData; |
| 1161 | } |
| 1162 | |
| 1163 | /* |
| 1164 | ** String (zVar, nVar) must contain the name of a scalar variable or |
| 1165 | ** array member. If the variable does not exist it is created. The |
| @@ -1240,11 +1241,11 @@ | |
| 1241 | ** in the interpreter result and TH_ERROR is returned. |
| 1242 | */ |
| 1243 | int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){ |
| 1244 | Th_Variable *pValue; |
| 1245 | |
| 1246 | pValue = thFindValue(interp, zVar, nVar, 0, 1); |
| 1247 | if( !pValue ){ |
| 1248 | return TH_ERROR; |
| 1249 | } |
| 1250 | |
| 1251 | Th_Free(interp, pValue->zData); |
| 1252 |
+35
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -107,5 +107,40 @@ | ||
| 107 | 107 | ############################################################################### |
| 108 | 108 | |
| 109 | 109 | fossil test-th-eval "expr 42.0%0.0" |
| 110 | 110 | test th1-modulus-by-zero-4 {$RESULT eq \ |
| 111 | 111 | {TH_ERROR: expected integer, got: "42.0"}} |
| 112 | + | |
| 113 | +############################################################################### | |
| 114 | + | |
| 115 | +fossil test-th-eval "set var 1; info exists var" | |
| 116 | +test th1-info-exists-1 {$RESULT eq {1}} | |
| 117 | + | |
| 118 | +############################################################################### | |
| 119 | + | |
| 120 | +fossil test-th-eval "set var 1; unset var; info exists var" | |
| 121 | +test th1-info-exists-2 {$RESULT eq {0}} | |
| 122 | + | |
| 123 | +############################################################################### | |
| 124 | + | |
| 125 | +fossil test-th-eval "set var 1; unset var; set var 2; info exists var" | |
| 126 | +test th1-info-exists-3 {$RESULT eq {1}} | |
| 127 | + | |
| 128 | +############################################################################### | |
| 129 | + | |
| 130 | +fossil test-th-eval "set var 1; expr {\$var+0}" | |
| 131 | +test th1-info-exists-4 {$RESULT eq {1}} | |
| 132 | + | |
| 133 | +############################################################################### | |
| 134 | + | |
| 135 | +fossil test-th-eval "set var 1; unset var; expr {\$var+0}" | |
| 136 | +test th1-info-exists-5 {$RESULT eq {TH_ERROR: no such variable: var}} | |
| 137 | + | |
| 138 | +############################################################################### | |
| 139 | + | |
| 140 | +fossil test-th-eval "set var 1; unset var" | |
| 141 | +test th1-unset-1 {$RESULT eq {var}} | |
| 142 | + | |
| 143 | +############################################################################### | |
| 144 | + | |
| 145 | +fossil test-th-eval "unset var" | |
| 146 | +test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}} | |
| 112 | 147 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -107,5 +107,40 @@ | |
| 107 | ############################################################################### |
| 108 | |
| 109 | fossil test-th-eval "expr 42.0%0.0" |
| 110 | test th1-modulus-by-zero-4 {$RESULT eq \ |
| 111 | {TH_ERROR: expected integer, got: "42.0"}} |
| 112 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -107,5 +107,40 @@ | |
| 107 | ############################################################################### |
| 108 | |
| 109 | fossil test-th-eval "expr 42.0%0.0" |
| 110 | test th1-modulus-by-zero-4 {$RESULT eq \ |
| 111 | {TH_ERROR: expected integer, got: "42.0"}} |
| 112 | |
| 113 | ############################################################################### |
| 114 | |
| 115 | fossil test-th-eval "set var 1; info exists var" |
| 116 | test th1-info-exists-1 {$RESULT eq {1}} |
| 117 | |
| 118 | ############################################################################### |
| 119 | |
| 120 | fossil test-th-eval "set var 1; unset var; info exists var" |
| 121 | test th1-info-exists-2 {$RESULT eq {0}} |
| 122 | |
| 123 | ############################################################################### |
| 124 | |
| 125 | fossil test-th-eval "set var 1; unset var; set var 2; info exists var" |
| 126 | test th1-info-exists-3 {$RESULT eq {1}} |
| 127 | |
| 128 | ############################################################################### |
| 129 | |
| 130 | fossil test-th-eval "set var 1; expr {\$var+0}" |
| 131 | test th1-info-exists-4 {$RESULT eq {1}} |
| 132 | |
| 133 | ############################################################################### |
| 134 | |
| 135 | fossil test-th-eval "set var 1; unset var; expr {\$var+0}" |
| 136 | test th1-info-exists-5 {$RESULT eq {TH_ERROR: no such variable: var}} |
| 137 | |
| 138 | ############################################################################### |
| 139 | |
| 140 | fossil test-th-eval "set var 1; unset var" |
| 141 | test th1-unset-1 {$RESULT eq {var}} |
| 142 | |
| 143 | ############################################################################### |
| 144 | |
| 145 | fossil test-th-eval "unset var" |
| 146 | test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}} |
| 147 |