Fossil SCM
Allow the form ymd=YYYYMMDD-YYYYMMDD to show a range of days in the /timeline.
Commit
7e68a6f1e029c6eb4929cf769db699744ec1036e2555f680fdbd448882236c1d
Parent
e9c68906107bc43…
1 file changed
+108
-5
+108
-5
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1345,10 +1345,45 @@ | ||
| 1345 | 1345 | zEDate[j] = 0; |
| 1346 | 1346 | |
| 1347 | 1347 | /* It looks like this may be a date. Return it with punctuation added. */ |
| 1348 | 1348 | return zEDate; |
| 1349 | 1349 | } |
| 1350 | + | |
| 1351 | +/* | |
| 1352 | +** Check to see if the argument is a date-span for the ymd= query | |
| 1353 | +** parameter. A valid date-span is of the form: | |
| 1354 | +** | |
| 1355 | +** 0123456789 123456 <-- index | |
| 1356 | +** YYYYMMDD-YYYYMMDD | |
| 1357 | +** | |
| 1358 | +** with an optional "Z" timeline modifier at the end. Return true if | |
| 1359 | +** the input is a valid date space and false if not. | |
| 1360 | +*/ | |
| 1361 | +static int timeline_is_datespan(const char *zDay){ | |
| 1362 | + size_t n = strlen(zDay); | |
| 1363 | + int i, d, m; | |
| 1364 | + | |
| 1365 | + if( n<17 || n>18 ) return 0; | |
| 1366 | + if( n==18 ){ | |
| 1367 | + if( zDay[17]!='Z' && zDay[17]!='z' ) return 0; | |
| 1368 | + n--; | |
| 1369 | + } | |
| 1370 | + if( zDay[8]!='-' ) return 0; | |
| 1371 | + for(i=0; i<17 && (fossil_isdigit(zDay[i]) || i==8); i++){} | |
| 1372 | + if( i!=17 ) return 0; | |
| 1373 | + i = atoi(zDay); | |
| 1374 | + d = i%100; | |
| 1375 | + if( d<1 || d>31 ) return 0; | |
| 1376 | + m = (i/100)%100; | |
| 1377 | + if( m<1 || m>12 ) return 0; | |
| 1378 | + i = atoi(zDay+9); | |
| 1379 | + d = i%100; | |
| 1380 | + if( d<1 || d>31 ) return 0; | |
| 1381 | + m = (i/100)%100; | |
| 1382 | + if( m<1 || m>12 ) return 0; | |
| 1383 | + return 1; | |
| 1384 | +} | |
| 1350 | 1385 | |
| 1351 | 1386 | /* |
| 1352 | 1387 | ** Find the first check-in encountered with a particular tag |
| 1353 | 1388 | ** when moving either forwards are backwards in time from a |
| 1354 | 1389 | ** particular starting point (iFrom). Return the rid of that |
| @@ -1598,15 +1633,17 @@ | ||
| 1598 | 1633 | ** deltabg Background color red for delta manifests or green |
| 1599 | 1634 | ** for baseline manifests |
| 1600 | 1635 | ** namechng Show only check-ins that have filename changes |
| 1601 | 1636 | ** forks Show only forks and their children |
| 1602 | 1637 | ** cherrypicks Show all cherrypicks |
| 1603 | -** ym=YYYY-MM Show only events for the given year/month | |
| 1604 | -** yw=YYYY-WW Show only events for the given week of the given year | |
| 1605 | -** yw=YYYY-MM-DD Show events for the week that includes the given day | |
| 1606 | -** ymd=YYYY-MM-DD Show only events on the given day. The use "ymd=now" | |
| 1607 | -** to see all changes for the current week. | |
| 1638 | +** ym=YYYYMM Show only events for the given year/month | |
| 1639 | +** yw=YYYYWW Show only events for the given week of the given year | |
| 1640 | +** yw=YYYYMMDD Show events for the week that includes the given day | |
| 1641 | +** ymd=YYYYMMDD Show only events on the given day. The use "ymd=now" | |
| 1642 | +** to see all changes for the current week. Add "z" at end | |
| 1643 | +** to divide days at UTC instead of localtime days. | |
| 1644 | +** Use ymd=YYYYMMDD-YYYYMMDD (with optional "z") for a range. | |
| 1608 | 1645 | ** year=YYYY Show only events on the given year. The use "year=0" |
| 1609 | 1646 | ** to see all changes for the current year. |
| 1610 | 1647 | ** days=N Show events over the previous N days |
| 1611 | 1648 | ** datefmt=N Override the date format: 0=HH:MM, 1=HH:MM:SS, |
| 1612 | 1649 | ** 2=YYYY-MM-DD HH:MM:SS, 3=YYMMDD HH:MM, and 4 means "off". |
| @@ -2474,15 +2511,81 @@ | ||
| 2474 | 2511 | zYearWeekStart, zTZMod, zYearWeekStart, zTZMod); |
| 2475 | 2512 | nEntry = -1; |
| 2476 | 2513 | if( fossil_ui_localtime() && bZulu ){ |
| 2477 | 2514 | zYearWeekStart = mprintf("%zZ", zYearWeekStart); |
| 2478 | 2515 | } |
| 2516 | + } | |
| 2517 | + else if( zDay && timeline_is_datespan(zDay) ){ | |
| 2518 | + char *zNext; | |
| 2519 | + char *zStart, *zEnd; | |
| 2520 | + int nDay; | |
| 2521 | + int bZulu = 0; | |
| 2522 | + const char *zTZMod; | |
| 2523 | + zEnd = db_text(0, "SELECT date(%Q)", | |
| 2524 | + timeline_expand_datetime(zDay+9, &bZulu)); | |
| 2525 | + zStart = db_text(0, "SELECT date('%.4q-%.2q-%.2q')", | |
| 2526 | + zDay, zDay+4, zDay+6); | |
| 2527 | + nDay = db_int(0, "SELECT julianday(%Q)-julianday(%Q)", zEnd, zStart); | |
| 2528 | + if( nDay==0 ){ | |
| 2529 | + zDay = &zDay[9]; | |
| 2530 | + goto single_ymd; | |
| 2531 | + } | |
| 2532 | + if( nDay<0 ){ | |
| 2533 | + char *zTemp = zEnd; | |
| 2534 | + zEnd = zStart; | |
| 2535 | + zStart = zTemp; | |
| 2536 | + nDay = 1 - nDay; | |
| 2537 | + }else{ | |
| 2538 | + nDay += 1; | |
| 2539 | + } | |
| 2540 | + zTZMod = (bZulu==0 && fossil_ui_localtime()) ? "utc" : "+00:00"; | |
| 2541 | + if( nDay>0 && db_int(0, | |
| 2542 | + "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob" | |
| 2543 | + " WHERE blob.rid=event.objid" | |
| 2544 | + " AND mtime>=julianday(%Q,'1 day',%Q)%s)", | |
| 2545 | + zEnd, zTZMod, blob_sql_text(&cond)) | |
| 2546 | + ){ | |
| 2547 | + zNext = db_text(0, | |
| 2548 | + "SELECT strftime('%%Y%%m%%d-',%Q,'%d days')||" | |
| 2549 | + "strftime('%%Y%%m%%d%q',%Q,'%d day');", | |
| 2550 | + zStart, nDay, &"Z"[!bZulu], zEnd, nDay); | |
| 2551 | + zNewerButton = fossil_strdup(url_render(&url, "ymd", zNext, 0, 0)); | |
| 2552 | + zNewerButtonLabel = mprintf("Following %d days", nDay); | |
| 2553 | + fossil_free(zNext); | |
| 2554 | + } | |
| 2555 | + if( nDay>1 && db_int(0, | |
| 2556 | + "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob" | |
| 2557 | + " WHERE blob.rid=event.objid" | |
| 2558 | + " AND mtime<julianday(%Q,'-1 day',%Q)%s)", | |
| 2559 | + zStart, zTZMod, blob_sql_text(&cond)) | |
| 2560 | + ){ | |
| 2561 | + zNext = db_text(0, | |
| 2562 | + "SELECT strftime('%%Y%%m%%d-',%Q,'%d days')||" | |
| 2563 | + "strftime('%%Y%%m%%d%q',%Q,'%d day');", | |
| 2564 | + zStart, -nDay, &"Z"[!bZulu], zEnd, -nDay); | |
| 2565 | + zOlderButton = fossil_strdup(url_render(&url, "ymd", zNext, 0, 0)); | |
| 2566 | + zOlderButtonLabel = mprintf("Previous %d days", nDay); | |
| 2567 | + fossil_free(zNext); | |
| 2568 | + } | |
| 2569 | + blob_append_sql(&cond, | |
| 2570 | + " AND event.mtime>=julianday(%Q,%Q)" | |
| 2571 | + " AND event.mtime<julianday(%Q,%Q,'+1 day')\n", | |
| 2572 | + zStart, zTZMod, zEnd, zTZMod); | |
| 2573 | + nEntry = -1; | |
| 2574 | + | |
| 2575 | + if( fossil_ui_localtime() && bZulu ){ | |
| 2576 | + zDay = mprintf("%d days between %zZ through %zZ", nDay, zStart, zEnd); | |
| 2577 | + }else{ | |
| 2578 | + zDay = mprintf("%d days between %z through %z", nDay, zStart, zEnd); | |
| 2579 | + } | |
| 2479 | 2580 | } |
| 2480 | 2581 | else if( zDay ){ |
| 2481 | 2582 | char *zNext; |
| 2482 | 2583 | int bZulu = 0; |
| 2483 | 2584 | const char *zTZMod; |
| 2585 | + single_ymd: | |
| 2586 | + bZulu = 0; | |
| 2484 | 2587 | zDay = timeline_expand_datetime(zDay, &bZulu); |
| 2485 | 2588 | zDay = db_text(0, "SELECT date(%Q)", zDay); |
| 2486 | 2589 | if( zDay==0 || zDay[0]==0 ){ |
| 2487 | 2590 | zDay = db_text(0, "SELECT date('now')"); |
| 2488 | 2591 | } |
| 2489 | 2592 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1345,10 +1345,45 @@ | |
| 1345 | zEDate[j] = 0; |
| 1346 | |
| 1347 | /* It looks like this may be a date. Return it with punctuation added. */ |
| 1348 | return zEDate; |
| 1349 | } |
| 1350 | |
| 1351 | /* |
| 1352 | ** Find the first check-in encountered with a particular tag |
| 1353 | ** when moving either forwards are backwards in time from a |
| 1354 | ** particular starting point (iFrom). Return the rid of that |
| @@ -1598,15 +1633,17 @@ | |
| 1598 | ** deltabg Background color red for delta manifests or green |
| 1599 | ** for baseline manifests |
| 1600 | ** namechng Show only check-ins that have filename changes |
| 1601 | ** forks Show only forks and their children |
| 1602 | ** cherrypicks Show all cherrypicks |
| 1603 | ** ym=YYYY-MM Show only events for the given year/month |
| 1604 | ** yw=YYYY-WW Show only events for the given week of the given year |
| 1605 | ** yw=YYYY-MM-DD Show events for the week that includes the given day |
| 1606 | ** ymd=YYYY-MM-DD Show only events on the given day. The use "ymd=now" |
| 1607 | ** to see all changes for the current week. |
| 1608 | ** year=YYYY Show only events on the given year. The use "year=0" |
| 1609 | ** to see all changes for the current year. |
| 1610 | ** days=N Show events over the previous N days |
| 1611 | ** datefmt=N Override the date format: 0=HH:MM, 1=HH:MM:SS, |
| 1612 | ** 2=YYYY-MM-DD HH:MM:SS, 3=YYMMDD HH:MM, and 4 means "off". |
| @@ -2474,15 +2511,81 @@ | |
| 2474 | zYearWeekStart, zTZMod, zYearWeekStart, zTZMod); |
| 2475 | nEntry = -1; |
| 2476 | if( fossil_ui_localtime() && bZulu ){ |
| 2477 | zYearWeekStart = mprintf("%zZ", zYearWeekStart); |
| 2478 | } |
| 2479 | } |
| 2480 | else if( zDay ){ |
| 2481 | char *zNext; |
| 2482 | int bZulu = 0; |
| 2483 | const char *zTZMod; |
| 2484 | zDay = timeline_expand_datetime(zDay, &bZulu); |
| 2485 | zDay = db_text(0, "SELECT date(%Q)", zDay); |
| 2486 | if( zDay==0 || zDay[0]==0 ){ |
| 2487 | zDay = db_text(0, "SELECT date('now')"); |
| 2488 | } |
| 2489 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1345,10 +1345,45 @@ | |
| 1345 | zEDate[j] = 0; |
| 1346 | |
| 1347 | /* It looks like this may be a date. Return it with punctuation added. */ |
| 1348 | return zEDate; |
| 1349 | } |
| 1350 | |
| 1351 | /* |
| 1352 | ** Check to see if the argument is a date-span for the ymd= query |
| 1353 | ** parameter. A valid date-span is of the form: |
| 1354 | ** |
| 1355 | ** 0123456789 123456 <-- index |
| 1356 | ** YYYYMMDD-YYYYMMDD |
| 1357 | ** |
| 1358 | ** with an optional "Z" timeline modifier at the end. Return true if |
| 1359 | ** the input is a valid date space and false if not. |
| 1360 | */ |
| 1361 | static int timeline_is_datespan(const char *zDay){ |
| 1362 | size_t n = strlen(zDay); |
| 1363 | int i, d, m; |
| 1364 | |
| 1365 | if( n<17 || n>18 ) return 0; |
| 1366 | if( n==18 ){ |
| 1367 | if( zDay[17]!='Z' && zDay[17]!='z' ) return 0; |
| 1368 | n--; |
| 1369 | } |
| 1370 | if( zDay[8]!='-' ) return 0; |
| 1371 | for(i=0; i<17 && (fossil_isdigit(zDay[i]) || i==8); i++){} |
| 1372 | if( i!=17 ) return 0; |
| 1373 | i = atoi(zDay); |
| 1374 | d = i%100; |
| 1375 | if( d<1 || d>31 ) return 0; |
| 1376 | m = (i/100)%100; |
| 1377 | if( m<1 || m>12 ) return 0; |
| 1378 | i = atoi(zDay+9); |
| 1379 | d = i%100; |
| 1380 | if( d<1 || d>31 ) return 0; |
| 1381 | m = (i/100)%100; |
| 1382 | if( m<1 || m>12 ) return 0; |
| 1383 | return 1; |
| 1384 | } |
| 1385 | |
| 1386 | /* |
| 1387 | ** Find the first check-in encountered with a particular tag |
| 1388 | ** when moving either forwards are backwards in time from a |
| 1389 | ** particular starting point (iFrom). Return the rid of that |
| @@ -1598,15 +1633,17 @@ | |
| 1633 | ** deltabg Background color red for delta manifests or green |
| 1634 | ** for baseline manifests |
| 1635 | ** namechng Show only check-ins that have filename changes |
| 1636 | ** forks Show only forks and their children |
| 1637 | ** cherrypicks Show all cherrypicks |
| 1638 | ** ym=YYYYMM Show only events for the given year/month |
| 1639 | ** yw=YYYYWW Show only events for the given week of the given year |
| 1640 | ** yw=YYYYMMDD Show events for the week that includes the given day |
| 1641 | ** ymd=YYYYMMDD Show only events on the given day. The use "ymd=now" |
| 1642 | ** to see all changes for the current week. Add "z" at end |
| 1643 | ** to divide days at UTC instead of localtime days. |
| 1644 | ** Use ymd=YYYYMMDD-YYYYMMDD (with optional "z") for a range. |
| 1645 | ** year=YYYY Show only events on the given year. The use "year=0" |
| 1646 | ** to see all changes for the current year. |
| 1647 | ** days=N Show events over the previous N days |
| 1648 | ** datefmt=N Override the date format: 0=HH:MM, 1=HH:MM:SS, |
| 1649 | ** 2=YYYY-MM-DD HH:MM:SS, 3=YYMMDD HH:MM, and 4 means "off". |
| @@ -2474,15 +2511,81 @@ | |
| 2511 | zYearWeekStart, zTZMod, zYearWeekStart, zTZMod); |
| 2512 | nEntry = -1; |
| 2513 | if( fossil_ui_localtime() && bZulu ){ |
| 2514 | zYearWeekStart = mprintf("%zZ", zYearWeekStart); |
| 2515 | } |
| 2516 | } |
| 2517 | else if( zDay && timeline_is_datespan(zDay) ){ |
| 2518 | char *zNext; |
| 2519 | char *zStart, *zEnd; |
| 2520 | int nDay; |
| 2521 | int bZulu = 0; |
| 2522 | const char *zTZMod; |
| 2523 | zEnd = db_text(0, "SELECT date(%Q)", |
| 2524 | timeline_expand_datetime(zDay+9, &bZulu)); |
| 2525 | zStart = db_text(0, "SELECT date('%.4q-%.2q-%.2q')", |
| 2526 | zDay, zDay+4, zDay+6); |
| 2527 | nDay = db_int(0, "SELECT julianday(%Q)-julianday(%Q)", zEnd, zStart); |
| 2528 | if( nDay==0 ){ |
| 2529 | zDay = &zDay[9]; |
| 2530 | goto single_ymd; |
| 2531 | } |
| 2532 | if( nDay<0 ){ |
| 2533 | char *zTemp = zEnd; |
| 2534 | zEnd = zStart; |
| 2535 | zStart = zTemp; |
| 2536 | nDay = 1 - nDay; |
| 2537 | }else{ |
| 2538 | nDay += 1; |
| 2539 | } |
| 2540 | zTZMod = (bZulu==0 && fossil_ui_localtime()) ? "utc" : "+00:00"; |
| 2541 | if( nDay>0 && db_int(0, |
| 2542 | "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob" |
| 2543 | " WHERE blob.rid=event.objid" |
| 2544 | " AND mtime>=julianday(%Q,'1 day',%Q)%s)", |
| 2545 | zEnd, zTZMod, blob_sql_text(&cond)) |
| 2546 | ){ |
| 2547 | zNext = db_text(0, |
| 2548 | "SELECT strftime('%%Y%%m%%d-',%Q,'%d days')||" |
| 2549 | "strftime('%%Y%%m%%d%q',%Q,'%d day');", |
| 2550 | zStart, nDay, &"Z"[!bZulu], zEnd, nDay); |
| 2551 | zNewerButton = fossil_strdup(url_render(&url, "ymd", zNext, 0, 0)); |
| 2552 | zNewerButtonLabel = mprintf("Following %d days", nDay); |
| 2553 | fossil_free(zNext); |
| 2554 | } |
| 2555 | if( nDay>1 && db_int(0, |
| 2556 | "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob" |
| 2557 | " WHERE blob.rid=event.objid" |
| 2558 | " AND mtime<julianday(%Q,'-1 day',%Q)%s)", |
| 2559 | zStart, zTZMod, blob_sql_text(&cond)) |
| 2560 | ){ |
| 2561 | zNext = db_text(0, |
| 2562 | "SELECT strftime('%%Y%%m%%d-',%Q,'%d days')||" |
| 2563 | "strftime('%%Y%%m%%d%q',%Q,'%d day');", |
| 2564 | zStart, -nDay, &"Z"[!bZulu], zEnd, -nDay); |
| 2565 | zOlderButton = fossil_strdup(url_render(&url, "ymd", zNext, 0, 0)); |
| 2566 | zOlderButtonLabel = mprintf("Previous %d days", nDay); |
| 2567 | fossil_free(zNext); |
| 2568 | } |
| 2569 | blob_append_sql(&cond, |
| 2570 | " AND event.mtime>=julianday(%Q,%Q)" |
| 2571 | " AND event.mtime<julianday(%Q,%Q,'+1 day')\n", |
| 2572 | zStart, zTZMod, zEnd, zTZMod); |
| 2573 | nEntry = -1; |
| 2574 | |
| 2575 | if( fossil_ui_localtime() && bZulu ){ |
| 2576 | zDay = mprintf("%d days between %zZ through %zZ", nDay, zStart, zEnd); |
| 2577 | }else{ |
| 2578 | zDay = mprintf("%d days between %z through %z", nDay, zStart, zEnd); |
| 2579 | } |
| 2580 | } |
| 2581 | else if( zDay ){ |
| 2582 | char *zNext; |
| 2583 | int bZulu = 0; |
| 2584 | const char *zTZMod; |
| 2585 | single_ymd: |
| 2586 | bZulu = 0; |
| 2587 | zDay = timeline_expand_datetime(zDay, &bZulu); |
| 2588 | zDay = db_text(0, "SELECT date(%Q)", zDay); |
| 2589 | if( zDay==0 || zDay[0]==0 ){ |
| 2590 | zDay = db_text(0, "SELECT date('now')"); |
| 2591 | } |
| 2592 |