Fossil SCM
Make it easier to debug the ZIP web page. Enhance consistency between the Tarball and ZIP web pages.
Commit
953cfbd497b227b28846a9e08eeaca4702faabbb
Parent
a3d8b27b45173f6…
2 files changed
+8
-9
+44
-26
+8
-9
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -544,11 +544,11 @@ | ||
| 544 | 544 | } |
| 545 | 545 | |
| 546 | 546 | /* |
| 547 | 547 | ** COMMAND: tarball* |
| 548 | 548 | ** |
| 549 | -** Usage: %fossil tarball VERSION OUTPUTFILE | |
| 549 | +** Usage: %fossil tarball VERSION OUTPUTFILE [OPTIONS] | |
| 550 | 550 | ** |
| 551 | 551 | ** Generate a compressed tarball for a specified version. If the --name |
| 552 | 552 | ** option is used, its argument becomes the name of the top-level directory |
| 553 | 553 | ** in the resulting tarball. If --name is omitted, the top-level directory |
| 554 | 554 | ** name is derived from the project name, the check-in date and time, and |
| @@ -612,21 +612,21 @@ | ||
| 612 | 612 | |
| 613 | 613 | /* |
| 614 | 614 | ** WEBPAGE: tarball |
| 615 | 615 | ** URL: /tarball |
| 616 | 616 | ** |
| 617 | -** Generate a compressed tarball for a check-in and return that | |
| 618 | -** tarball as the HTTP reply content. | |
| 617 | +** Generate a compressed tarball for the check-in specified by the "uuid" | |
| 618 | +** query parameter. Return that ZIP archive as the HTTP reply content. | |
| 619 | 619 | ** |
| 620 | 620 | ** Query parameters: |
| 621 | 621 | ** |
| 622 | 622 | ** name=NAME[.tar.gz] The base name of the output file. The default |
| 623 | 623 | ** value is a configuration parameter in the project |
| 624 | -** settings. A prefix of the name, omitting the extension, | |
| 625 | -** is used as the top-most directory name. | |
| 624 | +** settings. A prefix of the name, omitting the | |
| 625 | +** extension, is used as the top-most directory name. | |
| 626 | 626 | ** |
| 627 | -** uuid=TAG The check-in that is turned into a tarball. | |
| 627 | +** uuid=TAG The check-in that is turned into a compressed tarball. | |
| 628 | 628 | ** Defaults to "trunk". |
| 629 | 629 | ** |
| 630 | 630 | ** in=PATTERN Only include files that match the comma-separate |
| 631 | 631 | ** list of GLOB patterns in PATTERN, as with ex= |
| 632 | 632 | ** |
| @@ -655,11 +655,10 @@ | ||
| 655 | 655 | nRid = strlen(zRid); |
| 656 | 656 | zInclude = P("in"); |
| 657 | 657 | if( zInclude ) pInclude = glob_create(zInclude); |
| 658 | 658 | zExclude = P("ex"); |
| 659 | 659 | if( zExclude ) pExclude = glob_create(zExclude); |
| 660 | - | |
| 661 | 660 | if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){ |
| 662 | 661 | /* Special case: Remove the ".tar.gz" suffix. */ |
| 663 | 662 | nName -= 7; |
| 664 | 663 | zName[nName] = 0; |
| 665 | 664 | }else{ |
| @@ -680,13 +679,13 @@ | ||
| 680 | 679 | if( nRid==0 && nName>10 ) zName[10] = 0; |
| 681 | 680 | |
| 682 | 681 | /* Compute a unique key for the cache entry based on query parameters */ |
| 683 | 682 | blob_init(&cacheKey, 0, 0); |
| 684 | 683 | blob_appendf(&cacheKey, "/tarball/%z", rid_to_uuid(rid)); |
| 684 | + blob_appendf(&cacheKey, "/%q", zName); | |
| 685 | 685 | if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); |
| 686 | 686 | if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); |
| 687 | - blob_appendf(&cacheKey, "/%q", zName); | |
| 688 | 687 | zKey = blob_str(&cacheKey); |
| 689 | 688 | |
| 690 | 689 | if( P("debug")!=0 ){ |
| 691 | 690 | style_header("Tarball Generator Debug Screen"); |
| 692 | 691 | @ zName = "%h(zName)"<br /> |
| @@ -701,11 +700,11 @@ | ||
| 701 | 700 | style_footer(); |
| 702 | 701 | return; |
| 703 | 702 | } |
| 704 | 703 | if( referred_from_login() ){ |
| 705 | 704 | style_header("Tarball Download"); |
| 706 | - @ <form action='%R/tarball'> | |
| 705 | + @ <form action='%R/tarball/%h(zName).tar.gz'> | |
| 707 | 706 | cgi_query_parameters_to_hidden(); |
| 708 | 707 | @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content |
| 709 | 708 | @ of check-in <b>%h(zRid)</b>: |
| 710 | 709 | @ <input type="submit" value="Download" /> |
| 711 | 710 | @ </form> |
| 712 | 711 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -544,11 +544,11 @@ | |
| 544 | } |
| 545 | |
| 546 | /* |
| 547 | ** COMMAND: tarball* |
| 548 | ** |
| 549 | ** Usage: %fossil tarball VERSION OUTPUTFILE |
| 550 | ** |
| 551 | ** Generate a compressed tarball for a specified version. If the --name |
| 552 | ** option is used, its argument becomes the name of the top-level directory |
| 553 | ** in the resulting tarball. If --name is omitted, the top-level directory |
| 554 | ** name is derived from the project name, the check-in date and time, and |
| @@ -612,21 +612,21 @@ | |
| 612 | |
| 613 | /* |
| 614 | ** WEBPAGE: tarball |
| 615 | ** URL: /tarball |
| 616 | ** |
| 617 | ** Generate a compressed tarball for a check-in and return that |
| 618 | ** tarball as the HTTP reply content. |
| 619 | ** |
| 620 | ** Query parameters: |
| 621 | ** |
| 622 | ** name=NAME[.tar.gz] The base name of the output file. The default |
| 623 | ** value is a configuration parameter in the project |
| 624 | ** settings. A prefix of the name, omitting the extension, |
| 625 | ** is used as the top-most directory name. |
| 626 | ** |
| 627 | ** uuid=TAG The check-in that is turned into a tarball. |
| 628 | ** Defaults to "trunk". |
| 629 | ** |
| 630 | ** in=PATTERN Only include files that match the comma-separate |
| 631 | ** list of GLOB patterns in PATTERN, as with ex= |
| 632 | ** |
| @@ -655,11 +655,10 @@ | |
| 655 | nRid = strlen(zRid); |
| 656 | zInclude = P("in"); |
| 657 | if( zInclude ) pInclude = glob_create(zInclude); |
| 658 | zExclude = P("ex"); |
| 659 | if( zExclude ) pExclude = glob_create(zExclude); |
| 660 | |
| 661 | if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){ |
| 662 | /* Special case: Remove the ".tar.gz" suffix. */ |
| 663 | nName -= 7; |
| 664 | zName[nName] = 0; |
| 665 | }else{ |
| @@ -680,13 +679,13 @@ | |
| 680 | if( nRid==0 && nName>10 ) zName[10] = 0; |
| 681 | |
| 682 | /* Compute a unique key for the cache entry based on query parameters */ |
| 683 | blob_init(&cacheKey, 0, 0); |
| 684 | blob_appendf(&cacheKey, "/tarball/%z", rid_to_uuid(rid)); |
| 685 | if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); |
| 686 | if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); |
| 687 | blob_appendf(&cacheKey, "/%q", zName); |
| 688 | zKey = blob_str(&cacheKey); |
| 689 | |
| 690 | if( P("debug")!=0 ){ |
| 691 | style_header("Tarball Generator Debug Screen"); |
| 692 | @ zName = "%h(zName)"<br /> |
| @@ -701,11 +700,11 @@ | |
| 701 | style_footer(); |
| 702 | return; |
| 703 | } |
| 704 | if( referred_from_login() ){ |
| 705 | style_header("Tarball Download"); |
| 706 | @ <form action='%R/tarball'> |
| 707 | cgi_query_parameters_to_hidden(); |
| 708 | @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content |
| 709 | @ of check-in <b>%h(zRid)</b>: |
| 710 | @ <input type="submit" value="Download" /> |
| 711 | @ </form> |
| 712 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -544,11 +544,11 @@ | |
| 544 | } |
| 545 | |
| 546 | /* |
| 547 | ** COMMAND: tarball* |
| 548 | ** |
| 549 | ** Usage: %fossil tarball VERSION OUTPUTFILE [OPTIONS] |
| 550 | ** |
| 551 | ** Generate a compressed tarball for a specified version. If the --name |
| 552 | ** option is used, its argument becomes the name of the top-level directory |
| 553 | ** in the resulting tarball. If --name is omitted, the top-level directory |
| 554 | ** name is derived from the project name, the check-in date and time, and |
| @@ -612,21 +612,21 @@ | |
| 612 | |
| 613 | /* |
| 614 | ** WEBPAGE: tarball |
| 615 | ** URL: /tarball |
| 616 | ** |
| 617 | ** Generate a compressed tarball for the check-in specified by the "uuid" |
| 618 | ** query parameter. Return that ZIP archive as the HTTP reply content. |
| 619 | ** |
| 620 | ** Query parameters: |
| 621 | ** |
| 622 | ** name=NAME[.tar.gz] The base name of the output file. The default |
| 623 | ** value is a configuration parameter in the project |
| 624 | ** settings. A prefix of the name, omitting the |
| 625 | ** extension, is used as the top-most directory name. |
| 626 | ** |
| 627 | ** uuid=TAG The check-in that is turned into a compressed tarball. |
| 628 | ** Defaults to "trunk". |
| 629 | ** |
| 630 | ** in=PATTERN Only include files that match the comma-separate |
| 631 | ** list of GLOB patterns in PATTERN, as with ex= |
| 632 | ** |
| @@ -655,11 +655,10 @@ | |
| 655 | nRid = strlen(zRid); |
| 656 | zInclude = P("in"); |
| 657 | if( zInclude ) pInclude = glob_create(zInclude); |
| 658 | zExclude = P("ex"); |
| 659 | if( zExclude ) pExclude = glob_create(zExclude); |
| 660 | if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){ |
| 661 | /* Special case: Remove the ".tar.gz" suffix. */ |
| 662 | nName -= 7; |
| 663 | zName[nName] = 0; |
| 664 | }else{ |
| @@ -680,13 +679,13 @@ | |
| 679 | if( nRid==0 && nName>10 ) zName[10] = 0; |
| 680 | |
| 681 | /* Compute a unique key for the cache entry based on query parameters */ |
| 682 | blob_init(&cacheKey, 0, 0); |
| 683 | blob_appendf(&cacheKey, "/tarball/%z", rid_to_uuid(rid)); |
| 684 | blob_appendf(&cacheKey, "/%q", zName); |
| 685 | if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); |
| 686 | if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); |
| 687 | zKey = blob_str(&cacheKey); |
| 688 | |
| 689 | if( P("debug")!=0 ){ |
| 690 | style_header("Tarball Generator Debug Screen"); |
| 691 | @ zName = "%h(zName)"<br /> |
| @@ -701,11 +700,11 @@ | |
| 700 | style_footer(); |
| 701 | return; |
| 702 | } |
| 703 | if( referred_from_login() ){ |
| 704 | style_header("Tarball Download"); |
| 705 | @ <form action='%R/tarball/%h(zName).tar.gz'> |
| 706 | cgi_query_parameters_to_hidden(); |
| 707 | @ <p>Tarball named <b>%h(zName).tar.gz</b> holding the content |
| 708 | @ of check-in <b>%h(zRid)</b>: |
| 709 | @ <input type="submit" value="Download" /> |
| 710 | @ </form> |
| 711 |
+44
-26
| --- src/zip.c | ||
| +++ src/zip.c | ||
| @@ -402,11 +402,11 @@ | ||
| 402 | 402 | ** Usage: %fossil zip VERSION OUTPUTFILE [OPTIONS] |
| 403 | 403 | ** |
| 404 | 404 | ** Generate a ZIP archive for a check-in. If the --name option is |
| 405 | 405 | ** used, its argument becomes the name of the top-level directory in the |
| 406 | 406 | ** resulting ZIP archive. If --name is omitted, the top-level directory |
| 407 | -** named is derived from the project name, the check-in date and time, and | |
| 407 | +** name is derived from the project name, the check-in date and time, and | |
| 408 | 408 | ** the artifact ID of the check-in. |
| 409 | 409 | ** |
| 410 | 410 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 411 | 411 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 412 | 412 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| @@ -437,11 +437,16 @@ | ||
| 437 | 437 | verify_all_options(); |
| 438 | 438 | |
| 439 | 439 | if( g.argc!=4 ){ |
| 440 | 440 | usage("VERSION OUTPUTFILE"); |
| 441 | 441 | } |
| 442 | - rid = name_to_typed_rid(g.argv[2],"ci"); | |
| 442 | + rid = name_to_typed_rid(g.argv[2], "ci"); | |
| 443 | + if( rid==0 ){ | |
| 444 | + fossil_fatal("Check-in not found: %s", g.argv[2]); | |
| 445 | + return; | |
| 446 | + } | |
| 447 | + | |
| 443 | 448 | if( zName==0 ){ |
| 444 | 449 | zName = db_text("default-name", |
| 445 | 450 | "SELECT replace(%Q,' ','_') " |
| 446 | 451 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| 447 | 452 | " || substr(blob.uuid, 1, 10)" |
| @@ -450,31 +455,31 @@ | ||
| 450 | 455 | " AND blob.rid=%d", |
| 451 | 456 | db_get("project-name", "unnamed"), rid, rid |
| 452 | 457 | ); |
| 453 | 458 | } |
| 454 | 459 | zip_of_checkin(rid, &zip, zName, pInclude, pExclude); |
| 455 | - blob_write_to_file(&zip, g.argv[3]); | |
| 456 | 460 | glob_free(pInclude); |
| 457 | 461 | glob_free(pExclude); |
| 462 | + blob_write_to_file(&zip, g.argv[3]); | |
| 463 | + blob_reset(&zip); | |
| 458 | 464 | } |
| 459 | 465 | |
| 460 | 466 | /* |
| 461 | 467 | ** WEBPAGE: zip |
| 462 | 468 | ** URL: /zip |
| 463 | 469 | ** |
| 464 | -** Generate a ZIP archive for a checkin specified by the uuid= query parameter. | |
| 465 | -** Return that ZIP archive as the HTTP reply content. | |
| 470 | +** Generate a ZIP archive for the check-in specified by the "uuid" | |
| 471 | +** query parameter. Return that ZIP archive as the HTTP reply content. | |
| 466 | 472 | ** |
| 467 | 473 | ** Query parameters: |
| 468 | 474 | ** |
| 469 | 475 | ** name=NAME[.zip] The base name of the output file. The default |
| 470 | 476 | ** value is a configuration parameter in the project |
| 471 | -** settings. A prefix of the name, omitting the extension, | |
| 472 | -** is used as the top-most directory name. | |
| 473 | - | |
| 477 | +** settings. A prefix of the name, omitting the | |
| 478 | +** extension, is used as the top-most directory name. | |
| 474 | 479 | ** |
| 475 | -** uuid=TAG The check-in that is turned into a ZIP file. | |
| 480 | +** uuid=TAG The check-in that is turned into a ZIP archive. | |
| 476 | 481 | ** Defaults to "trunk". |
| 477 | 482 | ** |
| 478 | 483 | ** in=PATTERN Only include files that match the comma-separate |
| 479 | 484 | ** list of GLOB patterns in PATTERN, as with ex= |
| 480 | 485 | ** |
| @@ -483,19 +488,18 @@ | ||
| 483 | 488 | ** pattern can optionally be quoted using ".." or '..'. |
| 484 | 489 | ** Any file matching both ex= and in= is excluded. |
| 485 | 490 | */ |
| 486 | 491 | void baseline_zip_page(void){ |
| 487 | 492 | int rid; |
| 488 | - char *zName, *zRid; | |
| 493 | + char *zName, *zRid, *zKey; | |
| 489 | 494 | int nName, nRid; |
| 490 | - Blob zip; | |
| 491 | - char *zKey; | |
| 492 | 495 | const char *zInclude; /* The in= query parameter */ |
| 493 | 496 | const char *zExclude; /* The ex= query parameter */ |
| 494 | 497 | Blob cacheKey; /* The key to cache */ |
| 495 | 498 | Glob *pInclude = 0; /* The compiled in= glob pattern */ |
| 496 | 499 | Glob *pExclude = 0; /* The compiled ex= glob pattern */ |
| 500 | + Blob zip; /* ZIP archive accumulated here */ | |
| 497 | 501 | |
| 498 | 502 | login_check_credentials(); |
| 499 | 503 | if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; } |
| 500 | 504 | load_control(); |
| 501 | 505 | zName = mprintf("%s", PD("name","")); |
| @@ -518,14 +522,38 @@ | ||
| 518 | 522 | zName[nName] = 0; |
| 519 | 523 | break; |
| 520 | 524 | } |
| 521 | 525 | } |
| 522 | 526 | } |
| 523 | - rid = name_to_typed_rid(nRid?zRid:zName,"ci"); | |
| 527 | + rid = name_to_typed_rid(nRid?zRid:zName, "ci"); | |
| 524 | 528 | if( rid==0 ){ |
| 525 | 529 | @ Not found |
| 526 | 530 | return; |
| 531 | + } | |
| 532 | + if( nRid==0 && nName>10 ) zName[10] = 0; | |
| 533 | + | |
| 534 | + /* Compute a unique key for the cache entry based on query parameters */ | |
| 535 | + blob_init(&cacheKey, 0, 0); | |
| 536 | + blob_appendf(&cacheKey, "/zip/%z", rid_to_uuid(rid)); | |
| 537 | + blob_appendf(&cacheKey, "/%q", zName); | |
| 538 | + if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); | |
| 539 | + if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); | |
| 540 | + zKey = blob_str(&cacheKey); | |
| 541 | + | |
| 542 | + if( P("debug")!=0 ){ | |
| 543 | + style_header("ZIP Archive Generator Debug Screen"); | |
| 544 | + @ zName = "%h(zName)"<br /> | |
| 545 | + @ rid = %d(rid)<br /> | |
| 546 | + if( zInclude ){ | |
| 547 | + @ zInclude = "%h(zInclude)"<br /> | |
| 548 | + } | |
| 549 | + if( zExclude ){ | |
| 550 | + @ zExclude = "%h(zExclude)"<br /> | |
| 551 | + } | |
| 552 | + @ zKey = "%h(zKey)" | |
| 553 | + style_footer(); | |
| 554 | + return; | |
| 527 | 555 | } |
| 528 | 556 | if( referred_from_login() ){ |
| 529 | 557 | style_header("ZIP Archive Download"); |
| 530 | 558 | @ <form action='%R/zip/%h(zName).zip'> |
| 531 | 559 | cgi_query_parameters_to_hidden(); |
| @@ -534,28 +562,18 @@ | ||
| 534 | 562 | @ <input type="submit" value="Download" /> |
| 535 | 563 | @ </form> |
| 536 | 564 | style_footer(); |
| 537 | 565 | return; |
| 538 | 566 | } |
| 539 | - if( nRid==0 && nName>10 ) zName[10] = 0; | |
| 540 | - | |
| 541 | - /* Compute a unique key for the cache entry based on query parameters */ | |
| 542 | - blob_init(&cacheKey, 0, 0); | |
| 543 | - blob_appendf(&cacheKey, "/zip/%z", rid_to_uuid(rid)); | |
| 544 | - if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); | |
| 545 | - if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); | |
| 546 | - blob_appendf(&cacheKey, "/%q", zName); | |
| 547 | - zKey = blob_str(&cacheKey); | |
| 548 | - | |
| 549 | 567 | blob_zero(&zip); |
| 550 | 568 | if( cache_read(&zip, zKey)==0 ){ |
| 551 | 569 | zip_of_checkin(rid, &zip, zName, pInclude, pExclude); |
| 552 | 570 | cache_write(&zip, zKey); |
| 553 | 571 | } |
| 554 | - fossil_free( zName ); | |
| 555 | - fossil_free( zRid ); | |
| 556 | - blob_reset(&cacheKey); | |
| 557 | 572 | glob_free(pInclude); |
| 558 | 573 | glob_free(pExclude); |
| 574 | + fossil_free(zName); | |
| 575 | + fossil_free(zRid); | |
| 576 | + blob_reset(&cacheKey); | |
| 559 | 577 | cgi_set_content(&zip); |
| 560 | 578 | cgi_set_content_type("application/zip"); |
| 561 | 579 | } |
| 562 | 580 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -402,11 +402,11 @@ | |
| 402 | ** Usage: %fossil zip VERSION OUTPUTFILE [OPTIONS] |
| 403 | ** |
| 404 | ** Generate a ZIP archive for a check-in. If the --name option is |
| 405 | ** used, its argument becomes the name of the top-level directory in the |
| 406 | ** resulting ZIP archive. If --name is omitted, the top-level directory |
| 407 | ** named is derived from the project name, the check-in date and time, and |
| 408 | ** the artifact ID of the check-in. |
| 409 | ** |
| 410 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 411 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 412 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| @@ -437,11 +437,16 @@ | |
| 437 | verify_all_options(); |
| 438 | |
| 439 | if( g.argc!=4 ){ |
| 440 | usage("VERSION OUTPUTFILE"); |
| 441 | } |
| 442 | rid = name_to_typed_rid(g.argv[2],"ci"); |
| 443 | if( zName==0 ){ |
| 444 | zName = db_text("default-name", |
| 445 | "SELECT replace(%Q,' ','_') " |
| 446 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| 447 | " || substr(blob.uuid, 1, 10)" |
| @@ -450,31 +455,31 @@ | |
| 450 | " AND blob.rid=%d", |
| 451 | db_get("project-name", "unnamed"), rid, rid |
| 452 | ); |
| 453 | } |
| 454 | zip_of_checkin(rid, &zip, zName, pInclude, pExclude); |
| 455 | blob_write_to_file(&zip, g.argv[3]); |
| 456 | glob_free(pInclude); |
| 457 | glob_free(pExclude); |
| 458 | } |
| 459 | |
| 460 | /* |
| 461 | ** WEBPAGE: zip |
| 462 | ** URL: /zip |
| 463 | ** |
| 464 | ** Generate a ZIP archive for a checkin specified by the uuid= query parameter. |
| 465 | ** Return that ZIP archive as the HTTP reply content. |
| 466 | ** |
| 467 | ** Query parameters: |
| 468 | ** |
| 469 | ** name=NAME[.zip] The base name of the output file. The default |
| 470 | ** value is a configuration parameter in the project |
| 471 | ** settings. A prefix of the name, omitting the extension, |
| 472 | ** is used as the top-most directory name. |
| 473 | |
| 474 | ** |
| 475 | ** uuid=TAG The check-in that is turned into a ZIP file. |
| 476 | ** Defaults to "trunk". |
| 477 | ** |
| 478 | ** in=PATTERN Only include files that match the comma-separate |
| 479 | ** list of GLOB patterns in PATTERN, as with ex= |
| 480 | ** |
| @@ -483,19 +488,18 @@ | |
| 483 | ** pattern can optionally be quoted using ".." or '..'. |
| 484 | ** Any file matching both ex= and in= is excluded. |
| 485 | */ |
| 486 | void baseline_zip_page(void){ |
| 487 | int rid; |
| 488 | char *zName, *zRid; |
| 489 | int nName, nRid; |
| 490 | Blob zip; |
| 491 | char *zKey; |
| 492 | const char *zInclude; /* The in= query parameter */ |
| 493 | const char *zExclude; /* The ex= query parameter */ |
| 494 | Blob cacheKey; /* The key to cache */ |
| 495 | Glob *pInclude = 0; /* The compiled in= glob pattern */ |
| 496 | Glob *pExclude = 0; /* The compiled ex= glob pattern */ |
| 497 | |
| 498 | login_check_credentials(); |
| 499 | if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; } |
| 500 | load_control(); |
| 501 | zName = mprintf("%s", PD("name","")); |
| @@ -518,14 +522,38 @@ | |
| 518 | zName[nName] = 0; |
| 519 | break; |
| 520 | } |
| 521 | } |
| 522 | } |
| 523 | rid = name_to_typed_rid(nRid?zRid:zName,"ci"); |
| 524 | if( rid==0 ){ |
| 525 | @ Not found |
| 526 | return; |
| 527 | } |
| 528 | if( referred_from_login() ){ |
| 529 | style_header("ZIP Archive Download"); |
| 530 | @ <form action='%R/zip/%h(zName).zip'> |
| 531 | cgi_query_parameters_to_hidden(); |
| @@ -534,28 +562,18 @@ | |
| 534 | @ <input type="submit" value="Download" /> |
| 535 | @ </form> |
| 536 | style_footer(); |
| 537 | return; |
| 538 | } |
| 539 | if( nRid==0 && nName>10 ) zName[10] = 0; |
| 540 | |
| 541 | /* Compute a unique key for the cache entry based on query parameters */ |
| 542 | blob_init(&cacheKey, 0, 0); |
| 543 | blob_appendf(&cacheKey, "/zip/%z", rid_to_uuid(rid)); |
| 544 | if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); |
| 545 | if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); |
| 546 | blob_appendf(&cacheKey, "/%q", zName); |
| 547 | zKey = blob_str(&cacheKey); |
| 548 | |
| 549 | blob_zero(&zip); |
| 550 | if( cache_read(&zip, zKey)==0 ){ |
| 551 | zip_of_checkin(rid, &zip, zName, pInclude, pExclude); |
| 552 | cache_write(&zip, zKey); |
| 553 | } |
| 554 | fossil_free( zName ); |
| 555 | fossil_free( zRid ); |
| 556 | blob_reset(&cacheKey); |
| 557 | glob_free(pInclude); |
| 558 | glob_free(pExclude); |
| 559 | cgi_set_content(&zip); |
| 560 | cgi_set_content_type("application/zip"); |
| 561 | } |
| 562 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -402,11 +402,11 @@ | |
| 402 | ** Usage: %fossil zip VERSION OUTPUTFILE [OPTIONS] |
| 403 | ** |
| 404 | ** Generate a ZIP archive for a check-in. If the --name option is |
| 405 | ** used, its argument becomes the name of the top-level directory in the |
| 406 | ** resulting ZIP archive. If --name is omitted, the top-level directory |
| 407 | ** name is derived from the project name, the check-in date and time, and |
| 408 | ** the artifact ID of the check-in. |
| 409 | ** |
| 410 | ** The GLOBLIST argument to --exclude and --include can be a comma-separated |
| 411 | ** list of glob patterns, where each glob pattern may optionally be enclosed |
| 412 | ** in "..." or '...' so that it may contain commas. If a file matches both |
| @@ -437,11 +437,16 @@ | |
| 437 | verify_all_options(); |
| 438 | |
| 439 | if( g.argc!=4 ){ |
| 440 | usage("VERSION OUTPUTFILE"); |
| 441 | } |
| 442 | rid = name_to_typed_rid(g.argv[2], "ci"); |
| 443 | if( rid==0 ){ |
| 444 | fossil_fatal("Check-in not found: %s", g.argv[2]); |
| 445 | return; |
| 446 | } |
| 447 | |
| 448 | if( zName==0 ){ |
| 449 | zName = db_text("default-name", |
| 450 | "SELECT replace(%Q,' ','_') " |
| 451 | " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) " |
| 452 | " || substr(blob.uuid, 1, 10)" |
| @@ -450,31 +455,31 @@ | |
| 455 | " AND blob.rid=%d", |
| 456 | db_get("project-name", "unnamed"), rid, rid |
| 457 | ); |
| 458 | } |
| 459 | zip_of_checkin(rid, &zip, zName, pInclude, pExclude); |
| 460 | glob_free(pInclude); |
| 461 | glob_free(pExclude); |
| 462 | blob_write_to_file(&zip, g.argv[3]); |
| 463 | blob_reset(&zip); |
| 464 | } |
| 465 | |
| 466 | /* |
| 467 | ** WEBPAGE: zip |
| 468 | ** URL: /zip |
| 469 | ** |
| 470 | ** Generate a ZIP archive for the check-in specified by the "uuid" |
| 471 | ** query parameter. Return that ZIP archive as the HTTP reply content. |
| 472 | ** |
| 473 | ** Query parameters: |
| 474 | ** |
| 475 | ** name=NAME[.zip] The base name of the output file. The default |
| 476 | ** value is a configuration parameter in the project |
| 477 | ** settings. A prefix of the name, omitting the |
| 478 | ** extension, is used as the top-most directory name. |
| 479 | ** |
| 480 | ** uuid=TAG The check-in that is turned into a ZIP archive. |
| 481 | ** Defaults to "trunk". |
| 482 | ** |
| 483 | ** in=PATTERN Only include files that match the comma-separate |
| 484 | ** list of GLOB patterns in PATTERN, as with ex= |
| 485 | ** |
| @@ -483,19 +488,18 @@ | |
| 488 | ** pattern can optionally be quoted using ".." or '..'. |
| 489 | ** Any file matching both ex= and in= is excluded. |
| 490 | */ |
| 491 | void baseline_zip_page(void){ |
| 492 | int rid; |
| 493 | char *zName, *zRid, *zKey; |
| 494 | int nName, nRid; |
| 495 | const char *zInclude; /* The in= query parameter */ |
| 496 | const char *zExclude; /* The ex= query parameter */ |
| 497 | Blob cacheKey; /* The key to cache */ |
| 498 | Glob *pInclude = 0; /* The compiled in= glob pattern */ |
| 499 | Glob *pExclude = 0; /* The compiled ex= glob pattern */ |
| 500 | Blob zip; /* ZIP archive accumulated here */ |
| 501 | |
| 502 | login_check_credentials(); |
| 503 | if( !g.perm.Zip ){ login_needed(g.anon.Zip); return; } |
| 504 | load_control(); |
| 505 | zName = mprintf("%s", PD("name","")); |
| @@ -518,14 +522,38 @@ | |
| 522 | zName[nName] = 0; |
| 523 | break; |
| 524 | } |
| 525 | } |
| 526 | } |
| 527 | rid = name_to_typed_rid(nRid?zRid:zName, "ci"); |
| 528 | if( rid==0 ){ |
| 529 | @ Not found |
| 530 | return; |
| 531 | } |
| 532 | if( nRid==0 && nName>10 ) zName[10] = 0; |
| 533 | |
| 534 | /* Compute a unique key for the cache entry based on query parameters */ |
| 535 | blob_init(&cacheKey, 0, 0); |
| 536 | blob_appendf(&cacheKey, "/zip/%z", rid_to_uuid(rid)); |
| 537 | blob_appendf(&cacheKey, "/%q", zName); |
| 538 | if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude); |
| 539 | if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude); |
| 540 | zKey = blob_str(&cacheKey); |
| 541 | |
| 542 | if( P("debug")!=0 ){ |
| 543 | style_header("ZIP Archive Generator Debug Screen"); |
| 544 | @ zName = "%h(zName)"<br /> |
| 545 | @ rid = %d(rid)<br /> |
| 546 | if( zInclude ){ |
| 547 | @ zInclude = "%h(zInclude)"<br /> |
| 548 | } |
| 549 | if( zExclude ){ |
| 550 | @ zExclude = "%h(zExclude)"<br /> |
| 551 | } |
| 552 | @ zKey = "%h(zKey)" |
| 553 | style_footer(); |
| 554 | return; |
| 555 | } |
| 556 | if( referred_from_login() ){ |
| 557 | style_header("ZIP Archive Download"); |
| 558 | @ <form action='%R/zip/%h(zName).zip'> |
| 559 | cgi_query_parameters_to_hidden(); |
| @@ -534,28 +562,18 @@ | |
| 562 | @ <input type="submit" value="Download" /> |
| 563 | @ </form> |
| 564 | style_footer(); |
| 565 | return; |
| 566 | } |
| 567 | blob_zero(&zip); |
| 568 | if( cache_read(&zip, zKey)==0 ){ |
| 569 | zip_of_checkin(rid, &zip, zName, pInclude, pExclude); |
| 570 | cache_write(&zip, zKey); |
| 571 | } |
| 572 | glob_free(pInclude); |
| 573 | glob_free(pExclude); |
| 574 | fossil_free(zName); |
| 575 | fossil_free(zRid); |
| 576 | blob_reset(&cacheKey); |
| 577 | cgi_set_content(&zip); |
| 578 | cgi_set_content_type("application/zip"); |
| 579 | } |
| 580 |