Fossil SCM

Simplifications to the merge and update logic. Fix update so that it correctly carries file edits across name changes.

drh 2010-12-14 15:44 trunk
Commit fd8698c8e0e2e57478cd25190900fb4d6ea9e9ab
2 files changed +6 -10 +99 -43
+6 -10
--- src/merge.c
+++ src/merge.c
@@ -153,11 +153,11 @@
153153
154154
/* Add files found in V
155155
*/
156156
db_multi_exec(
157157
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
158
- " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
158
+ " SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, chnged "
159159
" FROM vfile WHERE vid=%d",
160160
vid
161161
);
162162
163163
/*
@@ -177,11 +177,11 @@
177177
}
178178
fossil_free(aChng);
179179
db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
180180
}
181181
182
- /* Add files found in P
182
+ /* Add files found in P but not in V
183183
*/
184184
db_multi_exec(
185185
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
186186
" SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
187187
" FROM vfile"
@@ -203,11 +203,11 @@
203203
);
204204
}
205205
fossil_free(aChng);
206206
}
207207
208
- /* Add files found in M
208
+ /* Add files found in M but not in P or V.
209209
*/
210210
db_multi_exec(
211211
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
212212
" SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
213213
" FROM vfile"
@@ -215,23 +215,19 @@
215215
" AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)",
216216
mid
217217
);
218218
219219
/*
220
- ** Compute the file version ids for V, P, and M.
220
+ ** Compute the file version ids for P and M.
221221
*/
222222
db_multi_exec(
223223
"UPDATE fv SET"
224224
" idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
225225
" ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
226226
" idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
227
- " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0),"
228
- " idv=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fn),0),"
229
- " ridv=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fn),0),"
230
- " chnged=coalesce((SELECT chnged FROM vfile"
231
- " WHERE vid=%d AND pathname=fn),0)",
232
- pid, pid, mid, mid, vid, vid, vid
227
+ " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0)",
228
+ pid, pid, mid, mid
233229
);
234230
235231
if( debugFlag ){
236232
db_prepare(&q,
237233
"SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm FROM fv"
238234
--- src/merge.c
+++ src/merge.c
@@ -153,11 +153,11 @@
153
154 /* Add files found in V
155 */
156 db_multi_exec(
157 "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
158 " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
159 " FROM vfile WHERE vid=%d",
160 vid
161 );
162
163 /*
@@ -177,11 +177,11 @@
177 }
178 fossil_free(aChng);
179 db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
180 }
181
182 /* Add files found in P
183 */
184 db_multi_exec(
185 "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
186 " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
187 " FROM vfile"
@@ -203,11 +203,11 @@
203 );
204 }
205 fossil_free(aChng);
206 }
207
208 /* Add files found in M
209 */
210 db_multi_exec(
211 "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
212 " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
213 " FROM vfile"
@@ -215,23 +215,19 @@
215 " AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)",
216 mid
217 );
218
219 /*
220 ** Compute the file version ids for V, P, and M.
221 */
222 db_multi_exec(
223 "UPDATE fv SET"
224 " idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
225 " ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
226 " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
227 " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0),"
228 " idv=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fn),0),"
229 " ridv=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fn),0),"
230 " chnged=coalesce((SELECT chnged FROM vfile"
231 " WHERE vid=%d AND pathname=fn),0)",
232 pid, pid, mid, mid, vid, vid, vid
233 );
234
235 if( debugFlag ){
236 db_prepare(&q,
237 "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm FROM fv"
238
--- src/merge.c
+++ src/merge.c
@@ -153,11 +153,11 @@
153
154 /* Add files found in V
155 */
156 db_multi_exec(
157 "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
158 " SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, chnged "
159 " FROM vfile WHERE vid=%d",
160 vid
161 );
162
163 /*
@@ -177,11 +177,11 @@
177 }
178 fossil_free(aChng);
179 db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
180 }
181
182 /* Add files found in P but not in V
183 */
184 db_multi_exec(
185 "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
186 " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
187 " FROM vfile"
@@ -203,11 +203,11 @@
203 );
204 }
205 fossil_free(aChng);
206 }
207
208 /* Add files found in M but not in P or V.
209 */
210 db_multi_exec(
211 "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
212 " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
213 " FROM vfile"
@@ -215,23 +215,19 @@
215 " AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)",
216 mid
217 );
218
219 /*
220 ** Compute the file version ids for P and M.
221 */
222 db_multi_exec(
223 "UPDATE fv SET"
224 " idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
225 " ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
226 " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
227 " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0)",
228 pid, pid, mid, mid
 
 
 
 
229 );
230
231 if( debugFlag ){
232 db_prepare(&q,
233 "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm FROM fv"
234
+99 -43
--- src/update.c
+++ src/update.c
@@ -61,15 +61,20 @@
6161
int tid=0; /* Target version - version we are changing to */
6262
Stmt q;
6363
int latestFlag; /* --latest. Pick the latest version if true */
6464
int nochangeFlag; /* -n or --nochange. Do a dry run */
6565
int verboseFlag; /* -v or --verbose. Output extra information */
66
+ int debugFlag; /* --debug option */
67
+ int nChng; /* Number of file renames */
68
+ int *aChng; /* Array of file renames */
69
+ int i; /* Loop counter */
6670
6771
url_proxy_options();
6872
latestFlag = find_option("latest",0, 0)!=0;
6973
nochangeFlag = find_option("nochange","n",0)!=0;
7074
verboseFlag = find_option("verbose","v",0)!=0;
75
+ debugFlag = find_option("debug",0,0)!=0;
7176
db_must_be_within_tree();
7277
vid = db_lget_int("checkout", 0);
7378
if( vid==0 ){
7479
fossil_fatal("cannot find current version");
7580
}
@@ -95,10 +100,16 @@
95100
fossil_fatal("no such version: %s", g.argv[2]);
96101
}
97102
}
98103
}
99104
105
+ /* If no VERSION is specified on the command-line, then look for a
106
+ ** descendent of the current version. If there are multiple descendents,
107
+ ** look for one from the same branch as the current version. If there
108
+ ** are still multiple descendents, show them all and refuse to update
109
+ ** until the user selects one.
110
+ */
100111
if( tid==0 ){
101112
int closeCode = 1;
102113
compute_leaves(vid, closeCode);
103114
if( !db_exists("SELECT 1 FROM leaves") ){
104115
closeCode = 0;
@@ -148,44 +159,75 @@
148159
" fn TEXT PRIMARY KEY," /* The filename relative to root */
149160
" idv INTEGER," /* VFILE entry for current version */
150161
" idt INTEGER," /* VFILE entry for target version */
151162
" chnged BOOLEAN," /* True if current version has been edited */
152163
" ridv INTEGER," /* Record ID for current version */
153
- " ridt INTEGER " /* Record ID for target */
164
+ " ridt INTEGER," /* Record ID for target */
165
+ " fnt TEXT" /* Filename of same file on target version */
154166
");"
155
- "INSERT OR IGNORE INTO fv"
156
- " SELECT pathname, 0, 0, 0, 0, 0 FROM vfile"
157
- );
158
- db_prepare(&q,
159
- "SELECT id, pathname, rid FROM vfile"
160
- " WHERE vid=%d", tid
161
- );
162
- while( db_step(&q)==SQLITE_ROW ){
163
- int id = db_column_int(&q, 0);
164
- const char *fn = db_column_text(&q, 1);
165
- int rid = db_column_int(&q, 2);
166
- db_multi_exec(
167
- "UPDATE fv SET idt=%d, ridt=%d WHERE fn=%Q",
168
- id, rid, fn
169
- );
170
- }
171
- db_finalize(&q);
172
- db_prepare(&q,
173
- "SELECT id, pathname, rid, chnged FROM vfile"
174
- " WHERE vid=%d", vid
175
- );
176
- while( db_step(&q)==SQLITE_ROW ){
177
- int id = db_column_int(&q, 0);
178
- const char *fn = db_column_text(&q, 1);
179
- int rid = db_column_int(&q, 2);
180
- int chnged = db_column_int(&q, 3);
181
- db_multi_exec(
182
- "UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q",
183
- id, rid, chnged, fn
184
- );
185
- }
186
- db_finalize(&q);
167
+ );
168
+
169
+ /* Add files found in the current version
170
+ */
171
+ db_multi_exec(
172
+ "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)"
173
+ " SELECT pathname, pathname, id, 0, rid, 0, chnged FROM vfile WHERE vid=%d",
174
+ vid
175
+ );
176
+
177
+ /* Compute file name changes on V->T. Record name changes in files that
178
+ ** have changed locally.
179
+ */
180
+ find_filename_changes(vid, tid, &nChng, &aChng);
181
+ if( nChng ){
182
+ for(i=0; i<nChng; i++){
183
+ db_multi_exec(
184
+ "UPDATE fv"
185
+ " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
186
+ " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
187
+ aChng[i*2+1], aChng[i*2]
188
+ );
189
+ }
190
+ fossil_free(aChng);
191
+ }
192
+
193
+ /* Add files found in the target version T but missing from the current
194
+ ** version V.
195
+ */
196
+ db_multi_exec(
197
+ "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)"
198
+ " SELECT pathname, pathname, 0, 0, 0, 0, 0 FROM vfile"
199
+ " WHERE vid=%d"
200
+ " AND pathname NOT IN (SELECT fnt FROM fv)",
201
+ tid
202
+ );
203
+
204
+ /*
205
+ ** Compute the file version ids for T
206
+ */
207
+ db_multi_exec(
208
+ "UPDATE fv SET"
209
+ " idt=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnt),0),"
210
+ " ridt=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnt),0)",
211
+ tid, tid
212
+ );
213
+
214
+ if( debugFlag ){
215
+ db_prepare(&q,
216
+ "SELECT rowid, fn, fnt, chnged, ridv, ridt FROM fv"
217
+ );
218
+ while( db_step(&q)==SQLITE_ROW ){
219
+ printf("%3d: ridv=%-4d ridt=%-4d chnged=%d\n",
220
+ db_column_int(&q, 0),
221
+ db_column_int(&q, 4),
222
+ db_column_int(&q, 5),
223
+ db_column_int(&q, 3));
224
+ printf(" fnv = [%s]\n", db_column_text(&q, 1));
225
+ printf(" fnt = [%s]\n", db_column_text(&q, 2));
226
+ }
227
+ db_finalize(&q);
228
+ }
187229
188230
/* If FILES appear on the command-line, remove from the "fv" table
189231
** every entry that is not named on the command-line or which is not
190232
** in a directory named on the command-line.
191233
*/
@@ -215,12 +257,16 @@
215257
}
216258
db_multi_exec(blob_str(&sql));
217259
blob_reset(&sql);
218260
}
219261
262
+ /*
263
+ ** Alter the content of the checkout so that it conforms with the
264
+ ** target
265
+ */
220266
db_prepare(&q,
221
- "SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1"
267
+ "SELECT fn, idv, ridv, idt, ridt, chnged, fnt FROM fv ORDER BY 1"
222268
);
223269
assert( g.zLocalRoot!=0 );
224270
assert( strlen(g.zLocalRoot)>1 );
225271
assert( g.zLocalRoot[strlen(g.zLocalRoot)-1]=='/' );
226272
while( db_step(&q)==SQLITE_ROW ){
@@ -228,13 +274,18 @@
228274
int idv = db_column_int(&q, 1); /* VFILE entry for current */
229275
int ridv = db_column_int(&q, 2); /* RecordID for current */
230276
int idt = db_column_int(&q, 3); /* VFILE entry for target */
231277
int ridt = db_column_int(&q, 4); /* RecordID for target */
232278
int chnged = db_column_int(&q, 5); /* Current is edited */
279
+ const char *zNewName = db_column_text(&q,6);/* New filename */
233280
char *zFullPath; /* Full pathname of the file */
281
+ char *zFullNewPath; /* Full pathname of dest */
282
+ char nameChng; /* True if the name changed */
234283
235284
zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
285
+ zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
286
+ nameChng = strcmp(zName, zNewName);
236287
if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
237288
/* Conflict. This file has been added to the current checkout
238289
** but also exists in the target checkout. Use the current version.
239290
*/
240291
printf("CONFLICT %s\n", zName);
@@ -243,12 +294,12 @@
243294
printf("ADD %s\n", zName);
244295
undo_save(zName);
245296
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
246297
}else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
247298
/* The file is unedited. Change it to the target version */
248
- printf("UPDATE %s\n", zName);
249299
undo_save(zName);
300
+ printf("UPDATE %s\n", zName);
250301
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
251302
}else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
252303
/* The file missing from the local check-out. Restore it to the
253304
** version that appears in the target. */
254305
printf("UPDATE %s\n", zName);
@@ -258,39 +309,43 @@
258309
if( ridv==0 ){
259310
/* Added in current checkout. Continue to hold the file as
260311
** as an addition */
261312
db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
262313
}else if( chnged ){
263
- /* Edited locally but deleted from the target. Delete it. */
314
+ /* Edited locally but deleted from the target. Do not track the
315
+ ** file but keep the edited version around. */
264316
printf("CONFLICT %s\n", zName);
265317
}else{
266
- char *zFullPath;
267318
printf("REMOVE %s\n", zName);
268319
undo_save(zName);
269
- zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
270320
if( !nochangeFlag ) unlink(zFullPath);
271
- free(zFullPath);
272321
}
273322
}else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
274323
/* Merge the changes in the current tree into the target version */
275324
Blob e, r, t, v;
276325
int rc;
277
- printf("MERGE %s\n", zName);
326
+ if( nameChng ){
327
+ printf("MERGE %s -> %s\n", zName, zNewName);
328
+ }else{
329
+ printf("MERGE %s\n", zName);
330
+ }
278331
undo_save(zName);
279332
content_get(ridt, &t);
280333
content_get(ridv, &v);
281334
blob_zero(&e);
282335
blob_read_from_file(&e, zFullPath);
283336
rc = blob_merge(&v, &e, &t, &r);
284337
if( rc>=0 ){
285
- if( !nochangeFlag ) blob_write_to_file(&r, zFullPath);
338
+ if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath);
286339
if( rc>0 ){
287
- printf("***** %d merge conflicts in %s\n", rc, zName);
340
+ printf("***** %d merge conflicts in %s\n", rc, zNewName);
288341
}
289342
}else{
290
- printf("***** Cannot merge binary file %s\n", zName);
343
+ if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
344
+ printf("***** Cannot merge binary file %s\n", zNewName);
291345
}
346
+ if( nameChng && !nochangeFlag ) unlink(zFullPath);
292347
blob_reset(&v);
293348
blob_reset(&e);
294349
blob_reset(&t);
295350
blob_reset(&r);
296351
}else if( verboseFlag ){
@@ -299,10 +354,11 @@
299354
}else{
300355
printf("UNCHANGED %s\n", zName);
301356
}
302357
}
303358
free(zFullPath);
359
+ free(zFullNewPath);
304360
}
305361
db_finalize(&q);
306362
printf("--------------\n");
307363
show_common_info(tid, "updated-to:", 1, 0);
308364
309365
--- src/update.c
+++ src/update.c
@@ -61,15 +61,20 @@
61 int tid=0; /* Target version - version we are changing to */
62 Stmt q;
63 int latestFlag; /* --latest. Pick the latest version if true */
64 int nochangeFlag; /* -n or --nochange. Do a dry run */
65 int verboseFlag; /* -v or --verbose. Output extra information */
 
 
 
 
66
67 url_proxy_options();
68 latestFlag = find_option("latest",0, 0)!=0;
69 nochangeFlag = find_option("nochange","n",0)!=0;
70 verboseFlag = find_option("verbose","v",0)!=0;
 
71 db_must_be_within_tree();
72 vid = db_lget_int("checkout", 0);
73 if( vid==0 ){
74 fossil_fatal("cannot find current version");
75 }
@@ -95,10 +100,16 @@
95 fossil_fatal("no such version: %s", g.argv[2]);
96 }
97 }
98 }
99
 
 
 
 
 
 
100 if( tid==0 ){
101 int closeCode = 1;
102 compute_leaves(vid, closeCode);
103 if( !db_exists("SELECT 1 FROM leaves") ){
104 closeCode = 0;
@@ -148,44 +159,75 @@
148 " fn TEXT PRIMARY KEY," /* The filename relative to root */
149 " idv INTEGER," /* VFILE entry for current version */
150 " idt INTEGER," /* VFILE entry for target version */
151 " chnged BOOLEAN," /* True if current version has been edited */
152 " ridv INTEGER," /* Record ID for current version */
153 " ridt INTEGER " /* Record ID for target */
 
154 ");"
155 "INSERT OR IGNORE INTO fv"
156 " SELECT pathname, 0, 0, 0, 0, 0 FROM vfile"
157 );
158 db_prepare(&q,
159 "SELECT id, pathname, rid FROM vfile"
160 " WHERE vid=%d", tid
161 );
162 while( db_step(&q)==SQLITE_ROW ){
163 int id = db_column_int(&q, 0);
164 const char *fn = db_column_text(&q, 1);
165 int rid = db_column_int(&q, 2);
166 db_multi_exec(
167 "UPDATE fv SET idt=%d, ridt=%d WHERE fn=%Q",
168 id, rid, fn
169 );
170 }
171 db_finalize(&q);
172 db_prepare(&q,
173 "SELECT id, pathname, rid, chnged FROM vfile"
174 " WHERE vid=%d", vid
175 );
176 while( db_step(&q)==SQLITE_ROW ){
177 int id = db_column_int(&q, 0);
178 const char *fn = db_column_text(&q, 1);
179 int rid = db_column_int(&q, 2);
180 int chnged = db_column_int(&q, 3);
181 db_multi_exec(
182 "UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q",
183 id, rid, chnged, fn
184 );
185 }
186 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
188 /* If FILES appear on the command-line, remove from the "fv" table
189 ** every entry that is not named on the command-line or which is not
190 ** in a directory named on the command-line.
191 */
@@ -215,12 +257,16 @@
215 }
216 db_multi_exec(blob_str(&sql));
217 blob_reset(&sql);
218 }
219
 
 
 
 
220 db_prepare(&q,
221 "SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1"
222 );
223 assert( g.zLocalRoot!=0 );
224 assert( strlen(g.zLocalRoot)>1 );
225 assert( g.zLocalRoot[strlen(g.zLocalRoot)-1]=='/' );
226 while( db_step(&q)==SQLITE_ROW ){
@@ -228,13 +274,18 @@
228 int idv = db_column_int(&q, 1); /* VFILE entry for current */
229 int ridv = db_column_int(&q, 2); /* RecordID for current */
230 int idt = db_column_int(&q, 3); /* VFILE entry for target */
231 int ridt = db_column_int(&q, 4); /* RecordID for target */
232 int chnged = db_column_int(&q, 5); /* Current is edited */
 
233 char *zFullPath; /* Full pathname of the file */
 
 
234
235 zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
 
 
236 if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
237 /* Conflict. This file has been added to the current checkout
238 ** but also exists in the target checkout. Use the current version.
239 */
240 printf("CONFLICT %s\n", zName);
@@ -243,12 +294,12 @@
243 printf("ADD %s\n", zName);
244 undo_save(zName);
245 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
246 }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
247 /* The file is unedited. Change it to the target version */
248 printf("UPDATE %s\n", zName);
249 undo_save(zName);
 
250 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
251 }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
252 /* The file missing from the local check-out. Restore it to the
253 ** version that appears in the target. */
254 printf("UPDATE %s\n", zName);
@@ -258,39 +309,43 @@
258 if( ridv==0 ){
259 /* Added in current checkout. Continue to hold the file as
260 ** as an addition */
261 db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
262 }else if( chnged ){
263 /* Edited locally but deleted from the target. Delete it. */
 
264 printf("CONFLICT %s\n", zName);
265 }else{
266 char *zFullPath;
267 printf("REMOVE %s\n", zName);
268 undo_save(zName);
269 zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
270 if( !nochangeFlag ) unlink(zFullPath);
271 free(zFullPath);
272 }
273 }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
274 /* Merge the changes in the current tree into the target version */
275 Blob e, r, t, v;
276 int rc;
277 printf("MERGE %s\n", zName);
 
 
 
 
278 undo_save(zName);
279 content_get(ridt, &t);
280 content_get(ridv, &v);
281 blob_zero(&e);
282 blob_read_from_file(&e, zFullPath);
283 rc = blob_merge(&v, &e, &t, &r);
284 if( rc>=0 ){
285 if( !nochangeFlag ) blob_write_to_file(&r, zFullPath);
286 if( rc>0 ){
287 printf("***** %d merge conflicts in %s\n", rc, zName);
288 }
289 }else{
290 printf("***** Cannot merge binary file %s\n", zName);
 
291 }
 
292 blob_reset(&v);
293 blob_reset(&e);
294 blob_reset(&t);
295 blob_reset(&r);
296 }else if( verboseFlag ){
@@ -299,10 +354,11 @@
299 }else{
300 printf("UNCHANGED %s\n", zName);
301 }
302 }
303 free(zFullPath);
 
304 }
305 db_finalize(&q);
306 printf("--------------\n");
307 show_common_info(tid, "updated-to:", 1, 0);
308
309
--- src/update.c
+++ src/update.c
@@ -61,15 +61,20 @@
61 int tid=0; /* Target version - version we are changing to */
62 Stmt q;
63 int latestFlag; /* --latest. Pick the latest version if true */
64 int nochangeFlag; /* -n or --nochange. Do a dry run */
65 int verboseFlag; /* -v or --verbose. Output extra information */
66 int debugFlag; /* --debug option */
67 int nChng; /* Number of file renames */
68 int *aChng; /* Array of file renames */
69 int i; /* Loop counter */
70
71 url_proxy_options();
72 latestFlag = find_option("latest",0, 0)!=0;
73 nochangeFlag = find_option("nochange","n",0)!=0;
74 verboseFlag = find_option("verbose","v",0)!=0;
75 debugFlag = find_option("debug",0,0)!=0;
76 db_must_be_within_tree();
77 vid = db_lget_int("checkout", 0);
78 if( vid==0 ){
79 fossil_fatal("cannot find current version");
80 }
@@ -95,10 +100,16 @@
100 fossil_fatal("no such version: %s", g.argv[2]);
101 }
102 }
103 }
104
105 /* If no VERSION is specified on the command-line, then look for a
106 ** descendent of the current version. If there are multiple descendents,
107 ** look for one from the same branch as the current version. If there
108 ** are still multiple descendents, show them all and refuse to update
109 ** until the user selects one.
110 */
111 if( tid==0 ){
112 int closeCode = 1;
113 compute_leaves(vid, closeCode);
114 if( !db_exists("SELECT 1 FROM leaves") ){
115 closeCode = 0;
@@ -148,44 +159,75 @@
159 " fn TEXT PRIMARY KEY," /* The filename relative to root */
160 " idv INTEGER," /* VFILE entry for current version */
161 " idt INTEGER," /* VFILE entry for target version */
162 " chnged BOOLEAN," /* True if current version has been edited */
163 " ridv INTEGER," /* Record ID for current version */
164 " ridt INTEGER," /* Record ID for target */
165 " fnt TEXT" /* Filename of same file on target version */
166 ");"
167 );
168
169 /* Add files found in the current version
170 */
171 db_multi_exec(
172 "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)"
173 " SELECT pathname, pathname, id, 0, rid, 0, chnged FROM vfile WHERE vid=%d",
174 vid
175 );
176
177 /* Compute file name changes on V->T. Record name changes in files that
178 ** have changed locally.
179 */
180 find_filename_changes(vid, tid, &nChng, &aChng);
181 if( nChng ){
182 for(i=0; i<nChng; i++){
183 db_multi_exec(
184 "UPDATE fv"
185 " SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
186 " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
187 aChng[i*2+1], aChng[i*2]
188 );
189 }
190 fossil_free(aChng);
191 }
192
193 /* Add files found in the target version T but missing from the current
194 ** version V.
195 */
196 db_multi_exec(
197 "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)"
198 " SELECT pathname, pathname, 0, 0, 0, 0, 0 FROM vfile"
199 " WHERE vid=%d"
200 " AND pathname NOT IN (SELECT fnt FROM fv)",
201 tid
202 );
203
204 /*
205 ** Compute the file version ids for T
206 */
207 db_multi_exec(
208 "UPDATE fv SET"
209 " idt=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnt),0),"
210 " ridt=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnt),0)",
211 tid, tid
212 );
213
214 if( debugFlag ){
215 db_prepare(&q,
216 "SELECT rowid, fn, fnt, chnged, ridv, ridt FROM fv"
217 );
218 while( db_step(&q)==SQLITE_ROW ){
219 printf("%3d: ridv=%-4d ridt=%-4d chnged=%d\n",
220 db_column_int(&q, 0),
221 db_column_int(&q, 4),
222 db_column_int(&q, 5),
223 db_column_int(&q, 3));
224 printf(" fnv = [%s]\n", db_column_text(&q, 1));
225 printf(" fnt = [%s]\n", db_column_text(&q, 2));
226 }
227 db_finalize(&q);
228 }
229
230 /* If FILES appear on the command-line, remove from the "fv" table
231 ** every entry that is not named on the command-line or which is not
232 ** in a directory named on the command-line.
233 */
@@ -215,12 +257,16 @@
257 }
258 db_multi_exec(blob_str(&sql));
259 blob_reset(&sql);
260 }
261
262 /*
263 ** Alter the content of the checkout so that it conforms with the
264 ** target
265 */
266 db_prepare(&q,
267 "SELECT fn, idv, ridv, idt, ridt, chnged, fnt FROM fv ORDER BY 1"
268 );
269 assert( g.zLocalRoot!=0 );
270 assert( strlen(g.zLocalRoot)>1 );
271 assert( g.zLocalRoot[strlen(g.zLocalRoot)-1]=='/' );
272 while( db_step(&q)==SQLITE_ROW ){
@@ -228,13 +274,18 @@
274 int idv = db_column_int(&q, 1); /* VFILE entry for current */
275 int ridv = db_column_int(&q, 2); /* RecordID for current */
276 int idt = db_column_int(&q, 3); /* VFILE entry for target */
277 int ridt = db_column_int(&q, 4); /* RecordID for target */
278 int chnged = db_column_int(&q, 5); /* Current is edited */
279 const char *zNewName = db_column_text(&q,6);/* New filename */
280 char *zFullPath; /* Full pathname of the file */
281 char *zFullNewPath; /* Full pathname of dest */
282 char nameChng; /* True if the name changed */
283
284 zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
285 zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
286 nameChng = strcmp(zName, zNewName);
287 if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
288 /* Conflict. This file has been added to the current checkout
289 ** but also exists in the target checkout. Use the current version.
290 */
291 printf("CONFLICT %s\n", zName);
@@ -243,12 +294,12 @@
294 printf("ADD %s\n", zName);
295 undo_save(zName);
296 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
297 }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
298 /* The file is unedited. Change it to the target version */
 
299 undo_save(zName);
300 printf("UPDATE %s\n", zName);
301 if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
302 }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
303 /* The file missing from the local check-out. Restore it to the
304 ** version that appears in the target. */
305 printf("UPDATE %s\n", zName);
@@ -258,39 +309,43 @@
309 if( ridv==0 ){
310 /* Added in current checkout. Continue to hold the file as
311 ** as an addition */
312 db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
313 }else if( chnged ){
314 /* Edited locally but deleted from the target. Do not track the
315 ** file but keep the edited version around. */
316 printf("CONFLICT %s\n", zName);
317 }else{
 
318 printf("REMOVE %s\n", zName);
319 undo_save(zName);
 
320 if( !nochangeFlag ) unlink(zFullPath);
 
321 }
322 }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
323 /* Merge the changes in the current tree into the target version */
324 Blob e, r, t, v;
325 int rc;
326 if( nameChng ){
327 printf("MERGE %s -> %s\n", zName, zNewName);
328 }else{
329 printf("MERGE %s\n", zName);
330 }
331 undo_save(zName);
332 content_get(ridt, &t);
333 content_get(ridv, &v);
334 blob_zero(&e);
335 blob_read_from_file(&e, zFullPath);
336 rc = blob_merge(&v, &e, &t, &r);
337 if( rc>=0 ){
338 if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath);
339 if( rc>0 ){
340 printf("***** %d merge conflicts in %s\n", rc, zNewName);
341 }
342 }else{
343 if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
344 printf("***** Cannot merge binary file %s\n", zNewName);
345 }
346 if( nameChng && !nochangeFlag ) unlink(zFullPath);
347 blob_reset(&v);
348 blob_reset(&e);
349 blob_reset(&t);
350 blob_reset(&r);
351 }else if( verboseFlag ){
@@ -299,10 +354,11 @@
354 }else{
355 printf("UNCHANGED %s\n", zName);
356 }
357 }
358 free(zFullPath);
359 free(zFullNewPath);
360 }
361 db_finalize(&q);
362 printf("--------------\n");
363 show_common_info(tid, "updated-to:", 1, 0);
364
365

Keyboard Shortcuts

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