dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2007 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License version 2 as published by the Free Software Foundation. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This file contains code used to merge the changes in the current dbda8d6ce9 2007-07-21 drh: ** checkout into a different version and switch to that version. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "update.h" dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* b5d82ebd7e 2007-09-22 drh: ** Return true if artifact rid is a version b5d82ebd7e 2007-09-22 drh: */ b5d82ebd7e 2007-09-22 drh: int is_a_version(int rid){ b5d82ebd7e 2007-09-22 drh: return db_exists("SELECT 1 FROM plink WHERE cid=%d", rid); b5d82ebd7e 2007-09-22 drh: } b5d82ebd7e 2007-09-22 drh: b5d82ebd7e 2007-09-22 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: update dbda8d6ce9 2007-07-21 drh: ** 2d996b080e 2009-12-17 drh: ** Usage: %fossil update ?VERSION? ?FILES...? 1d9ebd9e4a 2009-12-17 drh: ** 1d9ebd9e4a 2009-12-17 drh: ** Change the version of the current checkout to VERSION. Any uncommitted 1d9ebd9e4a 2009-12-17 drh: ** changes are retained and applied to the new checkout. 1d9ebd9e4a 2009-12-17 drh: ** 1d9ebd9e4a 2009-12-17 drh: ** The VERSION argument can be a specific version or tag or branch name. 1d9ebd9e4a 2009-12-17 drh: ** If the VERSION argument is omitted, then the leaf of the the subtree 1d9ebd9e4a 2009-12-17 drh: ** that begins at the current version is used, if there is only a single 2d996b080e 2009-12-17 drh: ** leaf. VERSION can also be "current" to select the leaf of the current 2d996b080e 2009-12-17 drh: ** version or "latest" to select the most recent check-in. 6607844a01 2007-08-18 drh: ** 2d996b080e 2009-12-17 drh: ** If one or more FILES are listed after the VERSION then only the 2d996b080e 2009-12-17 drh: ** named files are candidates to be updated. If FILES is omitted, all 2d996b080e 2009-12-17 drh: ** files in the current checkout are subject to be updated. 6607844a01 2007-08-18 drh: ** 1d9ebd9e4a 2009-12-17 drh: ** The -n or --nochange option causes this command to do a "dry run". It 1d9ebd9e4a 2009-12-17 drh: ** prints out what would have happened but does not actually make any 1d9ebd9e4a 2009-12-17 drh: ** changes to the current checkout or the repository. dbda8d6ce9 2007-07-21 drh: ** 1d9ebd9e4a 2009-12-17 drh: ** The -v or --verbose option prints status information about unchanged 1d9ebd9e4a 2009-12-17 drh: ** files in addition to those file that actually do change. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void update_cmd(void){ dbda8d6ce9 2007-07-21 drh: int vid; /* Current version */ b773dda29b 2007-09-25 jnc: int tid=0; /* Target version - version we are changing to */ dbda8d6ce9 2007-07-21 drh: Stmt q; 1d9ebd9e4a 2009-12-17 drh: int latestFlag; /* --latest. Pick the latest version if true */ 1d9ebd9e4a 2009-12-17 drh: int nochangeFlag; /* -n or --nochange. Do a dry run */ 1d9ebd9e4a 2009-12-17 drh: int verboseFlag; /* -v or --verbose. Output extra information */ b714ab1ea7 2008-05-07 drh: b714ab1ea7 2008-05-07 drh: url_proxy_options(); ff4cc5fae2 2007-09-23 drh: latestFlag = find_option("latest",0, 0)!=0; 1d9ebd9e4a 2009-12-17 drh: nochangeFlag = find_option("nochange","n",0)!=0; 1d9ebd9e4a 2009-12-17 drh: verboseFlag = find_option("verbose","v",0)!=0; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: vid = db_lget_int("checkout", 0); dbda8d6ce9 2007-07-21 drh: if( vid==0 ){ ff4cc5fae2 2007-09-23 drh: fossil_fatal("cannot find current version"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( db_exists("SELECT 1 FROM vmerge") ){ dbda8d6ce9 2007-07-21 drh: fossil_fatal("cannot update an uncommitted merge"); dbda8d6ce9 2007-07-21 drh: } b773dda29b 2007-09-25 jnc: 2d996b080e 2009-12-17 drh: if( g.argc>=3 ){ 2d996b080e 2009-12-17 drh: if( strcmp(g.argv[2], "current")==0 ){ 2d996b080e 2009-12-17 drh: /* If VERSION is "current", then use the same algorithm to find the 2d996b080e 2009-12-17 drh: ** target as if VERSION were omitted. */ 2d996b080e 2009-12-17 drh: }else if( strcmp(g.argv[2], "latest")==0 ){ 2d996b080e 2009-12-17 drh: /* If VERSION is "latest", then use the same algorithm to find the 2d996b080e 2009-12-17 drh: ** target as if VERSION were omitted and the --latest flag is present. 2d996b080e 2009-12-17 drh: */ 2d996b080e 2009-12-17 drh: latestFlag = 1; 2d996b080e 2009-12-17 drh: }else{ 2d996b080e 2009-12-17 drh: tid = name_to_rid(g.argv[2]); 2d996b080e 2009-12-17 drh: if( tid==0 ){ 2d996b080e 2009-12-17 drh: fossil_fatal("no such version: %s", g.argv[2]); 2d996b080e 2009-12-17 drh: }else if( !is_a_version(tid) ){ 2d996b080e 2009-12-17 drh: fossil_fatal("no such version: %s", g.argv[2]); 2d996b080e 2009-12-17 drh: } dbda8d6ce9 2007-07-21 drh: } b773dda29b 2007-09-25 jnc: } 1d9ebd9e4a 2009-12-17 drh: if( !nochangeFlag ) autosync(AUTOSYNC_PULL); b773dda29b 2007-09-25 jnc: b773dda29b 2007-09-25 jnc: if( tid==0 ){ b6e22e62cf 2009-01-20 drh: compute_leaves(vid, 1); ff4cc5fae2 2007-09-23 drh: if( !latestFlag && db_int(0, "SELECT count(*) FROM leaves")>1 ){ fcabd4774c 2007-09-13 drh: db_prepare(&q, 9395aba4f4 2007-09-22 drh: "%s " fcabd4774c 2007-09-13 drh: " AND event.objid IN leaves" 9395aba4f4 2007-09-22 drh: " ORDER BY event.mtime DESC", 9395aba4f4 2007-09-22 drh: timeline_query_for_tty() fcabd4774c 2007-09-13 drh: ); fcabd4774c 2007-09-13 drh: print_timeline(&q, 100); fcabd4774c 2007-09-13 drh: db_finalize(&q); 6458f020fc 2008-05-14 drh: fossil_fatal("Multiple descendants"); dbda8d6ce9 2007-07-21 drh: } ff4cc5fae2 2007-09-23 drh: tid = db_int(0, "SELECT rid FROM leaves, event" ff4cc5fae2 2007-09-23 drh: " WHERE event.objid=leaves.rid" ff4cc5fae2 2007-09-23 drh: " ORDER BY event.mtime DESC"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: db_begin_transaction(); 76f169fca6 2009-12-18 drh: vfile_check_signature(vid, 1); a36177bcce 2007-09-11 drh: undo_begin(); dbda8d6ce9 2007-07-21 drh: load_vfile_from_rid(tid); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** The record.fn field is used to match files against each other. The dbda8d6ce9 2007-07-21 drh: ** FV table contains one row for each each unique filename in dbda8d6ce9 2007-07-21 drh: ** in the current checkout, the pivot, and the version being merged. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: db_multi_exec( dbda8d6ce9 2007-07-21 drh: "DROP TABLE IF EXISTS fv;" dbda8d6ce9 2007-07-21 drh: "CREATE TEMP TABLE fv(" 2d996b080e 2009-12-17 drh: " fn TEXT PRIMARY KEY," /* The filename relative to root */ dbda8d6ce9 2007-07-21 drh: " idv INTEGER," /* VFILE entry for current version */ dbda8d6ce9 2007-07-21 drh: " idt INTEGER," /* VFILE entry for target version */ dbda8d6ce9 2007-07-21 drh: " chnged BOOLEAN," /* True if current version has been edited */ dbda8d6ce9 2007-07-21 drh: " ridv INTEGER," /* Record ID for current version */ dbda8d6ce9 2007-07-21 drh: " ridt INTEGER " /* Record ID for target */ dbda8d6ce9 2007-07-21 drh: ");" dbda8d6ce9 2007-07-21 drh: "INSERT OR IGNORE INTO fv" dbda8d6ce9 2007-07-21 drh: " SELECT pathname, 0, 0, 0, 0, 0 FROM vfile" dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, dbda8d6ce9 2007-07-21 drh: "SELECT id, pathname, rid FROM vfile" dbda8d6ce9 2007-07-21 drh: " WHERE vid=%d", tid dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int id = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: const char *fn = db_column_text(&q, 1); dbda8d6ce9 2007-07-21 drh: int rid = db_column_int(&q, 2); dbda8d6ce9 2007-07-21 drh: db_multi_exec( dbda8d6ce9 2007-07-21 drh: "UPDATE fv SET idt=%d, ridt=%d WHERE fn=%Q", dbda8d6ce9 2007-07-21 drh: id, rid, fn dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, dbda8d6ce9 2007-07-21 drh: "SELECT id, pathname, rid, chnged FROM vfile" dbda8d6ce9 2007-07-21 drh: " WHERE vid=%d", vid dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int id = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: const char *fn = db_column_text(&q, 1); dbda8d6ce9 2007-07-21 drh: int rid = db_column_int(&q, 2); dbda8d6ce9 2007-07-21 drh: int chnged = db_column_int(&q, 3); dbda8d6ce9 2007-07-21 drh: db_multi_exec( dbda8d6ce9 2007-07-21 drh: "UPDATE fv SET idv=%d, ridv=%d, chnged=%d WHERE fn=%Q", dbda8d6ce9 2007-07-21 drh: id, rid, chnged, fn dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: 2d996b080e 2009-12-17 drh: /* If FILES appear on the command-line, remove from the "fv" table 2d996b080e 2009-12-17 drh: ** every entry that is not named on the command-line. 2d996b080e 2009-12-17 drh: */ 2d996b080e 2009-12-17 drh: if( g.argc>=4 ){ 2d996b080e 2009-12-17 drh: Blob sql; /* SQL statement to purge unwanted entries */ 2d996b080e 2009-12-17 drh: char *zSep = "("; /* Separator in the list of filenames */ 2d996b080e 2009-12-17 drh: Blob treename; /* Normalized filename */ 2d996b080e 2009-12-17 drh: int i; /* Loop counter */ 2d996b080e 2009-12-17 drh: 2d996b080e 2009-12-17 drh: blob_zero(&sql); 2d996b080e 2009-12-17 drh: blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1); 2d996b080e 2009-12-17 drh: for(i=3; i<g.argc; i++){ 2d996b080e 2009-12-17 drh: file_tree_name(g.argv[i], &treename, 1); 2d996b080e 2009-12-17 drh: blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename)); 2d996b080e 2009-12-17 drh: blob_reset(&treename); 2d996b080e 2009-12-17 drh: zSep = ","; 2d996b080e 2009-12-17 drh: } 2d996b080e 2009-12-17 drh: blob_append(&sql, ")", -1); 2d996b080e 2009-12-17 drh: db_multi_exec(blob_str(&sql)); 2d996b080e 2009-12-17 drh: blob_reset(&sql); 2d996b080e 2009-12-17 drh: } 2d996b080e 2009-12-17 drh: dbda8d6ce9 2007-07-21 drh: db_prepare(&q, dbda8d6ce9 2007-07-21 drh: "SELECT fn, idv, ridv, idt, ridt, chnged FROM fv ORDER BY 1" dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ 2d996b080e 2009-12-17 drh: const char *zName = db_column_text(&q, 0); /* The filename from root */ d861fe77fb 2009-12-17 drh: int idv = db_column_int(&q, 1); /* VFILE entry for current */ d861fe77fb 2009-12-17 drh: int ridv = db_column_int(&q, 2); /* RecordID for current */ d861fe77fb 2009-12-17 drh: int idt = db_column_int(&q, 3); /* VFILE entry for target */ d861fe77fb 2009-12-17 drh: int ridt = db_column_int(&q, 4); /* RecordID for target */ d861fe77fb 2009-12-17 drh: int chnged = db_column_int(&q, 5); /* Current is edited */ 2d996b080e 2009-12-17 drh: char *zFullPath; /* Full pathname of the file */ 2d996b080e 2009-12-17 drh: 2d996b080e 2009-12-17 drh: zFullPath = mprintf("%s/%s", g.zLocalRoot, zName); dbda8d6ce9 2007-07-21 drh: if( idv>0 && ridv==0 && idt>0 ){ dbda8d6ce9 2007-07-21 drh: /* Conflict. This file has been added to the current checkout dbda8d6ce9 2007-07-21 drh: ** but also exists in the target checkout. Use the current version. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: printf("CONFLICT %s\n", zName); dbda8d6ce9 2007-07-21 drh: }else if( idt>0 && idv==0 ){ dbda8d6ce9 2007-07-21 drh: /* File added in the target. */ dbda8d6ce9 2007-07-21 drh: printf("ADD %s\n", zName); a36177bcce 2007-09-11 drh: undo_save(zName); 1d9ebd9e4a 2009-12-17 drh: if( !nochangeFlag ) vfile_to_disk(0, idt, 0); dbda8d6ce9 2007-07-21 drh: }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){ dbda8d6ce9 2007-07-21 drh: /* The file is unedited. Change it to the target version */ dbda8d6ce9 2007-07-21 drh: printf("UPDATE %s\n", zName); a36177bcce 2007-09-11 drh: undo_save(zName); 1d9ebd9e4a 2009-12-17 drh: if( !nochangeFlag ) vfile_to_disk(0, idt, 0); 2d996b080e 2009-12-17 drh: }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){ 2d996b080e 2009-12-17 drh: /* The file missing from the local check-out. Restore it to the 2d996b080e 2009-12-17 drh: ** version that appears in the target. */ 2d996b080e 2009-12-17 drh: printf("UPDATE %s\n", zName); 2d996b080e 2009-12-17 drh: undo_save(zName); 2d996b080e 2009-12-17 drh: if( !nochangeFlag ) vfile_to_disk(0, idt, 0); dbda8d6ce9 2007-07-21 drh: }else if( idt==0 && idv>0 ){ e124881a70 2009-07-07 drh: if( ridv==0 ){ e124881a70 2009-07-07 drh: /* Added in current checkout. Continue to hold the file as e124881a70 2009-07-07 drh: ** as an addition */ e124881a70 2009-07-07 drh: db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv); e124881a70 2009-07-07 drh: }else if( chnged ){ 2d996b080e 2009-12-17 drh: /* Edited locally but deleted from the target. Delete it. */ fe6ee8a431 2007-08-08 drh: printf("CONFLICT %s\n", zName); fe6ee8a431 2007-08-08 drh: }else{ fe6ee8a431 2007-08-08 drh: char *zFullPath; fe6ee8a431 2007-08-08 drh: printf("REMOVE %s\n", zName); a36177bcce 2007-09-11 drh: undo_save(zName); fe6ee8a431 2007-08-08 drh: zFullPath = mprintf("%s/%s", g.zLocalRoot, zName); 1d9ebd9e4a 2009-12-17 drh: if( !nochangeFlag ) unlink(zFullPath); fe6ee8a431 2007-08-08 drh: free(zFullPath); fe6ee8a431 2007-08-08 drh: } dbda8d6ce9 2007-07-21 drh: }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){ dbda8d6ce9 2007-07-21 drh: /* Merge the changes in the current tree into the target version */ dbda8d6ce9 2007-07-21 drh: Blob e, r, t, v; 36b96b8616 2007-11-16 drh: int rc; dbda8d6ce9 2007-07-21 drh: printf("MERGE %s\n", zName); a36177bcce 2007-09-11 drh: undo_save(zName); dbda8d6ce9 2007-07-21 drh: content_get(ridt, &t); dbda8d6ce9 2007-07-21 drh: content_get(ridv, &v); dbda8d6ce9 2007-07-21 drh: blob_zero(&e); dbda8d6ce9 2007-07-21 drh: blob_read_from_file(&e, zFullPath); 36b96b8616 2007-11-16 drh: rc = blob_merge(&v, &e, &t, &r); 36b96b8616 2007-11-16 drh: if( rc>=0 ){ 1d9ebd9e4a 2009-12-17 drh: if( !nochangeFlag ) blob_write_to_file(&r, zFullPath); 36b96b8616 2007-11-16 drh: if( rc>0 ){ 36b96b8616 2007-11-16 drh: printf("***** %d merge conflicts in %s\n", rc, zName); 36b96b8616 2007-11-16 drh: } 36b96b8616 2007-11-16 drh: }else{ 36b96b8616 2007-11-16 drh: printf("***** Cannot merge binary file %s\n", zName); 36b96b8616 2007-11-16 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&v); dbda8d6ce9 2007-07-21 drh: blob_reset(&e); dbda8d6ce9 2007-07-21 drh: blob_reset(&t); dbda8d6ce9 2007-07-21 drh: blob_reset(&r); 1d9ebd9e4a 2009-12-17 drh: }else if( verboseFlag ){ 1d9ebd9e4a 2009-12-17 drh: printf("UNCHANGED %s\n", zName); dbda8d6ce9 2007-07-21 drh: } 2d996b080e 2009-12-17 drh: free(zFullPath); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Clean up the mid and pid VFILE entries. Then commit the changes. dbda8d6ce9 2007-07-21 drh: */ 1d9ebd9e4a 2009-12-17 drh: if( nochangeFlag ){ 1d9ebd9e4a 2009-12-17 drh: db_end_transaction(1); /* With --nochange, rollback changes */ 1d9ebd9e4a 2009-12-17 drh: }else{ 2d996b080e 2009-12-17 drh: if( g.argc<=3 ){ 2d996b080e 2009-12-17 drh: /* All files updated. Shift the current checkout to the target. */ 2d996b080e 2009-12-17 drh: db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid); 2d996b080e 2009-12-17 drh: manifest_to_disk(tid); 2d996b080e 2009-12-17 drh: db_lset_int("checkout", tid); 2d996b080e 2009-12-17 drh: }else{ 2d996b080e 2009-12-17 drh: /* A subset of files have been checked out. Keep the current 2d996b080e 2009-12-17 drh: ** checkout unchanged. */ 2d996b080e 2009-12-17 drh: db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); 2d996b080e 2009-12-17 drh: } 1d9ebd9e4a 2009-12-17 drh: db_end_transaction(0); 1d9ebd9e4a 2009-12-17 drh: } 371dd6574c 2007-12-04 drh: } 371dd6574c 2007-12-04 drh: 371dd6574c 2007-12-04 drh: 371dd6574c 2007-12-04 drh: /* 371dd6574c 2007-12-04 drh: ** Get the contents of a file within a given revision. 371dd6574c 2007-12-04 drh: */ 371dd6574c 2007-12-04 drh: int historical_version_of_file( 371dd6574c 2007-12-04 drh: const char *revision, /* The baseline name containing the file */ 371dd6574c 2007-12-04 drh: const char *file, /* Full treename of the file */ 7b82a73bd3 2009-12-17 drh: Blob *content, /* Put the content here */ 7b82a73bd3 2009-12-17 drh: int errCode /* Error code if file not found. Panic if 0. */ 371dd6574c 2007-12-04 drh: ){ 371dd6574c 2007-12-04 drh: Blob mfile; 371dd6574c 2007-12-04 drh: Manifest m; 371dd6574c 2007-12-04 drh: int i, rid=0; 371dd6574c 2007-12-04 drh: a51808c0a5 2009-11-06 drh: if( revision ){ a51808c0a5 2009-11-06 drh: rid = name_to_rid(revision); a51808c0a5 2009-11-06 drh: }else{ a51808c0a5 2009-11-06 drh: rid = db_lget_int("checkout", 0); a51808c0a5 2009-11-06 drh: } a51808c0a5 2009-11-06 drh: if( !is_a_version(rid) ){ 7b82a73bd3 2009-12-17 drh: if( errCode>0 ) return errCode; a51808c0a5 2009-11-06 drh: fossil_fatal("no such check-out: %s", revision); a51808c0a5 2009-11-06 drh: } 371dd6574c 2007-12-04 drh: content_get(rid, &mfile); 371dd6574c 2007-12-04 drh: 371dd6574c 2007-12-04 drh: if( manifest_parse(&m, &mfile) ){ 371dd6574c 2007-12-04 drh: for(i=0; i<m.nFile; i++){ 371dd6574c 2007-12-04 drh: if( strcmp(m.aFile[i].zName, file)==0 ){ 371dd6574c 2007-12-04 drh: rid = uuid_to_rid(m.aFile[i].zUuid, 0); 371dd6574c 2007-12-04 drh: return content_get(rid, content); 371dd6574c 2007-12-04 drh: } 371dd6574c 2007-12-04 drh: } 7b82a73bd3 2009-12-17 drh: if( errCode<=0 ){ 7b82a73bd3 2009-12-17 drh: fossil_fatal("file %s does not exist in baseline: %s", file, revision); 7b82a73bd3 2009-12-17 drh: } 7b82a73bd3 2009-12-17 drh: }else if( errCode<=0 ){ 371dd6574c 2007-12-04 drh: fossil_panic("could not parse manifest for baseline: %s", revision); 371dd6574c 2007-12-04 drh: } 7b82a73bd3 2009-12-17 drh: return errCode; 255bacf907 2007-09-24 jnc: } 371dd6574c 2007-12-04 drh: 255bacf907 2007-09-24 jnc: 255bacf907 2007-09-24 jnc: /* 255bacf907 2007-09-24 jnc: ** COMMAND: revert 255bacf907 2007-09-24 jnc: ** 7b82a73bd3 2009-12-17 drh: ** Usage: %fossil revert ?-r REVISION? FILE ... 371dd6574c 2007-12-04 drh: ** 371dd6574c 2007-12-04 drh: ** Revert to the current repository version of FILE, or to 371dd6574c 2007-12-04 drh: ** the version associated with baseline REVISION if the -r flag 7b82a73bd3 2009-12-17 drh: ** appears. 255bacf907 2007-09-24 jnc: ** 7b82a73bd3 2009-12-17 drh: ** If a file is reverted accidently, it can be restored using 7b82a73bd3 2009-12-17 drh: ** the "fossil undo" command. 7b82a73bd3 2009-12-17 drh: */ 255bacf907 2007-09-24 jnc: void revert_cmd(void){ 353297a149 2009-12-17 drh: char *zFile; 574763bab9 2007-09-26 jnc: const char *zRevision; 255bacf907 2007-09-24 jnc: Blob fname; 255bacf907 2007-09-24 jnc: Blob record; 353297a149 2009-12-17 drh: int i; 7b82a73bd3 2009-12-17 drh: int errCode; d861fe77fb 2009-12-17 drh: int rid = 0; 255bacf907 2007-09-24 jnc: 574763bab9 2007-09-26 jnc: zRevision = find_option("revision", "r", 1); 255bacf907 2007-09-24 jnc: verify_all_options(); 255bacf907 2007-09-24 jnc: 255bacf907 2007-09-24 jnc: if( g.argc<3 ){ 7b82a73bd3 2009-12-17 drh: usage("?OPTIONS? FILE ..."); 255bacf907 2007-09-24 jnc: } 255bacf907 2007-09-24 jnc: db_must_be_within_tree(); 7b82a73bd3 2009-12-17 drh: db_begin_transaction(); 7b82a73bd3 2009-12-17 drh: undo_begin(); 255bacf907 2007-09-24 jnc: 353297a149 2009-12-17 drh: for(i=2; i<g.argc; i++){ 353297a149 2009-12-17 drh: zFile = mprintf("%/", g.argv[i]); 353297a149 2009-12-17 drh: file_tree_name(zFile, &fname, 1); 255bacf907 2007-09-24 jnc: 7b82a73bd3 2009-12-17 drh: if( zRevision!=0 ){ 7b82a73bd3 2009-12-17 drh: errCode = historical_version_of_file(zRevision, blob_str(&fname), 7b82a73bd3 2009-12-17 drh: &record, 2); 7b82a73bd3 2009-12-17 drh: }else{ 7b82a73bd3 2009-12-17 drh: rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); 7b82a73bd3 2009-12-17 drh: if( rid==0 ){ 7b82a73bd3 2009-12-17 drh: errCode = 2; 7b82a73bd3 2009-12-17 drh: }else{ 7b82a73bd3 2009-12-17 drh: content_get(rid, &record); 7b82a73bd3 2009-12-17 drh: errCode = 0; 7b82a73bd3 2009-12-17 drh: } 255bacf907 2007-09-24 jnc: } 574763bab9 2007-09-26 jnc: 7b82a73bd3 2009-12-17 drh: if( errCode==2 ){ 7b82a73bd3 2009-12-17 drh: fossil_warning("file not in repository: %s", zFile); 7b82a73bd3 2009-12-17 drh: }else{ 7b82a73bd3 2009-12-17 drh: undo_save(blob_str(&fname)); 353297a149 2009-12-17 drh: blob_write_to_file(&record, zFile); 353297a149 2009-12-17 drh: printf("%s reverted\n", zFile); 353297a149 2009-12-17 drh: } 255bacf907 2007-09-24 jnc: blob_reset(&record); 255bacf907 2007-09-24 jnc: blob_reset(&fname); 353297a149 2009-12-17 drh: free(zFile); 255bacf907 2007-09-24 jnc: } dbda8d6ce9 2007-07-21 drh: db_end_transaction(0); dbda8d6ce9 2007-07-21 drh: }