Fossil SCM
Show before and after context on the /ci_edit page.
Commit
664da57e00c2be88ec4ce4a4af1ab1cf956fd44bba7b532b0e2bd0ea3ef68de4
Parent
2bee647ed6fd4bf…
1 file changed
+121
-92
+121
-92
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -271,13 +271,18 @@ | ||
| 271 | 271 | } |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | 274 | /* |
| 275 | 275 | ** Show the context graph (immediate parents and children) for |
| 276 | -** check-in rid and rid2 | |
| 276 | +** check-in rid and rid2. rid2 might be zero, in which case only | |
| 277 | +** show the context for rid1. | |
| 277 | 278 | */ |
| 278 | -void render_checkin_context(int rid, int rid2, int parentsOnly, int mFlags){ | |
| 279 | +void render_checkin_context( | |
| 280 | + int rid, int rid2, /* One or two checkins for which to show context */ | |
| 281 | + int mRCCFlags, /* Flags. 1: parents only. 2: no-highlight */ | |
| 282 | + int mFlags /* Graph flags */ | |
| 283 | +){ | |
| 279 | 284 | Blob sql; |
| 280 | 285 | Stmt q; |
| 281 | 286 | int rx[2]; |
| 282 | 287 | int i, n; |
| 283 | 288 | rx[0] = rid; |
| @@ -295,11 +300,11 @@ | ||
| 295 | 300 | "INSERT OR IGNORE INTO ok VALUES(%d);" |
| 296 | 301 | "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;", |
| 297 | 302 | rx[i], rx[i] |
| 298 | 303 | ); |
| 299 | 304 | } |
| 300 | - if( !parentsOnly ){ | |
| 305 | + if( (mRCCFlags & 0x01)==0 ){ | |
| 301 | 306 | for(i=0; i<n; i++){ |
| 302 | 307 | db_multi_exec( |
| 303 | 308 | "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rx[i] |
| 304 | 309 | ); |
| 305 | 310 | if( db_table_exists("repository","cherrypick") ){ |
| @@ -313,10 +318,13 @@ | ||
| 313 | 318 | } |
| 314 | 319 | } |
| 315 | 320 | } |
| 316 | 321 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 317 | 322 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 323 | + if( mRCCFlags & 0x02 ){ | |
| 324 | + rid = rid2 = 0; | |
| 325 | + } | |
| 318 | 326 | www_print_timeline(&q, |
| 319 | 327 | mFlags |
| 320 | 328 | |TIMELINE_GRAPH |
| 321 | 329 | |TIMELINE_FILLGAPS |
| 322 | 330 | |TIMELINE_NOSCROLL |
| @@ -3453,74 +3461,93 @@ | ||
| 3453 | 3461 | while( fossil_isspace(zA[0]) ) zA++; |
| 3454 | 3462 | return zA[0]==0 && zB[0]==0; |
| 3455 | 3463 | } |
| 3456 | 3464 | |
| 3457 | 3465 | /* |
| 3458 | -** The following methods operate on the newtags temporary table | |
| 3459 | -** that is used to collect various changes to be added to a control | |
| 3460 | -** artifact for a check-in edit. | |
| 3466 | +***************************************************************************** | |
| 3467 | +** The following methods operate on the "newtags" temporary table. This | |
| 3468 | +** table collects changes for a control artifact that will implement an | |
| 3469 | +** edit to a check-in. | |
| 3470 | +** | |
| 3471 | +** Initialize the newtags table | |
| 3461 | 3472 | */ |
| 3462 | 3473 | static void init_newtags(void){ |
| 3463 | 3474 | db_multi_exec("CREATE TEMP TABLE newtags(tag UNIQUE, prefix, value)"); |
| 3464 | 3475 | } |
| 3465 | 3476 | |
| 3477 | +/* Add a new changes to the newtags table */ | |
| 3466 | 3478 | static void change_special( |
| 3467 | 3479 | const char *zName, /* Name of the special tag */ |
| 3468 | 3480 | const char *zOp, /* Operation prefix (e.g. +,-,*) */ |
| 3469 | 3481 | const char *zValue /* Value of the tag */ |
| 3470 | 3482 | ){ |
| 3471 | 3483 | db_multi_exec("REPLACE INTO newtags VALUES(%Q,'%q',%Q)", zName, zOp, zValue); |
| 3472 | 3484 | } |
| 3473 | 3485 | |
| 3486 | +/* Change a symbolic tag */ | |
| 3474 | 3487 | static void change_sym_tag(const char *zTag, const char *zOp){ |
| 3475 | 3488 | db_multi_exec("REPLACE INTO newtags VALUES('sym-%q',%Q,NULL)", zTag, zOp); |
| 3476 | 3489 | } |
| 3477 | 3490 | |
| 3491 | +/* Cancel a tag */ | |
| 3478 | 3492 | static void cancel_special(const char *zTag){ |
| 3479 | 3493 | change_special(zTag,"-",0); |
| 3480 | 3494 | } |
| 3481 | 3495 | |
| 3496 | +/* Add a background color tag. This will be propagating tag | |
| 3497 | +** if fPropagateColor is true. */ | |
| 3482 | 3498 | static void add_color(const char *zNewColor, int fPropagateColor){ |
| 3483 | 3499 | change_special("bgcolor",fPropagateColor ? "*" : "+", zNewColor); |
| 3484 | 3500 | } |
| 3485 | 3501 | |
| 3502 | +/* Cancel a background color tag */ | |
| 3486 | 3503 | static void cancel_color(void){ |
| 3487 | 3504 | change_special("bgcolor","-",0); |
| 3488 | 3505 | } |
| 3489 | 3506 | |
| 3507 | +/* Add a comment-change tag */ | |
| 3490 | 3508 | static void add_comment(const char *zNewComment){ |
| 3491 | 3509 | change_special("comment","+",zNewComment); |
| 3492 | 3510 | } |
| 3493 | 3511 | |
| 3512 | +/* Add a date-change tag */ | |
| 3494 | 3513 | static void add_date(const char *zNewDate){ |
| 3495 | 3514 | change_special("date","+",zNewDate); |
| 3496 | 3515 | } |
| 3497 | 3516 | |
| 3517 | +/* Add a change-user tag */ | |
| 3498 | 3518 | static void add_user(const char *zNewUser){ |
| 3499 | 3519 | change_special("user","+",zNewUser); |
| 3500 | 3520 | } |
| 3501 | 3521 | |
| 3522 | +/* Add a generic symbolic tag (one that has no value) */ | |
| 3502 | 3523 | static void add_tag(const char *zNewTag){ |
| 3503 | 3524 | change_sym_tag(zNewTag,"+"); |
| 3504 | 3525 | } |
| 3505 | 3526 | |
| 3527 | +/* Cancel an existing symbolic tag associated with check-in rid */ | |
| 3506 | 3528 | static void cancel_tag(int rid, const char *zCancelTag){ |
| 3507 | 3529 | if( db_exists("SELECT 1 FROM tagxref, tag" |
| 3508 | 3530 | " WHERE tagxref.rid=%d AND tagtype>0" |
| 3509 | 3531 | " AND tagxref.tagid=tag.tagid AND tagname='sym-%q'", |
| 3510 | 3532 | rid, zCancelTag) |
| 3511 | - ) change_sym_tag(zCancelTag,"-"); | |
| 3533 | + ){ | |
| 3534 | + change_sym_tag(zCancelTag,"-"); | |
| 3535 | + } | |
| 3512 | 3536 | } |
| 3513 | 3537 | |
| 3538 | +/* Add a hidden tag that propagates to all ancestors */ | |
| 3514 | 3539 | static void hide_branch(void){ |
| 3515 | 3540 | change_special("hidden","*",0); |
| 3516 | 3541 | } |
| 3517 | 3542 | |
| 3543 | +/* Close the branch */ | |
| 3518 | 3544 | static void close_leaf(int rid){ |
| 3519 | 3545 | change_special("closed",is_a_leaf(rid)?"+":"*",0); |
| 3520 | 3546 | } |
| 3521 | 3547 | |
| 3548 | +/* Move the check-in to a different branch */ | |
| 3522 | 3549 | static void change_branch(int rid, const char *zNewBranch){ |
| 3523 | 3550 | db_multi_exec( |
| 3524 | 3551 | "REPLACE INTO newtags " |
| 3525 | 3552 | " SELECT tagname, '-', NULL FROM tagxref, tag" |
| 3526 | 3553 | " WHERE tagxref.rid=%d AND tagtype==2" |
| @@ -3531,19 +3558,31 @@ | ||
| 3531 | 3558 | change_special("branch","*",zNewBranch); |
| 3532 | 3559 | change_sym_tag(zNewBranch,"*"); |
| 3533 | 3560 | } |
| 3534 | 3561 | |
| 3535 | 3562 | /* |
| 3536 | -** The apply_newtags method is called after all newtags have been added | |
| 3537 | -** and the control artifact is completed and then written to the DB. | |
| 3563 | +** Construct a control artifact. | |
| 3564 | +** | |
| 3565 | +** Preconditions: | |
| 3566 | +** | |
| 3567 | +** (1) "ctrl" contains the beginning of a control artifact with | |
| 3568 | +** just the D-card showing the timestamp on the control artifact | |
| 3569 | +** itself. | |
| 3570 | +** | |
| 3571 | +** (2) The newtags temporary table has been constructed. | |
| 3572 | +** | |
| 3573 | +** (3) Zero or more methods may have been called to populate the | |
| 3574 | +** newtags table. Or the newtags table might be empty. | |
| 3575 | +** | |
| 3576 | +** Construct the complete control artifact. Or, if there are not | |
| 3577 | +** changes, just zero out the ctrl blob. | |
| 3538 | 3578 | */ |
| 3539 | -static void apply_newtags( | |
| 3540 | - Blob *ctrl, | |
| 3541 | - int rid, | |
| 3542 | - const char *zUuid, | |
| 3543 | - const char *zUserOvrd, /* The user name on the control artifact */ | |
| 3544 | - int fDryRun /* Print control artifact, but make no changes */ | |
| 3579 | +static void construct_newtags_artifact( | |
| 3580 | + Blob *ctrl, /* The control artifact text */ | |
| 3581 | + int rid, /* rid of the check-in that the artifact applies to */ | |
| 3582 | + const char *zUuid, /* UUID of the check-in to which the artifact applies*/ | |
| 3583 | + const char *zUserOvrd /* The user name on the control artifact */ | |
| 3545 | 3584 | ){ |
| 3546 | 3585 | Stmt q; |
| 3547 | 3586 | int nChng = 0; |
| 3548 | 3587 | |
| 3549 | 3588 | db_prepare(&q, "SELECT tag, prefix, value FROM newtags" |
| @@ -3559,33 +3598,46 @@ | ||
| 3559 | 3598 | blob_appendf(ctrl, "T %s%F %s\n", zPrefix, zTag, zUuid); |
| 3560 | 3599 | } |
| 3561 | 3600 | } |
| 3562 | 3601 | db_finalize(&q); |
| 3563 | 3602 | if( nChng>0 ){ |
| 3564 | - int nrid; | |
| 3565 | 3603 | Blob cksum; |
| 3566 | 3604 | if( zUserOvrd && zUserOvrd[0] ){ |
| 3567 | 3605 | blob_appendf(ctrl, "U %F\n", zUserOvrd); |
| 3568 | 3606 | }else{ |
| 3569 | 3607 | blob_appendf(ctrl, "U %F\n", login_name()); |
| 3570 | 3608 | } |
| 3571 | 3609 | md5sum_blob(ctrl, &cksum); |
| 3572 | 3610 | blob_appendf(ctrl, "Z %b\n", &cksum); |
| 3573 | - if( fDryRun ){ | |
| 3574 | - assert( g.isHTTP==0 ); /* Only print control artifact in console mode. */ | |
| 3575 | - fossil_print("%s", blob_str(ctrl)); | |
| 3576 | - blob_reset(ctrl); | |
| 3577 | - }else{ | |
| 3578 | - db_begin_transaction(); | |
| 3579 | - g.markPrivate = content_is_private(rid); | |
| 3580 | - nrid = content_put(ctrl); | |
| 3581 | - manifest_crosslink(nrid, ctrl, MC_PERMIT_HOOKS); | |
| 3582 | - db_end_transaction(0); | |
| 3583 | - } | |
| 3584 | - assert( blob_is_reset(ctrl) ); | |
| 3611 | + blob_reset(&cksum); | |
| 3612 | + }else{ | |
| 3613 | + blob_reset(ctrl); | |
| 3614 | + } | |
| 3615 | +} | |
| 3616 | + | |
| 3617 | +/* | |
| 3618 | +** Return true if the artifact is complete. We assume that any non-empty | |
| 3619 | +** artifact is complete. | |
| 3620 | +*/ | |
| 3621 | +static int artifact_is_complete(Blob *ctrl){ | |
| 3622 | + return blob_size(ctrl)>0; | |
| 3623 | +} | |
| 3624 | + | |
| 3625 | +/* | |
| 3626 | +** Apply a control artifact to the repository database. Except, if the | |
| 3627 | +** artifact is empty, this routine is a no-op. | |
| 3628 | +*/ | |
| 3629 | +static void publish_newtags_artifact(Blob *ctrl, int rid){ | |
| 3630 | + if( artifact_is_complete(ctrl) ){ | |
| 3631 | + int nrid; | |
| 3632 | + g.markPrivate = content_is_private(rid); | |
| 3633 | + nrid = content_put(ctrl); | |
| 3634 | + manifest_crosslink(nrid, ctrl, MC_PERMIT_HOOKS); | |
| 3585 | 3635 | } |
| 3586 | 3636 | } |
| 3637 | +/* End of the newtags subsystem | |
| 3638 | +******************************************************************************/ | |
| 3587 | 3639 | |
| 3588 | 3640 | /* |
| 3589 | 3641 | ** This method checks that the date can be parsed. |
| 3590 | 3642 | ** Returns 1 if datetime() can validate, 0 otherwise. |
| 3591 | 3643 | */ |
| @@ -3644,14 +3696,17 @@ | ||
| 3644 | 3696 | int fPropagateColor; /* True if color propagates before edit */ |
| 3645 | 3697 | int fNewPropagateColor; /* True if color propagates after edit */ |
| 3646 | 3698 | int fHasHidden = 0; /* True if hidden tag already set */ |
| 3647 | 3699 | int fHasClosed = 0; /* True if closed tag already set */ |
| 3648 | 3700 | const char *zChngTime = 0; /* Value of chngtime= query param, if any */ |
| 3701 | + int bApply = P("apply")!=0 && cgi_csrf_safe(2); | |
| 3702 | + int bPreview = P("preview")!=0; | |
| 3649 | 3703 | char *zUuid; |
| 3650 | 3704 | Blob comment; |
| 3651 | 3705 | char *zBranchName = 0; |
| 3652 | 3706 | Stmt q; |
| 3707 | + Blob ctrl; /* The generated control artifact */ | |
| 3653 | 3708 | |
| 3654 | 3709 | login_check_credentials(); |
| 3655 | 3710 | if( !g.perm.Write ){ login_needed(g.anon.Write); return; } |
| 3656 | 3711 | rid = name_to_typed_rid(P("r"), "ci"); |
| 3657 | 3712 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -3684,16 +3739,13 @@ | ||
| 3684 | 3739 | zNewBrFlag = P("newbr") ? " checked" : ""; |
| 3685 | 3740 | zNewBranch = PDT("brname",""); |
| 3686 | 3741 | zBranchName = branch_of_rid(rid); |
| 3687 | 3742 | zCloseFlag = P("close") ? " checked" : ""; |
| 3688 | 3743 | zHideFlag = P("hide") ? " checked" : ""; |
| 3689 | - if( P("apply") && cgi_csrf_safe(2) ){ | |
| 3690 | - Blob ctrl; | |
| 3691 | - char *zNow; | |
| 3692 | - | |
| 3693 | - blob_zero(&ctrl); | |
| 3694 | - zNow = date_in_standard_format(zChngTime ? zChngTime : "now"); | |
| 3744 | + blob_zero(&ctrl); | |
| 3745 | + if( bApply || bPreview ){ | |
| 3746 | + char *zNow = date_in_standard_format(zChngTime ? zChngTime : "now"); | |
| 3695 | 3747 | blob_appendf(&ctrl, "D %s\n", zNow); |
| 3696 | 3748 | init_newtags(); |
| 3697 | 3749 | if( zNewColorFlag[0] |
| 3698 | 3750 | && zNewColor[0] |
| 3699 | 3751 | && (fPropagateColor!=fNewPropagateColor |
| @@ -3719,69 +3771,39 @@ | ||
| 3719 | 3771 | db_finalize(&q); |
| 3720 | 3772 | if( zHideFlag[0] ) hide_branch(); |
| 3721 | 3773 | if( zCloseFlag[0] ) close_leaf(rid); |
| 3722 | 3774 | if( zNewTagFlag[0] && zNewTag[0] ) add_tag(zNewTag); |
| 3723 | 3775 | if( zNewBrFlag[0] && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 3724 | - apply_newtags(&ctrl, rid, zUuid, 0, 0); | |
| 3725 | - cgi_redirectf("%R/ci/%S", zUuid); | |
| 3776 | + construct_newtags_artifact(&ctrl, rid, zUuid, 0); | |
| 3777 | + if( bApply && artifact_is_complete(&ctrl) ){ | |
| 3778 | + db_begin_transaction(); | |
| 3779 | + publish_newtags_artifact(&ctrl, rid); | |
| 3780 | + db_end_transaction(0); | |
| 3781 | + blob_reset(&ctrl); | |
| 3782 | + cgi_redirectf("%R/ci/%S", zUuid); | |
| 3783 | + } | |
| 3726 | 3784 | } |
| 3727 | 3785 | blob_zero(&comment); |
| 3728 | 3786 | blob_append(&comment, zNewComment, -1); |
| 3729 | - zUuid[10] = 0; | |
| 3730 | - style_header("Edit Check-in [%s]", zUuid); | |
| 3731 | - if( P("preview") ){ | |
| 3732 | - Blob suffix; | |
| 3733 | - int nTag = 0; | |
| 3734 | - const char *zDplyBr; /* Branch name used to determine BG color */ | |
| 3735 | - const char *zMainBranch = db_main_branch(); | |
| 3736 | - if( zNewBrFlag[0] && zNewBranch[0] ){ | |
| 3737 | - zDplyBr = zNewBranch; | |
| 3738 | - }else{ | |
| 3739 | - zDplyBr = zBranchName; | |
| 3740 | - } | |
| 3741 | - @ <b>Preview:</b> | |
| 3742 | - @ <blockquote> | |
| 3743 | - @ <table border=0> | |
| 3744 | - if( zNewColorFlag[0] && zNewColor && zNewColor[0] ){ | |
| 3745 | - @ <tr><td style="background-color:%h(reasonable_bg_color(zNewColor,0));"> | |
| 3746 | - }else if( zColor[0] ){ | |
| 3747 | - @ <tr><td style="background-color:%h(reasonable_bg_color(zColor,0));"> | |
| 3748 | - }else if( zDplyBr && fossil_strcmp(zDplyBr, zMainBranch)!=0 ){ | |
| 3749 | - @ <tr><td style="background-color:%h(hash_color(zDplyBr));"> | |
| 3750 | - }else{ | |
| 3751 | - @ <tr><td> | |
| 3752 | - } | |
| 3753 | - @ %!W(blob_str(&comment)) | |
| 3754 | - blob_zero(&suffix); | |
| 3755 | - blob_appendf(&suffix, "(user: %h", zNewUser); | |
| 3756 | - db_prepare(&q, "SELECT substr(tagname,5) FROM tagxref, tag" | |
| 3757 | - " WHERE tagname GLOB 'sym-*' AND tagxref.rid=%d" | |
| 3758 | - " AND tagtype>1 AND tag.tagid=tagxref.tagid", | |
| 3759 | - rid); | |
| 3760 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 3761 | - const char *zTag = db_column_text(&q, 0); | |
| 3762 | - if( nTag==0 ){ | |
| 3763 | - blob_appendf(&suffix, ", tags: %h", zTag); | |
| 3764 | - }else{ | |
| 3765 | - blob_appendf(&suffix, ", %h", zTag); | |
| 3766 | - } | |
| 3767 | - nTag++; | |
| 3768 | - } | |
| 3769 | - db_finalize(&q); | |
| 3770 | - blob_appendf(&suffix, ")"); | |
| 3771 | - @ %s(blob_str(&suffix)) | |
| 3772 | - @ </td></tr></table> | |
| 3773 | - if( zChngTime ){ | |
| 3774 | - @ <p>The timestamp on the tag used to make the changes above | |
| 3775 | - @ will be overridden as: %s(date_in_standard_format(zChngTime))</p> | |
| 3776 | - } | |
| 3777 | - @ </blockquote> | |
| 3778 | - @ <hr> | |
| 3779 | - blob_reset(&suffix); | |
| 3780 | - } | |
| 3781 | - @ <p>Make changes to attributes of check-in | |
| 3782 | - @ [%z(href("%R/ci/%!S",zUuid))%s(zUuid)</a>]:</p> | |
| 3787 | + style_header("Edit Check-in %S", zUuid); | |
| 3788 | + @ <div class="section accordion">Original Context Around \ | |
| 3789 | + @ Check-in %S(zUuid) on %s(zDate)</div> | |
| 3790 | + @ <div class="accordion_panel"> | |
| 3791 | + render_checkin_context(rid, 0, 2, 0); | |
| 3792 | + @ </div> | |
| 3793 | + if( bPreview ){ | |
| 3794 | + @ <div class="section accordion">After The Proposed Changes</div> | |
| 3795 | + @ <div class="accordion_panel"> | |
| 3796 | + db_begin_transaction(); | |
| 3797 | + publish_newtags_artifact(&ctrl, rid); | |
| 3798 | + render_checkin_context(rid, 0, 2, 0); | |
| 3799 | + db_end_transaction(1); | |
| 3800 | + @ </div> | |
| 3801 | + } | |
| 3802 | + @ <div class="section accordion">Proposed Changes For \ | |
| 3803 | + @ Check-In %S(zUuid):</div> | |
| 3804 | + @ <div class="accordion_panel"> | |
| 3783 | 3805 | form_begin(0, "%R/ci_edit"); |
| 3784 | 3806 | @ <div><input type="hidden" name="r" value="%s(zUuid)"> |
| 3785 | 3807 | @ <table border="0" cellspacing="10"> |
| 3786 | 3808 | |
| 3787 | 3809 | @ <tr><th align="right" valign="top">User:</th> |
| @@ -4194,13 +4216,20 @@ | ||
| 4194 | 4216 | fossil_free((void *)pzCancelTags); |
| 4195 | 4217 | } |
| 4196 | 4218 | if( fHide && !fHasHidden ) hide_branch(); |
| 4197 | 4219 | if( fClose && !fHasClosed ) close_leaf(rid); |
| 4198 | 4220 | if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 4199 | - apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun); | |
| 4200 | - if( fDryRun==0 ){ | |
| 4221 | + if( !fDryRun ) db_begin_transaction(); | |
| 4222 | + construct_newtags_artifact(&ctrl, rid, zUuid, zUserOvrd); | |
| 4223 | + if( fDryRun ){ | |
| 4224 | + fossil_print("%s", blob_str(&ctrl)); | |
| 4225 | + blob_reset(&ctrl); | |
| 4226 | + }else{ | |
| 4227 | + db_begin_transaction(); | |
| 4228 | + publish_newtags_artifact(&ctrl, rid); | |
| 4201 | 4229 | show_common_info(rid, "hash:", 1, 0); |
| 4230 | + db_end_transaction(0); | |
| 4202 | 4231 | } |
| 4203 | 4232 | if( g.localOpen ){ |
| 4204 | 4233 | manifest_to_disk(rid); |
| 4205 | 4234 | } |
| 4206 | 4235 | } |
| 4207 | 4236 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -271,13 +271,18 @@ | |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | ** Show the context graph (immediate parents and children) for |
| 276 | ** check-in rid and rid2 |
| 277 | */ |
| 278 | void render_checkin_context(int rid, int rid2, int parentsOnly, int mFlags){ |
| 279 | Blob sql; |
| 280 | Stmt q; |
| 281 | int rx[2]; |
| 282 | int i, n; |
| 283 | rx[0] = rid; |
| @@ -295,11 +300,11 @@ | |
| 295 | "INSERT OR IGNORE INTO ok VALUES(%d);" |
| 296 | "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;", |
| 297 | rx[i], rx[i] |
| 298 | ); |
| 299 | } |
| 300 | if( !parentsOnly ){ |
| 301 | for(i=0; i<n; i++){ |
| 302 | db_multi_exec( |
| 303 | "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rx[i] |
| 304 | ); |
| 305 | if( db_table_exists("repository","cherrypick") ){ |
| @@ -313,10 +318,13 @@ | |
| 313 | } |
| 314 | } |
| 315 | } |
| 316 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 317 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 318 | www_print_timeline(&q, |
| 319 | mFlags |
| 320 | |TIMELINE_GRAPH |
| 321 | |TIMELINE_FILLGAPS |
| 322 | |TIMELINE_NOSCROLL |
| @@ -3453,74 +3461,93 @@ | |
| 3453 | while( fossil_isspace(zA[0]) ) zA++; |
| 3454 | return zA[0]==0 && zB[0]==0; |
| 3455 | } |
| 3456 | |
| 3457 | /* |
| 3458 | ** The following methods operate on the newtags temporary table |
| 3459 | ** that is used to collect various changes to be added to a control |
| 3460 | ** artifact for a check-in edit. |
| 3461 | */ |
| 3462 | static void init_newtags(void){ |
| 3463 | db_multi_exec("CREATE TEMP TABLE newtags(tag UNIQUE, prefix, value)"); |
| 3464 | } |
| 3465 | |
| 3466 | static void change_special( |
| 3467 | const char *zName, /* Name of the special tag */ |
| 3468 | const char *zOp, /* Operation prefix (e.g. +,-,*) */ |
| 3469 | const char *zValue /* Value of the tag */ |
| 3470 | ){ |
| 3471 | db_multi_exec("REPLACE INTO newtags VALUES(%Q,'%q',%Q)", zName, zOp, zValue); |
| 3472 | } |
| 3473 | |
| 3474 | static void change_sym_tag(const char *zTag, const char *zOp){ |
| 3475 | db_multi_exec("REPLACE INTO newtags VALUES('sym-%q',%Q,NULL)", zTag, zOp); |
| 3476 | } |
| 3477 | |
| 3478 | static void cancel_special(const char *zTag){ |
| 3479 | change_special(zTag,"-",0); |
| 3480 | } |
| 3481 | |
| 3482 | static void add_color(const char *zNewColor, int fPropagateColor){ |
| 3483 | change_special("bgcolor",fPropagateColor ? "*" : "+", zNewColor); |
| 3484 | } |
| 3485 | |
| 3486 | static void cancel_color(void){ |
| 3487 | change_special("bgcolor","-",0); |
| 3488 | } |
| 3489 | |
| 3490 | static void add_comment(const char *zNewComment){ |
| 3491 | change_special("comment","+",zNewComment); |
| 3492 | } |
| 3493 | |
| 3494 | static void add_date(const char *zNewDate){ |
| 3495 | change_special("date","+",zNewDate); |
| 3496 | } |
| 3497 | |
| 3498 | static void add_user(const char *zNewUser){ |
| 3499 | change_special("user","+",zNewUser); |
| 3500 | } |
| 3501 | |
| 3502 | static void add_tag(const char *zNewTag){ |
| 3503 | change_sym_tag(zNewTag,"+"); |
| 3504 | } |
| 3505 | |
| 3506 | static void cancel_tag(int rid, const char *zCancelTag){ |
| 3507 | if( db_exists("SELECT 1 FROM tagxref, tag" |
| 3508 | " WHERE tagxref.rid=%d AND tagtype>0" |
| 3509 | " AND tagxref.tagid=tag.tagid AND tagname='sym-%q'", |
| 3510 | rid, zCancelTag) |
| 3511 | ) change_sym_tag(zCancelTag,"-"); |
| 3512 | } |
| 3513 | |
| 3514 | static void hide_branch(void){ |
| 3515 | change_special("hidden","*",0); |
| 3516 | } |
| 3517 | |
| 3518 | static void close_leaf(int rid){ |
| 3519 | change_special("closed",is_a_leaf(rid)?"+":"*",0); |
| 3520 | } |
| 3521 | |
| 3522 | static void change_branch(int rid, const char *zNewBranch){ |
| 3523 | db_multi_exec( |
| 3524 | "REPLACE INTO newtags " |
| 3525 | " SELECT tagname, '-', NULL FROM tagxref, tag" |
| 3526 | " WHERE tagxref.rid=%d AND tagtype==2" |
| @@ -3531,19 +3558,31 @@ | |
| 3531 | change_special("branch","*",zNewBranch); |
| 3532 | change_sym_tag(zNewBranch,"*"); |
| 3533 | } |
| 3534 | |
| 3535 | /* |
| 3536 | ** The apply_newtags method is called after all newtags have been added |
| 3537 | ** and the control artifact is completed and then written to the DB. |
| 3538 | */ |
| 3539 | static void apply_newtags( |
| 3540 | Blob *ctrl, |
| 3541 | int rid, |
| 3542 | const char *zUuid, |
| 3543 | const char *zUserOvrd, /* The user name on the control artifact */ |
| 3544 | int fDryRun /* Print control artifact, but make no changes */ |
| 3545 | ){ |
| 3546 | Stmt q; |
| 3547 | int nChng = 0; |
| 3548 | |
| 3549 | db_prepare(&q, "SELECT tag, prefix, value FROM newtags" |
| @@ -3559,33 +3598,46 @@ | |
| 3559 | blob_appendf(ctrl, "T %s%F %s\n", zPrefix, zTag, zUuid); |
| 3560 | } |
| 3561 | } |
| 3562 | db_finalize(&q); |
| 3563 | if( nChng>0 ){ |
| 3564 | int nrid; |
| 3565 | Blob cksum; |
| 3566 | if( zUserOvrd && zUserOvrd[0] ){ |
| 3567 | blob_appendf(ctrl, "U %F\n", zUserOvrd); |
| 3568 | }else{ |
| 3569 | blob_appendf(ctrl, "U %F\n", login_name()); |
| 3570 | } |
| 3571 | md5sum_blob(ctrl, &cksum); |
| 3572 | blob_appendf(ctrl, "Z %b\n", &cksum); |
| 3573 | if( fDryRun ){ |
| 3574 | assert( g.isHTTP==0 ); /* Only print control artifact in console mode. */ |
| 3575 | fossil_print("%s", blob_str(ctrl)); |
| 3576 | blob_reset(ctrl); |
| 3577 | }else{ |
| 3578 | db_begin_transaction(); |
| 3579 | g.markPrivate = content_is_private(rid); |
| 3580 | nrid = content_put(ctrl); |
| 3581 | manifest_crosslink(nrid, ctrl, MC_PERMIT_HOOKS); |
| 3582 | db_end_transaction(0); |
| 3583 | } |
| 3584 | assert( blob_is_reset(ctrl) ); |
| 3585 | } |
| 3586 | } |
| 3587 | |
| 3588 | /* |
| 3589 | ** This method checks that the date can be parsed. |
| 3590 | ** Returns 1 if datetime() can validate, 0 otherwise. |
| 3591 | */ |
| @@ -3644,14 +3696,17 @@ | |
| 3644 | int fPropagateColor; /* True if color propagates before edit */ |
| 3645 | int fNewPropagateColor; /* True if color propagates after edit */ |
| 3646 | int fHasHidden = 0; /* True if hidden tag already set */ |
| 3647 | int fHasClosed = 0; /* True if closed tag already set */ |
| 3648 | const char *zChngTime = 0; /* Value of chngtime= query param, if any */ |
| 3649 | char *zUuid; |
| 3650 | Blob comment; |
| 3651 | char *zBranchName = 0; |
| 3652 | Stmt q; |
| 3653 | |
| 3654 | login_check_credentials(); |
| 3655 | if( !g.perm.Write ){ login_needed(g.anon.Write); return; } |
| 3656 | rid = name_to_typed_rid(P("r"), "ci"); |
| 3657 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -3684,16 +3739,13 @@ | |
| 3684 | zNewBrFlag = P("newbr") ? " checked" : ""; |
| 3685 | zNewBranch = PDT("brname",""); |
| 3686 | zBranchName = branch_of_rid(rid); |
| 3687 | zCloseFlag = P("close") ? " checked" : ""; |
| 3688 | zHideFlag = P("hide") ? " checked" : ""; |
| 3689 | if( P("apply") && cgi_csrf_safe(2) ){ |
| 3690 | Blob ctrl; |
| 3691 | char *zNow; |
| 3692 | |
| 3693 | blob_zero(&ctrl); |
| 3694 | zNow = date_in_standard_format(zChngTime ? zChngTime : "now"); |
| 3695 | blob_appendf(&ctrl, "D %s\n", zNow); |
| 3696 | init_newtags(); |
| 3697 | if( zNewColorFlag[0] |
| 3698 | && zNewColor[0] |
| 3699 | && (fPropagateColor!=fNewPropagateColor |
| @@ -3719,69 +3771,39 @@ | |
| 3719 | db_finalize(&q); |
| 3720 | if( zHideFlag[0] ) hide_branch(); |
| 3721 | if( zCloseFlag[0] ) close_leaf(rid); |
| 3722 | if( zNewTagFlag[0] && zNewTag[0] ) add_tag(zNewTag); |
| 3723 | if( zNewBrFlag[0] && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 3724 | apply_newtags(&ctrl, rid, zUuid, 0, 0); |
| 3725 | cgi_redirectf("%R/ci/%S", zUuid); |
| 3726 | } |
| 3727 | blob_zero(&comment); |
| 3728 | blob_append(&comment, zNewComment, -1); |
| 3729 | zUuid[10] = 0; |
| 3730 | style_header("Edit Check-in [%s]", zUuid); |
| 3731 | if( P("preview") ){ |
| 3732 | Blob suffix; |
| 3733 | int nTag = 0; |
| 3734 | const char *zDplyBr; /* Branch name used to determine BG color */ |
| 3735 | const char *zMainBranch = db_main_branch(); |
| 3736 | if( zNewBrFlag[0] && zNewBranch[0] ){ |
| 3737 | zDplyBr = zNewBranch; |
| 3738 | }else{ |
| 3739 | zDplyBr = zBranchName; |
| 3740 | } |
| 3741 | @ <b>Preview:</b> |
| 3742 | @ <blockquote> |
| 3743 | @ <table border=0> |
| 3744 | if( zNewColorFlag[0] && zNewColor && zNewColor[0] ){ |
| 3745 | @ <tr><td style="background-color:%h(reasonable_bg_color(zNewColor,0));"> |
| 3746 | }else if( zColor[0] ){ |
| 3747 | @ <tr><td style="background-color:%h(reasonable_bg_color(zColor,0));"> |
| 3748 | }else if( zDplyBr && fossil_strcmp(zDplyBr, zMainBranch)!=0 ){ |
| 3749 | @ <tr><td style="background-color:%h(hash_color(zDplyBr));"> |
| 3750 | }else{ |
| 3751 | @ <tr><td> |
| 3752 | } |
| 3753 | @ %!W(blob_str(&comment)) |
| 3754 | blob_zero(&suffix); |
| 3755 | blob_appendf(&suffix, "(user: %h", zNewUser); |
| 3756 | db_prepare(&q, "SELECT substr(tagname,5) FROM tagxref, tag" |
| 3757 | " WHERE tagname GLOB 'sym-*' AND tagxref.rid=%d" |
| 3758 | " AND tagtype>1 AND tag.tagid=tagxref.tagid", |
| 3759 | rid); |
| 3760 | while( db_step(&q)==SQLITE_ROW ){ |
| 3761 | const char *zTag = db_column_text(&q, 0); |
| 3762 | if( nTag==0 ){ |
| 3763 | blob_appendf(&suffix, ", tags: %h", zTag); |
| 3764 | }else{ |
| 3765 | blob_appendf(&suffix, ", %h", zTag); |
| 3766 | } |
| 3767 | nTag++; |
| 3768 | } |
| 3769 | db_finalize(&q); |
| 3770 | blob_appendf(&suffix, ")"); |
| 3771 | @ %s(blob_str(&suffix)) |
| 3772 | @ </td></tr></table> |
| 3773 | if( zChngTime ){ |
| 3774 | @ <p>The timestamp on the tag used to make the changes above |
| 3775 | @ will be overridden as: %s(date_in_standard_format(zChngTime))</p> |
| 3776 | } |
| 3777 | @ </blockquote> |
| 3778 | @ <hr> |
| 3779 | blob_reset(&suffix); |
| 3780 | } |
| 3781 | @ <p>Make changes to attributes of check-in |
| 3782 | @ [%z(href("%R/ci/%!S",zUuid))%s(zUuid)</a>]:</p> |
| 3783 | form_begin(0, "%R/ci_edit"); |
| 3784 | @ <div><input type="hidden" name="r" value="%s(zUuid)"> |
| 3785 | @ <table border="0" cellspacing="10"> |
| 3786 | |
| 3787 | @ <tr><th align="right" valign="top">User:</th> |
| @@ -4194,13 +4216,20 @@ | |
| 4194 | fossil_free((void *)pzCancelTags); |
| 4195 | } |
| 4196 | if( fHide && !fHasHidden ) hide_branch(); |
| 4197 | if( fClose && !fHasClosed ) close_leaf(rid); |
| 4198 | if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 4199 | apply_newtags(&ctrl, rid, zUuid, zUserOvrd, fDryRun); |
| 4200 | if( fDryRun==0 ){ |
| 4201 | show_common_info(rid, "hash:", 1, 0); |
| 4202 | } |
| 4203 | if( g.localOpen ){ |
| 4204 | manifest_to_disk(rid); |
| 4205 | } |
| 4206 | } |
| 4207 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -271,13 +271,18 @@ | |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | /* |
| 275 | ** Show the context graph (immediate parents and children) for |
| 276 | ** check-in rid and rid2. rid2 might be zero, in which case only |
| 277 | ** show the context for rid1. |
| 278 | */ |
| 279 | void render_checkin_context( |
| 280 | int rid, int rid2, /* One or two checkins for which to show context */ |
| 281 | int mRCCFlags, /* Flags. 1: parents only. 2: no-highlight */ |
| 282 | int mFlags /* Graph flags */ |
| 283 | ){ |
| 284 | Blob sql; |
| 285 | Stmt q; |
| 286 | int rx[2]; |
| 287 | int i, n; |
| 288 | rx[0] = rid; |
| @@ -295,11 +300,11 @@ | |
| 300 | "INSERT OR IGNORE INTO ok VALUES(%d);" |
| 301 | "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;", |
| 302 | rx[i], rx[i] |
| 303 | ); |
| 304 | } |
| 305 | if( (mRCCFlags & 0x01)==0 ){ |
| 306 | for(i=0; i<n; i++){ |
| 307 | db_multi_exec( |
| 308 | "INSERT OR IGNORE INTO ok SELECT cid FROM plink WHERE pid=%d;", rx[i] |
| 309 | ); |
| 310 | if( db_table_exists("repository","cherrypick") ){ |
| @@ -313,10 +318,13 @@ | |
| 318 | } |
| 319 | } |
| 320 | } |
| 321 | blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); |
| 322 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 323 | if( mRCCFlags & 0x02 ){ |
| 324 | rid = rid2 = 0; |
| 325 | } |
| 326 | www_print_timeline(&q, |
| 327 | mFlags |
| 328 | |TIMELINE_GRAPH |
| 329 | |TIMELINE_FILLGAPS |
| 330 | |TIMELINE_NOSCROLL |
| @@ -3453,74 +3461,93 @@ | |
| 3461 | while( fossil_isspace(zA[0]) ) zA++; |
| 3462 | return zA[0]==0 && zB[0]==0; |
| 3463 | } |
| 3464 | |
| 3465 | /* |
| 3466 | ***************************************************************************** |
| 3467 | ** The following methods operate on the "newtags" temporary table. This |
| 3468 | ** table collects changes for a control artifact that will implement an |
| 3469 | ** edit to a check-in. |
| 3470 | ** |
| 3471 | ** Initialize the newtags table |
| 3472 | */ |
| 3473 | static void init_newtags(void){ |
| 3474 | db_multi_exec("CREATE TEMP TABLE newtags(tag UNIQUE, prefix, value)"); |
| 3475 | } |
| 3476 | |
| 3477 | /* Add a new changes to the newtags table */ |
| 3478 | static void change_special( |
| 3479 | const char *zName, /* Name of the special tag */ |
| 3480 | const char *zOp, /* Operation prefix (e.g. +,-,*) */ |
| 3481 | const char *zValue /* Value of the tag */ |
| 3482 | ){ |
| 3483 | db_multi_exec("REPLACE INTO newtags VALUES(%Q,'%q',%Q)", zName, zOp, zValue); |
| 3484 | } |
| 3485 | |
| 3486 | /* Change a symbolic tag */ |
| 3487 | static void change_sym_tag(const char *zTag, const char *zOp){ |
| 3488 | db_multi_exec("REPLACE INTO newtags VALUES('sym-%q',%Q,NULL)", zTag, zOp); |
| 3489 | } |
| 3490 | |
| 3491 | /* Cancel a tag */ |
| 3492 | static void cancel_special(const char *zTag){ |
| 3493 | change_special(zTag,"-",0); |
| 3494 | } |
| 3495 | |
| 3496 | /* Add a background color tag. This will be propagating tag |
| 3497 | ** if fPropagateColor is true. */ |
| 3498 | static void add_color(const char *zNewColor, int fPropagateColor){ |
| 3499 | change_special("bgcolor",fPropagateColor ? "*" : "+", zNewColor); |
| 3500 | } |
| 3501 | |
| 3502 | /* Cancel a background color tag */ |
| 3503 | static void cancel_color(void){ |
| 3504 | change_special("bgcolor","-",0); |
| 3505 | } |
| 3506 | |
| 3507 | /* Add a comment-change tag */ |
| 3508 | static void add_comment(const char *zNewComment){ |
| 3509 | change_special("comment","+",zNewComment); |
| 3510 | } |
| 3511 | |
| 3512 | /* Add a date-change tag */ |
| 3513 | static void add_date(const char *zNewDate){ |
| 3514 | change_special("date","+",zNewDate); |
| 3515 | } |
| 3516 | |
| 3517 | /* Add a change-user tag */ |
| 3518 | static void add_user(const char *zNewUser){ |
| 3519 | change_special("user","+",zNewUser); |
| 3520 | } |
| 3521 | |
| 3522 | /* Add a generic symbolic tag (one that has no value) */ |
| 3523 | static void add_tag(const char *zNewTag){ |
| 3524 | change_sym_tag(zNewTag,"+"); |
| 3525 | } |
| 3526 | |
| 3527 | /* Cancel an existing symbolic tag associated with check-in rid */ |
| 3528 | static void cancel_tag(int rid, const char *zCancelTag){ |
| 3529 | if( db_exists("SELECT 1 FROM tagxref, tag" |
| 3530 | " WHERE tagxref.rid=%d AND tagtype>0" |
| 3531 | " AND tagxref.tagid=tag.tagid AND tagname='sym-%q'", |
| 3532 | rid, zCancelTag) |
| 3533 | ){ |
| 3534 | change_sym_tag(zCancelTag,"-"); |
| 3535 | } |
| 3536 | } |
| 3537 | |
| 3538 | /* Add a hidden tag that propagates to all ancestors */ |
| 3539 | static void hide_branch(void){ |
| 3540 | change_special("hidden","*",0); |
| 3541 | } |
| 3542 | |
| 3543 | /* Close the branch */ |
| 3544 | static void close_leaf(int rid){ |
| 3545 | change_special("closed",is_a_leaf(rid)?"+":"*",0); |
| 3546 | } |
| 3547 | |
| 3548 | /* Move the check-in to a different branch */ |
| 3549 | static void change_branch(int rid, const char *zNewBranch){ |
| 3550 | db_multi_exec( |
| 3551 | "REPLACE INTO newtags " |
| 3552 | " SELECT tagname, '-', NULL FROM tagxref, tag" |
| 3553 | " WHERE tagxref.rid=%d AND tagtype==2" |
| @@ -3531,19 +3558,31 @@ | |
| 3558 | change_special("branch","*",zNewBranch); |
| 3559 | change_sym_tag(zNewBranch,"*"); |
| 3560 | } |
| 3561 | |
| 3562 | /* |
| 3563 | ** Construct a control artifact. |
| 3564 | ** |
| 3565 | ** Preconditions: |
| 3566 | ** |
| 3567 | ** (1) "ctrl" contains the beginning of a control artifact with |
| 3568 | ** just the D-card showing the timestamp on the control artifact |
| 3569 | ** itself. |
| 3570 | ** |
| 3571 | ** (2) The newtags temporary table has been constructed. |
| 3572 | ** |
| 3573 | ** (3) Zero or more methods may have been called to populate the |
| 3574 | ** newtags table. Or the newtags table might be empty. |
| 3575 | ** |
| 3576 | ** Construct the complete control artifact. Or, if there are not |
| 3577 | ** changes, just zero out the ctrl blob. |
| 3578 | */ |
| 3579 | static void construct_newtags_artifact( |
| 3580 | Blob *ctrl, /* The control artifact text */ |
| 3581 | int rid, /* rid of the check-in that the artifact applies to */ |
| 3582 | const char *zUuid, /* UUID of the check-in to which the artifact applies*/ |
| 3583 | const char *zUserOvrd /* The user name on the control artifact */ |
| 3584 | ){ |
| 3585 | Stmt q; |
| 3586 | int nChng = 0; |
| 3587 | |
| 3588 | db_prepare(&q, "SELECT tag, prefix, value FROM newtags" |
| @@ -3559,33 +3598,46 @@ | |
| 3598 | blob_appendf(ctrl, "T %s%F %s\n", zPrefix, zTag, zUuid); |
| 3599 | } |
| 3600 | } |
| 3601 | db_finalize(&q); |
| 3602 | if( nChng>0 ){ |
| 3603 | Blob cksum; |
| 3604 | if( zUserOvrd && zUserOvrd[0] ){ |
| 3605 | blob_appendf(ctrl, "U %F\n", zUserOvrd); |
| 3606 | }else{ |
| 3607 | blob_appendf(ctrl, "U %F\n", login_name()); |
| 3608 | } |
| 3609 | md5sum_blob(ctrl, &cksum); |
| 3610 | blob_appendf(ctrl, "Z %b\n", &cksum); |
| 3611 | blob_reset(&cksum); |
| 3612 | }else{ |
| 3613 | blob_reset(ctrl); |
| 3614 | } |
| 3615 | } |
| 3616 | |
| 3617 | /* |
| 3618 | ** Return true if the artifact is complete. We assume that any non-empty |
| 3619 | ** artifact is complete. |
| 3620 | */ |
| 3621 | static int artifact_is_complete(Blob *ctrl){ |
| 3622 | return blob_size(ctrl)>0; |
| 3623 | } |
| 3624 | |
| 3625 | /* |
| 3626 | ** Apply a control artifact to the repository database. Except, if the |
| 3627 | ** artifact is empty, this routine is a no-op. |
| 3628 | */ |
| 3629 | static void publish_newtags_artifact(Blob *ctrl, int rid){ |
| 3630 | if( artifact_is_complete(ctrl) ){ |
| 3631 | int nrid; |
| 3632 | g.markPrivate = content_is_private(rid); |
| 3633 | nrid = content_put(ctrl); |
| 3634 | manifest_crosslink(nrid, ctrl, MC_PERMIT_HOOKS); |
| 3635 | } |
| 3636 | } |
| 3637 | /* End of the newtags subsystem |
| 3638 | ******************************************************************************/ |
| 3639 | |
| 3640 | /* |
| 3641 | ** This method checks that the date can be parsed. |
| 3642 | ** Returns 1 if datetime() can validate, 0 otherwise. |
| 3643 | */ |
| @@ -3644,14 +3696,17 @@ | |
| 3696 | int fPropagateColor; /* True if color propagates before edit */ |
| 3697 | int fNewPropagateColor; /* True if color propagates after edit */ |
| 3698 | int fHasHidden = 0; /* True if hidden tag already set */ |
| 3699 | int fHasClosed = 0; /* True if closed tag already set */ |
| 3700 | const char *zChngTime = 0; /* Value of chngtime= query param, if any */ |
| 3701 | int bApply = P("apply")!=0 && cgi_csrf_safe(2); |
| 3702 | int bPreview = P("preview")!=0; |
| 3703 | char *zUuid; |
| 3704 | Blob comment; |
| 3705 | char *zBranchName = 0; |
| 3706 | Stmt q; |
| 3707 | Blob ctrl; /* The generated control artifact */ |
| 3708 | |
| 3709 | login_check_credentials(); |
| 3710 | if( !g.perm.Write ){ login_needed(g.anon.Write); return; } |
| 3711 | rid = name_to_typed_rid(P("r"), "ci"); |
| 3712 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -3684,16 +3739,13 @@ | |
| 3739 | zNewBrFlag = P("newbr") ? " checked" : ""; |
| 3740 | zNewBranch = PDT("brname",""); |
| 3741 | zBranchName = branch_of_rid(rid); |
| 3742 | zCloseFlag = P("close") ? " checked" : ""; |
| 3743 | zHideFlag = P("hide") ? " checked" : ""; |
| 3744 | blob_zero(&ctrl); |
| 3745 | if( bApply || bPreview ){ |
| 3746 | char *zNow = date_in_standard_format(zChngTime ? zChngTime : "now"); |
| 3747 | blob_appendf(&ctrl, "D %s\n", zNow); |
| 3748 | init_newtags(); |
| 3749 | if( zNewColorFlag[0] |
| 3750 | && zNewColor[0] |
| 3751 | && (fPropagateColor!=fNewPropagateColor |
| @@ -3719,69 +3771,39 @@ | |
| 3771 | db_finalize(&q); |
| 3772 | if( zHideFlag[0] ) hide_branch(); |
| 3773 | if( zCloseFlag[0] ) close_leaf(rid); |
| 3774 | if( zNewTagFlag[0] && zNewTag[0] ) add_tag(zNewTag); |
| 3775 | if( zNewBrFlag[0] && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 3776 | construct_newtags_artifact(&ctrl, rid, zUuid, 0); |
| 3777 | if( bApply && artifact_is_complete(&ctrl) ){ |
| 3778 | db_begin_transaction(); |
| 3779 | publish_newtags_artifact(&ctrl, rid); |
| 3780 | db_end_transaction(0); |
| 3781 | blob_reset(&ctrl); |
| 3782 | cgi_redirectf("%R/ci/%S", zUuid); |
| 3783 | } |
| 3784 | } |
| 3785 | blob_zero(&comment); |
| 3786 | blob_append(&comment, zNewComment, -1); |
| 3787 | style_header("Edit Check-in %S", zUuid); |
| 3788 | @ <div class="section accordion">Original Context Around \ |
| 3789 | @ Check-in %S(zUuid) on %s(zDate)</div> |
| 3790 | @ <div class="accordion_panel"> |
| 3791 | render_checkin_context(rid, 0, 2, 0); |
| 3792 | @ </div> |
| 3793 | if( bPreview ){ |
| 3794 | @ <div class="section accordion">After The Proposed Changes</div> |
| 3795 | @ <div class="accordion_panel"> |
| 3796 | db_begin_transaction(); |
| 3797 | publish_newtags_artifact(&ctrl, rid); |
| 3798 | render_checkin_context(rid, 0, 2, 0); |
| 3799 | db_end_transaction(1); |
| 3800 | @ </div> |
| 3801 | } |
| 3802 | @ <div class="section accordion">Proposed Changes For \ |
| 3803 | @ Check-In %S(zUuid):</div> |
| 3804 | @ <div class="accordion_panel"> |
| 3805 | form_begin(0, "%R/ci_edit"); |
| 3806 | @ <div><input type="hidden" name="r" value="%s(zUuid)"> |
| 3807 | @ <table border="0" cellspacing="10"> |
| 3808 | |
| 3809 | @ <tr><th align="right" valign="top">User:</th> |
| @@ -4194,13 +4216,20 @@ | |
| 4216 | fossil_free((void *)pzCancelTags); |
| 4217 | } |
| 4218 | if( fHide && !fHasHidden ) hide_branch(); |
| 4219 | if( fClose && !fHasClosed ) close_leaf(rid); |
| 4220 | if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch); |
| 4221 | if( !fDryRun ) db_begin_transaction(); |
| 4222 | construct_newtags_artifact(&ctrl, rid, zUuid, zUserOvrd); |
| 4223 | if( fDryRun ){ |
| 4224 | fossil_print("%s", blob_str(&ctrl)); |
| 4225 | blob_reset(&ctrl); |
| 4226 | }else{ |
| 4227 | db_begin_transaction(); |
| 4228 | publish_newtags_artifact(&ctrl, rid); |
| 4229 | show_common_info(rid, "hash:", 1, 0); |
| 4230 | db_end_transaction(0); |
| 4231 | } |
| 4232 | if( g.localOpen ){ |
| 4233 | manifest_to_disk(rid); |
| 4234 | } |
| 4235 | } |
| 4236 |