Fossil SCM
The backoffice now invokes after-receive hooks.
Commit
4777999d32b65002b6f38ce09a97d8a19d0f2f8b59243c2dd75a55d58256c674
Parent
af817f346bd0873…
2 files changed
+3
+49
+3
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -19,10 +19,11 @@ | ||
| 19 | 19 | ** occur after user interaction with the repository. Examples of |
| 20 | 20 | ** backoffice processing includes: |
| 21 | 21 | ** |
| 22 | 22 | ** * Sending alerts and notifications |
| 23 | 23 | ** * Processing the email queue |
| 24 | +** * Handling post-receive hooks | |
| 24 | 25 | ** * Automatically syncing to peer repositories |
| 25 | 26 | ** |
| 26 | 27 | ** Backoffice processing is automatically started whenever there are |
| 27 | 28 | ** changes to the repository. The backoffice process dies off after |
| 28 | 29 | ** a period of inactivity. |
| @@ -627,10 +628,12 @@ | ||
| 627 | 628 | /* Here is where the actual work of the backoffice happens */ |
| 628 | 629 | nThis = alert_backoffice(0); |
| 629 | 630 | if( nThis ){ backoffice_log("%d alerts", nThis); nTotal += nThis; } |
| 630 | 631 | nThis = smtp_cleanup(); |
| 631 | 632 | if( nThis ){ backoffice_log("%d SMTPs", nThis); nTotal += nThis; } |
| 633 | + nThis = hook_backoffice(); | |
| 634 | + if( nThis ){ backoffice_log("%d hooks", nThis); nTotal += nThis; } | |
| 632 | 635 | |
| 633 | 636 | /* Close the log */ |
| 634 | 637 | if( backofficeFILE ){ |
| 635 | 638 | if( nTotal || backofficeLogDetail ){ |
| 636 | 639 | if( nTotal==0 ) backoffice_log("no-op"); |
| 637 | 640 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -19,10 +19,11 @@ | |
| 19 | ** occur after user interaction with the repository. Examples of |
| 20 | ** backoffice processing includes: |
| 21 | ** |
| 22 | ** * Sending alerts and notifications |
| 23 | ** * Processing the email queue |
| 24 | ** * Automatically syncing to peer repositories |
| 25 | ** |
| 26 | ** Backoffice processing is automatically started whenever there are |
| 27 | ** changes to the repository. The backoffice process dies off after |
| 28 | ** a period of inactivity. |
| @@ -627,10 +628,12 @@ | |
| 627 | /* Here is where the actual work of the backoffice happens */ |
| 628 | nThis = alert_backoffice(0); |
| 629 | if( nThis ){ backoffice_log("%d alerts", nThis); nTotal += nThis; } |
| 630 | nThis = smtp_cleanup(); |
| 631 | if( nThis ){ backoffice_log("%d SMTPs", nThis); nTotal += nThis; } |
| 632 | |
| 633 | /* Close the log */ |
| 634 | if( backofficeFILE ){ |
| 635 | if( nTotal || backofficeLogDetail ){ |
| 636 | if( nTotal==0 ) backoffice_log("no-op"); |
| 637 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -19,10 +19,11 @@ | |
| 19 | ** occur after user interaction with the repository. Examples of |
| 20 | ** backoffice processing includes: |
| 21 | ** |
| 22 | ** * Sending alerts and notifications |
| 23 | ** * Processing the email queue |
| 24 | ** * Handling post-receive hooks |
| 25 | ** * Automatically syncing to peer repositories |
| 26 | ** |
| 27 | ** Backoffice processing is automatically started whenever there are |
| 28 | ** changes to the repository. The backoffice process dies off after |
| 29 | ** a period of inactivity. |
| @@ -627,10 +628,12 @@ | |
| 628 | /* Here is where the actual work of the backoffice happens */ |
| 629 | nThis = alert_backoffice(0); |
| 630 | if( nThis ){ backoffice_log("%d alerts", nThis); nTotal += nThis; } |
| 631 | nThis = smtp_cleanup(); |
| 632 | if( nThis ){ backoffice_log("%d SMTPs", nThis); nTotal += nThis; } |
| 633 | nThis = hook_backoffice(); |
| 634 | if( nThis ){ backoffice_log("%d hooks", nThis); nTotal += nThis; } |
| 635 | |
| 636 | /* Close the log */ |
| 637 | if( backofficeFILE ){ |
| 638 | if( nTotal || backofficeLogDetail ){ |
| 639 | if( nTotal==0 ) backoffice_log("no-op"); |
| 640 |
+49
| --- src/hook.c | ||
| +++ src/hook.c | ||
| @@ -352,5 +352,54 @@ | ||
| 352 | 352 | { |
| 353 | 353 | fossil_fatal("unknown command \"%s\" - should be one of: " |
| 354 | 354 | "add delete edit list test", zCmd); |
| 355 | 355 | } |
| 356 | 356 | } |
| 357 | + | |
| 358 | +/* | |
| 359 | +** The backoffice calls this routine to run the after-receive hooks. | |
| 360 | +*/ | |
| 361 | +int hook_backoffice(void){ | |
| 362 | + Stmt q; | |
| 363 | + const char *zLastRcvid = 0; | |
| 364 | + char *zNewRcvid = 0; | |
| 365 | + Blob chng; | |
| 366 | + int cnt = 0; | |
| 367 | + db_begin_write(); | |
| 368 | + if( !db_exists("SELECT 1 FROM config WHERE name='hooks'") ){ | |
| 369 | + goto hook_backoffice_done; /* No hooks */ | |
| 370 | + } | |
| 371 | + zLastRcvid = db_get("hook-last-rcvid","0"); | |
| 372 | + zNewRcvid = db_text("0","SELECT max(rcvid) FROM rcvfrom"); | |
| 373 | + if( atoi(zLastRcvid)>=atoi(zNewRcvid) ){ | |
| 374 | + goto hook_backoffice_done; /* no new content */ | |
| 375 | + } | |
| 376 | + blob_init(&chng, 0, 0); | |
| 377 | + db_prepare(&q, | |
| 378 | + "SELECT json_extract(jx.value,'$.cmd') " | |
| 379 | + " FROM config, json_each(config.value) AS jx" | |
| 380 | + " WHERE config.name='hooks' AND json_valid(config.value)" | |
| 381 | + " AND json_extract(jx.value,'$.type')='after-receive'" | |
| 382 | + " ORDER BY json_extract(jx.value,'$.seq');" | |
| 383 | + ); | |
| 384 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 385 | + char *zCmd; | |
| 386 | + FILE *f; | |
| 387 | + if( cnt==0 ){ | |
| 388 | + hook_changes(&chng, zLastRcvid, 0); | |
| 389 | + } | |
| 390 | + zCmd = hook_subst(db_column_text(&q,0)); | |
| 391 | + f = popen(zCmd, "w"); | |
| 392 | + if( f ){ | |
| 393 | + fwrite(blob_buffer(&chng),1,blob_size(&chng),f); | |
| 394 | + pclose(f); | |
| 395 | + } | |
| 396 | + fossil_free(zCmd); | |
| 397 | + cnt++; | |
| 398 | + } | |
| 399 | + db_finalize(&q); | |
| 400 | + db_set("hook-last-rcvid", zNewRcvid, 0); | |
| 401 | + blob_reset(&chng); | |
| 402 | +hook_backoffice_done: | |
| 403 | + db_commit_transaction(); | |
| 404 | + return cnt; | |
| 405 | +} | |
| 357 | 406 |
| --- src/hook.c | |
| +++ src/hook.c | |
| @@ -352,5 +352,54 @@ | |
| 352 | { |
| 353 | fossil_fatal("unknown command \"%s\" - should be one of: " |
| 354 | "add delete edit list test", zCmd); |
| 355 | } |
| 356 | } |
| 357 |
| --- src/hook.c | |
| +++ src/hook.c | |
| @@ -352,5 +352,54 @@ | |
| 352 | { |
| 353 | fossil_fatal("unknown command \"%s\" - should be one of: " |
| 354 | "add delete edit list test", zCmd); |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /* |
| 359 | ** The backoffice calls this routine to run the after-receive hooks. |
| 360 | */ |
| 361 | int hook_backoffice(void){ |
| 362 | Stmt q; |
| 363 | const char *zLastRcvid = 0; |
| 364 | char *zNewRcvid = 0; |
| 365 | Blob chng; |
| 366 | int cnt = 0; |
| 367 | db_begin_write(); |
| 368 | if( !db_exists("SELECT 1 FROM config WHERE name='hooks'") ){ |
| 369 | goto hook_backoffice_done; /* No hooks */ |
| 370 | } |
| 371 | zLastRcvid = db_get("hook-last-rcvid","0"); |
| 372 | zNewRcvid = db_text("0","SELECT max(rcvid) FROM rcvfrom"); |
| 373 | if( atoi(zLastRcvid)>=atoi(zNewRcvid) ){ |
| 374 | goto hook_backoffice_done; /* no new content */ |
| 375 | } |
| 376 | blob_init(&chng, 0, 0); |
| 377 | db_prepare(&q, |
| 378 | "SELECT json_extract(jx.value,'$.cmd') " |
| 379 | " FROM config, json_each(config.value) AS jx" |
| 380 | " WHERE config.name='hooks' AND json_valid(config.value)" |
| 381 | " AND json_extract(jx.value,'$.type')='after-receive'" |
| 382 | " ORDER BY json_extract(jx.value,'$.seq');" |
| 383 | ); |
| 384 | while( db_step(&q)==SQLITE_ROW ){ |
| 385 | char *zCmd; |
| 386 | FILE *f; |
| 387 | if( cnt==0 ){ |
| 388 | hook_changes(&chng, zLastRcvid, 0); |
| 389 | } |
| 390 | zCmd = hook_subst(db_column_text(&q,0)); |
| 391 | f = popen(zCmd, "w"); |
| 392 | if( f ){ |
| 393 | fwrite(blob_buffer(&chng),1,blob_size(&chng),f); |
| 394 | pclose(f); |
| 395 | } |
| 396 | fossil_free(zCmd); |
| 397 | cnt++; |
| 398 | } |
| 399 | db_finalize(&q); |
| 400 | db_set("hook-last-rcvid", zNewRcvid, 0); |
| 401 | blob_reset(&chng); |
| 402 | hook_backoffice_done: |
| 403 | db_commit_transaction(); |
| 404 | return cnt; |
| 405 | } |
| 406 |