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 c9fdb846fb 2007-08-18 drh: ** c82fb61775 2007-09-24 jnc: ** Usage: %fossil diff ?-i 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. c82fb61775 2007-09-24 jnc: ** If -i is supplied, the internal diff command will be executed c82fb61775 2007-09-24 jnc: ** otherwise, fossil attempts to use the user configured diff-command. 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: ** c82fb61775 2007-09-24 jnc: ** %fossil config diff-command=tkdiff c82fb61775 2007-09-24 jnc: ** %fossil config diff-command=eskill22 c82fb61775 2007-09-24 jnc: ** %fossil config diff-command=tortoisemerge c82fb61775 2007-09-24 jnc: ** %fossil config diff-command=meld c82fb61775 2007-09-24 jnc: ** %fossil config diff-command=xxdiff c82fb61775 2007-09-24 jnc: ** %fossil config diff-command=kdiff3 dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void diff_cmd(void){ dbda8d6ce9 2007-07-21 drh: const char *zFile; dbda8d6ce9 2007-07-21 drh: Blob cmd; dbda8d6ce9 2007-07-21 drh: Blob fname; c82fb61775 2007-09-24 jnc: int i, internalDiff; dbda8d6ce9 2007-07-21 drh: char *zV1 = 0; dbda8d6ce9 2007-07-21 drh: char *zV2 = 0; c82fb61775 2007-09-24 jnc: c82fb61775 2007-09-24 jnc: internalDiff = find_option("intertal","i",0)!=0; 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 ){ c82fb61775 2007-09-24 jnc: const char *zExternalCommand = db_global_get("diff-command", 0); c82fb61775 2007-09-24 jnc: if( zExternalCommand==0 ){ c82fb61775 2007-09-24 jnc: internalDiff=1; c82fb61775 2007-09-24 jnc: } c82fb61775 2007-09-24 jnc: blob_zero(&cmd); c82fb61775 2007-09-24 jnc: blob_appendf(&cmd, "%s ", zExternalCommand); c82fb61775 2007-09-24 jnc: } dbda8d6ce9 2007-07-21 drh: for(i=2; i<g.argc-1; i++){ dbda8d6ce9 2007-07-21 drh: const char *z = g.argv[i]; dbda8d6ce9 2007-07-21 drh: if( (strcmp(z,"-v")==0 || strcmp(z,"--version")==0) && i<g.argc-2 ){ dbda8d6ce9 2007-07-21 drh: if( zV1==0 ){ dbda8d6ce9 2007-07-21 drh: zV1 = g.argv[i+1]; dbda8d6ce9 2007-07-21 drh: }else if( zV2==0 ){ dbda8d6ce9 2007-07-21 drh: zV2 = g.argv[i+1]; dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: fossil_panic("too many versions"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: }else{ c82fb61775 2007-09-24 jnc: if( internalDiff==0 ){ c82fb61775 2007-09-24 jnc: blob_appendf(&cmd, "%s ", z); c82fb61775 2007-09-24 jnc: } dbda8d6ce9 2007-07-21 drh: } 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: } dbda8d6ce9 2007-07-21 drh: if( zV1==0 ){ dbda8d6ce9 2007-07-21 drh: int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); dbda8d6ce9 2007-07-21 drh: Blob record; dbda8d6ce9 2007-07-21 drh: Blob vname; dbda8d6ce9 2007-07-21 drh: int cnt = 0; dbda8d6ce9 2007-07-21 drh: 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: blob_zero(&vname); dbda8d6ce9 2007-07-21 drh: do{ dbda8d6ce9 2007-07-21 drh: blob_reset(&vname); dbda8d6ce9 2007-07-21 drh: blob_appendf(&vname, "%s~%d", zFile, cnt++); dbda8d6ce9 2007-07-21 drh: }while( access(blob_str(&vname),0)==0 ); dbda8d6ce9 2007-07-21 drh: content_get(rid, &record); c82fb61775 2007-09-24 jnc: if( internalDiff==1 ){ c82fb61775 2007-09-24 jnc: Blob current; c82fb61775 2007-09-24 jnc: Blob out; c82fb61775 2007-09-24 jnc: blob_zero(¤t); c82fb61775 2007-09-24 jnc: blob_read_from_file(¤t, zFile); c82fb61775 2007-09-24 jnc: blob_zero(&out); c82fb61775 2007-09-24 jnc: unified_diff(¤t, &record, 5, &out); c82fb61775 2007-09-24 jnc: printf("%s\n", blob_str(&out)); c82fb61775 2007-09-24 jnc: blob_reset(¤t); c82fb61775 2007-09-24 jnc: blob_reset(&out); c82fb61775 2007-09-24 jnc: }else{ c82fb61775 2007-09-24 jnc: blob_write_to_file(&record, blob_str(&vname)); c82fb61775 2007-09-24 jnc: blob_reset(&record); c82fb61775 2007-09-24 jnc: shell_escape(&cmd, blob_str(&vname)); c82fb61775 2007-09-24 jnc: blob_appendf(&cmd, " "); c82fb61775 2007-09-24 jnc: shell_escape(&cmd, zFile); c82fb61775 2007-09-24 jnc: system(blob_str(&cmd)); c82fb61775 2007-09-24 jnc: unlink(blob_str(&vname)); c82fb61775 2007-09-24 jnc: blob_reset(&vname); c82fb61775 2007-09-24 jnc: blob_reset(&cmd); c82fb61775 2007-09-24 jnc: } dbda8d6ce9 2007-07-21 drh: }else{ dbda8d6ce9 2007-07-21 drh: fossil_panic("not yet implemented"); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&fname); dbda8d6ce9 2007-07-21 drh: }