Fossil SCM
Bring in fixes for SSH from trunk.
Commit
c55d1b7b2657ae366cf410f89e93543162625956b84ded39096242ee373b5f28
Parent
c454059a18bd2c3…
10 files changed
+8
-3
+49
-2
+10
-3
+10
-3
+4
+41
-31
+4
+5
-2
+1
-1
+22
-24
+8
-3
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -19,10 +19,11 @@ | ||
| 19 | 19 | ** text files. |
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "diff.h" |
| 23 | 23 | #include <assert.h> |
| 24 | +#include <errno.h> | |
| 24 | 25 | |
| 25 | 26 | |
| 26 | 27 | #if INTERFACE |
| 27 | 28 | /* |
| 28 | 29 | ** Flag parameters to the text_diff() routine used to control the formatting |
| @@ -3157,13 +3158,17 @@ | ||
| 3157 | 3158 | /* Undocumented and unsupported flags used for development |
| 3158 | 3159 | ** debugging and analysis: */ |
| 3159 | 3160 | if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG; |
| 3160 | 3161 | if( find_option("raw",0,0)!=0 ) diffFlags |= DIFF_RAW; |
| 3161 | 3162 | } |
| 3162 | - if( (z = find_option("context","c",1))!=0 && (f = atoi(z))!=0 ){ | |
| 3163 | - pCfg->nContext = f; | |
| 3164 | - diffFlags |= DIFF_CONTEXT_EX; | |
| 3163 | + if( (z = find_option("context","c",1))!=0 ){ | |
| 3164 | + char *zEnd; | |
| 3165 | + f = (int)strtol(z, &zEnd, 10); | |
| 3166 | + if( zEnd[0]==0 && errno!=ERANGE ){ | |
| 3167 | + pCfg->nContext = f; | |
| 3168 | + diffFlags |= DIFF_CONTEXT_EX; | |
| 3169 | + } | |
| 3165 | 3170 | } |
| 3166 | 3171 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 3167 | 3172 | pCfg->wColumn = f; |
| 3168 | 3173 | } |
| 3169 | 3174 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 3170 | 3175 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -19,10 +19,11 @@ | |
| 19 | ** text files. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "diff.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | |
| 26 | #if INTERFACE |
| 27 | /* |
| 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| @@ -3157,13 +3158,17 @@ | |
| 3157 | /* Undocumented and unsupported flags used for development |
| 3158 | ** debugging and analysis: */ |
| 3159 | if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG; |
| 3160 | if( find_option("raw",0,0)!=0 ) diffFlags |= DIFF_RAW; |
| 3161 | } |
| 3162 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))!=0 ){ |
| 3163 | pCfg->nContext = f; |
| 3164 | diffFlags |= DIFF_CONTEXT_EX; |
| 3165 | } |
| 3166 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 3167 | pCfg->wColumn = f; |
| 3168 | } |
| 3169 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 3170 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -19,10 +19,11 @@ | |
| 19 | ** text files. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "diff.h" |
| 23 | #include <assert.h> |
| 24 | #include <errno.h> |
| 25 | |
| 26 | |
| 27 | #if INTERFACE |
| 28 | /* |
| 29 | ** Flag parameters to the text_diff() routine used to control the formatting |
| @@ -3157,13 +3158,17 @@ | |
| 3158 | /* Undocumented and unsupported flags used for development |
| 3159 | ** debugging and analysis: */ |
| 3160 | if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG; |
| 3161 | if( find_option("raw",0,0)!=0 ) diffFlags |= DIFF_RAW; |
| 3162 | } |
| 3163 | if( (z = find_option("context","c",1))!=0 ){ |
| 3164 | char *zEnd; |
| 3165 | f = (int)strtol(z, &zEnd, 10); |
| 3166 | if( zEnd[0]==0 && errno!=ERANGE ){ |
| 3167 | pCfg->nContext = f; |
| 3168 | diffFlags |= DIFF_CONTEXT_EX; |
| 3169 | } |
| 3170 | } |
| 3171 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 3172 | pCfg->wColumn = f; |
| 3173 | } |
| 3174 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 3175 |
+49
-2
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -304,10 +304,21 @@ | ||
| 304 | 304 | |
| 305 | 305 | if( g.zHttpCmd!=0 ){ |
| 306 | 306 | /* Handle the --transport-command option for "fossil sync" and similar */ |
| 307 | 307 | return http_exchange_external(pSend,pReply,mHttpFlags,zAltMimetype); |
| 308 | 308 | } |
| 309 | + | |
| 310 | + /* Activate the PATH= auxiliary argument to the ssh command if that | |
| 311 | + ** is called for. | |
| 312 | + */ | |
| 313 | + if( g.url.isSsh && (g.url.flags & URL_SSH_RETRY)==0 ){ | |
| 314 | + char *z = mprintf("use-path-for-ssh:%s", g.url.hostname); | |
| 315 | + if( db_get_boolean(z/*works-like:"x"*/, 0) ){ | |
| 316 | + g.url.flags |= URL_SSH_PATH; | |
| 317 | + } | |
| 318 | + fossil_free(z); | |
| 319 | + } | |
| 309 | 320 | |
| 310 | 321 | if( transport_open(&g.url) ){ |
| 311 | 322 | fossil_warning("%s", transport_errmsg(&g.url)); |
| 312 | 323 | return 1; |
| 313 | 324 | } |
| @@ -484,12 +495,48 @@ | ||
| 484 | 495 | } |
| 485 | 496 | } |
| 486 | 497 | } |
| 487 | 498 | } |
| 488 | 499 | if( iLength<0 ){ |
| 489 | - fossil_warning("server did not reply"); | |
| 490 | - goto write_err; | |
| 500 | + /* We got nothing back from the server. If using the ssh: protocol, | |
| 501 | + ** this might mean we need to add or remove the PATH=... argument | |
| 502 | + ** to the SSH command being sent. If that is the case, retry the | |
| 503 | + ** request after adding or removing the PATH= argument. | |
| 504 | + */ | |
| 505 | + if( g.url.isSsh /* This is an SSH: sync */ | |
| 506 | + && (g.url.flags & URL_SSH_EXE)==0 /* Does not have ?fossil=.... */ | |
| 507 | + && (g.url.flags & URL_SSH_RETRY)==0 /* Not retried already */ | |
| 508 | + ){ | |
| 509 | + /* Retry after flipping the SSH_PATH setting */ | |
| 510 | + transport_close(&g.url); | |
| 511 | + if( g.fSshTrace ){ | |
| 512 | + printf("Retry after %s the PATH= argument to the SSH command\n", | |
| 513 | + (g.url.flags & URL_SSH_PATH)!=0 ? "removing" : "adding"); | |
| 514 | + } | |
| 515 | + g.url.flags ^= URL_SSH_PATH|URL_SSH_RETRY; | |
| 516 | + rc = http_exchange(pSend,pReply,mHttpFlags,0,zAltMimetype); | |
| 517 | + if( rc==0 ){ | |
| 518 | + char *z = mprintf("use-path-for-ssh:%s", g.url.hostname); | |
| 519 | + if( (g.url.flags & URL_SSH_PATH) ){ | |
| 520 | + db_set(z/*works-like:"x"*/, "1", 0); | |
| 521 | + }else{ | |
| 522 | + db_unset(z/*works-like:"x"*/, 0); | |
| 523 | + } | |
| 524 | + fossil_free(z); | |
| 525 | + } | |
| 526 | + return rc; | |
| 527 | + }else{ | |
| 528 | + /* The problem could not be corrected by retrying. Report the | |
| 529 | + ** the error. */ | |
| 530 | + if( g.url.isSsh && !g.fSshTrace ){ | |
| 531 | + fossil_warning("server did not reply: " | |
| 532 | + " rerun with --sshtrace for diagnostics"); | |
| 533 | + }else{ | |
| 534 | + fossil_warning("server did not reply"); | |
| 535 | + } | |
| 536 | + goto write_err; | |
| 537 | + } | |
| 491 | 538 | } |
| 492 | 539 | if( rc!=200 ){ |
| 493 | 540 | fossil_warning("\"location:\" missing from %d redirect reply", rc); |
| 494 | 541 | goto write_err; |
| 495 | 542 | } |
| 496 | 543 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -304,10 +304,21 @@ | |
| 304 | |
| 305 | if( g.zHttpCmd!=0 ){ |
| 306 | /* Handle the --transport-command option for "fossil sync" and similar */ |
| 307 | return http_exchange_external(pSend,pReply,mHttpFlags,zAltMimetype); |
| 308 | } |
| 309 | |
| 310 | if( transport_open(&g.url) ){ |
| 311 | fossil_warning("%s", transport_errmsg(&g.url)); |
| 312 | return 1; |
| 313 | } |
| @@ -484,12 +495,48 @@ | |
| 484 | } |
| 485 | } |
| 486 | } |
| 487 | } |
| 488 | if( iLength<0 ){ |
| 489 | fossil_warning("server did not reply"); |
| 490 | goto write_err; |
| 491 | } |
| 492 | if( rc!=200 ){ |
| 493 | fossil_warning("\"location:\" missing from %d redirect reply", rc); |
| 494 | goto write_err; |
| 495 | } |
| 496 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -304,10 +304,21 @@ | |
| 304 | |
| 305 | if( g.zHttpCmd!=0 ){ |
| 306 | /* Handle the --transport-command option for "fossil sync" and similar */ |
| 307 | return http_exchange_external(pSend,pReply,mHttpFlags,zAltMimetype); |
| 308 | } |
| 309 | |
| 310 | /* Activate the PATH= auxiliary argument to the ssh command if that |
| 311 | ** is called for. |
| 312 | */ |
| 313 | if( g.url.isSsh && (g.url.flags & URL_SSH_RETRY)==0 ){ |
| 314 | char *z = mprintf("use-path-for-ssh:%s", g.url.hostname); |
| 315 | if( db_get_boolean(z/*works-like:"x"*/, 0) ){ |
| 316 | g.url.flags |= URL_SSH_PATH; |
| 317 | } |
| 318 | fossil_free(z); |
| 319 | } |
| 320 | |
| 321 | if( transport_open(&g.url) ){ |
| 322 | fossil_warning("%s", transport_errmsg(&g.url)); |
| 323 | return 1; |
| 324 | } |
| @@ -484,12 +495,48 @@ | |
| 495 | } |
| 496 | } |
| 497 | } |
| 498 | } |
| 499 | if( iLength<0 ){ |
| 500 | /* We got nothing back from the server. If using the ssh: protocol, |
| 501 | ** this might mean we need to add or remove the PATH=... argument |
| 502 | ** to the SSH command being sent. If that is the case, retry the |
| 503 | ** request after adding or removing the PATH= argument. |
| 504 | */ |
| 505 | if( g.url.isSsh /* This is an SSH: sync */ |
| 506 | && (g.url.flags & URL_SSH_EXE)==0 /* Does not have ?fossil=.... */ |
| 507 | && (g.url.flags & URL_SSH_RETRY)==0 /* Not retried already */ |
| 508 | ){ |
| 509 | /* Retry after flipping the SSH_PATH setting */ |
| 510 | transport_close(&g.url); |
| 511 | if( g.fSshTrace ){ |
| 512 | printf("Retry after %s the PATH= argument to the SSH command\n", |
| 513 | (g.url.flags & URL_SSH_PATH)!=0 ? "removing" : "adding"); |
| 514 | } |
| 515 | g.url.flags ^= URL_SSH_PATH|URL_SSH_RETRY; |
| 516 | rc = http_exchange(pSend,pReply,mHttpFlags,0,zAltMimetype); |
| 517 | if( rc==0 ){ |
| 518 | char *z = mprintf("use-path-for-ssh:%s", g.url.hostname); |
| 519 | if( (g.url.flags & URL_SSH_PATH) ){ |
| 520 | db_set(z/*works-like:"x"*/, "1", 0); |
| 521 | }else{ |
| 522 | db_unset(z/*works-like:"x"*/, 0); |
| 523 | } |
| 524 | fossil_free(z); |
| 525 | } |
| 526 | return rc; |
| 527 | }else{ |
| 528 | /* The problem could not be corrected by retrying. Report the |
| 529 | ** the error. */ |
| 530 | if( g.url.isSsh && !g.fSshTrace ){ |
| 531 | fossil_warning("server did not reply: " |
| 532 | " rerun with --sshtrace for diagnostics"); |
| 533 | }else{ |
| 534 | fossil_warning("server did not reply"); |
| 535 | } |
| 536 | goto write_err; |
| 537 | } |
| 538 | } |
| 539 | if( rc!=200 ){ |
| 540 | fossil_warning("\"location:\" missing from %d redirect reply", rc); |
| 541 | goto write_err; |
| 542 | } |
| 543 |
+10
-3
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -131,15 +131,22 @@ | ||
| 131 | 131 | blob_append_escaped_arg(&zCmd, zHost, 0); |
| 132 | 132 | fossil_free(zHost); |
| 133 | 133 | }else{ |
| 134 | 134 | blob_append_escaped_arg(&zCmd, pUrlData->name, 0); |
| 135 | 135 | } |
| 136 | - if( !is_safe_fossil_command(pUrlData->fossil) ){ | |
| 136 | + if( (pUrlData->flags & URL_SSH_EXE)!=0 | |
| 137 | + && !is_safe_fossil_command(pUrlData->fossil) | |
| 138 | + ){ | |
| 137 | 139 | fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " |
| 138 | 140 | "the server.", pUrlData->fossil); |
| 139 | 141 | } |
| 140 | - blob_append_escaped_arg(&zCmd, "PATH=$HOME/bin:$PATH", 1); | |
| 142 | + if( (pUrlData->flags & URL_SSH_EXE)==0 | |
| 143 | + && (pUrlData->flags & URL_SSH_PATH)!=0 | |
| 144 | + ){ | |
| 145 | + blob_append_escaped_arg(&zCmd, | |
| 146 | + "PATH=bin:/usr/local/bin:/opt/homebrew/bin:$PATH", 1); | |
| 147 | + } | |
| 141 | 148 | blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1); |
| 142 | 149 | blob_append(&zCmd, " test-http", 10); |
| 143 | 150 | if( pUrlData->path && pUrlData->path[0] ){ |
| 144 | 151 | blob_append_escaped_arg(&zCmd, pUrlData->path, 1); |
| 145 | 152 | }else{ |
| @@ -313,11 +320,11 @@ | ||
| 313 | 320 | ** Read N bytes of content directly from the wire and write into |
| 314 | 321 | ** the buffer. |
| 315 | 322 | */ |
| 316 | 323 | static int transport_fetch(UrlData *pUrlData, char *zBuf, int N){ |
| 317 | 324 | int got; |
| 318 | - if( sshIn ){ | |
| 325 | + if( pUrlData->isSsh ){ | |
| 319 | 326 | int x; |
| 320 | 327 | int wanted = N; |
| 321 | 328 | got = 0; |
| 322 | 329 | while( wanted>0 ){ |
| 323 | 330 | x = read(sshIn, &zBuf[got], wanted); |
| 324 | 331 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -131,15 +131,22 @@ | |
| 131 | blob_append_escaped_arg(&zCmd, zHost, 0); |
| 132 | fossil_free(zHost); |
| 133 | }else{ |
| 134 | blob_append_escaped_arg(&zCmd, pUrlData->name, 0); |
| 135 | } |
| 136 | if( !is_safe_fossil_command(pUrlData->fossil) ){ |
| 137 | fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " |
| 138 | "the server.", pUrlData->fossil); |
| 139 | } |
| 140 | blob_append_escaped_arg(&zCmd, "PATH=$HOME/bin:$PATH", 1); |
| 141 | blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1); |
| 142 | blob_append(&zCmd, " test-http", 10); |
| 143 | if( pUrlData->path && pUrlData->path[0] ){ |
| 144 | blob_append_escaped_arg(&zCmd, pUrlData->path, 1); |
| 145 | }else{ |
| @@ -313,11 +320,11 @@ | |
| 313 | ** Read N bytes of content directly from the wire and write into |
| 314 | ** the buffer. |
| 315 | */ |
| 316 | static int transport_fetch(UrlData *pUrlData, char *zBuf, int N){ |
| 317 | int got; |
| 318 | if( sshIn ){ |
| 319 | int x; |
| 320 | int wanted = N; |
| 321 | got = 0; |
| 322 | while( wanted>0 ){ |
| 323 | x = read(sshIn, &zBuf[got], wanted); |
| 324 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -131,15 +131,22 @@ | |
| 131 | blob_append_escaped_arg(&zCmd, zHost, 0); |
| 132 | fossil_free(zHost); |
| 133 | }else{ |
| 134 | blob_append_escaped_arg(&zCmd, pUrlData->name, 0); |
| 135 | } |
| 136 | if( (pUrlData->flags & URL_SSH_EXE)!=0 |
| 137 | && !is_safe_fossil_command(pUrlData->fossil) |
| 138 | ){ |
| 139 | fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " |
| 140 | "the server.", pUrlData->fossil); |
| 141 | } |
| 142 | if( (pUrlData->flags & URL_SSH_EXE)==0 |
| 143 | && (pUrlData->flags & URL_SSH_PATH)!=0 |
| 144 | ){ |
| 145 | blob_append_escaped_arg(&zCmd, |
| 146 | "PATH=bin:/usr/local/bin:/opt/homebrew/bin:$PATH", 1); |
| 147 | } |
| 148 | blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1); |
| 149 | blob_append(&zCmd, " test-http", 10); |
| 150 | if( pUrlData->path && pUrlData->path[0] ){ |
| 151 | blob_append_escaped_arg(&zCmd, pUrlData->path, 1); |
| 152 | }else{ |
| @@ -313,11 +320,11 @@ | |
| 320 | ** Read N bytes of content directly from the wire and write into |
| 321 | ** the buffer. |
| 322 | */ |
| 323 | static int transport_fetch(UrlData *pUrlData, char *zBuf, int N){ |
| 324 | int got; |
| 325 | if( pUrlData->isSsh ){ |
| 326 | int x; |
| 327 | int wanted = N; |
| 328 | got = 0; |
| 329 | while( wanted>0 ){ |
| 330 | x = read(sshIn, &zBuf[got], wanted); |
| 331 |
+10
-3
| --- src/popen.c | ||
| +++ src/popen.c | ||
| @@ -129,19 +129,18 @@ | ||
| 129 | 129 | FILE **ppOut, /* Write to child using this file descriptor */ |
| 130 | 130 | int *pChildPid, /* PID of the child process */ |
| 131 | 131 | int bDirect /* 0: run zCmd as a shell cmd. 1: run directly */ |
| 132 | 132 | ){ |
| 133 | 133 | #ifdef _WIN32 |
| 134 | - HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr; | |
| 134 | + HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr; | |
| 135 | 135 | SECURITY_ATTRIBUTES saAttr; |
| 136 | 136 | DWORD childPid = 0; |
| 137 | 137 | int fd; |
| 138 | 138 | |
| 139 | 139 | saAttr.nLength = sizeof(saAttr); |
| 140 | 140 | saAttr.bInheritHandle = TRUE; |
| 141 | 141 | saAttr.lpSecurityDescriptor = NULL; |
| 142 | - hStderr = GetStdHandle(STD_ERROR_HANDLE); | |
| 143 | 142 | if( !CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 4096) ){ |
| 144 | 143 | win32_fatal_error("cannot create pipe for stdout"); |
| 145 | 144 | } |
| 146 | 145 | SetHandleInformation( hStdoutRd, HANDLE_FLAG_INHERIT, FALSE); |
| 147 | 146 | |
| @@ -149,11 +148,16 @@ | ||
| 149 | 148 | win32_fatal_error("cannot create pipe for stdin"); |
| 150 | 149 | } |
| 151 | 150 | SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); |
| 152 | 151 | |
| 153 | 152 | win32_create_child_process(fossil_utf8_to_unicode(zCmd), |
| 154 | - hStdinRd, hStdoutWr, hStderr,&childPid); | |
| 153 | + hStdinRd,hStdoutWr,hStdoutWr,&childPid); | |
| 154 | + /* ^^^^^^^^^ ^^^^^^^^^ | |
| 155 | + ** Send both stdout and stderr to to *ppOut. | |
| 156 | + ** See check-in 857495ec92a521bb (2024-02-06) and earlier for | |
| 157 | + ** an example of how to leave stderr going to console */ | |
| 158 | + | |
| 155 | 159 | *pChildPid = childPid; |
| 156 | 160 | *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); |
| 157 | 161 | fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); |
| 158 | 162 | *ppOut = _fdopen(fd, "w"); |
| 159 | 163 | CloseHandle(hStdinRd); |
| @@ -194,10 +198,13 @@ | ||
| 194 | 198 | close(1); |
| 195 | 199 | fd = dup(pin[1]); |
| 196 | 200 | if( fd!=1 ) fossil_panic("popen() failed to open file descriptor 1"); |
| 197 | 201 | close(pin[0]); |
| 198 | 202 | close(pin[1]); |
| 203 | + close(2); | |
| 204 | + fd = dup(1); | |
| 205 | + if( fd!=2 ) fossil_panic("popen() failed to redirect stderr into stdout"); | |
| 199 | 206 | if( bDirect ){ |
| 200 | 207 | execl(zCmd, zCmd, (char*)0); |
| 201 | 208 | }else{ |
| 202 | 209 | execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0); |
| 203 | 210 | } |
| 204 | 211 |
| --- src/popen.c | |
| +++ src/popen.c | |
| @@ -129,19 +129,18 @@ | |
| 129 | FILE **ppOut, /* Write to child using this file descriptor */ |
| 130 | int *pChildPid, /* PID of the child process */ |
| 131 | int bDirect /* 0: run zCmd as a shell cmd. 1: run directly */ |
| 132 | ){ |
| 133 | #ifdef _WIN32 |
| 134 | HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr; |
| 135 | SECURITY_ATTRIBUTES saAttr; |
| 136 | DWORD childPid = 0; |
| 137 | int fd; |
| 138 | |
| 139 | saAttr.nLength = sizeof(saAttr); |
| 140 | saAttr.bInheritHandle = TRUE; |
| 141 | saAttr.lpSecurityDescriptor = NULL; |
| 142 | hStderr = GetStdHandle(STD_ERROR_HANDLE); |
| 143 | if( !CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 4096) ){ |
| 144 | win32_fatal_error("cannot create pipe for stdout"); |
| 145 | } |
| 146 | SetHandleInformation( hStdoutRd, HANDLE_FLAG_INHERIT, FALSE); |
| 147 | |
| @@ -149,11 +148,16 @@ | |
| 149 | win32_fatal_error("cannot create pipe for stdin"); |
| 150 | } |
| 151 | SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); |
| 152 | |
| 153 | win32_create_child_process(fossil_utf8_to_unicode(zCmd), |
| 154 | hStdinRd, hStdoutWr, hStderr,&childPid); |
| 155 | *pChildPid = childPid; |
| 156 | *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); |
| 157 | fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); |
| 158 | *ppOut = _fdopen(fd, "w"); |
| 159 | CloseHandle(hStdinRd); |
| @@ -194,10 +198,13 @@ | |
| 194 | close(1); |
| 195 | fd = dup(pin[1]); |
| 196 | if( fd!=1 ) fossil_panic("popen() failed to open file descriptor 1"); |
| 197 | close(pin[0]); |
| 198 | close(pin[1]); |
| 199 | if( bDirect ){ |
| 200 | execl(zCmd, zCmd, (char*)0); |
| 201 | }else{ |
| 202 | execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0); |
| 203 | } |
| 204 |
| --- src/popen.c | |
| +++ src/popen.c | |
| @@ -129,19 +129,18 @@ | |
| 129 | FILE **ppOut, /* Write to child using this file descriptor */ |
| 130 | int *pChildPid, /* PID of the child process */ |
| 131 | int bDirect /* 0: run zCmd as a shell cmd. 1: run directly */ |
| 132 | ){ |
| 133 | #ifdef _WIN32 |
| 134 | HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr; |
| 135 | SECURITY_ATTRIBUTES saAttr; |
| 136 | DWORD childPid = 0; |
| 137 | int fd; |
| 138 | |
| 139 | saAttr.nLength = sizeof(saAttr); |
| 140 | saAttr.bInheritHandle = TRUE; |
| 141 | saAttr.lpSecurityDescriptor = NULL; |
| 142 | if( !CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 4096) ){ |
| 143 | win32_fatal_error("cannot create pipe for stdout"); |
| 144 | } |
| 145 | SetHandleInformation( hStdoutRd, HANDLE_FLAG_INHERIT, FALSE); |
| 146 | |
| @@ -149,11 +148,16 @@ | |
| 148 | win32_fatal_error("cannot create pipe for stdin"); |
| 149 | } |
| 150 | SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); |
| 151 | |
| 152 | win32_create_child_process(fossil_utf8_to_unicode(zCmd), |
| 153 | hStdinRd,hStdoutWr,hStdoutWr,&childPid); |
| 154 | /* ^^^^^^^^^ ^^^^^^^^^ |
| 155 | ** Send both stdout and stderr to to *ppOut. |
| 156 | ** See check-in 857495ec92a521bb (2024-02-06) and earlier for |
| 157 | ** an example of how to leave stderr going to console */ |
| 158 | |
| 159 | *pChildPid = childPid; |
| 160 | *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); |
| 161 | fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); |
| 162 | *ppOut = _fdopen(fd, "w"); |
| 163 | CloseHandle(hStdinRd); |
| @@ -194,10 +198,13 @@ | |
| 198 | close(1); |
| 199 | fd = dup(pin[1]); |
| 200 | if( fd!=1 ) fossil_panic("popen() failed to open file descriptor 1"); |
| 201 | close(pin[0]); |
| 202 | close(pin[1]); |
| 203 | close(2); |
| 204 | fd = dup(1); |
| 205 | if( fd!=2 ) fossil_panic("popen() failed to redirect stderr into stdout"); |
| 206 | if( bDirect ){ |
| 207 | execl(zCmd, zCmd, (char*)0); |
| 208 | }else{ |
| 209 | execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0); |
| 210 | } |
| 211 |
+4
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1789,10 +1789,14 @@ | ||
| 1789 | 1789 | /* Undocumented query parameter to set JS mode */ |
| 1790 | 1790 | builtin_set_js_delivery_mode(P("jsmode"),1); |
| 1791 | 1791 | |
| 1792 | 1792 | secondaryRid = name_to_typed_rid(P("sel2"),"ci"); |
| 1793 | 1793 | selectedRid = name_to_typed_rid(P("sel1"),"ci"); |
| 1794 | + if( from_rid!=0 && to_rid!=0 ){ | |
| 1795 | + if( selectedRid==0 ) selectedRid = from_rid; | |
| 1796 | + if( secondaryRid==0 ) secondaryRid = to_rid; | |
| 1797 | + } | |
| 1794 | 1798 | tmFlags |= timeline_ss_submenu(); |
| 1795 | 1799 | cookie_link_parameter("advm","advm","0"); |
| 1796 | 1800 | advancedMenu = atoi(PD("advm","0")); |
| 1797 | 1801 | |
| 1798 | 1802 | /* Omit all cherry-pick merge lines if the "ncp" query parameter is |
| 1799 | 1803 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1789,10 +1789,14 @@ | |
| 1789 | /* Undocumented query parameter to set JS mode */ |
| 1790 | builtin_set_js_delivery_mode(P("jsmode"),1); |
| 1791 | |
| 1792 | secondaryRid = name_to_typed_rid(P("sel2"),"ci"); |
| 1793 | selectedRid = name_to_typed_rid(P("sel1"),"ci"); |
| 1794 | tmFlags |= timeline_ss_submenu(); |
| 1795 | cookie_link_parameter("advm","advm","0"); |
| 1796 | advancedMenu = atoi(PD("advm","0")); |
| 1797 | |
| 1798 | /* Omit all cherry-pick merge lines if the "ncp" query parameter is |
| 1799 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1789,10 +1789,14 @@ | |
| 1789 | /* Undocumented query parameter to set JS mode */ |
| 1790 | builtin_set_js_delivery_mode(P("jsmode"),1); |
| 1791 | |
| 1792 | secondaryRid = name_to_typed_rid(P("sel2"),"ci"); |
| 1793 | selectedRid = name_to_typed_rid(P("sel1"),"ci"); |
| 1794 | if( from_rid!=0 && to_rid!=0 ){ |
| 1795 | if( selectedRid==0 ) selectedRid = from_rid; |
| 1796 | if( secondaryRid==0 ) secondaryRid = to_rid; |
| 1797 | } |
| 1798 | tmFlags |= timeline_ss_submenu(); |
| 1799 | cookie_link_parameter("advm","advm","0"); |
| 1800 | advancedMenu = atoi(PD("advm","0")); |
| 1801 | |
| 1802 | /* Omit all cherry-pick merge lines if the "ncp" query parameter is |
| 1803 |
+41
-31
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -33,18 +33,21 @@ | ||
| 33 | 33 | |
| 34 | 34 | #if INTERFACE |
| 35 | 35 | /* |
| 36 | 36 | ** Flags for url_parse() |
| 37 | 37 | */ |
| 38 | -#define URL_PROMPT_PW 0x001 /* Prompt for password if needed */ | |
| 39 | -#define URL_REMEMBER 0x002 /* Remember the url for later reuse */ | |
| 40 | -#define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */ | |
| 41 | -#define URL_REMEMBER_PW 0x008 /* Should remember pw */ | |
| 42 | -#define URL_PROMPTED 0x010 /* Prompted for PW already */ | |
| 43 | -#define URL_OMIT_USER 0x020 /* Omit the user name from URL */ | |
| 44 | -#define URL_USE_CONFIG 0x040 /* Use remembered URLs from CONFIG table */ | |
| 45 | -#define URL_USE_PARENT 0x080 /* Use the URL of the parent project */ | |
| 38 | +#define URL_PROMPT_PW 0x0001 /* Prompt for password if needed */ | |
| 39 | +#define URL_REMEMBER 0x0002 /* Remember the url for later reuse */ | |
| 40 | +#define URL_ASK_REMEMBER_PW 0x0004 /* Ask whether to remember prompted pw */ | |
| 41 | +#define URL_REMEMBER_PW 0x0008 /* Should remember pw */ | |
| 42 | +#define URL_PROMPTED 0x0010 /* Prompted for PW already */ | |
| 43 | +#define URL_OMIT_USER 0x0020 /* Omit the user name from URL */ | |
| 44 | +#define URL_USE_CONFIG 0x0040 /* Use remembered URLs from CONFIG table */ | |
| 45 | +#define URL_USE_PARENT 0x0080 /* Use the URL of the parent project */ | |
| 46 | +#define URL_SSH_PATH 0x0100 /* Include PATH= on SSH syncs */ | |
| 47 | +#define URL_SSH_RETRY 0x0200 /* This a retry of an SSH */ | |
| 48 | +#define URL_SSH_EXE 0x0400 /* ssh: URL contains fossil= query param*/ | |
| 46 | 49 | |
| 47 | 50 | /* |
| 48 | 51 | ** The URL related data used with this subsystem. |
| 49 | 52 | */ |
| 50 | 53 | struct UrlData { |
| @@ -110,11 +113,11 @@ | ||
| 110 | 113 | UrlData *pUrlData |
| 111 | 114 | ){ |
| 112 | 115 | int i, j, c; |
| 113 | 116 | char *zFile = 0; |
| 114 | 117 | |
| 115 | - pUrlData->pwConfig = 0; | |
| 118 | + memset(pUrlData, 0, sizeof(*pUrlData)); | |
| 116 | 119 | if( urlFlags & URL_USE_CONFIG ){ |
| 117 | 120 | if( zUrl==0 || strcmp(zUrl,"default")==0 ){ |
| 118 | 121 | const char *zPwConfig = "last-sync-pw"; |
| 119 | 122 | if( urlFlags & URL_USE_PARENT ){ |
| 120 | 123 | zUrl = db_get("parent-project-url", 0); |
| @@ -159,12 +162,10 @@ | ||
| 159 | 162 | int iStart; |
| 160 | 163 | char *zLogin; |
| 161 | 164 | char *zExe; |
| 162 | 165 | char cQuerySep = '?'; |
| 163 | 166 | |
| 164 | - pUrlData->isFile = 0; | |
| 165 | - pUrlData->useProxy = 0; | |
| 166 | 167 | if( zUrl[4]=='s' ){ |
| 167 | 168 | pUrlData->isHttps = 1; |
| 168 | 169 | pUrlData->protocol = "https"; |
| 169 | 170 | pUrlData->dfltPort = 443; |
| 170 | 171 | iStart = 8; |
| @@ -255,15 +256,17 @@ | ||
| 255 | 256 | if( pUrlData->path[i] ){ |
| 256 | 257 | pUrlData->path[i] = 0; |
| 257 | 258 | i++; |
| 258 | 259 | } |
| 259 | 260 | if( fossil_strcmp(zName,"fossil")==0 ){ |
| 261 | + fossil_free(pUrlData->fossil); | |
| 260 | 262 | pUrlData->fossil = fossil_strdup(zValue); |
| 261 | 263 | dehttpize(pUrlData->fossil); |
| 262 | 264 | fossil_free(zExe); |
| 263 | 265 | zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil); |
| 264 | 266 | cQuerySep = '&'; |
| 267 | + urlFlags |= URL_SSH_EXE; | |
| 265 | 268 | } |
| 266 | 269 | } |
| 267 | 270 | |
| 268 | 271 | dehttpize(pUrlData->path); |
| 269 | 272 | if( pUrlData->dfltPort==pUrlData->port ){ |
| @@ -453,10 +456,36 @@ | ||
| 453 | 456 | ** g.url.pwConfig is NULL. |
| 454 | 457 | */ |
| 455 | 458 | void url_parse(const char *zUrl, unsigned int urlFlags){ |
| 456 | 459 | url_parse_local(zUrl, urlFlags, &g.url); |
| 457 | 460 | } |
| 461 | + | |
| 462 | +/* | |
| 463 | +** Print the content of g.url | |
| 464 | +*/ | |
| 465 | +void urlparse_print(int showPw){ | |
| 466 | + fossil_print("g.url.isFile = %d\n", g.url.isFile); | |
| 467 | + fossil_print("g.url.isHttps = %d\n", g.url.isHttps); | |
| 468 | + fossil_print("g.url.isSsh = %d\n", g.url.isSsh); | |
| 469 | + fossil_print("g.url.protocol = %s\n", g.url.protocol); | |
| 470 | + fossil_print("g.url.name = %s\n", g.url.name); | |
| 471 | + fossil_print("g.url.port = %d\n", g.url.port); | |
| 472 | + fossil_print("g.url.dfltPort = %d\n", g.url.dfltPort); | |
| 473 | + fossil_print("g.url.hostname = %s\n", g.url.hostname); | |
| 474 | + fossil_print("g.url.path = %s\n", g.url.path); | |
| 475 | + fossil_print("g.url.user = %s\n", g.url.user); | |
| 476 | + if( showPw || g.url.pwConfig==0 ){ | |
| 477 | + fossil_print("g.url.passwd = %s\n", g.url.passwd); | |
| 478 | + }else{ | |
| 479 | + fossil_print("g.url.passwd = ************\n"); | |
| 480 | + } | |
| 481 | + fossil_print("g.url.pwConfig = %s\n", g.url.pwConfig); | |
| 482 | + fossil_print("g.url.canonical = %s\n", g.url.canonical); | |
| 483 | + fossil_print("g.url.fossil = %s\n", g.url.fossil); | |
| 484 | + fossil_print("g.url.flags = 0x%04x\n", g.url.flags); | |
| 485 | + fossil_print("url_full(g.url) = %z\n", url_full(&g.url)); | |
| 486 | +} | |
| 458 | 487 | |
| 459 | 488 | /* |
| 460 | 489 | ** COMMAND: test-urlparser |
| 461 | 490 | ** |
| 462 | 491 | ** Usage: %fossil test-urlparser URL ?options? |
| @@ -482,30 +511,11 @@ | ||
| 482 | 511 | if( g.argc!=3 && g.argc!=4 ){ |
| 483 | 512 | usage("URL"); |
| 484 | 513 | } |
| 485 | 514 | url_parse(g.argv[2], fg); |
| 486 | 515 | for(i=0; i<2; i++){ |
| 487 | - fossil_print("g.url.isFile = %d\n", g.url.isFile); | |
| 488 | - fossil_print("g.url.isHttps = %d\n", g.url.isHttps); | |
| 489 | - fossil_print("g.url.isSsh = %d\n", g.url.isSsh); | |
| 490 | - fossil_print("g.url.protocol = %s\n", g.url.protocol); | |
| 491 | - fossil_print("g.url.name = %s\n", g.url.name); | |
| 492 | - fossil_print("g.url.port = %d\n", g.url.port); | |
| 493 | - fossil_print("g.url.dfltPort = %d\n", g.url.dfltPort); | |
| 494 | - fossil_print("g.url.hostname = %s\n", g.url.hostname); | |
| 495 | - fossil_print("g.url.path = %s\n", g.url.path); | |
| 496 | - fossil_print("g.url.user = %s\n", g.url.user); | |
| 497 | - if( showPw || g.url.pwConfig==0 ){ | |
| 498 | - fossil_print("g.url.passwd = %s\n", g.url.passwd); | |
| 499 | - }else{ | |
| 500 | - fossil_print("g.url.passwd = ************\n"); | |
| 501 | - } | |
| 502 | - fossil_print("g.url.pwConfig = %s\n", g.url.pwConfig); | |
| 503 | - fossil_print("g.url.canonical = %s\n", g.url.canonical); | |
| 504 | - fossil_print("g.url.fossil = %s\n", g.url.fossil); | |
| 505 | - fossil_print("g.url.flags = 0x%02x\n", g.url.flags); | |
| 506 | - fossil_print("url_full(g.url) = %z\n", url_full(&g.url)); | |
| 516 | + urlparse_print(showPw); | |
| 507 | 517 | if( g.url.isFile || g.url.isSsh ) break; |
| 508 | 518 | if( i==0 ){ |
| 509 | 519 | fossil_print("********\n"); |
| 510 | 520 | url_enable_proxy("Using proxy: "); |
| 511 | 521 | } |
| 512 | 522 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -33,18 +33,21 @@ | |
| 33 | |
| 34 | #if INTERFACE |
| 35 | /* |
| 36 | ** Flags for url_parse() |
| 37 | */ |
| 38 | #define URL_PROMPT_PW 0x001 /* Prompt for password if needed */ |
| 39 | #define URL_REMEMBER 0x002 /* Remember the url for later reuse */ |
| 40 | #define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */ |
| 41 | #define URL_REMEMBER_PW 0x008 /* Should remember pw */ |
| 42 | #define URL_PROMPTED 0x010 /* Prompted for PW already */ |
| 43 | #define URL_OMIT_USER 0x020 /* Omit the user name from URL */ |
| 44 | #define URL_USE_CONFIG 0x040 /* Use remembered URLs from CONFIG table */ |
| 45 | #define URL_USE_PARENT 0x080 /* Use the URL of the parent project */ |
| 46 | |
| 47 | /* |
| 48 | ** The URL related data used with this subsystem. |
| 49 | */ |
| 50 | struct UrlData { |
| @@ -110,11 +113,11 @@ | |
| 110 | UrlData *pUrlData |
| 111 | ){ |
| 112 | int i, j, c; |
| 113 | char *zFile = 0; |
| 114 | |
| 115 | pUrlData->pwConfig = 0; |
| 116 | if( urlFlags & URL_USE_CONFIG ){ |
| 117 | if( zUrl==0 || strcmp(zUrl,"default")==0 ){ |
| 118 | const char *zPwConfig = "last-sync-pw"; |
| 119 | if( urlFlags & URL_USE_PARENT ){ |
| 120 | zUrl = db_get("parent-project-url", 0); |
| @@ -159,12 +162,10 @@ | |
| 159 | int iStart; |
| 160 | char *zLogin; |
| 161 | char *zExe; |
| 162 | char cQuerySep = '?'; |
| 163 | |
| 164 | pUrlData->isFile = 0; |
| 165 | pUrlData->useProxy = 0; |
| 166 | if( zUrl[4]=='s' ){ |
| 167 | pUrlData->isHttps = 1; |
| 168 | pUrlData->protocol = "https"; |
| 169 | pUrlData->dfltPort = 443; |
| 170 | iStart = 8; |
| @@ -255,15 +256,17 @@ | |
| 255 | if( pUrlData->path[i] ){ |
| 256 | pUrlData->path[i] = 0; |
| 257 | i++; |
| 258 | } |
| 259 | if( fossil_strcmp(zName,"fossil")==0 ){ |
| 260 | pUrlData->fossil = fossil_strdup(zValue); |
| 261 | dehttpize(pUrlData->fossil); |
| 262 | fossil_free(zExe); |
| 263 | zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil); |
| 264 | cQuerySep = '&'; |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | dehttpize(pUrlData->path); |
| 269 | if( pUrlData->dfltPort==pUrlData->port ){ |
| @@ -453,10 +456,36 @@ | |
| 453 | ** g.url.pwConfig is NULL. |
| 454 | */ |
| 455 | void url_parse(const char *zUrl, unsigned int urlFlags){ |
| 456 | url_parse_local(zUrl, urlFlags, &g.url); |
| 457 | } |
| 458 | |
| 459 | /* |
| 460 | ** COMMAND: test-urlparser |
| 461 | ** |
| 462 | ** Usage: %fossil test-urlparser URL ?options? |
| @@ -482,30 +511,11 @@ | |
| 482 | if( g.argc!=3 && g.argc!=4 ){ |
| 483 | usage("URL"); |
| 484 | } |
| 485 | url_parse(g.argv[2], fg); |
| 486 | for(i=0; i<2; i++){ |
| 487 | fossil_print("g.url.isFile = %d\n", g.url.isFile); |
| 488 | fossil_print("g.url.isHttps = %d\n", g.url.isHttps); |
| 489 | fossil_print("g.url.isSsh = %d\n", g.url.isSsh); |
| 490 | fossil_print("g.url.protocol = %s\n", g.url.protocol); |
| 491 | fossil_print("g.url.name = %s\n", g.url.name); |
| 492 | fossil_print("g.url.port = %d\n", g.url.port); |
| 493 | fossil_print("g.url.dfltPort = %d\n", g.url.dfltPort); |
| 494 | fossil_print("g.url.hostname = %s\n", g.url.hostname); |
| 495 | fossil_print("g.url.path = %s\n", g.url.path); |
| 496 | fossil_print("g.url.user = %s\n", g.url.user); |
| 497 | if( showPw || g.url.pwConfig==0 ){ |
| 498 | fossil_print("g.url.passwd = %s\n", g.url.passwd); |
| 499 | }else{ |
| 500 | fossil_print("g.url.passwd = ************\n"); |
| 501 | } |
| 502 | fossil_print("g.url.pwConfig = %s\n", g.url.pwConfig); |
| 503 | fossil_print("g.url.canonical = %s\n", g.url.canonical); |
| 504 | fossil_print("g.url.fossil = %s\n", g.url.fossil); |
| 505 | fossil_print("g.url.flags = 0x%02x\n", g.url.flags); |
| 506 | fossil_print("url_full(g.url) = %z\n", url_full(&g.url)); |
| 507 | if( g.url.isFile || g.url.isSsh ) break; |
| 508 | if( i==0 ){ |
| 509 | fossil_print("********\n"); |
| 510 | url_enable_proxy("Using proxy: "); |
| 511 | } |
| 512 |
| --- src/url.c | |
| +++ src/url.c | |
| @@ -33,18 +33,21 @@ | |
| 33 | |
| 34 | #if INTERFACE |
| 35 | /* |
| 36 | ** Flags for url_parse() |
| 37 | */ |
| 38 | #define URL_PROMPT_PW 0x0001 /* Prompt for password if needed */ |
| 39 | #define URL_REMEMBER 0x0002 /* Remember the url for later reuse */ |
| 40 | #define URL_ASK_REMEMBER_PW 0x0004 /* Ask whether to remember prompted pw */ |
| 41 | #define URL_REMEMBER_PW 0x0008 /* Should remember pw */ |
| 42 | #define URL_PROMPTED 0x0010 /* Prompted for PW already */ |
| 43 | #define URL_OMIT_USER 0x0020 /* Omit the user name from URL */ |
| 44 | #define URL_USE_CONFIG 0x0040 /* Use remembered URLs from CONFIG table */ |
| 45 | #define URL_USE_PARENT 0x0080 /* Use the URL of the parent project */ |
| 46 | #define URL_SSH_PATH 0x0100 /* Include PATH= on SSH syncs */ |
| 47 | #define URL_SSH_RETRY 0x0200 /* This a retry of an SSH */ |
| 48 | #define URL_SSH_EXE 0x0400 /* ssh: URL contains fossil= query param*/ |
| 49 | |
| 50 | /* |
| 51 | ** The URL related data used with this subsystem. |
| 52 | */ |
| 53 | struct UrlData { |
| @@ -110,11 +113,11 @@ | |
| 113 | UrlData *pUrlData |
| 114 | ){ |
| 115 | int i, j, c; |
| 116 | char *zFile = 0; |
| 117 | |
| 118 | memset(pUrlData, 0, sizeof(*pUrlData)); |
| 119 | if( urlFlags & URL_USE_CONFIG ){ |
| 120 | if( zUrl==0 || strcmp(zUrl,"default")==0 ){ |
| 121 | const char *zPwConfig = "last-sync-pw"; |
| 122 | if( urlFlags & URL_USE_PARENT ){ |
| 123 | zUrl = db_get("parent-project-url", 0); |
| @@ -159,12 +162,10 @@ | |
| 162 | int iStart; |
| 163 | char *zLogin; |
| 164 | char *zExe; |
| 165 | char cQuerySep = '?'; |
| 166 | |
| 167 | if( zUrl[4]=='s' ){ |
| 168 | pUrlData->isHttps = 1; |
| 169 | pUrlData->protocol = "https"; |
| 170 | pUrlData->dfltPort = 443; |
| 171 | iStart = 8; |
| @@ -255,15 +256,17 @@ | |
| 256 | if( pUrlData->path[i] ){ |
| 257 | pUrlData->path[i] = 0; |
| 258 | i++; |
| 259 | } |
| 260 | if( fossil_strcmp(zName,"fossil")==0 ){ |
| 261 | fossil_free(pUrlData->fossil); |
| 262 | pUrlData->fossil = fossil_strdup(zValue); |
| 263 | dehttpize(pUrlData->fossil); |
| 264 | fossil_free(zExe); |
| 265 | zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil); |
| 266 | cQuerySep = '&'; |
| 267 | urlFlags |= URL_SSH_EXE; |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | dehttpize(pUrlData->path); |
| 272 | if( pUrlData->dfltPort==pUrlData->port ){ |
| @@ -453,10 +456,36 @@ | |
| 456 | ** g.url.pwConfig is NULL. |
| 457 | */ |
| 458 | void url_parse(const char *zUrl, unsigned int urlFlags){ |
| 459 | url_parse_local(zUrl, urlFlags, &g.url); |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | ** Print the content of g.url |
| 464 | */ |
| 465 | void urlparse_print(int showPw){ |
| 466 | fossil_print("g.url.isFile = %d\n", g.url.isFile); |
| 467 | fossil_print("g.url.isHttps = %d\n", g.url.isHttps); |
| 468 | fossil_print("g.url.isSsh = %d\n", g.url.isSsh); |
| 469 | fossil_print("g.url.protocol = %s\n", g.url.protocol); |
| 470 | fossil_print("g.url.name = %s\n", g.url.name); |
| 471 | fossil_print("g.url.port = %d\n", g.url.port); |
| 472 | fossil_print("g.url.dfltPort = %d\n", g.url.dfltPort); |
| 473 | fossil_print("g.url.hostname = %s\n", g.url.hostname); |
| 474 | fossil_print("g.url.path = %s\n", g.url.path); |
| 475 | fossil_print("g.url.user = %s\n", g.url.user); |
| 476 | if( showPw || g.url.pwConfig==0 ){ |
| 477 | fossil_print("g.url.passwd = %s\n", g.url.passwd); |
| 478 | }else{ |
| 479 | fossil_print("g.url.passwd = ************\n"); |
| 480 | } |
| 481 | fossil_print("g.url.pwConfig = %s\n", g.url.pwConfig); |
| 482 | fossil_print("g.url.canonical = %s\n", g.url.canonical); |
| 483 | fossil_print("g.url.fossil = %s\n", g.url.fossil); |
| 484 | fossil_print("g.url.flags = 0x%04x\n", g.url.flags); |
| 485 | fossil_print("url_full(g.url) = %z\n", url_full(&g.url)); |
| 486 | } |
| 487 | |
| 488 | /* |
| 489 | ** COMMAND: test-urlparser |
| 490 | ** |
| 491 | ** Usage: %fossil test-urlparser URL ?options? |
| @@ -482,30 +511,11 @@ | |
| 511 | if( g.argc!=3 && g.argc!=4 ){ |
| 512 | usage("URL"); |
| 513 | } |
| 514 | url_parse(g.argv[2], fg); |
| 515 | for(i=0; i<2; i++){ |
| 516 | urlparse_print(showPw); |
| 517 | if( g.url.isFile || g.url.isSsh ) break; |
| 518 | if( i==0 ){ |
| 519 | fossil_print("********\n"); |
| 520 | url_enable_proxy("Using proxy: "); |
| 521 | } |
| 522 |
+4
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,9 +1,13 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | 3 | <h2 id='v2_24'>Changes for version 2.24 (pending)</h2> |
| 4 | 4 | |
| 5 | + * If an ssh: sync fails in a way that suggests that the fossil executable | |
| 6 | + could not be found on the remote host, then retry after adding a PATH= | |
| 7 | + prefix to the command. This helps "ssh:" to "just work" when the server | |
| 8 | + is a Mac. | |
| 5 | 9 | * Add the x= query paramater to the [/help?cmd=/timeline|/timeline page]. |
| 6 | 10 | * Moved the /museum/repo.fossil file referenced from the Dockerfile from |
| 7 | 11 | the ENTRYPOINT to the CMD part to allow use of --repolist mode. |
| 8 | 12 | * The /uvlist page now shows the hash algorithm used so that |
| 9 | 13 | outsiders don't have to guess it from the hash length when |
| 10 | 14 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,9 +1,13 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2 id='v2_24'>Changes for version 2.24 (pending)</h2> |
| 4 | |
| 5 | * Add the x= query paramater to the [/help?cmd=/timeline|/timeline page]. |
| 6 | * Moved the /museum/repo.fossil file referenced from the Dockerfile from |
| 7 | the ENTRYPOINT to the CMD part to allow use of --repolist mode. |
| 8 | * The /uvlist page now shows the hash algorithm used so that |
| 9 | outsiders don't have to guess it from the hash length when |
| 10 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,9 +1,13 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2 id='v2_24'>Changes for version 2.24 (pending)</h2> |
| 4 | |
| 5 | * If an ssh: sync fails in a way that suggests that the fossil executable |
| 6 | could not be found on the remote host, then retry after adding a PATH= |
| 7 | prefix to the command. This helps "ssh:" to "just work" when the server |
| 8 | is a Mac. |
| 9 | * Add the x= query paramater to the [/help?cmd=/timeline|/timeline page]. |
| 10 | * Moved the /museum/repo.fossil file referenced from the Dockerfile from |
| 11 | the ENTRYPOINT to the CMD part to allow use of --repolist mode. |
| 12 | * The /uvlist page now shows the hash algorithm used so that |
| 13 | outsiders don't have to guess it from the hash length when |
| 14 |
+5
-2
| --- www/loadmgmt.md | ||
| +++ www/loadmgmt.md | ||
| @@ -25,15 +25,18 @@ | ||
| 25 | 25 | 1. An optional cache is available that remembers the 10 most recently |
| 26 | 26 | requested `/zip` or `/tarball` pages and returns the precomputed |
| 27 | 27 | answer if the same page is requested again. |
| 28 | 28 | |
| 29 | 29 | 2. Page requests can be configured to fail with a |
| 30 | - “[503 Server Overload][503]” HTTP error if an expensive request is | |
| 30 | + “[503 Server Overload][503]” HTTP error if any request is | |
| 31 | 31 | received while the host load average is too high. |
| 32 | 32 | |
| 33 | 33 | Both of these load-control mechanisms are turned off by default, but |
| 34 | -they are recommended for high-traffic sites. | |
| 34 | +they are recommended for high-traffic sites. Users with [admin | |
| 35 | +permissions](caps/index.md) are exempt from these restrictions, | |
| 36 | +provided they are logged in before the load gets too high (login is | |
| 37 | +disabled under high load). | |
| 35 | 38 | |
| 36 | 39 | The webpage cache is activated using the [`fossil cache init`](/help/cache) |
| 37 | 40 | command-line on the server. Add a `-R` option to |
| 38 | 41 | specify the specific repository for which to enable caching. If running |
| 39 | 42 | this command as root, be sure to “`chown`” the cache database to give |
| 40 | 43 |
| --- www/loadmgmt.md | |
| +++ www/loadmgmt.md | |
| @@ -25,15 +25,18 @@ | |
| 25 | 1. An optional cache is available that remembers the 10 most recently |
| 26 | requested `/zip` or `/tarball` pages and returns the precomputed |
| 27 | answer if the same page is requested again. |
| 28 | |
| 29 | 2. Page requests can be configured to fail with a |
| 30 | “[503 Server Overload][503]” HTTP error if an expensive request is |
| 31 | received while the host load average is too high. |
| 32 | |
| 33 | Both of these load-control mechanisms are turned off by default, but |
| 34 | they are recommended for high-traffic sites. |
| 35 | |
| 36 | The webpage cache is activated using the [`fossil cache init`](/help/cache) |
| 37 | command-line on the server. Add a `-R` option to |
| 38 | specify the specific repository for which to enable caching. If running |
| 39 | this command as root, be sure to “`chown`” the cache database to give |
| 40 |
| --- www/loadmgmt.md | |
| +++ www/loadmgmt.md | |
| @@ -25,15 +25,18 @@ | |
| 25 | 1. An optional cache is available that remembers the 10 most recently |
| 26 | requested `/zip` or `/tarball` pages and returns the precomputed |
| 27 | answer if the same page is requested again. |
| 28 | |
| 29 | 2. Page requests can be configured to fail with a |
| 30 | “[503 Server Overload][503]” HTTP error if any request is |
| 31 | received while the host load average is too high. |
| 32 | |
| 33 | Both of these load-control mechanisms are turned off by default, but |
| 34 | they are recommended for high-traffic sites. Users with [admin |
| 35 | permissions](caps/index.md) are exempt from these restrictions, |
| 36 | provided they are logged in before the load gets too high (login is |
| 37 | disabled under high load). |
| 38 | |
| 39 | The webpage cache is activated using the [`fossil cache init`](/help/cache) |
| 40 | command-line on the server. Add a `-R` option to |
| 41 | specify the specific repository for which to enable caching. If running |
| 42 | this command as root, be sure to “`chown`” the cache database to give |
| 43 |
+1
-1
| --- www/mirrortogithub.md | ||
| +++ www/mirrortogithub.md | ||
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | 3. Back on your workstation, move to a checkout for your Fossil |
| 19 | 19 | project and type: |
| 20 | 20 | |
| 21 | 21 | <blockquote> |
| 22 | 22 | <pre> |
| 23 | - $ fossil git export /path/to/git/repo --autopush \ | |
| 23 | + $ fossil git export /path/to/git/repo --autopush \ | |
| 24 | 24 | https://<font color="orange">username</font>:<font color="red">password</font>@github.com/username/project.git |
| 25 | 25 | </pre> |
| 26 | 26 | </blockquote> |
| 27 | 27 | |
| 28 | 28 | In place of the <code>/path/to...</code> argument above, put in |
| 29 | 29 |
| --- www/mirrortogithub.md | |
| +++ www/mirrortogithub.md | |
| @@ -18,11 +18,11 @@ | |
| 18 | 3. Back on your workstation, move to a checkout for your Fossil |
| 19 | project and type: |
| 20 | |
| 21 | <blockquote> |
| 22 | <pre> |
| 23 | $ fossil git export /path/to/git/repo --autopush \ |
| 24 | https://<font color="orange">username</font>:<font color="red">password</font>@github.com/username/project.git |
| 25 | </pre> |
| 26 | </blockquote> |
| 27 | |
| 28 | In place of the <code>/path/to...</code> argument above, put in |
| 29 |
| --- www/mirrortogithub.md | |
| +++ www/mirrortogithub.md | |
| @@ -18,11 +18,11 @@ | |
| 18 | 3. Back on your workstation, move to a checkout for your Fossil |
| 19 | project and type: |
| 20 | |
| 21 | <blockquote> |
| 22 | <pre> |
| 23 | $ fossil git export /path/to/git/repo --autopush \ |
| 24 | https://<font color="orange">username</font>:<font color="red">password</font>@github.com/username/project.git |
| 25 | </pre> |
| 26 | </blockquote> |
| 27 | |
| 28 | In place of the <code>/path/to...</code> argument above, put in |
| 29 |
+22
-24
| --- www/newrepo.wiki | ||
| +++ www/newrepo.wiki | ||
| @@ -7,11 +7,11 @@ | ||
| 7 | 7 | sharing it over the web. |
| 8 | 8 | |
| 9 | 9 | The first thing we need to do is create a fossil repository file: |
| 10 | 10 | |
| 11 | 11 | <verbatim> |
| 12 | -stephan@ludo:~/fossil$ fossil new demo.fossil | |
| 12 | +$ fossil new demo.fossil | |
| 13 | 13 | project-id: 9d8ccff5671796ee04e60af6932aa7788f0a990a |
| 14 | 14 | server-id: 145fe7d71e3b513ac37ac283979d73e12ca04bfe |
| 15 | 15 | admin-user: stephan (initial password is ******) |
| 16 | 16 | </verbatim> |
| 17 | 17 | |
| @@ -24,11 +24,11 @@ | ||
| 24 | 24 | |
| 25 | 25 | The first thing we normally want to do is to run fossil as a local server so |
| 26 | 26 | that you can configure the access rights to the repo: |
| 27 | 27 | |
| 28 | 28 | <verbatim> |
| 29 | -stephan@ludo:~/fossil$ fossil ui demo.fossil | |
| 29 | +$ fossil ui demo.fossil | |
| 30 | 30 | </verbatim> |
| 31 | 31 | |
| 32 | 32 | The <tt>ui</tt> command starts up a server (with an optional <tt>-port |
| 33 | 33 | NUMBER</tt> argument) and launches a web browser pointing at the |
| 34 | 34 | fossil server. From there it takes just a few moments to configure the |
| @@ -50,14 +50,13 @@ | ||
| 50 | 50 | |
| 51 | 51 | The next thing we need to do is <em>open</em> the repository. To do so |
| 52 | 52 | we create a working directory and then <tt>cd</tt> to it: |
| 53 | 53 | |
| 54 | 54 | <verbatim> |
| 55 | -stephan@ludo:~/fossil$ mkdir demo | |
| 56 | -stephan@ludo:~/fossil$ cd demo | |
| 57 | -stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil | |
| 58 | -stephan@ludo:~/fossil/demo$ | |
| 55 | +$ mkdir demo | |
| 56 | +$ cd demo | |
| 57 | +$ fossil open ../demo.fossil | |
| 59 | 58 | </verbatim> |
| 60 | 59 | |
| 61 | 60 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | 61 | directory, and this file contains all kinds of fossil-related |
| 63 | 62 | information about your local repository. You can ignore it |
| @@ -67,36 +66,36 @@ | ||
| 67 | 66 | The next thing we need to do is add files to our repository. As it |
| 68 | 67 | happens, we have a few C source files lying around, which we'll |
| 69 | 68 | simply copy into our working directory. |
| 70 | 69 | |
| 71 | 70 | <verbatim> |
| 72 | -stephan@ludo:~/fossil/demo$ cp ../csnip/*.{c,h} . | |
| 73 | -stephan@ludo:~/fossil/demo$ ls | |
| 74 | -clob.c clob.h clobz.c _FOSSIL_ mkdep.c test-clob.c | |
| 71 | +$ cp ../csnip/*.{c,h} . | |
| 72 | +$ ls | |
| 73 | +clob.c clob.h clobz.c mkdep.c test-clob.c | |
| 75 | 74 | tokenize_path.c tokenize_path.h vappendf.c vappendf.h |
| 76 | 75 | </verbatim> |
| 77 | 76 | |
| 78 | 77 | Fossil doesn't know about those files yet. Telling fossil about |
| 79 | 78 | a new file is a two-step process. First we <em>add</em> the file |
| 80 | 79 | to the repository, then we <em>commit</em> the file. This is a familiar |
| 81 | 80 | process for anyone who's worked with SCM systems before: |
| 82 | 81 | |
| 83 | 82 | <verbatim> |
| 84 | -stephan@ludo:~/fossil/demo$ fossil add *.{c,h} | |
| 85 | -stephan@ludo:~/fossil/demo$ fossil commit -m "egg" | |
| 83 | +$ fossil add *.{c,h} | |
| 84 | +$ fossil commit -m "egg" | |
| 86 | 85 | New_Version: d1296b4a08b9f8b943bb6c73698e51eed23f8f91 |
| 87 | 86 | </verbatim> |
| 88 | 87 | |
| 89 | 88 | We now have a working repository! The file <tt>demo.fossil</tt> |
| 90 | 89 | is the central storage, and we can share it amongst an arbitrary |
| 91 | 90 | number of trees. As a silly example: |
| 92 | 91 | |
| 93 | 92 | <verbatim> |
| 94 | -stephan@ludo:~/fossil/demo$ cd ~/fossil | |
| 95 | -stephan@ludo:~/fossil$ mkdir demo2 | |
| 96 | -stephan@ludo:~/fossil$ cd demo2 | |
| 97 | -stephan@ludo:~/fossil/demo2$ fossil open ../demo.fossil | |
| 93 | +$ cd ~/fossil | |
| 94 | +$ mkdir demo2 | |
| 95 | +$ cd demo2 | |
| 96 | +$ fossil open ../demo.fossil | |
| 98 | 97 | ADD clob.c |
| 99 | 98 | ADD clob.h |
| 100 | 99 | ADD clobz.c |
| 101 | 100 | ADD mkdep.c |
| 102 | 101 | ADD test-clob.c |
| @@ -112,12 +111,12 @@ | ||
| 112 | 111 | Making your repository available over the web is trivial to do. We |
| 113 | 112 | assume you have some web space where you can store your fossil file |
| 114 | 113 | and run a CGI script. If not, then this option is not for you. If |
| 115 | 114 | you do, then here's how... |
| 116 | 115 | |
| 117 | -Copy the fossil repository file to your web server (it doesn't | |
| 118 | -matter where, really). | |
| 116 | +Copy the fossil repository file to your web server (it doesn't matter | |
| 117 | +where, really, but it "should" be unreachable by web browser traffic). | |
| 119 | 118 | |
| 120 | 119 | In your <tt>cgi-bin</tt> (or equivalent) directory, create a file |
| 121 | 120 | which looks like this: |
| 122 | 121 | |
| 123 | 122 | <verbatim> |
| @@ -126,28 +125,27 @@ | ||
| 126 | 125 | </verbatim> |
| 127 | 126 | |
| 128 | 127 | Make that script executable, and you're all ready to go: |
| 129 | 128 | |
| 130 | 129 | <verbatim> |
| 131 | -~/www/cgi-bin> chmod +x myrepo.cgi | |
| 130 | +$ chmod +x ~/www/cgi-bin/myrepo.cgi | |
| 132 | 131 | </verbatim> |
| 133 | 132 | |
| 134 | 133 | Now simply point your browser to |
| 135 | -<tt>http://my.domain/cgi-bin/myrepo.cgi</tt> and you should | |
| 134 | +<tt>https://my.domain/cgi-bin/myrepo.cgi</tt> and you should | |
| 136 | 135 | be able to manage the repository from there. |
| 137 | 136 | |
| 138 | 137 | To check out a copy of your remote repository, use the |
| 139 | 138 | <em>clone</em> command: |
| 140 | 139 | |
| 141 | 140 | <verbatim> |
| 142 | -stephan@ludo:~/fossil$ fossil clone \ | |
| 143 | - http://MyAccountName:[email protected]/cgi-bin/myrepo.cgi | |
| 141 | +$ fossil clone \ | |
| 142 | + https://MyAccountName:[email protected]/cgi-bin/myrepo.cgi | |
| 144 | 143 | </verbatim> |
| 145 | 144 | |
| 146 | -Note that you should pass your fossil login name and password (as set | |
| 147 | -via local server mode) during the clone - that ensures that fossil | |
| 148 | -won't ask you for it on each commit! | |
| 145 | +If you do not provide your password in the URL, fossil will | |
| 146 | +interactively prompt you for it. | |
| 149 | 147 | |
| 150 | 148 | A clone is a local copy of a remote repository, and can be opened just |
| 151 | 149 | like a local one (as shown above). It is treated identically to your |
| 152 | 150 | local repository, with one very important difference. When you commit |
| 153 | 151 | changes to a cloned remote repository, they will be pushed back to the |
| 154 | 152 |
| --- www/newrepo.wiki | |
| +++ www/newrepo.wiki | |
| @@ -7,11 +7,11 @@ | |
| 7 | sharing it over the web. |
| 8 | |
| 9 | The first thing we need to do is create a fossil repository file: |
| 10 | |
| 11 | <verbatim> |
| 12 | stephan@ludo:~/fossil$ fossil new demo.fossil |
| 13 | project-id: 9d8ccff5671796ee04e60af6932aa7788f0a990a |
| 14 | server-id: 145fe7d71e3b513ac37ac283979d73e12ca04bfe |
| 15 | admin-user: stephan (initial password is ******) |
| 16 | </verbatim> |
| 17 | |
| @@ -24,11 +24,11 @@ | |
| 24 | |
| 25 | The first thing we normally want to do is to run fossil as a local server so |
| 26 | that you can configure the access rights to the repo: |
| 27 | |
| 28 | <verbatim> |
| 29 | stephan@ludo:~/fossil$ fossil ui demo.fossil |
| 30 | </verbatim> |
| 31 | |
| 32 | The <tt>ui</tt> command starts up a server (with an optional <tt>-port |
| 33 | NUMBER</tt> argument) and launches a web browser pointing at the |
| 34 | fossil server. From there it takes just a few moments to configure the |
| @@ -50,14 +50,13 @@ | |
| 50 | |
| 51 | The next thing we need to do is <em>open</em> the repository. To do so |
| 52 | we create a working directory and then <tt>cd</tt> to it: |
| 53 | |
| 54 | <verbatim> |
| 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | stephan@ludo:~/fossil/demo$ |
| 59 | </verbatim> |
| 60 | |
| 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | directory, and this file contains all kinds of fossil-related |
| 63 | information about your local repository. You can ignore it |
| @@ -67,36 +66,36 @@ | |
| 67 | The next thing we need to do is add files to our repository. As it |
| 68 | happens, we have a few C source files lying around, which we'll |
| 69 | simply copy into our working directory. |
| 70 | |
| 71 | <verbatim> |
| 72 | stephan@ludo:~/fossil/demo$ cp ../csnip/*.{c,h} . |
| 73 | stephan@ludo:~/fossil/demo$ ls |
| 74 | clob.c clob.h clobz.c _FOSSIL_ mkdep.c test-clob.c |
| 75 | tokenize_path.c tokenize_path.h vappendf.c vappendf.h |
| 76 | </verbatim> |
| 77 | |
| 78 | Fossil doesn't know about those files yet. Telling fossil about |
| 79 | a new file is a two-step process. First we <em>add</em> the file |
| 80 | to the repository, then we <em>commit</em> the file. This is a familiar |
| 81 | process for anyone who's worked with SCM systems before: |
| 82 | |
| 83 | <verbatim> |
| 84 | stephan@ludo:~/fossil/demo$ fossil add *.{c,h} |
| 85 | stephan@ludo:~/fossil/demo$ fossil commit -m "egg" |
| 86 | New_Version: d1296b4a08b9f8b943bb6c73698e51eed23f8f91 |
| 87 | </verbatim> |
| 88 | |
| 89 | We now have a working repository! The file <tt>demo.fossil</tt> |
| 90 | is the central storage, and we can share it amongst an arbitrary |
| 91 | number of trees. As a silly example: |
| 92 | |
| 93 | <verbatim> |
| 94 | stephan@ludo:~/fossil/demo$ cd ~/fossil |
| 95 | stephan@ludo:~/fossil$ mkdir demo2 |
| 96 | stephan@ludo:~/fossil$ cd demo2 |
| 97 | stephan@ludo:~/fossil/demo2$ fossil open ../demo.fossil |
| 98 | ADD clob.c |
| 99 | ADD clob.h |
| 100 | ADD clobz.c |
| 101 | ADD mkdep.c |
| 102 | ADD test-clob.c |
| @@ -112,12 +111,12 @@ | |
| 112 | Making your repository available over the web is trivial to do. We |
| 113 | assume you have some web space where you can store your fossil file |
| 114 | and run a CGI script. If not, then this option is not for you. If |
| 115 | you do, then here's how... |
| 116 | |
| 117 | Copy the fossil repository file to your web server (it doesn't |
| 118 | matter where, really). |
| 119 | |
| 120 | In your <tt>cgi-bin</tt> (or equivalent) directory, create a file |
| 121 | which looks like this: |
| 122 | |
| 123 | <verbatim> |
| @@ -126,28 +125,27 @@ | |
| 126 | </verbatim> |
| 127 | |
| 128 | Make that script executable, and you're all ready to go: |
| 129 | |
| 130 | <verbatim> |
| 131 | ~/www/cgi-bin> chmod +x myrepo.cgi |
| 132 | </verbatim> |
| 133 | |
| 134 | Now simply point your browser to |
| 135 | <tt>http://my.domain/cgi-bin/myrepo.cgi</tt> and you should |
| 136 | be able to manage the repository from there. |
| 137 | |
| 138 | To check out a copy of your remote repository, use the |
| 139 | <em>clone</em> command: |
| 140 | |
| 141 | <verbatim> |
| 142 | stephan@ludo:~/fossil$ fossil clone \ |
| 143 | http://MyAccountName:[email protected]/cgi-bin/myrepo.cgi |
| 144 | </verbatim> |
| 145 | |
| 146 | Note that you should pass your fossil login name and password (as set |
| 147 | via local server mode) during the clone - that ensures that fossil |
| 148 | won't ask you for it on each commit! |
| 149 | |
| 150 | A clone is a local copy of a remote repository, and can be opened just |
| 151 | like a local one (as shown above). It is treated identically to your |
| 152 | local repository, with one very important difference. When you commit |
| 153 | changes to a cloned remote repository, they will be pushed back to the |
| 154 |
| --- www/newrepo.wiki | |
| +++ www/newrepo.wiki | |
| @@ -7,11 +7,11 @@ | |
| 7 | sharing it over the web. |
| 8 | |
| 9 | The first thing we need to do is create a fossil repository file: |
| 10 | |
| 11 | <verbatim> |
| 12 | $ fossil new demo.fossil |
| 13 | project-id: 9d8ccff5671796ee04e60af6932aa7788f0a990a |
| 14 | server-id: 145fe7d71e3b513ac37ac283979d73e12ca04bfe |
| 15 | admin-user: stephan (initial password is ******) |
| 16 | </verbatim> |
| 17 | |
| @@ -24,11 +24,11 @@ | |
| 24 | |
| 25 | The first thing we normally want to do is to run fossil as a local server so |
| 26 | that you can configure the access rights to the repo: |
| 27 | |
| 28 | <verbatim> |
| 29 | $ fossil ui demo.fossil |
| 30 | </verbatim> |
| 31 | |
| 32 | The <tt>ui</tt> command starts up a server (with an optional <tt>-port |
| 33 | NUMBER</tt> argument) and launches a web browser pointing at the |
| 34 | fossil server. From there it takes just a few moments to configure the |
| @@ -50,14 +50,13 @@ | |
| 50 | |
| 51 | The next thing we need to do is <em>open</em> the repository. To do so |
| 52 | we create a working directory and then <tt>cd</tt> to it: |
| 53 | |
| 54 | <verbatim> |
| 55 | $ mkdir demo |
| 56 | $ cd demo |
| 57 | $ fossil open ../demo.fossil |
| 58 | </verbatim> |
| 59 | |
| 60 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 61 | directory, and this file contains all kinds of fossil-related |
| 62 | information about your local repository. You can ignore it |
| @@ -67,36 +66,36 @@ | |
| 66 | The next thing we need to do is add files to our repository. As it |
| 67 | happens, we have a few C source files lying around, which we'll |
| 68 | simply copy into our working directory. |
| 69 | |
| 70 | <verbatim> |
| 71 | $ cp ../csnip/*.{c,h} . |
| 72 | $ ls |
| 73 | clob.c clob.h clobz.c mkdep.c test-clob.c |
| 74 | tokenize_path.c tokenize_path.h vappendf.c vappendf.h |
| 75 | </verbatim> |
| 76 | |
| 77 | Fossil doesn't know about those files yet. Telling fossil about |
| 78 | a new file is a two-step process. First we <em>add</em> the file |
| 79 | to the repository, then we <em>commit</em> the file. This is a familiar |
| 80 | process for anyone who's worked with SCM systems before: |
| 81 | |
| 82 | <verbatim> |
| 83 | $ fossil add *.{c,h} |
| 84 | $ fossil commit -m "egg" |
| 85 | New_Version: d1296b4a08b9f8b943bb6c73698e51eed23f8f91 |
| 86 | </verbatim> |
| 87 | |
| 88 | We now have a working repository! The file <tt>demo.fossil</tt> |
| 89 | is the central storage, and we can share it amongst an arbitrary |
| 90 | number of trees. As a silly example: |
| 91 | |
| 92 | <verbatim> |
| 93 | $ cd ~/fossil |
| 94 | $ mkdir demo2 |
| 95 | $ cd demo2 |
| 96 | $ fossil open ../demo.fossil |
| 97 | ADD clob.c |
| 98 | ADD clob.h |
| 99 | ADD clobz.c |
| 100 | ADD mkdep.c |
| 101 | ADD test-clob.c |
| @@ -112,12 +111,12 @@ | |
| 111 | Making your repository available over the web is trivial to do. We |
| 112 | assume you have some web space where you can store your fossil file |
| 113 | and run a CGI script. If not, then this option is not for you. If |
| 114 | you do, then here's how... |
| 115 | |
| 116 | Copy the fossil repository file to your web server (it doesn't matter |
| 117 | where, really, but it "should" be unreachable by web browser traffic). |
| 118 | |
| 119 | In your <tt>cgi-bin</tt> (or equivalent) directory, create a file |
| 120 | which looks like this: |
| 121 | |
| 122 | <verbatim> |
| @@ -126,28 +125,27 @@ | |
| 125 | </verbatim> |
| 126 | |
| 127 | Make that script executable, and you're all ready to go: |
| 128 | |
| 129 | <verbatim> |
| 130 | $ chmod +x ~/www/cgi-bin/myrepo.cgi |
| 131 | </verbatim> |
| 132 | |
| 133 | Now simply point your browser to |
| 134 | <tt>https://my.domain/cgi-bin/myrepo.cgi</tt> and you should |
| 135 | be able to manage the repository from there. |
| 136 | |
| 137 | To check out a copy of your remote repository, use the |
| 138 | <em>clone</em> command: |
| 139 | |
| 140 | <verbatim> |
| 141 | $ fossil clone \ |
| 142 | https://MyAccountName:[email protected]/cgi-bin/myrepo.cgi |
| 143 | </verbatim> |
| 144 | |
| 145 | If you do not provide your password in the URL, fossil will |
| 146 | interactively prompt you for it. |
| 147 | |
| 148 | A clone is a local copy of a remote repository, and can be opened just |
| 149 | like a local one (as shown above). It is treated identically to your |
| 150 | local repository, with one very important difference. When you commit |
| 151 | changes to a cloned remote repository, they will be pushed back to the |
| 152 |