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: ** b7a93530ef 2008-02-01 aku: ** This file contains code used to check-in 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 "checkin.h" dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Generate text describing all changes. Prepend zPrefix to each line dbda8d6ce9 2007-07-21 drh: ** of output. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** We assume that vfile_check_signature has been run. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void status_report(Blob *report, const char *zPrefix){ dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: int nPrefix = strlen(zPrefix); 22552fb803 2007-08-03 dan: db_prepare(&q, e146d800ac 2008-11-09 drh: "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" e146d800ac 2008-11-09 drh: " FROM vfile " e146d800ac 2008-11-09 drh: " WHERE file_is_selected(id)" e146d800ac 2008-11-09 drh: " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1" 22552fb803 2007-08-03 dan: ); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: const char *zPathname = db_column_text(&q,0); dbda8d6ce9 2007-07-21 drh: int isDeleted = db_column_int(&q, 1); dbda8d6ce9 2007-07-21 drh: int isChnged = db_column_int(&q,2); dbda8d6ce9 2007-07-21 drh: int isNew = db_column_int(&q,3)==0; e146d800ac 2008-11-09 drh: int isRenamed = db_column_int(&q,4); 371dd6574c 2007-12-04 drh: char *zFullName = mprintf("%s/%s", g.zLocalRoot, zPathname); dbda8d6ce9 2007-07-21 drh: blob_append(report, zPrefix, nPrefix); 9346f2290c 2008-10-17 drh: if( isDeleted ){ 9346f2290c 2008-10-17 drh: blob_appendf(report, "DELETED %s\n", zPathname); 9346f2290c 2008-10-17 drh: }else if( access(zFullName, 0) ){ 371dd6574c 2007-12-04 drh: blob_appendf(report, "MISSING %s\n", zPathname); 371dd6574c 2007-12-04 drh: }else if( isNew ){ dbda8d6ce9 2007-07-21 drh: blob_appendf(report, "ADDED %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: }else if( isDeleted ){ dbda8d6ce9 2007-07-21 drh: blob_appendf(report, "DELETED %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: }else if( isChnged==2 ){ dbda8d6ce9 2007-07-21 drh: blob_appendf(report, "UPDATED_BY_MERGE %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: }else if( isChnged==3 ){ dbda8d6ce9 2007-07-21 drh: blob_appendf(report, "ADDED_BY_MERGE %s\n", zPathname); e146d800ac 2008-11-09 drh: }else if( isChnged==1 ){ dbda8d6ce9 2007-07-21 drh: blob_appendf(report, "EDITED %s\n", zPathname); e146d800ac 2008-11-09 drh: }else if( isRenamed ){ e146d800ac 2008-11-09 drh: blob_appendf(report, "RENAMED %s\n", zPathname); 371dd6574c 2007-12-04 drh: } 371dd6574c 2007-12-04 drh: free(zFullName); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT uuid FROM vmerge JOIN blob ON merge=rid" dbda8d6ce9 2007-07-21 drh: " WHERE id=0"); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: blob_append(report, zPrefix, nPrefix); dbda8d6ce9 2007-07-21 drh: blob_appendf(report, "MERGED_WITH %s\n", db_column_text(&q, 0)); 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: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: changes dbda8d6ce9 2007-07-21 drh: ** c9fdb846fb 2007-08-18 drh: ** Usage: %fossil changes 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Report on the edit status of all files in the current checkout. c9fdb846fb 2007-08-18 drh: ** See also the "status" and "extra" commands. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void changes_cmd(void){ dbda8d6ce9 2007-07-21 drh: Blob report; dbda8d6ce9 2007-07-21 drh: int vid; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: blob_zero(&report); dbda8d6ce9 2007-07-21 drh: vid = db_lget_int("checkout", 0); dbda8d6ce9 2007-07-21 drh: vfile_check_signature(vid); dbda8d6ce9 2007-07-21 drh: status_report(&report, ""); dbda8d6ce9 2007-07-21 drh: blob_write_to_file(&report, "-"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: status 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Usage: %fossil status 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Report on the status of the current checkout. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void status_cmd(void){ dbda8d6ce9 2007-07-21 drh: int vid; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: /* 012345678901234 */ dbda8d6ce9 2007-07-21 drh: printf("repository: %s\n", db_lget("repository","")); dbda8d6ce9 2007-07-21 drh: printf("local-root: %s\n", g.zLocalRoot); dbda8d6ce9 2007-07-21 drh: printf("server-code: %s\n", db_get("server-code", "")); dbda8d6ce9 2007-07-21 drh: vid = db_lget_int("checkout", 0); dbda8d6ce9 2007-07-21 drh: if( vid ){ dbda8d6ce9 2007-07-21 drh: show_common_info(vid, "checkout:", 0); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: changes_cmd(); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: ls dbda8d6ce9 2007-07-21 drh: ** c9fdb846fb 2007-08-18 drh: ** Usage: %fossil ls 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Show the names of all files in the current checkout dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void ls_cmd(void){ dbda8d6ce9 2007-07-21 drh: int vid; dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: 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: vfile_check_signature(vid); e146d800ac 2008-11-09 drh: db_prepare(&q, e146d800ac 2008-11-09 drh: "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" e146d800ac 2008-11-09 drh: " FROM vfile" e146d800ac 2008-11-09 drh: " ORDER BY 1" e146d800ac 2008-11-09 drh: ); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: const char *zPathname = db_column_text(&q,0); dbda8d6ce9 2007-07-21 drh: int isDeleted = db_column_int(&q, 1); dbda8d6ce9 2007-07-21 drh: int isNew = db_column_int(&q,2)==0; dbda8d6ce9 2007-07-21 drh: int chnged = db_column_int(&q,3); e146d800ac 2008-11-09 drh: int renamed = db_column_int(&q,4); 89d100b845 2008-10-31 drh: char *zFullName = mprintf("%s/%s", g.zLocalRoot, zPathname); dbda8d6ce9 2007-07-21 drh: if( isNew ){ dbda8d6ce9 2007-07-21 drh: printf("ADDED %s\n", zPathname); 89d100b845 2008-10-31 drh: }else if( access(zFullName, 0) ){ 89d100b845 2008-10-31 drh: printf("MISSING %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: }else if( isDeleted ){ dbda8d6ce9 2007-07-21 drh: printf("DELETED %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: }else if( chnged ){ dbda8d6ce9 2007-07-21 drh: printf("EDITED %s\n", zPathname); e146d800ac 2008-11-09 drh: }else if( renamed ){ e146d800ac 2008-11-09 drh: printf("RENAMED %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: printf("UNCHANGED %s\n", zPathname); dbda8d6ce9 2007-07-21 drh: } 89d100b845 2008-10-31 drh: free(zFullName); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: db_finalize(&q); c9fdb846fb 2007-08-18 drh: } c9fdb846fb 2007-08-18 drh: c9fdb846fb 2007-08-18 drh: /* 554d896209 2009-08-09 bch: ** COMMAND: extras 554d896209 2009-08-09 bch: ** Usage: %fossil extras 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Print a list of all files in the source tree that are not part of c9fdb846fb 2007-08-18 drh: ** the current checkout. See also the "clean" command. c9fdb846fb 2007-08-18 drh: */ c9fdb846fb 2007-08-18 drh: void extra_cmd(void){ c9fdb846fb 2007-08-18 drh: Blob path; 2ecc407d9b 2008-07-23 drh: Blob repo; c9fdb846fb 2007-08-18 drh: Stmt q; 849b94c631 2008-07-17 drh: int n; c9fdb846fb 2007-08-18 drh: db_must_be_within_tree(); c9fdb846fb 2007-08-18 drh: db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); 849b94c631 2008-07-17 drh: n = strlen(g.zLocalRoot); 849b94c631 2008-07-17 drh: blob_init(&path, g.zLocalRoot, n-1); 849b94c631 2008-07-17 drh: vfile_scan(0, &path, blob_size(&path)); c9fdb846fb 2007-08-18 drh: db_prepare(&q, c9fdb846fb 2007-08-18 drh: "SELECT x FROM sfile" 95e17f4e3f 2007-08-25 drh: " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')" c9fdb846fb 2007-08-18 drh: " ORDER BY 1"); 2ecc407d9b 2008-07-23 drh: if( file_tree_name(g.zRepositoryName, &repo, 0) ){ 2ecc407d9b 2008-07-23 drh: db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); 2ecc407d9b 2008-07-23 drh: } c9fdb846fb 2007-08-18 drh: while( db_step(&q)==SQLITE_ROW ){ c9fdb846fb 2007-08-18 drh: printf("%s\n", db_column_text(&q, 0)); 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: /* c9fdb846fb 2007-08-18 drh: ** COMMAND: clean 6b85fd173e 2008-05-10 drh: ** Usage: %fossil clean ?-all? 6b85fd173e 2008-05-10 drh: ** c9fdb846fb 2007-08-18 drh: ** Delete all "extra" files in the source tree. "Extra" files are c9fdb846fb 2007-08-18 drh: ** files that are not officially part of the checkout. See also 8372cc0b81 2007-09-22 jnc: ** the "extra" command. This operation cannot be undone. 8372cc0b81 2007-09-22 jnc: ** 8372cc0b81 2007-09-22 jnc: ** You will be prompted before removing each file. If you are 8372cc0b81 2007-09-22 jnc: ** sure you wish to remove all "extra" files you can specify the 8372cc0b81 2007-09-22 jnc: ** optional -all flag. dbda8d6ce9 2007-07-21 drh: */ c9fdb846fb 2007-08-18 drh: void clean_cmd(void){ 8372cc0b81 2007-09-22 jnc: int allFlag; 2ecc407d9b 2008-07-23 drh: Blob path, repo; dbda8d6ce9 2007-07-21 drh: Stmt q; 849b94c631 2008-07-17 drh: int n; 8372cc0b81 2007-09-22 jnc: allFlag = find_option("all","a",0)!=0; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); 849b94c631 2008-07-17 drh: n = strlen(g.zLocalRoot); 849b94c631 2008-07-17 drh: blob_init(&path, g.zLocalRoot, n-1); 849b94c631 2008-07-17 drh: vfile_scan(0, &path, blob_size(&path)); 77327ae14e 2007-08-08 drh: db_prepare(&q, c9fdb846fb 2007-08-18 drh: "SELECT %Q || x FROM sfile" 95e17f4e3f 2007-08-25 drh: " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')" c9fdb846fb 2007-08-18 drh: " ORDER BY 1", g.zLocalRoot); 2ecc407d9b 2008-07-23 drh: if( file_tree_name(g.zRepositoryName, &repo, 0) ){ 2ecc407d9b 2008-07-23 drh: db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); 2ecc407d9b 2008-07-23 drh: } dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ 8372cc0b81 2007-09-22 jnc: if( allFlag ){ 8372cc0b81 2007-09-22 jnc: unlink(db_column_text(&q, 0)); 820a1a1a53 2007-09-23 drh: }else{ 820a1a1a53 2007-09-23 drh: Blob ans; 820a1a1a53 2007-09-23 drh: char *prompt = mprintf("remove unmanaged file \"%s\" [y/N]? ", 820a1a1a53 2007-09-23 drh: db_column_text(&q, 0)); 820a1a1a53 2007-09-23 drh: blob_zero(&ans); 820a1a1a53 2007-09-23 drh: prompt_user(prompt, &ans); 820a1a1a53 2007-09-23 drh: if( blob_str(&ans)[0]=='y' ){ 820a1a1a53 2007-09-23 drh: unlink(db_column_text(&q, 0)); 820a1a1a53 2007-09-23 drh: } 8372cc0b81 2007-09-22 jnc: } 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: /* dbda8d6ce9 2007-07-21 drh: ** Prepare a commit comment. Let the user modify it using the dbda8d6ce9 2007-07-21 drh: ** editor specified in the global_config table or either dbda8d6ce9 2007-07-21 drh: ** the VISUAL or EDITOR environment variable. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Store the final commit comment in pComment. pComment is assumed dbda8d6ce9 2007-07-21 drh: ** to be uninitialized - any prior content is overwritten. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void prepare_commit_comment(Blob *pComment){ dbda8d6ce9 2007-07-21 drh: const char *zEditor; dbda8d6ce9 2007-07-21 drh: char *zCmd; dbda8d6ce9 2007-07-21 drh: char *zFile; dbda8d6ce9 2007-07-21 drh: Blob text, line; dbda8d6ce9 2007-07-21 drh: char *zComment; dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: blob_set(&text, 6f0a9f730b 2008-11-26 drh: "\n" 6f0a9f730b 2008-11-26 drh: "# Enter comments on this check-in. Lines beginning with # are ignored.\n" 6f0a9f730b 2008-11-26 drh: "# The check-in comment follows wiki formatting rules.\n" dbda8d6ce9 2007-07-21 drh: "#\n" dbda8d6ce9 2007-07-21 drh: ); 02a584f7f5 2009-08-26 drh: if( g.markPrivate ){ 02a584f7f5 2009-08-26 drh: blob_append(&text, 02a584f7f5 2009-08-26 drh: "# PRIVATE BRANCH: This check-in will be private and will not sync to\n" 02a584f7f5 2009-08-26 drh: "# repositories.\n" 02a584f7f5 2009-08-26 drh: "#\n", -1 02a584f7f5 2009-08-26 drh: ); 02a584f7f5 2009-08-26 drh: } dbda8d6ce9 2007-07-21 drh: status_report(&text, "# "); 134e2aeccc 2007-09-28 drh: zEditor = db_get("editor", 0); dbda8d6ce9 2007-07-21 drh: if( zEditor==0 ){ dbda8d6ce9 2007-07-21 drh: zEditor = getenv("VISUAL"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( zEditor==0 ){ dbda8d6ce9 2007-07-21 drh: zEditor = getenv("EDITOR"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( zEditor==0 ){ baf68cc18f 2008-08-11 drh: #ifdef __MINGW32__ baf68cc18f 2008-08-11 drh: zEditor = "notepad"; baf68cc18f 2008-08-11 drh: #else dbda8d6ce9 2007-07-21 drh: zEditor = "ed"; baf68cc18f 2008-08-11 drh: #endif dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: zFile = db_text(0, "SELECT '%qci-comment-' || hex(randomblob(6)) || '.txt'", dbda8d6ce9 2007-07-21 drh: g.zLocalRoot); e976aa6fcb 2008-06-08 drh: #ifdef __MINGW32__ e976aa6fcb 2008-06-08 drh: blob_add_cr(&text); e976aa6fcb 2008-06-08 drh: #endif dbda8d6ce9 2007-07-21 drh: blob_write_to_file(&text, zFile); 8372cc0b81 2007-09-22 jnc: zCmd = mprintf("%s \"%s\"", zEditor, zFile); c9fdb846fb 2007-08-18 drh: printf("%s\n", zCmd); dbda8d6ce9 2007-07-21 drh: if( system(zCmd) ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("editor aborted"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&text); dbda8d6ce9 2007-07-21 drh: blob_read_from_file(&text, zFile); e976aa6fcb 2008-06-08 drh: blob_remove_cr(&text); dbda8d6ce9 2007-07-21 drh: unlink(zFile); dbda8d6ce9 2007-07-21 drh: free(zFile); dbda8d6ce9 2007-07-21 drh: blob_zero(pComment); dbda8d6ce9 2007-07-21 drh: while( blob_line(&text, &line) ){ dbda8d6ce9 2007-07-21 drh: int i, n; dbda8d6ce9 2007-07-21 drh: char *z; dbda8d6ce9 2007-07-21 drh: n = blob_size(&line); dbda8d6ce9 2007-07-21 drh: z = blob_buffer(&line); dbda8d6ce9 2007-07-21 drh: for(i=0; i<n && isspace(z[i]); i++){} dbda8d6ce9 2007-07-21 drh: if( i<n && z[i]=='#' ) continue; f030c0aea7 2007-08-30 drh: if( i<n || blob_size(pComment)>0 ){ f030c0aea7 2007-08-30 drh: blob_appendf(pComment, "%b", &line); f030c0aea7 2007-08-30 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&text); dbda8d6ce9 2007-07-21 drh: zComment = blob_str(pComment); dbda8d6ce9 2007-07-21 drh: i = strlen(zComment); dbda8d6ce9 2007-07-21 drh: while( i>0 && isspace(zComment[i-1]) ){ i--; } dbda8d6ce9 2007-07-21 drh: blob_resize(pComment, i); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* 22552fb803 2007-08-03 dan: ** Populate the Global.aCommitFile[] based on the command line arguments 22552fb803 2007-08-03 dan: ** to a [commit] command. Global.aCommitFile is an array of integers 22552fb803 2007-08-03 dan: ** sized at (N+1), where N is the number of arguments passed to [commit]. 22552fb803 2007-08-03 dan: ** The contents are the [id] values from the vfile table corresponding 22552fb803 2007-08-03 dan: ** to the filenames passed as arguments. 22552fb803 2007-08-03 dan: ** 22552fb803 2007-08-03 dan: ** The last element of aCommitFile[] is always 0 - indicating the end 22552fb803 2007-08-03 dan: ** of the array. 22552fb803 2007-08-03 dan: ** 22552fb803 2007-08-03 dan: ** If there were no arguments passed to [commit], aCommitFile is not 22552fb803 2007-08-03 dan: ** allocated and remains NULL. Other parts of the code interpret this 22552fb803 2007-08-03 dan: ** to mean "all files". 22552fb803 2007-08-03 dan: */ 22552fb803 2007-08-03 dan: void select_commit_files(void){ 22552fb803 2007-08-03 dan: if( g.argc>2 ){ 22552fb803 2007-08-03 dan: int ii; 22552fb803 2007-08-03 dan: Blob b; aafd536a5c 2007-08-04 drh: blob_zero(&b); 22552fb803 2007-08-03 dan: g.aCommitFile = malloc(sizeof(int)*(g.argc-1)); 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: for(ii=2; ii<g.argc; ii++){ 22552fb803 2007-08-03 dan: int iId; 2ecc407d9b 2008-07-23 drh: file_tree_name(g.argv[ii], &b, 1); 22552fb803 2007-08-03 dan: iId = db_int(-1, "SELECT id FROM vfile WHERE pathname=%Q", blob_str(&b)); 22552fb803 2007-08-03 dan: if( iId<0 ){ 22552fb803 2007-08-03 dan: fossil_fatal("fossil knows nothing about: %s", g.argv[ii]); 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: g.aCommitFile[ii-2] = iId; aafd536a5c 2007-08-04 drh: blob_reset(&b); 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: g.aCommitFile[ii-2] = 0; 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* faf09dc7ae 2009-01-22 drh: ** Return true if the check-in with RID=rid is a leaf. 42c2a18e73 2009-01-22 drh: ** A leaf has no children in the same branch. b6e22e62cf 2009-01-20 drh: */ b7f32a71ab 2009-01-20 drh: int is_a_leaf(int rid){ 42c2a18e73 2009-01-22 drh: int rc; faf09dc7ae 2009-01-22 drh: static const char zSql[] = 42c2a18e73 2009-01-22 drh: @ SELECT 1 FROM plink 42c2a18e73 2009-01-22 drh: @ WHERE pid=%d 42c2a18e73 2009-01-22 drh: @ AND coalesce((SELECT value FROM tagxref 42c2a18e73 2009-01-22 drh: @ WHERE tagid=%d AND rid=plink.pid), 'trunk') 42c2a18e73 2009-01-22 drh: @ =coalesce((SELECT value FROM tagxref 42c2a18e73 2009-01-22 drh: @ WHERE tagid=%d AND rid=plink.cid), 'trunk') faf09dc7ae 2009-01-22 drh: ; 42c2a18e73 2009-01-22 drh: rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH); 42c2a18e73 2009-01-22 drh: return rc==0; b6e22e62cf 2009-01-20 drh: } b6e22e62cf 2009-01-20 drh: b6e22e62cf 2009-01-20 drh: /* 2bde9f9b3d 2008-10-21 drh: ** COMMAND: ci dbda8d6ce9 2007-07-21 drh: ** COMMAND: commit dbda8d6ce9 2007-07-21 drh: ** 4ac75b9107 2009-01-24 drh: ** Usage: %fossil commit ?OPTIONS? ?FILE...? c9fdb846fb 2007-08-18 drh: ** dbda8d6ce9 2007-07-21 drh: ** Create a new version containing all of the changes in the current c9fdb846fb 2007-08-18 drh: ** checkout. You will be prompted to enter a check-in comment unless 4c78a18ad2 2008-08-14 bch: ** the "-m" option is used to specify a comment line. You will be c9fdb846fb 2007-08-18 drh: ** prompted for your GPG passphrase in order to sign the new manifest c9fdb846fb 2007-08-18 drh: ** unless the "--nosign" options is used. All files that have c9fdb846fb 2007-08-18 drh: ** changed will be committed unless some subset of files is specified c9fdb846fb 2007-08-18 drh: ** on the command line. 4ac75b9107 2009-01-24 drh: ** 4ac75b9107 2009-01-24 drh: ** The --branch option followed by a branch name cases the new check-in 4ac75b9107 2009-01-24 drh: ** to be placed in the named branch. The --bgcolor option can be followed 4ac75b9107 2009-01-24 drh: ** by a color name (ex: '#ffc0c0') to specify the background color of 4ac75b9107 2009-01-24 drh: ** entries in the new branch when shown in the web timeline interface. 4ac75b9107 2009-01-24 drh: ** 4ac75b9107 2009-01-24 drh: ** A check-in is not permitted to fork unless the --force or -f 4ac75b9107 2009-01-24 drh: ** option appears. A check-in is not allowed against a closed check-in. 4ac75b9107 2009-01-24 drh: ** 02a584f7f5 2009-08-26 drh: ** The --private option creates a private check-in that is never synced. 02a584f7f5 2009-08-26 drh: ** Children of private check-ins are automatically private. 02a584f7f5 2009-08-26 drh: ** 4ac75b9107 2009-01-24 drh: ** Options: 22552fb803 2007-08-03 dan: ** 4ac75b9107 2009-01-24 drh: ** --comment|-m COMMENT-TEXT 4ac75b9107 2009-01-24 drh: ** --branch NEW-BRANCH-NAME 4ac75b9107 2009-01-24 drh: ** --bgcolor COLOR 4ac75b9107 2009-01-24 drh: ** --nosign 4ac75b9107 2009-01-24 drh: ** --force|-f 02a584f7f5 2009-08-26 drh: ** --private 4ac75b9107 2009-01-24 drh: ** dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void commit_cmd(void){ dbda8d6ce9 2007-07-21 drh: int rc; dbda8d6ce9 2007-07-21 drh: int vid, nrid, nvid; dbda8d6ce9 2007-07-21 drh: Blob comment; 9a9cd81738 2007-08-09 drh: const char *zComment; dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: Stmt q2; dbda8d6ce9 2007-07-21 drh: char *zUuid, *zDate; 6aff11f03f 2007-08-03 drh: int noSign = 0; /* True to omit signing the manifest using GPG */ 4c82c7773f 2007-08-30 drh: int isAMerge = 0; /* True if checking in a merge */ fff234b77c 2007-09-25 drh: int forceFlag = 0; /* Force a fork */ dbda8d6ce9 2007-07-21 drh: char *zManifestFile; /* Name of the manifest file */ 33c31f73cd 2008-02-21 drh: int nBasename; /* Length of "g.zLocalRoot/" */ 4ac75b9107 2009-01-24 drh: const char *zBranch; /* Create a new branch with this name */ 4ac75b9107 2009-01-24 drh: const char *zBgColor; /* Set background color when branching */ f6790b7c3c 2009-02-26 drh: const char *zDateOvrd; /* Override date string */ 8b630bb57a 2009-08-08 drh: const char *zUserOvrd; /* Override user name */ 33c31f73cd 2008-02-21 drh: Blob filename; /* complete filename */ dbda8d6ce9 2007-07-21 drh: Blob manifest; 741aac4d4e 2007-08-25 drh: Blob muuid; /* Manifest uuid */ dbda8d6ce9 2007-07-21 drh: Blob mcksum; /* Self-checksum on the manifest */ dbda8d6ce9 2007-07-21 drh: Blob cksum1, cksum2; /* Before and after commit checksums */ 3945057916 2007-08-01 drh: Blob cksum1b; /* Checksum recorded in the manifest */ 3945057916 2007-08-01 drh: b714ab1ea7 2008-05-07 drh: url_proxy_options(); 4ac75b9107 2009-01-24 drh: noSign = find_option("nosign",0,0)!=0; 9a9cd81738 2007-08-09 drh: zComment = find_option("comment","m",1); e0580dfeee 2008-02-04 drh: forceFlag = find_option("force", "f", 0)!=0; 4ac75b9107 2009-01-24 drh: zBranch = find_option("branch","b",1); 4ac75b9107 2009-01-24 drh: zBgColor = find_option("bgcolor",0,1); 02a584f7f5 2009-08-26 drh: if( find_option("private",0,0) ){ 02a584f7f5 2009-08-26 drh: g.markPrivate = 1; 02a584f7f5 2009-08-26 drh: if( zBranch==0 ) zBranch = "private"; 02a584f7f5 2009-08-26 drh: if( zBgColor==0 ) zBgColor = "#fec084"; /* Orange */ 02a584f7f5 2009-08-26 drh: } f6790b7c3c 2009-02-26 drh: zDateOvrd = find_option("date-override",0,1); 8b630bb57a 2009-08-08 drh: zUserOvrd = find_option("user-override",0,1); dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); 417e7662e5 2008-06-06 drh: noSign = db_get_boolean("omitsign", 0)|noSign; 3f706b92a5 2008-06-06 drh: if( db_get_boolean("clearsign", 1)==0 ){ noSign = 1; } 6aff11f03f 2007-08-03 drh: verify_all_options(); fff234b77c 2007-09-25 drh: 02a584f7f5 2009-08-26 drh: /* Get the ID of the parent manifest artifact */ dbda8d6ce9 2007-07-21 drh: vid = db_lget_int("checkout", 0); 02a584f7f5 2009-08-26 drh: if( content_is_private(vid) ){ 02a584f7f5 2009-08-26 drh: g.markPrivate = 1; 02a584f7f5 2009-08-26 drh: } 02a584f7f5 2009-08-26 drh: 02a584f7f5 2009-08-26 drh: /* 02a584f7f5 2009-08-26 drh: ** Autosync if autosync is enabled and this is not a private check-in. 02a584f7f5 2009-08-26 drh: */ 02a584f7f5 2009-08-26 drh: if( !g.markPrivate ){ 02a584f7f5 2009-08-26 drh: autosync(AUTOSYNC_PULL); 02a584f7f5 2009-08-26 drh: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* There are two ways this command may be executed. If there are 22552fb803 2007-08-03 dan: ** no arguments following the word "commit", then all modified files 22552fb803 2007-08-03 dan: ** in the checked out directory are committed. If one or more arguments 22552fb803 2007-08-03 dan: ** follows "commit", then only those files are committed. 22552fb803 2007-08-03 dan: ** 22552fb803 2007-08-03 dan: ** After the following function call has returned, the Global.aCommitFile[] 22552fb803 2007-08-03 dan: ** array is allocated to contain the "id" field from the vfile table 22552fb803 2007-08-03 dan: ** for each file to be committed. Or, if aCommitFile is NULL, all files 22552fb803 2007-08-03 dan: ** should be committed. 22552fb803 2007-08-03 dan: */ 22552fb803 2007-08-03 dan: select_commit_files(); 4c82c7773f 2007-08-30 drh: isAMerge = db_exists("SELECT 1 FROM vmerge"); 4c82c7773f 2007-08-30 drh: if( g.aCommitFile && isAMerge ){ aafd536a5c 2007-08-04 drh: fossil_fatal("cannot do a partial commit of a merge"); aafd536a5c 2007-08-04 drh: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: user_select(); e2a42f7a68 2008-01-29 drh: /* e2a42f7a68 2008-01-29 drh: ** Check that the user exists. e2a42f7a68 2008-01-29 drh: */ e2a42f7a68 2008-01-29 drh: if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ e2a42f7a68 2008-01-29 drh: fossil_fatal("no such user: %s", g.zLogin); e2a42f7a68 2008-01-29 drh: } e2a42f7a68 2008-01-29 drh: 22552fb803 2007-08-03 dan: db_begin_transaction(); 9346f2290c 2008-10-17 drh: db_record_repository_filename(0); 22552fb803 2007-08-03 dan: rc = unsaved_changes(); fff234b77c 2007-09-25 drh: if( rc==0 && !isAMerge && !forceFlag ){ 22552fb803 2007-08-03 dan: fossil_panic("nothing has changed"); 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* If one or more files that were named on the command line have not 22552fb803 2007-08-03 dan: ** been modified, bail out now. 22552fb803 2007-08-03 dan: */ 22552fb803 2007-08-03 dan: if( g.aCommitFile ){ 22552fb803 2007-08-03 dan: Blob unmodified; 22552fb803 2007-08-03 dan: memset(&unmodified, 0, sizeof(Blob)); 22552fb803 2007-08-03 dan: blob_init(&unmodified, 0, 0); 22552fb803 2007-08-03 dan: db_blob(&unmodified, 22552fb803 2007-08-03 dan: "SELECT pathname FROM vfile WHERE chnged = 0 AND file_is_selected(id)" 22552fb803 2007-08-03 dan: ); 22552fb803 2007-08-03 dan: if( strlen(blob_str(&unmodified)) ){ 22552fb803 2007-08-03 dan: fossil_panic("file %s has not changed", blob_str(&unmodified)); 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: } 22552fb803 2007-08-03 dan: 4ac75b9107 2009-01-24 drh: /* 4ac75b9107 2009-01-24 drh: ** Do not allow a commit that will cause a fork unless the --force flag 02a584f7f5 2009-08-26 drh: ** is used or unless this is a private check-in. 02a584f7f5 2009-08-26 drh: */ 02a584f7f5 2009-08-26 drh: if( zBranch==0 && forceFlag==0 && g.markPrivate==0 && !is_a_leaf(vid) ){ 4ac75b9107 2009-01-24 drh: fossil_fatal("would fork. \"update\" first or use -f or --force."); 4ac75b9107 2009-01-24 drh: } 4ac75b9107 2009-01-24 drh: 4ac75b9107 2009-01-24 drh: /* 4ac75b9107 2009-01-24 drh: ** Do not allow a commit against a closed leaf 4ac75b9107 2009-01-24 drh: */ 4ac75b9107 2009-01-24 drh: if( db_exists("SELECT 1 FROM tagxref" 4ac75b9107 2009-01-24 drh: " WHERE tagid=%d AND rid=%d AND tagtype>0", 4ac75b9107 2009-01-24 drh: TAG_CLOSED, vid) ){ 4ac75b9107 2009-01-24 drh: fossil_fatal("cannot commit against a closed leaf"); 4ac75b9107 2009-01-24 drh: } 4ac75b9107 2009-01-24 drh: dbda8d6ce9 2007-07-21 drh: vfile_aggregate_checksum_disk(vid, &cksum1); 9a9cd81738 2007-08-09 drh: if( zComment ){ 9a9cd81738 2007-08-09 drh: blob_zero(&comment); 9a9cd81738 2007-08-09 drh: blob_append(&comment, zComment, -1); 9a9cd81738 2007-08-09 drh: }else{ 9a9cd81738 2007-08-09 drh: prepare_commit_comment(&comment); 6f0a9f730b 2008-11-26 drh: if( blob_size(&comment)==0 ){ 6f0a9f730b 2008-11-26 drh: Blob ans; 6f0a9f730b 2008-11-26 drh: blob_zero(&ans); 6f0a9f730b 2008-11-26 drh: prompt_user("empty check-in comment. continue [y/N]? ", &ans); 6f0a9f730b 2008-11-26 drh: if( blob_str(&ans)[0]!='y' ){ 6f0a9f730b 2008-11-26 drh: db_end_transaction(1); 6f0a9f730b 2008-11-26 drh: exit(1); 6f0a9f730b 2008-11-26 drh: } 6f0a9f730b 2008-11-26 drh: } 9a9cd81738 2007-08-09 drh: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* Step 1: Insert records for all modified files into the blob 22552fb803 2007-08-03 dan: ** table. If there were arguments passed to this command, only 22552fb803 2007-08-03 dan: ** the identified fils are inserted (if they have been modified). 22552fb803 2007-08-03 dan: */ dbda8d6ce9 2007-07-21 drh: db_prepare(&q, 22552fb803 2007-08-03 dan: "SELECT id, %Q || pathname, mrid FROM vfile " 22552fb803 2007-08-03 dan: "WHERE chnged==1 AND NOT deleted AND file_is_selected(id)" 22552fb803 2007-08-03 dan: , g.zLocalRoot 22552fb803 2007-08-03 dan: ); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int id, rid; dbda8d6ce9 2007-07-21 drh: const char *zFullname; dbda8d6ce9 2007-07-21 drh: Blob content; dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: id = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: zFullname = db_column_text(&q, 1); dbda8d6ce9 2007-07-21 drh: rid = db_column_int(&q, 2); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: blob_zero(&content); dbda8d6ce9 2007-07-21 drh: blob_read_from_file(&content, zFullname); 573a464cb7 2007-08-10 drh: nrid = content_put(&content, 0, 0); f6790b7c3c 2009-02-26 drh: blob_reset(&content); dbda8d6ce9 2007-07-21 drh: if( rid>0 ){ dbda8d6ce9 2007-07-21 drh: content_deltify(rid, nrid, 0); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id); e1c1877c99 2007-09-08 drh: db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* Create the manifest */ dbda8d6ce9 2007-07-21 drh: blob_zero(&manifest); 1871a93dd4 2007-08-30 drh: if( blob_size(&comment)==0 ){ 1871a93dd4 2007-08-30 drh: blob_append(&comment, "(no comment)", -1); 1871a93dd4 2007-08-30 drh: } dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, "C %F\n", blob_str(&comment)); f6790b7c3c 2009-02-26 drh: zDate = db_text(0, "SELECT datetime('%q')", zDateOvrd ? zDateOvrd : "now"); dbda8d6ce9 2007-07-21 drh: zDate[10] = 'T'; dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, "D %s\n", zDate); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, 02a584f7f5 2009-08-26 drh: "SELECT pathname, uuid, origname, blob.rid" e146d800ac 2008-11-09 drh: " FROM vfile JOIN blob ON vfile.mrid=blob.rid" ac1dea8eac 2007-07-24 drh: " WHERE NOT deleted AND vfile.vid=%d" dbda8d6ce9 2007-07-21 drh: " ORDER BY 1", vid); 33c31f73cd 2008-02-21 drh: blob_zero(&filename); 33c31f73cd 2008-02-21 drh: blob_appendf(&filename, "%s/", g.zLocalRoot); 33c31f73cd 2008-02-21 drh: nBasename = blob_size(&filename); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: const char *zName = db_column_text(&q, 0); dbda8d6ce9 2007-07-21 drh: const char *zUuid = db_column_text(&q, 1); e146d800ac 2008-11-09 drh: const char *zOrig = db_column_text(&q, 2); 02a584f7f5 2009-08-26 drh: int frid = db_column_int(&q, 3); 33c31f73cd 2008-02-21 drh: const char *zPerm; 33c31f73cd 2008-02-21 drh: blob_append(&filename, zName, -1); 33c31f73cd 2008-02-21 drh: if( file_isexe(blob_str(&filename)) ){ 33c31f73cd 2008-02-21 drh: zPerm = " x"; 33c31f73cd 2008-02-21 drh: }else{ 33c31f73cd 2008-02-21 drh: zPerm = ""; 33c31f73cd 2008-02-21 drh: } 33c31f73cd 2008-02-21 drh: blob_resize(&filename, nBasename); e146d800ac 2008-11-09 drh: if( zOrig==0 || strcmp(zOrig,zName)==0 ){ e146d800ac 2008-11-09 drh: blob_appendf(&manifest, "F %F %s%s\n", zName, zUuid, zPerm); e146d800ac 2008-11-09 drh: }else{ e146d800ac 2008-11-09 drh: if( zPerm[0]==0 ){ zPerm = " w"; } e146d800ac 2008-11-09 drh: blob_appendf(&manifest, "F %F %s%s %F\n", zName, zUuid, zPerm, zOrig); e146d800ac 2008-11-09 drh: } 02a584f7f5 2009-08-26 drh: if( !g.markPrivate ) content_make_public(frid); 33c31f73cd 2008-02-21 drh: } 33c31f73cd 2008-02-21 drh: blob_reset(&filename); dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, "P %s", zUuid); 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: db_prepare(&q2, "SELECT merge FROM vmerge WHERE id=:id"); dbda8d6ce9 2007-07-21 drh: db_bind_int(&q2, ":id", 0); dbda8d6ce9 2007-07-21 drh: while( db_step(&q2)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int mid = db_column_int(&q2, 0); 02a584f7f5 2009-08-26 drh: if( !g.markPrivate && content_is_private(mid) ) continue; dbda8d6ce9 2007-07-21 drh: zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid); dbda8d6ce9 2007-07-21 drh: if( zUuid ){ dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, " %s", zUuid); dbda8d6ce9 2007-07-21 drh: free(zUuid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_reset(&q2); 22552fb803 2007-08-03 dan: dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, "\n"); dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, "R %b\n", &cksum1); 4ac75b9107 2009-01-24 drh: if( zBranch && zBranch[0] ){ 4ac75b9107 2009-01-24 drh: Stmt q; 4ac75b9107 2009-01-24 drh: if( zBgColor && zBgColor[0] ){ 4ac75b9107 2009-01-24 drh: blob_appendf(&manifest, "T *bgcolor * %F\n", zBgColor); 4ac75b9107 2009-01-24 drh: } 4ac75b9107 2009-01-24 drh: blob_appendf(&manifest, "T *branch * %F\n", zBranch); 4ac75b9107 2009-01-24 drh: blob_appendf(&manifest, "T *sym-%F *\n", zBranch); 4ac75b9107 2009-01-24 drh: 4ac75b9107 2009-01-24 drh: /* Cancel all other symbolic tags */ 4ac75b9107 2009-01-24 drh: db_prepare(&q, 4ac75b9107 2009-01-24 drh: "SELECT tagname FROM tagxref, tag" 4ac75b9107 2009-01-24 drh: " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid" 4ac75b9107 2009-01-24 drh: " AND tagtype>0 AND tagname GLOB 'sym-*'" 4ac75b9107 2009-01-24 drh: " AND tagname!='sym-'||%Q" 4ac75b9107 2009-01-24 drh: " ORDER BY tagname", 4ac75b9107 2009-01-24 drh: vid, zBranch); 4ac75b9107 2009-01-24 drh: while( db_step(&q)==SQLITE_ROW ){ 4ac75b9107 2009-01-24 drh: const char *zTag = db_column_text(&q, 0); 8be6204607 2009-02-09 bharder: blob_appendf(&manifest, "T -%F *\n", zTag); 4ac75b9107 2009-01-24 drh: } 4ac75b9107 2009-01-24 drh: db_finalize(&q); 4ac75b9107 2009-01-24 drh: } 8b630bb57a 2009-08-08 drh: blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : g.zLogin); dbda8d6ce9 2007-07-21 drh: md5sum_blob(&manifest, &mcksum); dbda8d6ce9 2007-07-21 drh: blob_appendf(&manifest, "Z %b\n", &mcksum); dbda8d6ce9 2007-07-21 drh: zManifestFile = mprintf("%smanifest", g.zLocalRoot); 02a584f7f5 2009-08-26 drh: if( !noSign && !g.markPrivate && clearsign(&manifest, &manifest) ){ e37451d9c2 2007-08-01 drh: Blob ans; e37451d9c2 2007-08-01 drh: blob_zero(&ans); e37451d9c2 2007-08-01 drh: prompt_user("unable to sign manifest. continue [y/N]? ", &ans); e37451d9c2 2007-08-01 drh: if( blob_str(&ans)[0]!='y' ){ e37451d9c2 2007-08-01 drh: db_end_transaction(1); e37451d9c2 2007-08-01 drh: exit(1); e37451d9c2 2007-08-01 drh: } e37451d9c2 2007-08-01 drh: } e37451d9c2 2007-08-01 drh: blob_write_to_file(&manifest, zManifestFile); dbda8d6ce9 2007-07-21 drh: blob_reset(&manifest); dbda8d6ce9 2007-07-21 drh: blob_read_from_file(&manifest, zManifestFile); dbda8d6ce9 2007-07-21 drh: free(zManifestFile); 573a464cb7 2007-08-10 drh: nvid = content_put(&manifest, 0, 0); dbda8d6ce9 2007-07-21 drh: if( nvid==0 ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("trouble committing manifest: %s", g.zErrMsg); dbda8d6ce9 2007-07-21 drh: } e1c1877c99 2007-09-08 drh: db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); dbda8d6ce9 2007-07-21 drh: manifest_crosslink(nvid, &manifest); dbda8d6ce9 2007-07-21 drh: content_deltify(vid, nvid, 0); dbda8d6ce9 2007-07-21 drh: zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); dbda8d6ce9 2007-07-21 drh: printf("New_Version: %s\n", zUuid); 741aac4d4e 2007-08-25 drh: zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot); 741aac4d4e 2007-08-25 drh: blob_zero(&muuid); 741aac4d4e 2007-08-25 drh: blob_appendf(&muuid, "%s\n", zUuid); 741aac4d4e 2007-08-25 drh: blob_write_to_file(&muuid, zManifestFile); 741aac4d4e 2007-08-25 drh: free(zManifestFile); 741aac4d4e 2007-08-25 drh: blob_reset(&muuid); 741aac4d4e 2007-08-25 drh: 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* Update the vfile and vmerge tables */ 22552fb803 2007-08-03 dan: db_multi_exec( 22552fb803 2007-08-03 dan: "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND file_is_selected(id);" 22552fb803 2007-08-03 dan: "DELETE FROM vmerge WHERE file_is_selected(id) OR id=0;" 22552fb803 2007-08-03 dan: "UPDATE vfile SET vid=%d;" e146d800ac 2008-11-09 drh: "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL" e146d800ac 2008-11-09 drh: " WHERE file_is_selected(id);" 22552fb803 2007-08-03 dan: , vid, nvid 22552fb803 2007-08-03 dan: ); dbda8d6ce9 2007-07-21 drh: db_lset_int("checkout", nvid); dbda8d6ce9 2007-07-21 drh: 22552fb803 2007-08-03 dan: /* Verify that the repository checksum matches the expected checksum 22552fb803 2007-08-03 dan: ** calculated before the checkin started (and stored as the R record 22552fb803 2007-08-03 dan: ** of the manifest file). 22552fb803 2007-08-03 dan: */ dbda8d6ce9 2007-07-21 drh: vfile_aggregate_checksum_repository(nvid, &cksum2); dbda8d6ce9 2007-07-21 drh: if( blob_compare(&cksum1, &cksum2) ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("tree checksum does not match repository after commit"); dbda8d6ce9 2007-07-21 drh: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* Verify that the manifest checksum matches the expected checksum */ 3945057916 2007-08-01 drh: vfile_aggregate_checksum_manifest(nvid, &cksum2, &cksum1b); 3945057916 2007-08-01 drh: if( blob_compare(&cksum1, &cksum1b) ){ 3945057916 2007-08-01 drh: fossil_panic("manifest checksum does not agree with manifest: " 3945057916 2007-08-01 drh: "%b versus %b", &cksum1, &cksum1b); 3945057916 2007-08-01 drh: } 5c3e87171a 2007-08-01 drh: if( blob_compare(&cksum1, &cksum2) ){ 3945057916 2007-08-01 drh: fossil_panic("tree checksum does not match manifest after commit: " 3945057916 2007-08-01 drh: "%b versus %b", &cksum1, &cksum2); 3945057916 2007-08-01 drh: } 22552fb803 2007-08-03 dan: 22552fb803 2007-08-03 dan: /* Verify that the commit did not modify any disk images. */ dbda8d6ce9 2007-07-21 drh: vfile_aggregate_checksum_disk(nvid, &cksum2); dbda8d6ce9 2007-07-21 drh: if( blob_compare(&cksum1, &cksum2) ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("tree checksums before and after commit do not match"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: a36177bcce 2007-09-11 drh: /* Clear the undo/redo stack */ a36177bcce 2007-09-11 drh: undo_reset(); a36177bcce 2007-09-11 drh: dbda8d6ce9 2007-07-21 drh: /* Commit */ dbda8d6ce9 2007-07-21 drh: db_end_transaction(0); 0431f14edf 2007-09-25 jnc: 02a584f7f5 2009-08-26 drh: if( !g.markPrivate ){ 02a584f7f5 2009-08-26 drh: autosync(AUTOSYNC_PUSH); 02a584f7f5 2009-08-26 drh: } 8d5ab7913e 2009-01-21 drh: if( count_nonbranch_children(vid)>1 ){ 49b59bc559 2008-02-09 drh: printf("**** warning: a fork has occurred *****\n"); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** COMMAND: test-import-manifest b7a93530ef 2008-02-01 aku: ** b7a93530ef 2008-02-01 aku: ** Usage: %fossil test-import-manifest DATE COMMENT ?-p PARENT_RECORDID?... ?-f (FILE_RECORDID PATH)?... b7a93530ef 2008-02-01 aku: ** 4c78a18ad2 2008-08-14 bch: ** Create a new version containing the specified file b7a93530ef 2008-02-01 aku: ** revisions (if any), and child of the given PARENT version. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: void import_manifest_cmd(void){ b7a93530ef 2008-02-01 aku: const char* zDate; /* argument - timestamp, as seconds since epoch (int) */ b7a93530ef 2008-02-01 aku: const char* zComment; /* argument - manifest comment */ b7a93530ef 2008-02-01 aku: char* zDateFmt; /* timestamp formatted for the manifest */ b7a93530ef 2008-02-01 aku: int* zParents; /* arguments - array of parent references */ b7a93530ef 2008-02-01 aku: int zParentCount; /* number of found parent references */ b7a93530ef 2008-02-01 aku: Blob manifest; /* container for the manifest to be generated */ b7a93530ef 2008-02-01 aku: Blob mcksum; /* Self-checksum on the manifest */ b7a93530ef 2008-02-01 aku: Blob cksum, cksum2; /* Before and after commit checksums */ b7a93530ef 2008-02-01 aku: Blob cksum1b; /* Checksum recorded in the manifest */ b7a93530ef 2008-02-01 aku: const char* parent; /* loop variable when collecting parent references */ b7a93530ef 2008-02-01 aku: int i, mid; /* Another loop index, and id of new manifest */ b7a93530ef 2008-02-01 aku: Stmt q; /* sql statement to query table of files */ b7fc4d9d04 2008-03-05 aku: char* zMidUuid; /* Uuid for the newly generated manifest */ b7fc4d9d04 2008-03-05 aku: b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: #define USAGE ("DATE COMMENT ?-p|-parent PARENT_RID...? ?-f|-file (FILE_RID PATH)...?") b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Validate and process arguments, collect information. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: db_must_be_within_tree(); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* Mandatory arguments */ b7a93530ef 2008-02-01 aku: if (g.argc < 4) { b7a93530ef 2008-02-01 aku: usage (USAGE); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: zDate = g.argv[2]; b7a93530ef 2008-02-01 aku: zComment = g.argv[3]; b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: remove_from_argv (2,2); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* Pull the optional parent arguments b7a93530ef 2008-02-01 aku: ** b7a93530ef 2008-02-01 aku: ** Note: In principle it is possible that the loop below extracts b7a93530ef 2008-02-01 aku: ** the wrong arguments, if we ever try to import a file whose path b7a93530ef 2008-02-01 aku: ** starts with -p/-parent. In that case however the removal of two b7a93530ef 2008-02-01 aku: ** arguments will leave the file bereft of an argument and the b7a93530ef 2008-02-01 aku: ** recheck of the number of arguments below should catch that. b7a93530ef 2008-02-01 aku: ** b7a93530ef 2008-02-01 aku: ** For a test command this is acceptable, it won't have lots of b7a93530ef 2008-02-01 aku: ** safety nets. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: zParentCount = 0; b7a93530ef 2008-02-01 aku: zParents = (int*)malloc(sizeof(int)*(1+g.argc)); b7a93530ef 2008-02-01 aku: /* 1+, to be ok with the default even if no arguments around */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: while ((parent = find_option("parent","p",1)) != NULL) { b7a93530ef 2008-02-01 aku: /* Check and store ... */ b7a93530ef 2008-02-01 aku: zParents [zParentCount] = name_to_rid (parent); b7a93530ef 2008-02-01 aku: zParentCount ++; b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Fall back to the root manifest as parent if none were specified b7a93530ef 2008-02-01 aku: ** explicitly. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: if (!zParentCount) { b7a93530ef 2008-02-01 aku: zParents [zParentCount] = 1; /* HACK: rid 1 is the baseline manifest b7a93530ef 2008-02-01 aku: ** which was entered when the repository b7a93530ef 2008-02-01 aku: ** was created via 'new'. It always has b7a93530ef 2008-02-01 aku: ** rid 1. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: zParentCount ++; b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* Pull the file arguments, at least one has to be present. They are b7a93530ef 2008-02-01 aku: ** the only things we can have here, now, and they are triples of b7a93530ef 2008-02-01 aku: ** '-f FID PATH', so use of find_option is out, and we can check the b7a93530ef 2008-02-01 aku: ** number of arguments. b7a93530ef 2008-02-01 aku: ** b7a93530ef 2008-02-01 aku: ** Note: We store the data in a temp. table, so that we later can b7a93530ef 2008-02-01 aku: ** pull it sorted, and also easily get the associated hash b7a93530ef 2008-02-01 aku: ** identifiers. b7a93530ef 2008-02-01 aku: ** b7a93530ef 2008-02-01 aku: ** Note 2: We expect at least one file, otherwise the manifest won't b7a93530ef 2008-02-01 aku: ** be recognized as a baseline by the manifest parser. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: if (((g.argc-2) % 3 != 0) || (g.argc < 5)) { b7a93530ef 2008-02-01 aku: usage (USAGE); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: db_begin_transaction(); b7a93530ef 2008-02-01 aku: db_multi_exec ("CREATE TEMP TABLE __im (" dfb6ee3bac 2008-02-02 aku: "rid INTEGER NOT NULL," dfb6ee3bac 2008-02-02 aku: "pathname TEXT NOT NULL)" ); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: while (g.argc > 2) { b7a93530ef 2008-02-01 aku: /* Check and store ... */ b7a93530ef 2008-02-01 aku: if (strcmp("-f", g.argv[2]) && b7a93530ef 2008-02-01 aku: strcmp("-file",g.argv[2])) { b7a93530ef 2008-02-01 aku: usage (USAGE); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* DANGER The %s for the path might lead itself to an injection b7a93530ef 2008-02-01 aku: ** attack. For now (i.e. testing) this is ok, but do something b7a93530ef 2008-02-01 aku: ** better in the future. 41561125cd 2007-09-26 jnc: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: db_multi_exec("INSERT INTO __im VALUES(%d,'%s')", b7a93530ef 2008-02-01 aku: name_to_rid (g.argv[3]), g.argv[4] ); b7a93530ef 2008-02-01 aku: remove_from_argv (2,3); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: verify_all_options(); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Determine the user the manifest will belong to, and check that b7a93530ef 2008-02-01 aku: ** this user exists. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: user_select(); b7a93530ef 2008-02-01 aku: if( !db_exists("SELECT 1 FROM user WHERE login=%Q", g.zLogin) ){ b7a93530ef 2008-02-01 aku: fossil_fatal("no such user: %s", g.zLogin); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Now generate the manifest in memory. b7a93530ef 2008-02-01 aku: ** b7a93530ef 2008-02-01 aku: ** Start with comment and date. The latter is converted to the b7a93530ef 2008-02-01 aku: ** proper format before insertion. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: blob_zero(&manifest); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: if (!strlen(zComment)) { b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "C %F\n", "(no comment)"); b7a93530ef 2008-02-01 aku: } else { bd9703dee6 2008-02-02 aku: blob_appendf(&manifest, "C %F\n", zComment); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: zDateFmt = db_text(0, "SELECT datetime(%Q,'unixepoch')",zDate); b7a93530ef 2008-02-01 aku: zDateFmt[10] = 'T'; b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "D %s\n", zDateFmt); b7a93530ef 2008-02-01 aku: free(zDateFmt); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Follow with all the collected files, properly sorted. Here were b7a93530ef 2008-02-01 aku: ** also compute the checksum over the files (paths, sizes, b7a93530ef 2008-02-01 aku: ** contents), similar to what 'vfile_aggregate_checksum_repository' b7a93530ef 2008-02-01 aku: ** does. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: md5sum_init(); b7a93530ef 2008-02-01 aku: db_prepare(&q, b7a93530ef 2008-02-01 aku: "SELECT pathname, uuid, __im.rid" b7a93530ef 2008-02-01 aku: " FROM __im JOIN blob ON __im.rid=blob.rid" b7a93530ef 2008-02-01 aku: " ORDER BY 1"); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: while( db_step(&q)==SQLITE_ROW ){ b7a93530ef 2008-02-01 aku: char zBuf[100]; b7a93530ef 2008-02-01 aku: Blob file; b7a93530ef 2008-02-01 aku: const char *zName = db_column_text(&q, 0); b7a93530ef 2008-02-01 aku: const char *zUuid = db_column_text(&q, 1); b7a93530ef 2008-02-01 aku: int zRid = db_column_int (&q, 2); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* Extend the manifest */ b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "F %F %s\n", zName, zUuid); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* Update the checksum */ b7a93530ef 2008-02-01 aku: md5sum_step_text(zName, -1); b7a93530ef 2008-02-01 aku: blob_zero(&file); b7a93530ef 2008-02-01 aku: content_get(zRid, &file); b7a93530ef 2008-02-01 aku: sprintf(zBuf, " %d\n", blob_size(&file)); b7a93530ef 2008-02-01 aku: md5sum_step_text(zBuf, -1); b7a93530ef 2008-02-01 aku: md5sum_step_blob(&file); b7a93530ef 2008-02-01 aku: blob_reset(&file); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: db_finalize(&q); b7a93530ef 2008-02-01 aku: md5sum_finish (&cksum); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Follow with all the specified parents. We know that there is at b7a93530ef 2008-02-01 aku: ** least one. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "P"); b7a93530ef 2008-02-01 aku: for (i=0;i<zParentCount;i++) { e146d800ac 2008-11-09 drh: char* zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", zParents[i]); b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, " %s", zUuid); b7a93530ef 2008-02-01 aku: free(zUuid); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "\n"); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Complete the manifest with user name and the various checksums b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "R %b\n", &cksum); b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "U %F\n", g.zLogin); b7a93530ef 2008-02-01 aku: md5sum_blob(&manifest, &mcksum); b7a93530ef 2008-02-01 aku: blob_appendf(&manifest, "Z %b\n", &mcksum); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** Now insert the new manifest, try to compress it relative to first b7a93530ef 2008-02-01 aku: ** parent (primary). b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /*blob_write_to_file (&manifest, "TEST_MANIFEST");*/ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: mid = content_put(&manifest, 0, 0); b7a93530ef 2008-02-01 aku: if( mid==0 ){ b7a93530ef 2008-02-01 aku: fossil_panic("trouble committing manifest: %s", g.zErrMsg); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: content_deltify(zParents[0], mid, 0); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* Verify that the repository checksum matches the expected checksum b7a93530ef 2008-02-01 aku: ** calculated before the checkin started (and stored as the R record b7a93530ef 2008-02-01 aku: ** of the manifest file). b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: vfile_aggregate_checksum_manifest(mid, &cksum2, &cksum1b); b7a93530ef 2008-02-01 aku: if( blob_compare(&cksum, &cksum1b) ){ b7a93530ef 2008-02-01 aku: fossil_panic("manifest checksum does not agree with manifest: " b7a93530ef 2008-02-01 aku: "%b versus %b", &cksum, &cksum1b); b7a93530ef 2008-02-01 aku: } b7a93530ef 2008-02-01 aku: if( blob_compare(&cksum, &cksum2) ){ b7a93530ef 2008-02-01 aku: fossil_panic("tree checksum does not match manifest after commit: " b7a93530ef 2008-02-01 aku: "%b versus %b", &cksum, &cksum2); 0431f14edf 2007-09-25 jnc: } b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7a93530ef 2008-02-01 aku: ** At last commit all changes, after getting rid of the temp b7a93530ef 2008-02-01 aku: ** holder for the files, and release allocated memory. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: db_multi_exec("DROP TABLE __im"); b7fc4d9d04 2008-03-05 aku: zMidUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid); b7a93530ef 2008-02-01 aku: db_end_transaction(0); b7a93530ef 2008-02-01 aku: free(zParents); b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: /* b7fc4d9d04 2008-03-05 aku: ** At the very last inform the caller about the id and uuid of the b7fc4d9d04 2008-03-05 aku: ** new manifest. b7a93530ef 2008-02-01 aku: */ b7a93530ef 2008-02-01 aku: b7fc4d9d04 2008-03-05 aku: b7fc4d9d04 2008-03-05 aku: printf("inserted as record %d, %s\n", mid, zMidUuid); b7fc4d9d04 2008-03-05 aku: free(zMidUuid); b7a93530ef 2008-02-01 aku: return; b7a93530ef 2008-02-01 aku: b7a93530ef 2008-02-01 aku: #undef USAGE dbda8d6ce9 2007-07-21 drh: }