CHANGED src/db.c Index: src/db.c =================================================================== --- src/db.c +++ src/db.c @@ -1525,10 +1525,16 @@ { "http-port", 0, 16, "8080" }, { "localauth", 0, 0, "0" }, { "mtime-changes", 0, 0, "0" }, { "pgp-command", 0, 32, "gpg --clearsign -o " }, { "proxy", 0, 32, "off" }, + { "push-hook-pattern-client", + 0, 32, "" }, + { "push-hook-pattern-cmd", + 0, 32, "" }, + { "push-hook-pattern-server", + 0, 32, "" }, { "ssh-command", 0, 32, "" }, { "web-browser", 0, 32, "" }, { 0,0,0,0 } }; @@ -1596,10 +1602,26 @@ ** ** proxy URL of the HTTP proxy. If undefined or "off" then ** the "http_proxy" environment variable is consulted. ** If the http_proxy environment variable is undefined ** then a direct HTTP connection is used. +** +** push-hook-pattern-client +** if set, a client push will sent this message to the +** server, to activate the push hook command. +** +** push-hook-pattern-cmd +** this is the command line, that will be activated +** as push hook. Output redirects should be added to +** this command line. +** The complete pattern, sent by the client will be +** appended to the command line. +** +** push-hook-pattern-server +** if set, and a client send this pattern at the end of +** a push, the push hook command will be executed. This +** might be a prefix of the pattern, sent by the client. ** ** ssh-command Command used to talk to a remote machine with ** the "ssh://" protocol. ** ** web-browser A shell command used to launch your preferred CHANGED src/xfer.c Index: src/xfer.c =================================================================== --- src/xfer.c +++ src/xfer.c @@ -40,10 +40,32 @@ int nDeltaRcvd; /* Number of deltas received */ int nDanglingFile; /* Number of dangling deltas received */ int mxSend; /* Stop sending "file" with pOut reaches this size */ }; +/* +** Let a server-side external agent know that a push has completed. /fatman +*/ +void post_push_hook(char const * const zPushHookLine){ + /* + ** TO DO: get the string cmd from a config file? Or the database local + ** settings, as someone suggested? Ditto output and error logs. /fatman + */ + const char *zCmd = db_get("push-hook-pattern-cmd", ""); + + if( zCmd && zCmd[0] ){ + int rc; + char * zCalledCmd; + + zCalledCmd = mprintf("%s %s",zCmd,zPushHookLine); + rc = system(zCalledCmd); + if (rc != 0) { + fossil_print("The post-push-hook command \"%s\" failed.", zCalledCmd); + } + free(zCalledCmd); + } +} /* ** The input blob contains a UUID. Convert it into a record ID. ** Create a phantom record if no prior record exists and ** phantomize is true. @@ -596,10 +618,13 @@ int isClone = 0; int nGimme = 0; int size; int recvConfig = 0; char *zNow; + const char *zPushHookPattern = db_get("push-hook-pattern-server", ""); + int lenPushHookPattern = (zPushHookPattern && zPushHookPattern[0]) + ? strlen(zPushHookPattern) : 0; if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ fossil_redirect_home(); } memset(&xfer, 0, sizeof(xfer)); @@ -617,11 +642,19 @@ ); zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')"); @ # timestamp %s(zNow) manifest_crosslink_begin(); while( blob_line(xfer.pIn, &xfer.line) ){ - if( blob_buffer(&xfer.line)[0]=='#' ) continue; + if( blob_buffer(&xfer.line)[0]=='#' ){ + if( lenPushHookPattern + && 0 == memcmp(blob_buffer(&xfer.line)+1, + zPushHookPattern, lenPushHookPattern) + ){ + post_push_hook(blob_buffer(&xfer.line)+1); + } + continue; + } xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); /* file UUID SIZE \n CONTENT ** file UUID DELTASRC SIZE \n CONTENT ** @@ -948,10 +981,12 @@ Blob send; /* Text we are sending to the server */ Blob recv; /* Reply we got back from the server */ Xfer xfer; /* Transfer data */ const char *zSCode = db_get("server-code", "x"); const char *zPCode = db_get("project-code", 0); + const char *zPushHookPattern = db_get("push-hook-pattern-client", ""); + if( db_get_boolean("dont-push", 0) ) pushFlag = 0; if( pushFlag + pullFlag + cloneFlag == 0 && configRcvMask==0 && configSendMask==0 ) return; @@ -1330,14 +1365,22 @@ } /* If this is a clone, the go at least two rounds */ if( cloneFlag && nCycle==1 ) go = 1; }; + if (pushFlag && nFileSend > 0) { + if( zPushHookPattern && zPushHookPattern[0] ){ + blob_appendf(&send, "#%s\n", zPushHookPattern); + http_exchange(&send, &recv, cloneFlag==0 || nCycle>0); + blob_reset(&send); + nCardSent++; + } + } transport_stats(&nSent, &nRcvd, 1); fossil_print("Total network traffic: %d bytes sent, %d bytes received\n", nSent, nRcvd); transport_close(); transport_global_shutdown(); db_multi_exec("DROP TABLE onremote"); manifest_crosslink_end(); db_end_transaction(0); }