fc95255785 2007-08-29 aku: /* fc95255785 2007-08-29 aku: ** Copyright (c) 2007 Andreas Kupries fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** This program is free software; you can redistribute it and/or fc95255785 2007-08-29 aku: ** modify it under the terms of the GNU General Public fc95255785 2007-08-29 aku: ** License version 2 as published by the Free Software Foundation. fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** This program is distributed in the hope that it will be useful, fc95255785 2007-08-29 aku: ** but WITHOUT ANY WARRANTY; without even the implied warranty of fc95255785 2007-08-29 aku: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU fc95255785 2007-08-29 aku: ** General Public License for more details. fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** You should have received a copy of the GNU General Public fc95255785 2007-08-29 aku: ** License along with this library; if not, write to the fc95255785 2007-08-29 aku: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, fc95255785 2007-08-29 aku: ** Boston, MA 02111-1307, USA. fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** Author contact information: fc95255785 2007-08-29 aku: ** akupries@shaw.ca fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ******************************************************************************* fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** This file contains code used to de- and reconstruct a repository fc95255785 2007-08-29 aku: ** into and from an indicated directory. fc95255785 2007-08-29 aku: */ fc95255785 2007-08-29 aku: #include "config.h" fc95255785 2007-08-29 aku: #include "construct.h" fc95255785 2007-08-29 aku: #include <assert.h> fc95255785 2007-08-29 aku: #include <sys/types.h> fc95255785 2007-08-29 aku: #include <dirent.h> fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: /* This function recursively scans the directory hierarchy starting at fc95255785 2007-08-29 aku: ** zOrigin and enters all found files into the repository. The uuid is fc95255785 2007-08-29 aku: ** generated from the file contents, and not taken from the, possibly fc95255785 2007-08-29 aku: ** modified, file name. While function is able to handle the directory fc95255785 2007-08-29 aku: ** structure created by 'deconstruct' it can actually much more. fc95255785 2007-08-29 aku: */ fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: static int import_origin(const char* zOrigin){ fc95255785 2007-08-29 aku: DIR *d; fc95255785 2007-08-29 aku: int count = 0; fc95255785 2007-08-29 aku: const char *zFormat; fc95255785 2007-08-29 aku: const char *zDir = zOrigin; fc95255785 2007-08-29 aku: struct dirent *pEntry; fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: if( zDir[0]==0 ){ fc95255785 2007-08-29 aku: zDir = "."; fc95255785 2007-08-29 aku: zFormat = "%s%s"; fc95255785 2007-08-29 aku: }else{ fc95255785 2007-08-29 aku: zFormat = "%s/%s"; fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: d = opendir(zDir); fc95255785 2007-08-29 aku: if( d ){ fc95255785 2007-08-29 aku: while( (pEntry=readdir(d))!=0 ){ fc95255785 2007-08-29 aku: char *zPath; fc95255785 2007-08-29 aku: if( pEntry->d_name[0]=='.' ) continue; fc95255785 2007-08-29 aku: zPath = mprintf(zFormat, zOrigin, pEntry->d_name); fc95255785 2007-08-29 aku: if( file_isdir(zPath)==1 ){ fc95255785 2007-08-29 aku: count += import_origin(zPath); fc95255785 2007-08-29 aku: }else if( file_isfile(zPath) ){ fc95255785 2007-08-29 aku: Blob zIn; fc95255785 2007-08-29 aku: blob_read_from_file (&zIn,zPath); fc95255785 2007-08-29 aku: content_put (&zIn, 0, 0); fc95255785 2007-08-29 aku: blob_reset (&zIn); fc95255785 2007-08-29 aku: count++; fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: free (zPath); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: closedir(d); fc95255785 2007-08-29 aku: return count; fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: /* fc95255785 2007-08-29 aku: ** COMMAND: deconstruct fc95255785 2007-08-29 aku: ** Usage %fossil deconstruct ?-R|--repository REPOSITORY? DESTINATION fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** Populates the indicated DESTINATION directory with copies of all fc95255785 2007-08-29 aku: ** files contained within the repository. Files are named AA/bbbbb fc95255785 2007-08-29 aku: ** where AA is the first 2 characters of the uuid and bbbbb is the fc95255785 2007-08-29 aku: ** remaining 38 characters. fc95255785 2007-08-29 aku: */ fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: void deconstruct_cmd(void){ fc95255785 2007-08-29 aku: const char* zDestination; fc95255785 2007-08-29 aku: Blob zOut; fc95255785 2007-08-29 aku: Stmt q; fc95255785 2007-08-29 aku: if( (g.argc != 3) && (g.argc != 5) ){ fc95255785 2007-08-29 aku: usage ("?-R|--repository REPOSITORY? DESTINATION"); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: db_find_and_open_repository (); fc95255785 2007-08-29 aku: zDestination = g.argv[g.argc-1]; fc95255785 2007-08-29 aku: if( !file_isdir (zDestination) ){ fc95255785 2007-08-29 aku: fossil_panic("not a directory: %s", zDestination); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: /* Iterate over all blobs in the repository, retrieve their fc95255785 2007-08-29 aku: * contents, and write them to a file with a name based on their fc95255785 2007-08-29 aku: * uuid. Note: Non-writable destination causes bail-out in the first fc95255785 2007-08-29 aku: * call of blob_write_to_file. fc95255785 2007-08-29 aku: */ fc95255785 2007-08-29 aku: db_prepare(&q, "SELECT rid,uuid FROM blob"); fc95255785 2007-08-29 aku: while( db_step(&q)==SQLITE_ROW ){ fc95255785 2007-08-29 aku: int rid = db_column_int (&q, 0); fc95255785 2007-08-29 aku: const char *zUuid = db_column_text(&q, 1); fc95255785 2007-08-29 aku: char *zFile = mprintf ("%s/%.2s/%s", zDestination, zUuid, zUuid + 2); fc95255785 2007-08-29 aku: content_get (rid,&zOut); fc95255785 2007-08-29 aku: blob_write_to_file (&zOut,zFile); fc95255785 2007-08-29 aku: blob_reset (&zOut); fc95255785 2007-08-29 aku: free(zFile); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: db_finalize(&q); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: /* fc95255785 2007-08-29 aku: ** COMMAND: reconstruct fc95255785 2007-08-29 aku: ** Usage %fossil reconstruct REPOSITORY ORIGIN fc95255785 2007-08-29 aku: ** fc95255785 2007-08-29 aku: ** Creates the REPOSITORY and populates it with the files in the fc95255785 2007-08-29 aku: ** indicated ORIGIN directory. fc95255785 2007-08-29 aku: */ fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: void reconstruct_cmd(void){ fc95255785 2007-08-29 aku: const char* zOrigin; fc95255785 2007-08-29 aku: const char* zRepository; fc95255785 2007-08-29 aku: int fileCnt; fc95255785 2007-08-29 aku: int errCnt; fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: if( g.argc != 4 ){ fc95255785 2007-08-29 aku: usage ("REPOSITORY ORIGIN"); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: zRepository = g.argv[2]; fc95255785 2007-08-29 aku: zOrigin = g.argv[3]; fc95255785 2007-08-29 aku: if( !file_isdir (zOrigin) ){ fc95255785 2007-08-29 aku: fossil_panic("not a directory: %s", zOrigin); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: /* Create the foundation */ fc95255785 2007-08-29 aku: db_create_repository(zRepository); fc95255785 2007-08-29 aku: db_open_repository(zRepository); fc95255785 2007-08-29 aku: db_open_config(); fc95255785 2007-08-29 aku: db_begin_transaction(); fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: db_initial_setup(0); fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: printf("project-id: %s\n", db_get("project-code", 0)); fc95255785 2007-08-29 aku: printf("server-id: %s\n", db_get("server-code", 0)); fc95255785 2007-08-29 aku: printf("admin-user: %s (no password set yet!)\n", g.zLogin); fc95255785 2007-08-29 aku: printf("baseline: %s\n", db_text(0, "SELECT uuid FROM blob")); fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: /* Scan origin and insert all files found inside */ fc95255785 2007-08-29 aku: fileCnt = import_origin (zOrigin); fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: printf("imported: %d %s\n", fileCnt, fileCnt == 1 ? fc95255785 2007-08-29 aku: "file" : "files"); fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: /* Finalize the repository, rebuild the derived tables */ ce1c1a2907 2007-09-21 drh: errCnt = rebuild_db(0); fc95255785 2007-08-29 aku: fc95255785 2007-08-29 aku: if( errCnt ){ fc95255785 2007-08-29 aku: printf("%d %s. Rolling back changes.\n", errCnt, errCnt == 1 ? fc95255785 2007-08-29 aku: "error" : "errors"); fc95255785 2007-08-29 aku: db_end_transaction(1); fc95255785 2007-08-29 aku: }else{ fc95255785 2007-08-29 aku: db_end_transaction(0); fc95255785 2007-08-29 aku: } fc95255785 2007-08-29 aku: }