Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Finish implementing the configuration command by adding method implementations for "import", "reset", and "pull". |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
28e56282c91556de4dde4860cf2618e5 |
User & Date: | drh 2008-05-23 19:21:03.000 |
Context
2008-05-23
| ||
21:41 | corrected wiki command short help ... (check-in: 92df4748 user: stephan tags: trunk) | |
19:21 | Finish implementing the configuration command by adding method implementations for "import", "reset", and "pull". ... (check-in: 28e56282 user: drh tags: trunk) | |
12:24 | removed USER stuff. Reorganized. i would have SWORN that i checked this in yesterday. ... (check-in: ab5ab462 user: stephan tags: trunk) | |
Changes
Changes to src/clone.c.
︙ | ︙ | |||
73 74 75 76 77 78 79 | db_multi_exec("INSERT OR IGNORE INTO %Q SELECT * FROM orig.%Q", zTab, zTab); } db_finalize(&q); }else{ url_enable_proxy(0); g.xlinkClusterOnly = 1; | | | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | db_multi_exec("INSERT OR IGNORE INTO %Q SELECT * FROM orig.%Q", zTab, zTab); } db_finalize(&q); }else{ url_enable_proxy(0); g.xlinkClusterOnly = 1; client_sync(0,0,1,CONFIGSET_ALL); g.xlinkClusterOnly = 0; } verify_cancel(); db_end_transaction(0); db_close(); db_open_repository(g.argv[3]); db_begin_transaction(); |
︙ | ︙ |
Changes to src/configure.c.
︙ | ︙ | |||
59 60 61 62 63 64 65 | /* ** The following is a list of settings that we are willing to ** transfer. */ static struct { const char *zName; /* Name of the configuration parameter */ int groupMask; /* Which config groups is it part of */ | | > > > > > > > > > > > > > > > > > > > | | > > | 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 | /* ** The following is a list of settings that we are willing to ** transfer. */ static struct { const char *zName; /* Name of the configuration parameter */ int groupMask; /* Which config groups is it part of */ } aConfig[] = { { "css", CONFIGSET_SKIN }, { "header", CONFIGSET_SKIN }, { "footer", CONFIGSET_SKIN }, { "project-name", CONFIGSET_PROJ }, { "project-description", CONFIGSET_PROJ }, { "index-page", CONFIGSET_SKIN }, { "timeline-block-markup", CONFIGSET_SKIN }, { "timeline-max-comment", CONFIGSET_SKIN }, }; static int iConfig = 0; /* ** Return name of first configuration property matching the given mask. */ const char *configure_first_name(int iMask){ iConfig = 0; return configure_next_name(iMask); } const char *configure_next_name(int iMask){ while( iConfig<count(aConfig) ){ if( aConfig[iConfig].groupMask & iMask ){ return aConfig[iConfig++].zName; }else{ iConfig++; } } return 0; } /* ** Return TRUE if a particular configuration parameter zName is ** safely exportable. */ int configure_is_exportable(const char *zName){ int i; for(i=0; i<count(aConfig); i++){ if( strcmp(zName, aConfig[i].zName)==0 ){ return aConfig[i].groupMask; } } return 0; } /* ** Identify a configuration group by name. Return its mask. ** Throw an error if no match. |
︙ | ︙ | |||
100 101 102 103 104 105 106 | } fossil_fatal("no such configuration area: \"%s\"", z); return 0; } /* | | | | | | | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | } fossil_fatal("no such configuration area: \"%s\"", z); return 0; } /* ** COMMAND: configuration ** ** Usage: %fossil configure METHOD ... ** ** Where METHOD is one of: export import pull reset. All methods ** accept the -R or --repository option to specific a repository. ** ** %fossil configuration export AREA FILENAME ** ** Write to FILENAME exported configuraton information for AREA. ** AREA can be one of: all ticket skin project ** ** %fossil configuration import FILENAME ** ** Read a configuration from FILENAME, overwriting the current ** configuration. Warning: Do not read a configuration from ** an untrusted source since the configuration is not checked ** for safety and can introduce security threats. ** ** %fossil configuration pull AREA URL ** ** Pull and install the configuration from a different server ** identified by URL. AREA is as in "export". ** ** %fossil configuration reset AREA ** ** Restore the configuration to the default. AREA as above. */ void configuration_cmd(void){ int n; const char *zMethod; if( g.argc<3 ){ usage("METHOD ..."); } db_find_and_open_repository(1); zMethod = g.argv[2]; |
︙ | ︙ | |||
156 157 158 159 160 161 162 | blob_zero(&out); blob_appendf(&sql, "SELECT 'REPLACE INTO config(name,value) VALUES('''" " || name || ''',' || quote(value) || ');'" " FROM config WHERE name IN " ); zSep = "("; | | | | | < > > > > > > > > > > > > > > > > > > > > > > > > > | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | blob_zero(&out); blob_appendf(&sql, "SELECT 'REPLACE INTO config(name,value) VALUES('''" " || name || ''',' || quote(value) || ');'" " FROM config WHERE name IN " ); zSep = "("; for(i=0; i<count(aConfig); i++){ if( aConfig[i].groupMask & mask ){ blob_appendf(&sql, "%s'%s'", zSep, aConfig[i].zName); zSep = ","; } } blob_appendf(&sql, ") ORDER BY name"); db_prepare(&q, blob_str(&sql)); blob_reset(&sql); blob_appendf(&out, "-- The \"%s\" configuration exported from\n" "-- repository \"%s\"\n" "-- on %s\n", g.argv[3], g.zRepositoryName, db_text(0, "SELECT datetime('now')") ); while( db_step(&q)==SQLITE_ROW ){ blob_appendf(&out, "%s\n", db_column_text(&q, 0)); } db_finalize(&q); blob_write_to_file(&out, g.argv[4]); blob_reset(&out); }else if( strncmp(zMethod, "import", n)==0 ){ Blob in; if( g.argc!=4 ) usage("import FILENAME"); blob_read_from_file(&in, g.argv[3]); db_begin_transaction(); db_multi_exec("%s", blob_str(&in)); db_end_transaction(0); }else if( strncmp(zMethod, "pull", n)==0 ){ int mask; url_proxy_options(); if( g.argc!=5 ) usage("pull AREA URL"); mask = find_area(g.argv[3]); url_parse(g.argv[4]); if( g.urlIsFile ){ fossil_fatal("network sync only"); } user_select(); client_sync(0,0,0,mask); }else if( strncmp(zMethod, "reset", n)==0 ){ int mask, i; if( g.argc!=4 ) usage("reset AREA"); mask = find_area(g.argv[3]); db_begin_transaction(); for(i=0; i<count(aConfig); i++){ if( (aConfig[i].groupMask & mask)==0 ) continue; db_multi_exec("DELETE FROM config WHERE name=%Q", aConfig[i].zName); } db_end_transaction(0); }else { fossil_fatal("METHOD should be one of: export import pull reset"); } } |
Changes to src/sync.c.
︙ | ︙ | |||
59 60 61 62 63 64 65 | } if( g.urlPort!=80 ){ printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath); }else{ printf("Autosync: http://%s%s\n", g.urlName, g.urlPath); } url_enable_proxy("via proxy: "); | | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | } if( g.urlPort!=80 ){ printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath); }else{ printf("Autosync: http://%s%s\n", g.urlName, g.urlPath); } url_enable_proxy("via proxy: "); client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0); } /* ** This routine processes the command-line argument for push, pull, ** and sync. If a command-line argument is given, that is the URL ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ void process_sync_args(void){ const char *zUrl = 0; url_proxy_options(); db_find_and_open_repository(1); if( g.argc==2 ){ zUrl = db_get("last-sync-url", 0); }else if( g.argc==3 ){ zUrl = g.argv[2]; |
︙ | ︙ | |||
120 121 122 123 124 125 126 | ** The "USER" substring specifies the login user. You will be ** prompted for the password on the command-line. The PORT ** specifies the TCP port of the server. The default port is ** 80. */ void pull_cmd(void){ process_sync_args(); | | | | | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | ** The "USER" substring specifies the login user. You will be ** prompted for the password on the command-line. The PORT ** specifies the TCP port of the server. The default port is ** 80. */ void pull_cmd(void){ process_sync_args(); client_sync(0,1,0,0); } /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?-R|--repository REPOSITORY? ** ** Push changes in the local repository over into a remote repository. ** See the "pull" command for additional information. */ void push_cmd(void){ process_sync_args(); client_sync(1,0,0,0); } /* ** COMMAND: sync ** ** Usage: %fossil sync ?URL? ?-R|--repository REPOSITORY? ** ** Synchronize the local repository with a remote repository. This is ** the equivalent of running both "push" and "pull" at the same time. ** See the "pull" command for additional information. */ void sync_cmd(void){ process_sync_args(); client_sync(1,1,0,0); } |
Changes to src/xfer.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ******************************************************************************* ** ** This file contains code to implement the file transfer protocol. */ #include "config.h" #include "xfer.h" | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ******************************************************************************* ** ** This file contains code to implement the file transfer protocol. */ #include "config.h" #include "xfer.h" /* ** This structure holds information about the current state of either ** a client or a server that is participating in xfer. */ typedef struct Xfer Xfer; struct Xfer { Blob *pIn; /* Input text from the other side */ |
︙ | ︙ | |||
678 679 680 681 682 683 684 | ** Request a configuration value */ if( blob_eq(&xfer.aToken[0], "reqconfig") && xfer.nToken==2 ){ if( g.okRead ){ char *zName = blob_str(&xfer.aToken[1]); | < | < | | | | | < < | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | ** Request a configuration value */ if( blob_eq(&xfer.aToken[0], "reqconfig") && xfer.nToken==2 ){ if( g.okRead ){ char *zName = blob_str(&xfer.aToken[1]); if( configure_is_exportable(zName) ){ char *zValue = db_get(zName, 0); if( zValue ){ blob_appendf(xfer.pOut, "config %s %d\n%s\n", zName, strlen(zValue), zValue); free(zValue); } } } }else /* cookie TEXT ** |
︙ | ︙ | |||
789 790 791 792 793 794 795 | ** Sync to the host identified in g.urlName and g.urlPath. This ** routine is called by the client. ** ** Records are pushed to the server if pushFlag is true. Records ** are pulled if pullFlag is true. A full sync occurs if both are ** true. */ | | > > | > | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | ** Sync to the host identified in g.urlName and g.urlPath. This ** routine is called by the client. ** ** Records are pushed to the server if pushFlag is true. Records ** are pulled if pullFlag is true. A full sync occurs if both are ** true. */ void client_sync(int pushFlag, int pullFlag, int cloneFlag, int configMask){ int go = 1; /* Loop until zero */ const char *zSCode = db_get("server-code", "x"); const char *zPCode = db_get("project-code", 0); int nCard = 0; /* Number of cards sent or received */ int nCycle = 0; /* Number of round trips to the server */ int size; /* Size of a config value */ int nFileSend = 0; int origConfigMask; /* Original value of configMask */ int nFileRecv; /* Number of files received */ int mxPhantomReq = 200; /* Max number of phantoms to request per comm */ const char *zCookie; /* Server cookie */ Blob send; /* Text we are sending to the server */ Blob recv; /* Reply we got back from the server */ Xfer xfer; /* Transfer data */ memset(&xfer, 0, sizeof(xfer)); xfer.pIn = &recv; xfer.pOut = &send; xfer.mxSend = db_get_int("max-upload", 250000); assert( pushFlag || pullFlag || cloneFlag || configMask ); assert( !g.urlIsFile ); /* This only works for networking */ db_begin_transaction(); db_multi_exec( "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" ); blobarray_zero(xfer.aToken, count(xfer.aToken)); blob_zero(&send); blob_zero(&recv); blob_zero(&xfer.err); blob_zero(&xfer.line); origConfigMask = configMask; /* ** Always begin with a clone, pull, or push message */ if( cloneFlag ){ blob_appendf(&send, "clone\n"); pushFlag = 0; |
︙ | ︙ | |||
861 862 863 864 865 866 867 868 869 870 871 872 873 874 | if( pullFlag || cloneFlag ){ request_phantoms(&xfer, mxPhantomReq); } if( pushFlag ){ send_unsent(&xfer); nCard += send_unclustered(&xfer); } /* Exchange messages with the server */ nFileSend = xfer.nFileSent + xfer.nDeltaSent; printf(zValueFormat, "Send:", blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent, xfer.nFileSent, xfer.nDeltaSent); #if 0 | > > > > > > > > > > > | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 | if( pullFlag || cloneFlag ){ request_phantoms(&xfer, mxPhantomReq); } if( pushFlag ){ send_unsent(&xfer); nCard += send_unclustered(&xfer); } /* Send configuration parameter requests */ if( configMask ){ const char *zName; zName = configure_first_name(configMask); while( zName ){ blob_appendf(&send, "reqconfig %s\n", zName); zName = configure_next_name(configMask); } configMask = 0; } /* Exchange messages with the server */ nFileSend = xfer.nFileSent + xfer.nDeltaSent; printf(zValueFormat, "Send:", blob_size(&send), nCard+xfer.nGimmeSent+xfer.nIGotSent, xfer.nFileSent, xfer.nDeltaSent); #if 0 |
︙ | ︙ | |||
974 975 976 977 978 979 980 | nCard++; }else /* config NAME SIZE \n CONTENT ** ** Receive a configuration value from the server. */ | | > > | > > | > > > > > | > | 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 | nCard++; }else /* config NAME SIZE \n CONTENT ** ** Receive a configuration value from the server. */ if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3 && blob_is_int(&xfer.aToken[2], &size) ){ const char *zName = blob_str(&xfer.aToken[1]); Blob content; blob_zero(&content); blob_extract(xfer.pIn, size, &content); if( configure_is_exportable(zName) & origConfigMask ){ db_multi_exec( "REPLACE INTO config(name,value) VALUES(%Q,%Q)", zName, blob_str(&content) ); } blob_reset(&content); blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR); }else /* cookie TEXT ** ** The server might include a cookie in its reply. The client ** should remember this cookie and send it back to the server |
︙ | ︙ |