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 implement the "diff" command dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "diffcmd.h" dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Shell-escape the given string. Append the result to a blob. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void shell_escape(Blob *pBlob, const char *zIn){ dbda8d6ce9 2007-07-21 drh: int n = blob_size(pBlob); dbda8d6ce9 2007-07-21 drh: int k = strlen(zIn); dbda8d6ce9 2007-07-21 drh: int i; dbda8d6ce9 2007-07-21 drh: char *z; dbda8d6ce9 2007-07-21 drh: blob_appendf(pBlob, "\"%s\"", zIn); dbda8d6ce9 2007-07-21 drh: z = blob_buffer(pBlob); dbda8d6ce9 2007-07-21 drh: for(i=n+1; i<=n+k; i++){ dbda8d6ce9 2007-07-21 drh: if( z[i]=='"' ) z[i] = '_'; 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: ** COMMAND: diff 01ce2cf3dc 2007-09-24 jnc: ** COMMAND: gdiff c9fdb846fb 2007-08-18 drh: ** 574763bab9 2007-09-26 jnc: ** Usage: %fossil diff|gdiff ?-i ?-r REVISION FILE... c82fb61775 2007-09-24 jnc: ** c9fdb846fb 2007-08-18 drh: ** Show the difference between the current version of a file (as it c82fb61775 2007-09-24 jnc: ** exists on disk) and that same file as it was checked out. 01ce2cf3dc 2007-09-24 jnc: ** 01ce2cf3dc 2007-09-24 jnc: ** diff will show a textual diff while gdiff will attempt to run a 01ce2cf3dc 2007-09-24 jnc: ** graphical diff command that you have setup. If the choosen command 01ce2cf3dc 2007-09-24 jnc: ** is not yet configured, the internal textual diff command will be 01ce2cf3dc 2007-09-24 jnc: ** used. 01ce2cf3dc 2007-09-24 jnc: ** 01ce2cf3dc 2007-09-24 jnc: ** If -i is supplied for either diff or gdiff, the internal textual 01ce2cf3dc 2007-09-24 jnc: ** diff command will be executed. c82fb61775 2007-09-24 jnc: ** c82fb61775 2007-09-24 jnc: ** Here are a few external diff command settings, for example: c82fb61775 2007-09-24 jnc: ** 01ce2cf3dc 2007-09-24 jnc: ** %fossil config diff-command=diff 01ce2cf3dc 2007-09-24 jnc: ** 01ce2cf3dc 2007-09-24 jnc: ** %fossil config gdiff-command=tkdiff 01ce2cf3dc 2007-09-24 jnc: ** %fossil config gdiff-command=eskill22 01ce2cf3dc 2007-09-24 jnc: ** %fossil config gdiff-command=tortoisemerge 01ce2cf3dc 2007-09-24 jnc: ** %fossil config gdiff-command=meld 01ce2cf3dc 2007-09-24 jnc: ** %fossil config gdiff-command=xxdiff 01ce2cf3dc 2007-09-24 jnc: ** %fossil config gdiff-command=kdiff3 dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void diff_cmd(void){ 574763bab9 2007-09-26 jnc: const char *zFile, *zRevision; dbda8d6ce9 2007-07-21 drh: Blob cmd; dbda8d6ce9 2007-07-21 drh: Blob fname; 574763bab9 2007-09-26 jnc: Blob vname; 574763bab9 2007-09-26 jnc: Blob record; 574763bab9 2007-09-26 jnc: int cnt=0,internalDiff; c82fb61775 2007-09-24 jnc: 01ce2cf3dc 2007-09-24 jnc: internalDiff = find_option("internal","i",0)!=0; 574763bab9 2007-09-26 jnc: zRevision = find_option("revision", "r", 1); 574763bab9 2007-09-26 jnc: verify_all_options(); dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: if( g.argc<3 ){ dbda8d6ce9 2007-07-21 drh: usage("?OPTIONS? FILE"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); c82fb61775 2007-09-24 jnc: c82fb61775 2007-09-24 jnc: if( internalDiff==0 ){ 01ce2cf3dc 2007-09-24 jnc: const char *zExternalCommand; 01ce2cf3dc 2007-09-24 jnc: if( strcmp(g.argv[1], "diff")==0 ){ 134e2aeccc 2007-09-28 drh: zExternalCommand = db_get("diff-command", 0); dbda8d6ce9 2007-07-21 drh: }else{ 134e2aeccc 2007-09-28 drh: zExternalCommand = db_get("gdiff-command", 0); 01ce2cf3dc 2007-09-24 jnc: } c82fb61775 2007-09-24 jnc: if( zExternalCommand==0 ){ c82fb61775 2007-09-24 jnc: internalDiff=1; dbda8d6ce9 2007-07-21 drh: } 01ce2cf3dc 2007-09-24 jnc: blob_zero(&cmd); 01ce2cf3dc 2007-09-24 jnc: blob_appendf(&cmd, "%s ", zExternalCommand); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: zFile = g.argv[g.argc-1]; dbda8d6ce9 2007-07-21 drh: if( !file_tree_name(zFile, &fname) ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("unknown file: %s", zFile); dbda8d6ce9 2007-07-21 drh: } 574763bab9 2007-09-26 jnc: 574763bab9 2007-09-26 jnc: blob_zero(&vname); 574763bab9 2007-09-26 jnc: do{ 574763bab9 2007-09-26 jnc: blob_reset(&vname); 574763bab9 2007-09-26 jnc: blob_appendf(&vname, "%s~%d", zFile, cnt++); 574763bab9 2007-09-26 jnc: }while( access(blob_str(&vname),0)==0 ); dbda8d6ce9 2007-07-21 drh: 574763bab9 2007-09-26 jnc: if( zRevision==0 ){ 574763bab9 2007-09-26 jnc: int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); dbda8d6ce9 2007-07-21 drh: if( rid==0 ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("no history for file: %b", &fname); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: content_get(rid, &record); 574763bab9 2007-09-26 jnc: }else{ 574763bab9 2007-09-26 jnc: content_get_historical_file(zRevision, zFile, &record); 574763bab9 2007-09-26 jnc: } 574763bab9 2007-09-26 jnc: if( internalDiff==1 ){ 574763bab9 2007-09-26 jnc: Blob out; 574763bab9 2007-09-26 jnc: Blob current; 574763bab9 2007-09-26 jnc: blob_zero(¤t); 574763bab9 2007-09-26 jnc: blob_read_from_file(¤t, zFile); 574763bab9 2007-09-26 jnc: blob_zero(&out); 57b2735ebd 2007-11-15 drh: text_diff(&record, ¤t, &out, 5); 574763bab9 2007-09-26 jnc: printf("%s\n", blob_str(&out)); 574763bab9 2007-09-26 jnc: blob_reset(¤t); 574763bab9 2007-09-26 jnc: blob_reset(&out); c82fb61775 2007-09-24 jnc: }else{ dbda8d6ce9 2007-07-21 drh: blob_write_to_file(&record, blob_str(&vname)); dbda8d6ce9 2007-07-21 drh: blob_reset(&record); dbda8d6ce9 2007-07-21 drh: shell_escape(&cmd, blob_str(&vname)); dbda8d6ce9 2007-07-21 drh: blob_appendf(&cmd, " "); dbda8d6ce9 2007-07-21 drh: shell_escape(&cmd, zFile); dbda8d6ce9 2007-07-21 drh: system(blob_str(&cmd)); dbda8d6ce9 2007-07-21 drh: unlink(blob_str(&vname)); dbda8d6ce9 2007-07-21 drh: blob_reset(&vname); dbda8d6ce9 2007-07-21 drh: blob_reset(&cmd); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&fname); dbda8d6ce9 2007-07-21 drh: }