File Annotation
Not logged in
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();
dbda8d6ce9 2007-07-21       drh:   vfile_check_signature(vid);
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: }