Fossil SCM

Enhance patchfiles to deal with renames.

drh 2021-06-21 21:20 patch-cmd
Commit 4d82a8d1d01e8ccba42e9940398201fb1a159912952b1b656a6f7d3aa7e9b12f
1 file changed +142 -19
+142 -19
--- src/patch.c
+++ src/patch.c
@@ -39,10 +39,72 @@
3939
sz = blob_read_from_file(&x, zName, RepoFILE);
4040
sqlite3_result_blob64(context, x.aData, sz, SQLITE_TRANSIENT);
4141
blob_reset(&x);
4242
}
4343
44
+/*
45
+** mkdelta(X,Y)
46
+**
47
+** X is an numeric artifact id. Y is a filename.
48
+**
49
+** Compute a compressed delta that carries X into Y. Or return NULL
50
+** if X is equal to Y.
51
+*/
52
+static void mkdeltaFunc(
53
+ sqlite3_context *context,
54
+ int argc,
55
+ sqlite3_value **argv
56
+){
57
+ const char *zFile;
58
+ Blob x, y;
59
+ int rid;
60
+ char *aOut;
61
+ int nOut;
62
+ sqlite3_int64 sz;
63
+
64
+ rid = sqlite3_value_int(argv[0]);
65
+ if( !content_get(rid, &x) ){
66
+ sqlite3_result_error(context, "mkdelta(X,Y): no content for X", -1);
67
+ return;
68
+ }
69
+ zFile = (const char*)sqlite3_value_text(argv[1]);
70
+ if( zFile==0 ){
71
+ sqlite3_result_error(context, "mkdelta(X,Y): NULL Y argument", -1);
72
+ blob_reset(&x);
73
+ return;
74
+ }
75
+ sz = blob_read_from_file(&y, zFile, RepoFILE);
76
+ if( sz<0 ){
77
+ sqlite3_result_error(context, "mkdelta(X,Y): cannot read file Y", -1);
78
+ blob_reset(&x);
79
+ return;
80
+ }
81
+ aOut = sqlite3_malloc64(sz+70);
82
+ if( aOut==0 ){
83
+ sqlite3_result_error_nomem(context);
84
+ blob_reset(&y);
85
+ blob_reset(&x);
86
+ return;
87
+ }
88
+ if( blob_size(&x)==blob_size(&y)
89
+ && memcmp(blob_buffer(&x), blob_buffer(&y), blob_size(&x))==0
90
+ ){
91
+ blob_reset(&y);
92
+ blob_reset(&x);
93
+ return;
94
+ }
95
+ nOut = delta_create(blob_buffer(&x),blob_size(&x),
96
+ blob_buffer(&y),blob_size(&y), aOut);
97
+ blob_reset(&x);
98
+ blob_reset(&y);
99
+ blob_init(&x, aOut, nOut);
100
+ blob_compress(&x, &x);
101
+ sqlite3_result_blob64(context, blob_buffer(&x), blob_size(&x),
102
+ SQLITE_TRANSIENT);
103
+ blob_reset(&x);
104
+}
105
+
44106
45107
/*
46108
** Generate a binary patch file and store it into the file
47109
** named zOut.
48110
*/
@@ -53,20 +115,23 @@
53115
}
54116
add_content_sql_commands(g.db);
55117
deltafunc_init(g.db);
56118
sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0,
57119
readfileFunc, 0, 0);
120
+ sqlite3_create_function(g.db, "mkdelta", 2, SQLITE_UTF8, 0,
121
+ mkdeltaFunc, 0, 0);
58122
db_multi_exec("ATTACH %Q AS patch;", zOut);
59123
db_multi_exec(
60124
"PRAGMA patch.journal_mode=OFF;\n"
61125
"PRAGMA patch.page_size=512;\n"
62126
"CREATE TABLE patch.chng(\n"
63
- " fname TEXT,\n" /* Filename */
64
- " hash TEXT,\n" /* Baseline hash. NULL for new files. */
65
- " isexe BOOL,\n" /* True if executable */
66
- " islink BOOL,\n" /* True if is a symbolic link */
67
- " delta BLOB\n" /* Delta. NULL if file deleted */
127
+ " pathname TEXT,\n" /* Filename */
128
+ " origname TEXT,\n" /* Name before rename. NULL if not renamed */
129
+ " hash TEXT,\n" /* Baseline hash. NULL for new files. */
130
+ " isexe BOOL,\n" /* True if executable */
131
+ " islink BOOL,\n" /* True if is a symbolic link */
132
+ " delta BLOB\n" /* Delta. NULL if file deleted or unchanged */
68133
");"
69134
"CREATE TABLE patch.cfg(\n"
70135
" key TEXT,\n"
71136
" value ANY\n"
72137
");"
@@ -80,30 +145,30 @@
80145
db_multi_exec("INSERT INTO patch.cfg(key,value)VALUES('merged',1);");
81146
}
82147
83148
/* New files */
84149
db_multi_exec(
85
- "INSERT INTO patch.chng(fname,hash,isexe,islink,delta)"
150
+ "INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)"
86151
" SELECT pathname, NULL, isexe, islink,"
87152
" compress(read_co_file(%Q||pathname))"
88153
" FROM vfile WHERE rid==0;",
89154
g.zLocalRoot
90155
);
91156
/* Deleted files */
92157
db_multi_exec(
93
- "INSERT INTO patch.chng(fname,hash,isexe,islink,delta)"
158
+ "INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)"
94159
" SELECT pathname, NULL, 0, 0, NULL"
95160
" FROM vfile WHERE deleted;"
96161
);
97162
/* Changed files */
98163
db_multi_exec(
99
- "INSERT INTO patch.chng(fname,hash,isexe,islink,delta)"
100
- " SELECT pathname, blob.uuid, isexe, islink,"
101
- " compress(delta_create(content(blob.uuid),"
102
- "read_co_file(%Q||pathname)))"
164
+ "INSERT INTO patch.chng(pathname,origname,hash,isexe,islink,delta)"
165
+ " SELECT pathname, origname, blob.uuid, isexe, islink,"
166
+ " mkdelta(blob.rid, %Q||pathname)"
103167
" FROM vfile, blob"
104
- " WHERE blob.rid=vfile.rid AND NOT deleted AND chnged;",
168
+ " WHERE blob.rid=vfile.rid"
169
+ " AND NOT deleted AND (chnged OR origname<>pathname);",
105170
g.zLocalRoot
106171
);
107172
}
108173
109174
/*
@@ -110,11 +175,11 @@
110175
** Attempt to load and validate a patchfile identified by the first
111176
** argument.
112177
*/
113178
void patch_attach(const char *zIn){
114179
Stmt q;
115
- if( !file_isfile(zIn, zIn) ){
180
+ if( !file_isfile(zIn, ExtFILE) ){
116181
fossil_fatal("no such file: %s", zIn);
117182
}
118183
if( g.db==0 ){
119184
sqlite3_open(":memory:", &g.db);
120185
}
@@ -138,22 +203,66 @@
138203
fossil_print("Patch against check-in %S\n", db_column_text(&q,0));
139204
}else{
140205
fossil_fatal("ERROR: Missing patch baseline");
141206
}
142207
db_finalize(&q);
143
- db_prepare(&q, "SELECT fname, hash IS NULL AS isnew, delta IS NULL AS isdel"
144
- " FROM patch.chng ORDER BY 1");
208
+ db_prepare(&q,
209
+ "SELECT pathname,"
210
+ " hash IS NULL AND delta IS NOT NULL,"
211
+ " delta IS NULL,"
212
+ " origname"
213
+ " FROM patch.chng ORDER BY 1");
145214
while( db_step(&q)==SQLITE_ROW ){
146215
const char *zClass = "CHANGED";
147
- if( db_column_int(&q, 1) ){
216
+ const char *zName = db_column_text(&q,0);
217
+ const char *zOrigName = db_column_text(&q, 3);
218
+ if( db_column_int(&q, 1) && zOrigName==0 ){
148219
zClass = "NEW";
149220
}else if( db_column_int(&q, 2) ){
150
- zClass = "DELETED";
221
+ zClass = zOrigName==0 ? "DELETED" : 0;
222
+ }
223
+ if( zOrigName!=0 && zOrigName[0]!=0 ){
224
+ fossil_print("%-10s %s -> %s\n", "RENAME",zOrigName,zName);
225
+ }
226
+ if( zClass ){
227
+ fossil_print("%-10s %s\n", zClass, zName);
151228
}
152
- fossil_print("%-10s %s\n", zClass, db_column_text(&q,0));
229
+ }
230
+ db_finalize(&q);
231
+}
232
+
233
+/*
234
+** Apply the patch currently attached as database "patch".
235
+**
236
+** First update the check-out to be at "baseline". Then loop through
237
+** and update all files.
238
+*/
239
+void patch_apply(void){
240
+ Stmt q;
241
+ Blob cmd;
242
+ blob_init(&cmd, 0, 0);
243
+ db_prepare(&q,
244
+ "SELECT patch.cfg.value"
245
+ " FROM patch.cfg, localdb.vvar"
246
+ " WHERE patch.cfg.key='baseline'"
247
+ " AND localdb.vvar.name='checkout-hash'"
248
+ " AND patch.cfg.key<>localdb.vvar.name"
249
+ );
250
+ if( db_step(&q)==SQLITE_ROW ){
251
+ blob_append_escaped_arg(&cmd, g.nameOfExe);
252
+ blob_appendf(&cmd, " update %s", db_column_text(&q, 0));
153253
}
154254
db_finalize(&q);
255
+ if( blob_size(&cmd)>0 ){
256
+ int rc = fossil_system(blob_str(&cmd));
257
+ if( rc ){
258
+ fossil_fatal("unable to update to the baseline check-out: %s",
259
+ blob_str(&cmd));
260
+ }
261
+ }
262
+ blob_reset(&cmd);
263
+
155264
}
156265
157266
158267
/*
159268
** COMMAND: patch
@@ -170,11 +279,14 @@
170279
** Create a new binary patch in FILENAME that captures all uncommitted
171280
** changes in the current check-out.
172281
**
173282
** > fossil patch apply FILENAME
174283
**
175
-** Apply the changes in FILENAME to the current check-out.
284
+** Apply the changes in FILENAME to the current check-out. Options:
285
+**
286
+** -f|--force Apply the patch even though there are unsaved
287
+** changes in the current check-out.
176288
**
177289
** > fossil patch diff [DIFF-FLAGS] FILENAME
178290
**
179291
** View the changes specified by the binary patch FILENAME in a
180292
** human-readable format. The usual diff flags apply.
@@ -186,10 +298,15 @@
186298
**
187299
** > fossil patch pull REMOTE-CHECKOUT
188300
**
189301
** Create a patch on a remote check-out, transfer that patch to the
190302
** local machine (using ssh) and apply the patch in the local checkout.
303
+**
304
+** > fossil patch view FILENAME
305
+**
306
+** View a summary of the the changes in the binary patch FILENAME.
307
+**
191308
*/
192309
void patch_cmd(void){
193310
const char *zCmd;
194311
size_t n;
195312
if( g.argc<3 ){
@@ -197,15 +314,21 @@
197314
usage("apply|create|pull|push|view");
198315
}
199316
zCmd = g.argv[2];
200317
n = strlen(zCmd);
201318
if( strncmp(zCmd, "apply", n)==0 ){
319
+ int forceFlag = find_option("force","f",0)!=0;
202320
db_must_be_within_tree();
203321
verify_all_options();
204322
if( g.argc!=4 ){
205323
usage("apply FILENAME");
206324
}
325
+ if( !forceFlag && unsaved_changes(0) ){
326
+ fossil_fatal("there are unsaved changes in the current checkout");
327
+ }
328
+ patch_attach(g.argv[3]);
329
+ patch_apply();
207330
}else
208331
if( strncmp(zCmd, "create", n)==0 ){
209332
db_must_be_within_tree();
210333
verify_all_options();
211334
if( g.argc!=4 ){
212335
--- src/patch.c
+++ src/patch.c
@@ -39,10 +39,72 @@
39 sz = blob_read_from_file(&x, zName, RepoFILE);
40 sqlite3_result_blob64(context, x.aData, sz, SQLITE_TRANSIENT);
41 blob_reset(&x);
42 }
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
45 /*
46 ** Generate a binary patch file and store it into the file
47 ** named zOut.
48 */
@@ -53,20 +115,23 @@
53 }
54 add_content_sql_commands(g.db);
55 deltafunc_init(g.db);
56 sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0,
57 readfileFunc, 0, 0);
 
 
58 db_multi_exec("ATTACH %Q AS patch;", zOut);
59 db_multi_exec(
60 "PRAGMA patch.journal_mode=OFF;\n"
61 "PRAGMA patch.page_size=512;\n"
62 "CREATE TABLE patch.chng(\n"
63 " fname TEXT,\n" /* Filename */
64 " hash TEXT,\n" /* Baseline hash. NULL for new files. */
65 " isexe BOOL,\n" /* True if executable */
66 " islink BOOL,\n" /* True if is a symbolic link */
67 " delta BLOB\n" /* Delta. NULL if file deleted */
 
68 ");"
69 "CREATE TABLE patch.cfg(\n"
70 " key TEXT,\n"
71 " value ANY\n"
72 ");"
@@ -80,30 +145,30 @@
80 db_multi_exec("INSERT INTO patch.cfg(key,value)VALUES('merged',1);");
81 }
82
83 /* New files */
84 db_multi_exec(
85 "INSERT INTO patch.chng(fname,hash,isexe,islink,delta)"
86 " SELECT pathname, NULL, isexe, islink,"
87 " compress(read_co_file(%Q||pathname))"
88 " FROM vfile WHERE rid==0;",
89 g.zLocalRoot
90 );
91 /* Deleted files */
92 db_multi_exec(
93 "INSERT INTO patch.chng(fname,hash,isexe,islink,delta)"
94 " SELECT pathname, NULL, 0, 0, NULL"
95 " FROM vfile WHERE deleted;"
96 );
97 /* Changed files */
98 db_multi_exec(
99 "INSERT INTO patch.chng(fname,hash,isexe,islink,delta)"
100 " SELECT pathname, blob.uuid, isexe, islink,"
101 " compress(delta_create(content(blob.uuid),"
102 "read_co_file(%Q||pathname)))"
103 " FROM vfile, blob"
104 " WHERE blob.rid=vfile.rid AND NOT deleted AND chnged;",
 
105 g.zLocalRoot
106 );
107 }
108
109 /*
@@ -110,11 +175,11 @@
110 ** Attempt to load and validate a patchfile identified by the first
111 ** argument.
112 */
113 void patch_attach(const char *zIn){
114 Stmt q;
115 if( !file_isfile(zIn, zIn) ){
116 fossil_fatal("no such file: %s", zIn);
117 }
118 if( g.db==0 ){
119 sqlite3_open(":memory:", &g.db);
120 }
@@ -138,22 +203,66 @@
138 fossil_print("Patch against check-in %S\n", db_column_text(&q,0));
139 }else{
140 fossil_fatal("ERROR: Missing patch baseline");
141 }
142 db_finalize(&q);
143 db_prepare(&q, "SELECT fname, hash IS NULL AS isnew, delta IS NULL AS isdel"
144 " FROM patch.chng ORDER BY 1");
 
 
 
 
145 while( db_step(&q)==SQLITE_ROW ){
146 const char *zClass = "CHANGED";
147 if( db_column_int(&q, 1) ){
 
 
148 zClass = "NEW";
149 }else if( db_column_int(&q, 2) ){
150 zClass = "DELETED";
 
 
 
 
 
 
151 }
152 fossil_print("%-10s %s\n", zClass, db_column_text(&q,0));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153 }
154 db_finalize(&q);
 
 
 
 
 
 
 
 
 
155 }
156
157
158 /*
159 ** COMMAND: patch
@@ -170,11 +279,14 @@
170 ** Create a new binary patch in FILENAME that captures all uncommitted
171 ** changes in the current check-out.
172 **
173 ** > fossil patch apply FILENAME
174 **
175 ** Apply the changes in FILENAME to the current check-out.
 
 
 
176 **
177 ** > fossil patch diff [DIFF-FLAGS] FILENAME
178 **
179 ** View the changes specified by the binary patch FILENAME in a
180 ** human-readable format. The usual diff flags apply.
@@ -186,10 +298,15 @@
186 **
187 ** > fossil patch pull REMOTE-CHECKOUT
188 **
189 ** Create a patch on a remote check-out, transfer that patch to the
190 ** local machine (using ssh) and apply the patch in the local checkout.
 
 
 
 
 
191 */
192 void patch_cmd(void){
193 const char *zCmd;
194 size_t n;
195 if( g.argc<3 ){
@@ -197,15 +314,21 @@
197 usage("apply|create|pull|push|view");
198 }
199 zCmd = g.argv[2];
200 n = strlen(zCmd);
201 if( strncmp(zCmd, "apply", n)==0 ){
 
202 db_must_be_within_tree();
203 verify_all_options();
204 if( g.argc!=4 ){
205 usage("apply FILENAME");
206 }
 
 
 
 
 
207 }else
208 if( strncmp(zCmd, "create", n)==0 ){
209 db_must_be_within_tree();
210 verify_all_options();
211 if( g.argc!=4 ){
212
--- src/patch.c
+++ src/patch.c
@@ -39,10 +39,72 @@
39 sz = blob_read_from_file(&x, zName, RepoFILE);
40 sqlite3_result_blob64(context, x.aData, sz, SQLITE_TRANSIENT);
41 blob_reset(&x);
42 }
43
44 /*
45 ** mkdelta(X,Y)
46 **
47 ** X is an numeric artifact id. Y is a filename.
48 **
49 ** Compute a compressed delta that carries X into Y. Or return NULL
50 ** if X is equal to Y.
51 */
52 static void mkdeltaFunc(
53 sqlite3_context *context,
54 int argc,
55 sqlite3_value **argv
56 ){
57 const char *zFile;
58 Blob x, y;
59 int rid;
60 char *aOut;
61 int nOut;
62 sqlite3_int64 sz;
63
64 rid = sqlite3_value_int(argv[0]);
65 if( !content_get(rid, &x) ){
66 sqlite3_result_error(context, "mkdelta(X,Y): no content for X", -1);
67 return;
68 }
69 zFile = (const char*)sqlite3_value_text(argv[1]);
70 if( zFile==0 ){
71 sqlite3_result_error(context, "mkdelta(X,Y): NULL Y argument", -1);
72 blob_reset(&x);
73 return;
74 }
75 sz = blob_read_from_file(&y, zFile, RepoFILE);
76 if( sz<0 ){
77 sqlite3_result_error(context, "mkdelta(X,Y): cannot read file Y", -1);
78 blob_reset(&x);
79 return;
80 }
81 aOut = sqlite3_malloc64(sz+70);
82 if( aOut==0 ){
83 sqlite3_result_error_nomem(context);
84 blob_reset(&y);
85 blob_reset(&x);
86 return;
87 }
88 if( blob_size(&x)==blob_size(&y)
89 && memcmp(blob_buffer(&x), blob_buffer(&y), blob_size(&x))==0
90 ){
91 blob_reset(&y);
92 blob_reset(&x);
93 return;
94 }
95 nOut = delta_create(blob_buffer(&x),blob_size(&x),
96 blob_buffer(&y),blob_size(&y), aOut);
97 blob_reset(&x);
98 blob_reset(&y);
99 blob_init(&x, aOut, nOut);
100 blob_compress(&x, &x);
101 sqlite3_result_blob64(context, blob_buffer(&x), blob_size(&x),
102 SQLITE_TRANSIENT);
103 blob_reset(&x);
104 }
105
106
107 /*
108 ** Generate a binary patch file and store it into the file
109 ** named zOut.
110 */
@@ -53,20 +115,23 @@
115 }
116 add_content_sql_commands(g.db);
117 deltafunc_init(g.db);
118 sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0,
119 readfileFunc, 0, 0);
120 sqlite3_create_function(g.db, "mkdelta", 2, SQLITE_UTF8, 0,
121 mkdeltaFunc, 0, 0);
122 db_multi_exec("ATTACH %Q AS patch;", zOut);
123 db_multi_exec(
124 "PRAGMA patch.journal_mode=OFF;\n"
125 "PRAGMA patch.page_size=512;\n"
126 "CREATE TABLE patch.chng(\n"
127 " pathname TEXT,\n" /* Filename */
128 " origname TEXT,\n" /* Name before rename. NULL if not renamed */
129 " hash TEXT,\n" /* Baseline hash. NULL for new files. */
130 " isexe BOOL,\n" /* True if executable */
131 " islink BOOL,\n" /* True if is a symbolic link */
132 " delta BLOB\n" /* Delta. NULL if file deleted or unchanged */
133 ");"
134 "CREATE TABLE patch.cfg(\n"
135 " key TEXT,\n"
136 " value ANY\n"
137 ");"
@@ -80,30 +145,30 @@
145 db_multi_exec("INSERT INTO patch.cfg(key,value)VALUES('merged',1);");
146 }
147
148 /* New files */
149 db_multi_exec(
150 "INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)"
151 " SELECT pathname, NULL, isexe, islink,"
152 " compress(read_co_file(%Q||pathname))"
153 " FROM vfile WHERE rid==0;",
154 g.zLocalRoot
155 );
156 /* Deleted files */
157 db_multi_exec(
158 "INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)"
159 " SELECT pathname, NULL, 0, 0, NULL"
160 " FROM vfile WHERE deleted;"
161 );
162 /* Changed files */
163 db_multi_exec(
164 "INSERT INTO patch.chng(pathname,origname,hash,isexe,islink,delta)"
165 " SELECT pathname, origname, blob.uuid, isexe, islink,"
166 " mkdelta(blob.rid, %Q||pathname)"
 
167 " FROM vfile, blob"
168 " WHERE blob.rid=vfile.rid"
169 " AND NOT deleted AND (chnged OR origname<>pathname);",
170 g.zLocalRoot
171 );
172 }
173
174 /*
@@ -110,11 +175,11 @@
175 ** Attempt to load and validate a patchfile identified by the first
176 ** argument.
177 */
178 void patch_attach(const char *zIn){
179 Stmt q;
180 if( !file_isfile(zIn, ExtFILE) ){
181 fossil_fatal("no such file: %s", zIn);
182 }
183 if( g.db==0 ){
184 sqlite3_open(":memory:", &g.db);
185 }
@@ -138,22 +203,66 @@
203 fossil_print("Patch against check-in %S\n", db_column_text(&q,0));
204 }else{
205 fossil_fatal("ERROR: Missing patch baseline");
206 }
207 db_finalize(&q);
208 db_prepare(&q,
209 "SELECT pathname,"
210 " hash IS NULL AND delta IS NOT NULL,"
211 " delta IS NULL,"
212 " origname"
213 " FROM patch.chng ORDER BY 1");
214 while( db_step(&q)==SQLITE_ROW ){
215 const char *zClass = "CHANGED";
216 const char *zName = db_column_text(&q,0);
217 const char *zOrigName = db_column_text(&q, 3);
218 if( db_column_int(&q, 1) && zOrigName==0 ){
219 zClass = "NEW";
220 }else if( db_column_int(&q, 2) ){
221 zClass = zOrigName==0 ? "DELETED" : 0;
222 }
223 if( zOrigName!=0 && zOrigName[0]!=0 ){
224 fossil_print("%-10s %s -> %s\n", "RENAME",zOrigName,zName);
225 }
226 if( zClass ){
227 fossil_print("%-10s %s\n", zClass, zName);
228 }
229 }
230 db_finalize(&q);
231 }
232
233 /*
234 ** Apply the patch currently attached as database "patch".
235 **
236 ** First update the check-out to be at "baseline". Then loop through
237 ** and update all files.
238 */
239 void patch_apply(void){
240 Stmt q;
241 Blob cmd;
242 blob_init(&cmd, 0, 0);
243 db_prepare(&q,
244 "SELECT patch.cfg.value"
245 " FROM patch.cfg, localdb.vvar"
246 " WHERE patch.cfg.key='baseline'"
247 " AND localdb.vvar.name='checkout-hash'"
248 " AND patch.cfg.key<>localdb.vvar.name"
249 );
250 if( db_step(&q)==SQLITE_ROW ){
251 blob_append_escaped_arg(&cmd, g.nameOfExe);
252 blob_appendf(&cmd, " update %s", db_column_text(&q, 0));
253 }
254 db_finalize(&q);
255 if( blob_size(&cmd)>0 ){
256 int rc = fossil_system(blob_str(&cmd));
257 if( rc ){
258 fossil_fatal("unable to update to the baseline check-out: %s",
259 blob_str(&cmd));
260 }
261 }
262 blob_reset(&cmd);
263
264 }
265
266
267 /*
268 ** COMMAND: patch
@@ -170,11 +279,14 @@
279 ** Create a new binary patch in FILENAME that captures all uncommitted
280 ** changes in the current check-out.
281 **
282 ** > fossil patch apply FILENAME
283 **
284 ** Apply the changes in FILENAME to the current check-out. Options:
285 **
286 ** -f|--force Apply the patch even though there are unsaved
287 ** changes in the current check-out.
288 **
289 ** > fossil patch diff [DIFF-FLAGS] FILENAME
290 **
291 ** View the changes specified by the binary patch FILENAME in a
292 ** human-readable format. The usual diff flags apply.
@@ -186,10 +298,15 @@
298 **
299 ** > fossil patch pull REMOTE-CHECKOUT
300 **
301 ** Create a patch on a remote check-out, transfer that patch to the
302 ** local machine (using ssh) and apply the patch in the local checkout.
303 **
304 ** > fossil patch view FILENAME
305 **
306 ** View a summary of the the changes in the binary patch FILENAME.
307 **
308 */
309 void patch_cmd(void){
310 const char *zCmd;
311 size_t n;
312 if( g.argc<3 ){
@@ -197,15 +314,21 @@
314 usage("apply|create|pull|push|view");
315 }
316 zCmd = g.argv[2];
317 n = strlen(zCmd);
318 if( strncmp(zCmd, "apply", n)==0 ){
319 int forceFlag = find_option("force","f",0)!=0;
320 db_must_be_within_tree();
321 verify_all_options();
322 if( g.argc!=4 ){
323 usage("apply FILENAME");
324 }
325 if( !forceFlag && unsaved_changes(0) ){
326 fossil_fatal("there are unsaved changes in the current checkout");
327 }
328 patch_attach(g.argv[3]);
329 patch_apply();
330 }else
331 if( strncmp(zCmd, "create", n)==0 ){
332 db_must_be_within_tree();
333 verify_all_options();
334 if( g.argc!=4 ){
335

Keyboard Shortcuts

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