Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Enhancements to the "update" command. Missing files are reverted. One or more files can be specified on the "update" command line after the VERSION and only the files named will be updated. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
2d996b080e1675dad33430598f4f4a75 |
| User & Date: | drh 2009-12-17 22:55:26.000 |
References
|
2009-12-18
| ||
| 00:32 | • Fixed ticket [d0d21c56d6]: Update should restore locally missing files plus 2 other changes artifact: 9999e7edac user: drh | |
Context
|
2009-12-18
| ||
| 00:29 | Detect when the check-out contains missing files and filesystem objects that ought to be files but are not. Issue reasonable warnings. check-in: 76f169fca6 user: drh tags: trunk | |
|
2009-12-17
| ||
| 22:55 | Enhancements to the "update" command. Missing files are reverted. One or more files can be specified on the "update" command line after the VERSION and only the files named will be updated. check-in: 2d996b080e user: drh tags: trunk | |
| 21:22 | Remove the --yes option from the "revert" command. In its place, make the "revert" opration undoable. check-in: 7b82a73bd3 user: drh tags: trunk | |
Changes
Changes to src/update.c.
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
int is_a_version(int rid){
return db_exists("SELECT 1 FROM plink WHERE cid=%d", rid);
}
/*
** COMMAND: update
**
| | | | > > > > < < < | > > > > > > > > > | | | < | | > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
int is_a_version(int rid){
return db_exists("SELECT 1 FROM plink WHERE cid=%d", rid);
}
/*
** COMMAND: update
**
** Usage: %fossil update ?VERSION? ?FILES...?
**
** Change the version of the current checkout to VERSION. Any uncommitted
** changes are retained and applied to the new checkout.
**
** The VERSION argument can be a specific version or tag or branch name.
** If the VERSION argument is omitted, then the leaf of the the subtree
** that begins at the current version is used, if there is only a single
** leaf. VERSION can also be "current" to select the leaf of the current
** version or "latest" to select the most recent check-in.
**
** If one or more FILES are listed after the VERSION then only the
** named files are candidates to be updated. If FILES is omitted, all
** files in the current checkout are subject to be updated.
**
** The -n or --nochange option causes this command to do a "dry run". It
** prints out what would have happened but does not actually make any
** changes to the current checkout or the repository.
**
** The -v or --verbose option prints status information about unchanged
** files in addition to those file that actually do change.
*/
void update_cmd(void){
int vid; /* Current version */
int tid=0; /* Target version - version we are changing to */
Stmt q;
int latestFlag; /* --latest. Pick the latest version if true */
int nochangeFlag; /* -n or --nochange. Do a dry run */
int verboseFlag; /* -v or --verbose. Output extra information */
url_proxy_options();
latestFlag = find_option("latest",0, 0)!=0;
nochangeFlag = find_option("nochange","n",0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("cannot find current version");
}
if( db_exists("SELECT 1 FROM vmerge") ){
fossil_fatal("cannot update an uncommitted merge");
}
if( g.argc>=3 ){
if( strcmp(g.argv[2], "current")==0 ){
/* If VERSION is "current", then use the same algorithm to find the
** target as if VERSION were omitted. */
}else if( strcmp(g.argv[2], "latest")==0 ){
/* If VERSION is "latest", then use the same algorithm to find the
** target as if VERSION were omitted and the --latest flag is present.
*/
latestFlag = 1;
}else{
tid = name_to_rid(g.argv[2]);
if( tid==0 ){
fossil_fatal("no such version: %s", g.argv[2]);
}else if( !is_a_version(tid) ){
fossil_fatal("no such version: %s", g.argv[2]);
}
}
}
if( !nochangeFlag ) autosync(AUTOSYNC_PULL);
if( tid==0 ){
compute_leaves(vid, 1);
if( !latestFlag && db_int(0, "SELECT count(*) FROM leaves")>1 ){
|
| ︙ | ︙ | |||
118 119 120 121 122 123 124 |
** The record.fn field is used to match files against each other. The
** FV table contains one row for each each unique filename in
** in the current checkout, the pivot, and the version being merged.
*/
db_multi_exec(
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv("
| | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
** The record.fn field is used to match files against each other. The
** FV table contains one row for each each unique filename in
** in the current checkout, the pivot, and the version being merged.
*/
db_multi_exec(
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv("
" fn TEXT PRIMARY KEY," /* The filename relative to root */
" idv INTEGER," /* VFILE entry for current version */
" idt INTEGER," /* VFILE entry for target version */
" chnged BOOLEAN," /* True if current version has been edited */
" ridv INTEGER," /* Record ID for current version */
" ridt INTEGER " /* Record ID for target */
");"
"INSERT OR IGNORE INTO fv"
|
| ︙ | ︙ | |||
157 158 159 160 161 162 163 164 165 166 167 168 |
int chnged = db_column_int(&q, 3);
db_multi_exec(
"UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q",
id, rid, chnged, fn
);
}
db_finalize(&q);
db_prepare(&q,
"SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1"
);
while( db_step(&q)==SQLITE_ROW ){
| > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > < < < > > > | | | > > > > > | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
int chnged = db_column_int(&q, 3);
db_multi_exec(
"UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q",
id, rid, chnged, fn
);
}
db_finalize(&q);
/* If FILES appear on the command-line, remove from the "fv" table
** every entry that is not named on the command-line.
*/
if( g.argc>=4 ){
Blob sql; /* SQL statement to purge unwanted entries */
char *zSep = "("; /* Separator in the list of filenames */
Blob treename; /* Normalized filename */
int i; /* Loop counter */
blob_zero(&sql);
blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1);
for(i=3; i<g.argc; i++){
file_tree_name(g.argv[i], &treename, 1);
blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename));
blob_reset(&treename);
zSep = ",";
}
blob_append(&sql, ")", -1);
db_multi_exec(blob_str(&sql));
blob_reset(&sql);
}
db_prepare(&q,
"SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0); /* The filename from root */
int idv = db_column_int(&q, 1); /* VFILE entry for current */
int ridv = db_column_int(&q, 2); /* RecordID for current */
int idt = db_column_int(&q, 3); /* VFILE entry for target */
int ridt = db_column_int(&q, 4); /* RecordID for target */
int chnged = db_column_int(&q, 5); /* Current is edited */
char *zFullPath; /* Full pathname of the file */
zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
if( idv>0 && ridv==0 && idt>0 ){
/* Conflict. This file has been added to the current checkout
** but also exists in the target checkout. Use the current version.
*/
printf("CONFLICT %s\n", zName);
}else if( idt>0 && idv==0 ){
/* File added in the target. */
printf("ADD %s\n", zName);
undo_save(zName);
if( !nochangeFlag ) vfile_to_disk(0, idt, 0);
}else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
/* The file is unedited. Change it to the target version */
printf("UPDATE %s\n", zName);
undo_save(zName);
if( !nochangeFlag ) vfile_to_disk(0, idt, 0);
}else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
/* The file missing from the local check-out. Restore it to the
** version that appears in the target. */
printf("UPDATE %s\n", zName);
undo_save(zName);
if( !nochangeFlag ) vfile_to_disk(0, idt, 0);
}else if( idt==0 && idv>0 ){
if( ridv==0 ){
/* Added in current checkout. Continue to hold the file as
** as an addition */
db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
}else if( chnged ){
/* Edited locally but deleted from the target. Delete it. */
printf("CONFLICT %s\n", zName);
}else{
char *zFullPath;
printf("REMOVE %s\n", zName);
undo_save(zName);
zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
if( !nochangeFlag ) unlink(zFullPath);
free(zFullPath);
}
}else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
/* Merge the changes in the current tree into the target version */
Blob e, r, t, v;
int rc;
printf("MERGE %s\n", zName);
undo_save(zName);
content_get(ridt, &t);
content_get(ridv, &v);
blob_zero(&e);
blob_read_from_file(&e, zFullPath);
rc = blob_merge(&v, &e, &t, &r);
if( rc>=0 ){
if( !nochangeFlag ) blob_write_to_file(&r, zFullPath);
if( rc>0 ){
printf("***** %d merge conflicts in %s\n", rc, zName);
}
}else{
printf("***** Cannot merge binary file %s\n", zName);
}
blob_reset(&v);
blob_reset(&e);
blob_reset(&t);
blob_reset(&r);
}else if( verboseFlag ){
printf("UNCHANGED %s\n", zName);
}
free(zFullPath);
}
db_finalize(&q);
/*
** Clean up the mid and pid VFILE entries. Then commit the changes.
*/
if( nochangeFlag ){
db_end_transaction(1); /* With --nochange, rollback changes */
}else{
if( g.argc<=3 ){
/* All files updated. Shift the current checkout to the target. */
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
manifest_to_disk(tid);
db_lset_int("checkout", tid);
}else{
/* A subset of files have been checked out. Keep the current
** checkout unchanged. */
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
}
db_end_transaction(0);
}
}
/*
** Get the contents of a file within a given revision.
|
| ︙ | ︙ |