Fossil

Check-in [9cf288de]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:merge from old hook branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | StvPrivateHook2
Files: files | file ages | folders
SHA1:9cf288de27c2eb720cab38f03b0890ae926e79e5
User & Date: wolfgang 2010-10-17 16:37:39
References
2010-10-19
08:03 Ticket [77de516a] Post-push patch status still Open with 1 other change artifact: 5f9da2a9 user: wolfgang
2010-10-18
14:07 Ticket [77de516a]: 1 change artifact: 98862f6f user: wolfgang
Context
2010-10-18
15:46
added output redirect and client force for hook check-in: ccef28b5 user: wolfgang tags: StvPrivateHook2
2010-10-17
16:37
merge from old hook branch check-in: 9cf288de user: wolfgang tags: StvPrivateHook2
2010-10-16
19:07
PellesC doesn't have pgmptr, update Makefile Leaf check-in: f8836874 user: wolfgang tags: wolfgangHelpCmd
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/db.c.

1523
1524
1525
1526
1527
1528
1529





1530
1531
1532
1533
1534
1535
1536
....
1595
1596
1597
1598
1599
1600
1601















1602
1603
1604
1605
1606
1607
1608
  { "gdiff-command", 0,               16, "gdiff"               },
  { "ignore-glob",   0,               40, ""                    },
  { "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"                 },





  { "ssh-command",   0,               32, ""                    },
  { "web-browser",   0,               32, ""                    },
  { 0,0,0,0 }
};

/*
** COMMAND: settings
................................................................................
**                  The default is "gpg --clearsign -o ".
**
**    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.
**















**    ssh-command   Command used to talk to a remote machine with
**                  the "ssh://" protocol.
**
**    web-browser   A shell command used to launch your preferred
**                  web browser when given a URL as an argument.
**                  Defaults to "start" on windows, "open" on Mac,
**                  and "firefox" on Unix.







>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
....
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
  { "gdiff-command", 0,               16, "gdiff"               },
  { "ignore-glob",   0,               40, ""                    },
  { "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-cmd", 0,               32, ""                    },
  { "push-hook-pattern-client",
                     0,               32, ""                    },
  { "push-hook-pattern-server",
                     0,               32, ""                    },
  { "ssh-command",   0,               32, ""                    },
  { "web-browser",   0,               32, ""                    },
  { 0,0,0,0 }
};

/*
** COMMAND: settings
................................................................................
**                  The default is "gpg --clearsign -o ".
**
**    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-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-client
**                  if set, a client push will sent this message to the
**                  server, to activate the push hook command.
**
**    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
**                  web browser when given a URL as an argument.
**                  Defaults to "start" on windows, "open" on Mac,
**                  and "firefox" on Unix.

Changes to src/sync.c.

162
163
164
165
166
167
168



169
170
171
172
173
174
175
** <a>clone</a>, <a>push</a>, <a>pull</a>, <a>remote-url</a>, or <a>sync</a> command
** is used.
**
** The URL specified normally becomes the new "remote-url" used for
** subsequent <a>push</a>, <a>pull</a>, and <a>sync</a> operations.  However,
** the "--once" command-line option makes the URL a one-time-use URL
** that is not saved.



**
** See also: <a>clone</a>, <a>pull</a>, <a>sync</a>, <a>remote-url</a>
*/
void push_cmd(void){
  process_sync_args();
  client_sync(1,0,0,0,0);
}







>
>
>







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
** <a>clone</a>, <a>push</a>, <a>pull</a>, <a>remote-url</a>, or <a>sync</a> command
** is used.
**
** The URL specified normally becomes the new "remote-url" used for
** subsequent <a>push</a>, <a>pull</a>, and <a>sync</a> operations.  However,
** the "--once" command-line option makes the URL a one-time-use URL
** that is not saved.
**
** If configured (<a>setting</a> push-hook-..), the push hook command will be executed
** after pushing files to the server.
**
** See also: <a>clone</a>, <a>pull</a>, <a>sync</a>, <a>remote-url</a>
*/
void push_cmd(void){
  process_sync_args();
  client_sync(1,0,0,0,0);
}

Changes to src/xfer.c.

38
39
40
41
42
43
44





























































45
46
47
48
49
50
51
...
594
595
596
597
598
599
600



601
602
603
604
605
606
607
...
615
616
617
618
619
620
621
622








623
624
625
626
627
628
629
...
946
947
948
949
950
951
952


953
954
955
956
957
958
959
....
1328
1329
1330
1331
1332
1333
1334








1335
1336
1337
1338
1339
1340
1341
1342
1343
  int nDeltaSent;     /* Number of deltas sent */
  int nFileRcvd;      /* Number of files received */
  int nDeltaRcvd;     /* Number of deltas received */
  int nDanglingFile;  /* Number of dangling deltas received */
  int mxSend;         /* Stop sending "file" with pOut reaches this size */
};































































/*
** 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.
**
** Compare to uuid_to_rid().  This routine takes a blob argument
................................................................................
  Xfer xfer;
  int deltaFlag = 0;
  int isClone = 0;
  int nGimme = 0;
  int size;
  int recvConfig = 0;
  char *zNow;




  if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
     fossil_redirect_home();
  }
  memset(&xfer, 0, sizeof(xfer));
  blobarray_zero(xfer.aToken, count(xfer.aToken));
  cgi_set_content_type(g.zContentType);
................................................................................
  db_multi_exec(
     "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
  );
  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;








    xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));

    /*   file UUID SIZE \n CONTENT
    **   file UUID DELTASRC SIZE \n CONTENT
    **
    ** Accept a file from the client.
    */
................................................................................
  const char *zCookie;    /* Server cookie */
  int nSent, nRcvd;       /* Bytes sent and received (after compression) */
  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);



  if( db_get_boolean("dont-push", 0) ) pushFlag = 0;
  if( pushFlag + pullFlag + cloneFlag == 0 
     && configRcvMask==0 && configSendMask==0 ) return;

  transport_stats(0, 0, 1);
  socket_global_init();
................................................................................
    if( xfer.nFileSent+xfer.nDeltaSent>0 ){
      go = 1;
    }

    /* If this is a clone, the go at least two rounds */
    if( cloneFlag && nCycle==1 ) go = 1;
  };








  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);
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







|
>
>
>
>
>
>
>
>







 







>
>







 







>
>
>
>
>
>
>
>









38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
...
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
....
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
....
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
  int nDeltaSent;     /* Number of deltas sent */
  int nFileRcvd;      /* Number of files received */
  int nDeltaRcvd;     /* Number of deltas received */
  int nDanglingFile;  /* Number of dangling deltas received */
  int mxSend;         /* Stop sending "file" with pOut reaches this size */
};

/*
** COMMAND: callhook
** %fossil callhook PUSHHOOKPATTERN ?--force|-f?
**
** Call the push hook command on a server, which will normally be called
** after a client push (<a>setting</a> push-hook-cmd).
**
** If --force is used, the given pattern is not checked against the
** configuration (<a>setting</a> push-hook-pattern-server).
**
** This command only works on the server side, it does not send a message
** from a client, but executes the hook directly on the server.
**
** See also <a>push</a>, <a>sync</a>, <a>setting</a>
*/
void callhook_cmd(void){
  int forceFlag = find_option("force","f",0)!=0;

  db_open_config(1);
  db_find_and_open_repository(0);
  if( (g.argc!=3) || (!g.argv[2]) || (!g.argv[2][0]) ){
    usage("PUSHHOOKPATTERN ?--force?");
  }
  if( !forceFlag ){
    const char *zPushHookPattern = db_get("push-hook-pattern-server", "");
    int lenPushHookPattern = (zPushHookPattern && zPushHookPattern[0])
                              ? strlen(zPushHookPattern) : 0;
    if(    (!lenPushHookPattern)
        || memcmp(g.argv[2], zPushHookPattern, lenPushHookPattern)
    ){
      fossil_fatal("push hook pattern '%s' doesn't match configuration '%s'\n",
                     g.argv[2],zPushHookPattern);
    }
  }
  post_push_hook(g.argv[2]);
}

/*
** 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-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);
  }else{
    fossil_print("No push hook configured, skipping call for '%s'\n", zPushHookLine);
  }
}

/*
** 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.
**
** Compare to uuid_to_rid().  This routine takes a blob argument
................................................................................
  Xfer xfer;
  int deltaFlag = 0;
  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));
  blobarray_zero(xfer.aToken, count(xfer.aToken));
  cgi_set_content_type(g.zContentType);
................................................................................
  db_multi_exec(
     "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
  );
  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]=='#' ){
      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
    **
    ** Accept a file from the client.
    */
................................................................................
  const char *zCookie;    /* Server cookie */
  int nSent, nRcvd;       /* Bytes sent and received (after compression) */
  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;

  transport_stats(0, 0, 1);
  socket_global_init();
................................................................................
    if( xfer.nFileSent+xfer.nDeltaSent>0 ){
      go = 1;
    }

    /* 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);
}