Fossil SCM

Add the new file_skip_userhost() function that will find an skip over a "USER@HOST:" prefix on a filename, if it exists. Use this to extract the USER@HOST prefix from names in the "fossil patch push/pull" commands.

drh 2021-06-30 17:39 trunk
Commit 89a85888539021dd76093725e299199da8f7af6cb76cf243284aff710671952f
2 files changed +53 -2 +2 -3
+53 -2
--- src/file.c
+++ src/file.c
@@ -909,10 +909,49 @@
909909
}else{
910910
rc = file_rmdir(zName);
911911
}
912912
sqlite3_result_int(context, rc);
913913
}
914
+
915
+/*
916
+** Check the input argument to see if it looks like it has an prefix that
917
+** indicates a remote file. If so, return the tail of the specification,
918
+** which is the name of the file on the remote system.
919
+**
920
+** If the input argument does not have a prefix that makes it look like
921
+** a remote file reference, then return NULL.
922
+**
923
+** Remote files look like: "HOST:PATH" or "USER@HOST:PATH". Host must
924
+** be a valid hostname, meaning it must follow these rules:
925
+**
926
+** * Only characters [-.a-zA-Z0-9]. No spaces or other punctuation
927
+** * Does not begin or end with -
928
+**
929
+** The USER section, it it exists, must not contain the '@' character.
930
+*/
931
+const char *file_skip_userhost(const char *zIn){
932
+ const char *zTail;
933
+ int n, i;
934
+ if( zIn[0]==':' ) return 0;
935
+ zTail = strchr(zIn, ':');
936
+ if( zTail==0 ) return 0;
937
+ if( zTail - zIn > 10000 ) return 0;
938
+ n = (int)(zTail - zIn);
939
+ if( zIn[n-1]=='-' || zIn[n-1]=='.' ) return 0;
940
+ for(i=n-1; i>0 && zIn[i-1]!='@'; i--){
941
+ if( !fossil_isalnum(zIn[i]) && zIn[i]!='-' && zIn[i]!='.' ) return 0;
942
+ }
943
+ if( zIn[i]=='-' || zIn[i]=='.' || i==1 ) return 0;
944
+ if( i>1 ){
945
+ i -= 2;
946
+ while( i>=0 ){
947
+ if( zIn[i]=='@' ) return 0;
948
+ i--;
949
+ }
950
+ }
951
+ return zTail+1;
952
+}
914953
915954
/*
916955
** Return true if the filename given is a valid filename for
917956
** a file in a repository. Valid filenames follow all of the
918957
** following rules:
@@ -1113,17 +1152,29 @@
11131152
/*
11141153
** COMMAND: test-simplify-name
11151154
**
11161155
** Usage: %fossil test-simplify-name FILENAME...
11171156
**
1118
-** Print the simplified versions of each FILENAME.
1157
+** Print the simplified versions of each FILENAME. This is used to test
1158
+** the file_simplify_name() routine.
1159
+**
1160
+** If FILENAME is of the form "HOST:PATH" or "USER@HOST:PATH", then remove
1161
+** and print the remote host prefix first. This is used to test the
1162
+** file_skip_userhost() interface.
11191163
*/
11201164
void cmd_test_simplify_name(void){
11211165
int i;
11221166
char *z;
1167
+ const char *zTail;
11231168
for(i=2; i<g.argc; i++){
1124
- z = mprintf("%s", g.argv[i]);
1169
+ zTail = file_skip_userhost(g.argv[i]);
1170
+ if( zTail ){
1171
+ fossil_print("... ON REMOTE: %.*s\n", (int)(zTail-g.argv[i]), g.argv[i]);
1172
+ z = mprintf("%s", zTail);
1173
+ }else{
1174
+ z = mprintf("%s", g.argv[i]);
1175
+ }
11251176
fossil_print("[%s] -> ", z);
11261177
file_simplify_name(z, -1, 0);
11271178
fossil_print("[%s]\n", z);
11281179
fossil_free(z);
11291180
}
11301181
--- src/file.c
+++ src/file.c
@@ -909,10 +909,49 @@
909 }else{
910 rc = file_rmdir(zName);
911 }
912 sqlite3_result_int(context, rc);
913 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
915 /*
916 ** Return true if the filename given is a valid filename for
917 ** a file in a repository. Valid filenames follow all of the
918 ** following rules:
@@ -1113,17 +1152,29 @@
1113 /*
1114 ** COMMAND: test-simplify-name
1115 **
1116 ** Usage: %fossil test-simplify-name FILENAME...
1117 **
1118 ** Print the simplified versions of each FILENAME.
 
 
 
 
 
1119 */
1120 void cmd_test_simplify_name(void){
1121 int i;
1122 char *z;
 
1123 for(i=2; i<g.argc; i++){
1124 z = mprintf("%s", g.argv[i]);
 
 
 
 
 
 
1125 fossil_print("[%s] -> ", z);
1126 file_simplify_name(z, -1, 0);
1127 fossil_print("[%s]\n", z);
1128 fossil_free(z);
1129 }
1130
--- src/file.c
+++ src/file.c
@@ -909,10 +909,49 @@
909 }else{
910 rc = file_rmdir(zName);
911 }
912 sqlite3_result_int(context, rc);
913 }
914
915 /*
916 ** Check the input argument to see if it looks like it has an prefix that
917 ** indicates a remote file. If so, return the tail of the specification,
918 ** which is the name of the file on the remote system.
919 **
920 ** If the input argument does not have a prefix that makes it look like
921 ** a remote file reference, then return NULL.
922 **
923 ** Remote files look like: "HOST:PATH" or "USER@HOST:PATH". Host must
924 ** be a valid hostname, meaning it must follow these rules:
925 **
926 ** * Only characters [-.a-zA-Z0-9]. No spaces or other punctuation
927 ** * Does not begin or end with -
928 **
929 ** The USER section, it it exists, must not contain the '@' character.
930 */
931 const char *file_skip_userhost(const char *zIn){
932 const char *zTail;
933 int n, i;
934 if( zIn[0]==':' ) return 0;
935 zTail = strchr(zIn, ':');
936 if( zTail==0 ) return 0;
937 if( zTail - zIn > 10000 ) return 0;
938 n = (int)(zTail - zIn);
939 if( zIn[n-1]=='-' || zIn[n-1]=='.' ) return 0;
940 for(i=n-1; i>0 && zIn[i-1]!='@'; i--){
941 if( !fossil_isalnum(zIn[i]) && zIn[i]!='-' && zIn[i]!='.' ) return 0;
942 }
943 if( zIn[i]=='-' || zIn[i]=='.' || i==1 ) return 0;
944 if( i>1 ){
945 i -= 2;
946 while( i>=0 ){
947 if( zIn[i]=='@' ) return 0;
948 i--;
949 }
950 }
951 return zTail+1;
952 }
953
954 /*
955 ** Return true if the filename given is a valid filename for
956 ** a file in a repository. Valid filenames follow all of the
957 ** following rules:
@@ -1113,17 +1152,29 @@
1152 /*
1153 ** COMMAND: test-simplify-name
1154 **
1155 ** Usage: %fossil test-simplify-name FILENAME...
1156 **
1157 ** Print the simplified versions of each FILENAME. This is used to test
1158 ** the file_simplify_name() routine.
1159 **
1160 ** If FILENAME is of the form "HOST:PATH" or "USER@HOST:PATH", then remove
1161 ** and print the remote host prefix first. This is used to test the
1162 ** file_skip_userhost() interface.
1163 */
1164 void cmd_test_simplify_name(void){
1165 int i;
1166 char *z;
1167 const char *zTail;
1168 for(i=2; i<g.argc; i++){
1169 zTail = file_skip_userhost(g.argv[i]);
1170 if( zTail ){
1171 fossil_print("... ON REMOTE: %.*s\n", (int)(zTail-g.argv[i]), g.argv[i]);
1172 z = mprintf("%s", zTail);
1173 }else{
1174 z = mprintf("%s", g.argv[i]);
1175 }
1176 fossil_print("[%s] -> ", z);
1177 file_simplify_name(z, -1, 0);
1178 fossil_print("[%s]\n", z);
1179 fossil_free(z);
1180 }
1181
+2 -3
--- src/patch.c
+++ src/patch.c
@@ -669,20 +669,19 @@
669669
const char *zForce = (mFlags & PATCH_FORCE)!=0 ? " -f" : "";
670670
if( g.argc!=4 ){
671671
usage(mprintf("%s [USER@]HOST:DIRECTORY", zThisCmd));
672672
}
673673
zRemote = fossil_strdup(g.argv[3]);
674
- zDir = strchr(zRemote,':');
674
+ zDir = (char*)file_skip_userhost(zRemote);
675675
if( zDir==0 ){
676676
zDir = zRemote;
677677
blob_init(&cmd, 0, 0);
678678
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
679679
blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir);
680680
}else{
681681
Blob remote;
682
- zDir[0] = 0;
683
- zDir++;
682
+ *(char*)(zDir-1) = 0;
684683
transport_ssh_command(&cmd);
685684
blob_append_escaped_arg(&cmd, zRemote, 0);
686685
blob_init(&remote, 0, 0);
687686
blob_appendf(&remote, "fossil patch %s%s --dir64 %z -",
688687
zRemoteCmd, zForce, encode64(zDir, -1));
689688
--- src/patch.c
+++ src/patch.c
@@ -669,20 +669,19 @@
669 const char *zForce = (mFlags & PATCH_FORCE)!=0 ? " -f" : "";
670 if( g.argc!=4 ){
671 usage(mprintf("%s [USER@]HOST:DIRECTORY", zThisCmd));
672 }
673 zRemote = fossil_strdup(g.argv[3]);
674 zDir = strchr(zRemote,':');
675 if( zDir==0 ){
676 zDir = zRemote;
677 blob_init(&cmd, 0, 0);
678 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
679 blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir);
680 }else{
681 Blob remote;
682 zDir[0] = 0;
683 zDir++;
684 transport_ssh_command(&cmd);
685 blob_append_escaped_arg(&cmd, zRemote, 0);
686 blob_init(&remote, 0, 0);
687 blob_appendf(&remote, "fossil patch %s%s --dir64 %z -",
688 zRemoteCmd, zForce, encode64(zDir, -1));
689
--- src/patch.c
+++ src/patch.c
@@ -669,20 +669,19 @@
669 const char *zForce = (mFlags & PATCH_FORCE)!=0 ? " -f" : "";
670 if( g.argc!=4 ){
671 usage(mprintf("%s [USER@]HOST:DIRECTORY", zThisCmd));
672 }
673 zRemote = fossil_strdup(g.argv[3]);
674 zDir = (char*)file_skip_userhost(zRemote);
675 if( zDir==0 ){
676 zDir = zRemote;
677 blob_init(&cmd, 0, 0);
678 blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
679 blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir);
680 }else{
681 Blob remote;
682 *(char*)(zDir-1) = 0;
 
683 transport_ssh_command(&cmd);
684 blob_append_escaped_arg(&cmd, zRemote, 0);
685 blob_init(&remote, 0, 0);
686 blob_appendf(&remote, "fossil patch %s%s --dir64 %z -",
687 zRemoteCmd, zForce, encode64(zDir, -1));
688

Keyboard Shortcuts

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