Fossil SCM

Omit the PATH= prefix on the ssh fossil syncs unless the first attempt to contact the remote fails. Change the prefix to include common directories for Fossil on Macs. Remember whether or not the PATH= prefix is needed based on hostname. See the discussion at [forum:/forumpost/4903cb4b691af7ce|forum thread 4903cb4b691af7ce].

drh 2024-02-05 22:00 trunk
Commit d07689d11d36645cfc460008704205c93dd60fd8f52a9ee2eb24e5e50cbc6a91
+44 -2
--- src/http.c
+++ src/http.c
@@ -304,10 +304,21 @@
304304
305305
if( g.zHttpCmd!=0 ){
306306
/* Handle the --transport-command option for "fossil sync" and similar */
307307
return http_exchange_external(pSend,pReply,mHttpFlags,zAltMimetype);
308308
}
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
+ }
309320
310321
if( transport_open(&g.url) ){
311322
fossil_warning("%s", transport_errmsg(&g.url));
312323
return 1;
313324
}
@@ -484,12 +495,43 @@
484495
}
485496
}
486497
}
487498
}
488499
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 && (g.url.flags & URL_REMEMBER)!=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", 1);
521
+ }else{
522
+ db_unset(z/*works-like:"x"*/, 1);
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
+ fossil_warning("server did not reply");
531
+ goto write_err;
532
+ }
491533
}
492534
if( rc!=200 ){
493535
fossil_warning("\"location:\" missing from %d redirect reply", rc);
494536
goto write_err;
495537
}
496538
--- 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,43 @@
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,43 @@
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 && (g.url.flags & URL_REMEMBER)!=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", 1);
521 }else{
522 db_unset(z/*works-like:"x"*/, 1);
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 fossil_warning("server did not reply");
531 goto write_err;
532 }
533 }
534 if( rc!=200 ){
535 fossil_warning("\"location:\" missing from %d redirect reply", rc);
536 goto write_err;
537 }
538
--- src/http_transport.c
+++ src/http_transport.c
@@ -131,15 +131,22 @@
131131
blob_append_escaped_arg(&zCmd, zHost, 0);
132132
fossil_free(zHost);
133133
}else{
134134
blob_append_escaped_arg(&zCmd, pUrlData->name, 0);
135135
}
136
- if( !is_safe_fossil_command(pUrlData->fossil) ){
136
+ if( (pUrlData->flags & URL_SSH_EXE)!=0
137
+ && !is_safe_fossil_command(pUrlData->fossil)
138
+ ){
137139
fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
138140
"the server.", pUrlData->fossil);
139141
}
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
+ }
141148
blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1);
142149
blob_append(&zCmd, " test-http", 10);
143150
if( pUrlData->path && pUrlData->path[0] ){
144151
blob_append_escaped_arg(&zCmd, pUrlData->path, 1);
145152
}else{
146153
--- 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{
146
--- 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{
153
--- src/popen.c
+++ src/popen.c
@@ -194,10 +194,11 @@
194194
close(1);
195195
fd = dup(pin[1]);
196196
if( fd!=1 ) fossil_panic("popen() failed to open file descriptor 1");
197197
close(pin[0]);
198198
close(pin[1]);
199
+ close(2); dup(1); /* Redirect stderr into the stdout pipe */
199200
if( bDirect ){
200201
execl(zCmd, zCmd, (char*)0);
201202
}else{
202203
execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
203204
}
204205
--- src/popen.c
+++ src/popen.c
@@ -194,10 +194,11 @@
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
@@ -194,10 +194,11 @@
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 close(2); dup(1); /* Redirect stderr into the stdout pipe */
200 if( bDirect ){
201 execl(zCmd, zCmd, (char*)0);
202 }else{
203 execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
204 }
205
+14 -9
--- src/url.c
+++ src/url.c
@@ -33,18 +33,21 @@
3333
3434
#if INTERFACE
3535
/*
3636
** Flags for url_parse()
3737
*/
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*/
4649
4750
/*
4851
** The URL related data used with this subsystem.
4952
*/
5053
struct UrlData {
@@ -255,15 +258,17 @@
255258
if( pUrlData->path[i] ){
256259
pUrlData->path[i] = 0;
257260
i++;
258261
}
259262
if( fossil_strcmp(zName,"fossil")==0 ){
263
+ fossil_free(pUrlData->fossil);
260264
pUrlData->fossil = fossil_strdup(zValue);
261265
dehttpize(pUrlData->fossil);
262266
fossil_free(zExe);
263267
zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil);
264268
cQuerySep = '&';
269
+ urlFlags |= URL_SSH_EXE;
265270
}
266271
}
267272
268273
dehttpize(pUrlData->path);
269274
if( pUrlData->dfltPort==pUrlData->port ){
@@ -500,11 +505,11 @@
500505
fossil_print("g.url.passwd = ************\n");
501506
}
502507
fossil_print("g.url.pwConfig = %s\n", g.url.pwConfig);
503508
fossil_print("g.url.canonical = %s\n", g.url.canonical);
504509
fossil_print("g.url.fossil = %s\n", g.url.fossil);
505
- fossil_print("g.url.flags = 0x%02x\n", g.url.flags);
510
+ fossil_print("g.url.flags = 0x%04x\n", g.url.flags);
506511
fossil_print("url_full(g.url) = %z\n", url_full(&g.url));
507512
if( g.url.isFile || g.url.isSsh ) break;
508513
if( i==0 ){
509514
fossil_print("********\n");
510515
url_enable_proxy("Using proxy: ");
511516
--- 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 {
@@ -255,15 +258,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 ){
@@ -500,11 +505,11 @@
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
--- 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 {
@@ -255,15 +258,17 @@
258 if( pUrlData->path[i] ){
259 pUrlData->path[i] = 0;
260 i++;
261 }
262 if( fossil_strcmp(zName,"fossil")==0 ){
263 fossil_free(pUrlData->fossil);
264 pUrlData->fossil = fossil_strdup(zValue);
265 dehttpize(pUrlData->fossil);
266 fossil_free(zExe);
267 zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil);
268 cQuerySep = '&';
269 urlFlags |= URL_SSH_EXE;
270 }
271 }
272
273 dehttpize(pUrlData->path);
274 if( pUrlData->dfltPort==pUrlData->port ){
@@ -500,11 +505,11 @@
505 fossil_print("g.url.passwd = ************\n");
506 }
507 fossil_print("g.url.pwConfig = %s\n", g.url.pwConfig);
508 fossil_print("g.url.canonical = %s\n", g.url.canonical);
509 fossil_print("g.url.fossil = %s\n", g.url.fossil);
510 fossil_print("g.url.flags = 0x%04x\n", g.url.flags);
511 fossil_print("url_full(g.url) = %z\n", url_full(&g.url));
512 if( g.url.isFile || g.url.isSsh ) break;
513 if( i==0 ){
514 fossil_print("********\n");
515 url_enable_proxy("Using proxy: ");
516

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button