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 check-out versions of the project
dbda8d6ce9 2007-07-21       drh: ** from the local repository.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "checkout.h"
dbda8d6ce9 2007-07-21       drh: #include <assert.h>
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Check to see if there is an existing checkout that has been
dbda8d6ce9 2007-07-21       drh: ** modified.  Return values:
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: **     0:   There is an existing checkout but it is unmodified
dbda8d6ce9 2007-07-21       drh: **     1:   There is a modified checkout - there are unsaved changes
dbda8d6ce9 2007-07-21       drh: **     2:   There is no existing checkout
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int unsaved_changes(void){
dbda8d6ce9 2007-07-21       drh:   int vid;
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 ) return 2;
76f169fca6 2009-12-18       drh:   vfile_check_signature(vid, 1);
e146d800ac 2008-11-09       drh:   return db_exists("SELECT 1 FROM vfile WHERE chnged"
e146d800ac 2008-11-09       drh:                    " OR coalesce(origname!=pathname,0)");
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Undo the current check-out.  Unlink all files from the disk.
dbda8d6ce9 2007-07-21       drh: ** Clear the VFILE table.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void uncheckout(int vid){
dbda8d6ce9 2007-07-21       drh:   if( vid==0 ) return;
dbda8d6ce9 2007-07-21       drh:   vfile_unlink(vid);
dbda8d6ce9 2007-07-21       drh:   db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Given the abbreviated UUID name of a version, load the content of that
dbda8d6ce9 2007-07-21       drh: ** version in the VFILE table.  Return the VID for the version.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** If anything goes wrong, panic.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int load_vfile(const char *zName){
dbda8d6ce9 2007-07-21       drh:   Blob uuid;
dbda8d6ce9 2007-07-21       drh:   int vid;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   blob_init(&uuid, zName, -1);
dbda8d6ce9 2007-07-21       drh:   if( name_to_uuid(&uuid, 1) ){
dbda8d6ce9 2007-07-21       drh:     fossil_panic(g.zErrMsg);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
dbda8d6ce9 2007-07-21       drh:   if( vid==0 ){
c774e298c3 2009-09-18       drh:     fossil_fatal("no such check-in: %s", g.argv[2]);
c774e298c3 2009-09-18       drh:   }
999b1779e7 2009-10-31       drh:   if( !is_a_version(vid) ){
c774e298c3 2009-09-18       drh:     fossil_fatal("object [%.10s] is not a check-in", blob_str(&uuid));
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   load_vfile_from_rid(vid);
dbda8d6ce9 2007-07-21       drh:   return vid;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Load a vfile from a record ID.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void load_vfile_from_rid(int vid){
dbda8d6ce9 2007-07-21       drh:   Blob manifest;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
dbda8d6ce9 2007-07-21       drh:     return;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   content_get(vid, &manifest);
dbda8d6ce9 2007-07-21       drh:   vfile_build(vid, &manifest);
dbda8d6ce9 2007-07-21       drh:   blob_reset(&manifest);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
a040ae6e17 2007-08-08       drh: ** Read the manifest file given by vid out of the repository
a040ae6e17 2007-08-08       drh: ** and store it in the root of the local check-out.
a040ae6e17 2007-08-08       drh: */
a040ae6e17 2007-08-08       drh: void manifest_to_disk(int vid){
a040ae6e17 2007-08-08       drh:   char *zManFile;
a040ae6e17 2007-08-08       drh:   Blob manifest;
95e17f4e3f 2007-08-25       drh:   Blob hash;
33c31f73cd 2008-02-21       drh:   Blob filename;
33c31f73cd 2008-02-21       drh:   int baseLen;
33c31f73cd 2008-02-21       drh:   int i;
33c31f73cd 2008-02-21       drh:   Manifest m;
a040ae6e17 2007-08-08       drh: 
a040ae6e17 2007-08-08       drh:   blob_zero(&manifest);
a040ae6e17 2007-08-08       drh:   zManFile = mprintf("%smanifest", g.zLocalRoot);
a040ae6e17 2007-08-08       drh:   content_get(vid, &manifest);
a040ae6e17 2007-08-08       drh:   blob_write_to_file(&manifest, zManFile);
a040ae6e17 2007-08-08       drh:   free(zManFile);
95e17f4e3f 2007-08-25       drh:   blob_zero(&hash);
95e17f4e3f 2007-08-25       drh:   sha1sum_blob(&manifest, &hash);
95e17f4e3f 2007-08-25       drh:   zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
95e17f4e3f 2007-08-25       drh:   blob_append(&hash, "\n", 1);
95e17f4e3f 2007-08-25       drh:   blob_write_to_file(&hash, zManFile);
95e17f4e3f 2007-08-25       drh:   free(zManFile);
95e17f4e3f 2007-08-25       drh:   blob_reset(&hash);
33c31f73cd 2008-02-21       drh:   manifest_parse(&m, &manifest);
33c31f73cd 2008-02-21       drh:   blob_zero(&filename);
33c31f73cd 2008-02-21       drh:   blob_appendf(&filename, "%s/", g.zLocalRoot);
33c31f73cd 2008-02-21       drh:   baseLen = blob_size(&filename);
33c31f73cd 2008-02-21       drh:   for(i=0; i<m.nFile; i++){
33c31f73cd 2008-02-21       drh:     int isExe;
33c31f73cd 2008-02-21       drh:     blob_append(&filename, m.aFile[i].zName, -1);
33c31f73cd 2008-02-21       drh:     isExe = m.aFile[i].zPerm && strstr(m.aFile[i].zPerm, "x");
33c31f73cd 2008-02-21       drh:     file_setexe(blob_str(&filename), isExe);
33c31f73cd 2008-02-21       drh:     blob_resize(&filename, baseLen);
33c31f73cd 2008-02-21       drh:   }
33c31f73cd 2008-02-21       drh:   blob_reset(&filename);
33c31f73cd 2008-02-21       drh:   manifest_clear(&m);
a040ae6e17 2007-08-08       drh: }
a040ae6e17 2007-08-08       drh: 
a040ae6e17 2007-08-08       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND: checkout
a89b436bc9 2009-02-11   bharder: ** COMMAND: co
c9fdb846fb 2007-08-18       drh: **
915bfd99fe 2009-05-28       drh: ** Usage: %fossil checkout VERSION ?-f|--force? ?--keep?
6b85fd173e 2008-05-10       drh: **
c9fdb846fb 2007-08-18       drh: ** Check out a version specified on the command-line.  This command
915bfd99fe 2009-05-28       drh: ** will abort if there are edited files in the current checkout unless
915bfd99fe 2009-05-28       drh: ** the --force option appears on the command-line.  The --keep option
915bfd99fe 2009-05-28       drh: ** leaves files on disk unchanged, except the manifest and manifest.uuid
915bfd99fe 2009-05-28       drh: ** files.
915bfd99fe 2009-05-28       drh: **
915bfd99fe 2009-05-28       drh: ** The --latest flag can be used in place of VERSION to checkout the
915bfd99fe 2009-05-28       drh: ** latest version in the repository.
dbda8d6ce9 2007-07-21       drh: **
c9fdb846fb 2007-08-18       drh: ** See also the "update" command.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void checkout_cmd(void){
915bfd99fe 2009-05-28       drh:   int forceFlag;                 /* Force checkout even if edits exist */
915bfd99fe 2009-05-28       drh:   int keepFlag;                  /* Do not change any files on disk */
915bfd99fe 2009-05-28       drh:   int latestFlag;                /* Checkout the latest version */
915bfd99fe 2009-05-28       drh:   char *zVers;                   /* Version to checkout */
dbda8d6ce9 2007-07-21       drh:   int vid, prior;
3945057916 2007-08-01       drh:   Blob cksum1, cksum1b, cksum2;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   db_must_be_within_tree();
dbda8d6ce9 2007-07-21       drh:   db_begin_transaction();
dbda8d6ce9 2007-07-21       drh:   forceFlag = find_option("force","f",0)!=0;
915bfd99fe 2009-05-28       drh:   keepFlag = find_option("keep",0,0)!=0;
915bfd99fe 2009-05-28       drh:   latestFlag = find_option("latest",0,0)!=0;
915bfd99fe 2009-05-28       drh:   if( (latestFlag!=0 && g.argc!=2) || (latestFlag==0 && g.argc!=3) ){
915bfd99fe 2009-05-28       drh:      usage("VERSION|--latest ?--force? ?--keep?");
915bfd99fe 2009-05-28       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( !forceFlag && unsaved_changes()==1 ){
4452576730 2007-08-11       drh:     fossil_fatal("there are unsaved changes in the current checkout");
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( forceFlag ){
dbda8d6ce9 2007-07-21       drh:     db_multi_exec("DELETE FROM vfile");
dbda8d6ce9 2007-07-21       drh:     prior = 0;
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     prior = db_lget_int("checkout",0);
dbda8d6ce9 2007-07-21       drh:   }
915bfd99fe 2009-05-28       drh:   if( latestFlag ){
915bfd99fe 2009-05-28       drh:     compute_leaves(db_lget_int("checkout",0), 1);
915bfd99fe 2009-05-28       drh:     zVers = db_text(0, "SELECT uuid FROM leaves, event, blob"
915bfd99fe 2009-05-28       drh:                        " WHERE event.objid=leaves.rid AND blob.rid=leaves.rid"
915bfd99fe 2009-05-28       drh:                        " ORDER BY event.mtime DESC");
915bfd99fe 2009-05-28       drh:     if( zVers==0 ){
e00a5de0f1 2009-08-01       drh:       fossil_fatal("cannot locate \"latest\" checkout");
915bfd99fe 2009-05-28       drh:     }
915bfd99fe 2009-05-28       drh:   }else{
915bfd99fe 2009-05-28       drh:     zVers = g.argv[2];
915bfd99fe 2009-05-28       drh:   }
915bfd99fe 2009-05-28       drh:   vid = load_vfile(zVers);
dbda8d6ce9 2007-07-21       drh:   if( prior==vid ){
dbda8d6ce9 2007-07-21       drh:     return;
dbda8d6ce9 2007-07-21       drh:   }
915bfd99fe 2009-05-28       drh:   if( !keepFlag ){
dbda8d6ce9 2007-07-21       drh:     uncheckout(prior);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
915bfd99fe 2009-05-28       drh:   if( !keepFlag ){
dbda8d6ce9 2007-07-21       drh:     vfile_to_disk(vid, 0, 1);
dbda8d6ce9 2007-07-21       drh:   }
915bfd99fe 2009-05-28       drh:   manifest_to_disk(vid);
915bfd99fe 2009-05-28       drh:   db_lset_int("checkout", vid);
915bfd99fe 2009-05-28       drh:   undo_reset();
dbda8d6ce9 2007-07-21       drh:   db_multi_exec("DELETE FROM vmerge");
915bfd99fe 2009-05-28       drh:   if( !keepFlag ){
915bfd99fe 2009-05-28       drh:     vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
915bfd99fe 2009-05-28       drh:     vfile_aggregate_checksum_disk(vid, &cksum2);
915bfd99fe 2009-05-28       drh:     if( blob_compare(&cksum1, &cksum2) ){
915bfd99fe 2009-05-28       drh:       printf("WARNING: manifest checksum does not agree with disk\n");
915bfd99fe 2009-05-28       drh:     }
915bfd99fe 2009-05-28       drh:     if( blob_compare(&cksum1, &cksum1b) ){
915bfd99fe 2009-05-28       drh:       printf("WARNING: manifest checksum does not agree with manifest\n");
915bfd99fe 2009-05-28       drh:     }
3945057916 2007-08-01       drh:   }
dbda8d6ce9 2007-07-21       drh:   db_end_transaction(0);
4452576730 2007-08-11       drh: }
4452576730 2007-08-11       drh: 
4452576730 2007-08-11       drh: /*
915bfd99fe 2009-05-28       drh: ** Unlink the local database file
915bfd99fe 2009-05-28       drh: */
915bfd99fe 2009-05-28       drh: void unlink_local_database(void){
915bfd99fe 2009-05-28       drh:   static const char *azFile[] = {
915bfd99fe 2009-05-28       drh:      "%s_FOSSIL_",
915bfd99fe 2009-05-28       drh:      "%s_FOSSIL_-journal",
915bfd99fe 2009-05-28       drh:      "%s.fos",
915bfd99fe 2009-05-28       drh:      "%s.fos-journal",
915bfd99fe 2009-05-28       drh:   };
915bfd99fe 2009-05-28       drh:   int i;
915bfd99fe 2009-05-28       drh:   for(i=0; i<sizeof(azFile)/sizeof(azFile[0]); i++){
915bfd99fe 2009-05-28       drh:     char *z = mprintf(azFile[i], g.zLocalRoot);
915bfd99fe 2009-05-28       drh:     unlink(z);
915bfd99fe 2009-05-28       drh:     free(z);
915bfd99fe 2009-05-28       drh:   }
6b85fd173e 2008-05-10       drh: }
6b85fd173e 2008-05-10       drh: 
6b85fd173e 2008-05-10       drh: /*
4452576730 2007-08-11       drh: ** COMMAND: close
c9fdb846fb 2007-08-18       drh: **
c9fdb846fb 2007-08-18       drh: ** Usage: %fossil close ?-f|--force?
4452576730 2007-08-11       drh: **
4452576730 2007-08-11       drh: ** The opposite of "open".  Close the current database connection.
4452576730 2007-08-11       drh: ** Require a -f or --force flag if there are unsaved changed in the
4452576730 2007-08-11       drh: ** current check-out.
4452576730 2007-08-11       drh: */
4452576730 2007-08-11       drh: void close_cmd(void){
4452576730 2007-08-11       drh:   int forceFlag = find_option("force","f",0)!=0;
4452576730 2007-08-11       drh:   db_must_be_within_tree();
4452576730 2007-08-11       drh:   if( !forceFlag && unsaved_changes()==1 ){
4452576730 2007-08-11       drh:     fossil_fatal("there are unsaved changes in the current checkout");
4452576730 2007-08-11       drh:   }
4452576730 2007-08-11       drh:   db_close();
915bfd99fe 2009-05-28       drh:   unlink_local_database();
dbda8d6ce9 2007-07-21       drh: }