Artifact Content
Not logged in

Artifact 4af4f0ff55bd4fbeef90a57acf89d1658f026843

File src/diffcmd.c part of check-in [01ce2cf3dc] - Added a gdiff command. diff command now runs config diff-command, gdiff command (graphical diff) now runs config gdiff-command. With both, if -i is supplied, internal diff is used. With both, if they are not configured, internal diff is used. Fixed bug with internal diff giving files in reverse order. Also put div id="sub-menu" inside of submenu if, as to not display the sub menu if no sub menu items exist by jnc on 2007-09-24 14:02:30.

/*
** Copyright (c) 2007 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License version 2 as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** General Public License for more details.
** 
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains code used to implement the "diff" command
*/
#include "config.h"
#include "diffcmd.h"
#include <assert.h>

/*
** Shell-escape the given string.  Append the result to a blob.
*/
static void shell_escape(Blob *pBlob, const char *zIn){
  int n = blob_size(pBlob);
  int k = strlen(zIn);
  int i;
  char *z;
  blob_appendf(pBlob, "\"%s\"", zIn);
  z = blob_buffer(pBlob);
  for(i=n+1; i<=n+k; i++){
    if( z[i]=='"' ) z[i] = '_';
  }
}

/*
** COMMAND: diff
** COMMAND: gdiff
**
** Usage: %fossil diff|gdiff ?-i FILE...
**
** Show the difference between the current version of a file (as it
** exists on disk) and that same file as it was checked out.
**
** diff will show a textual diff while gdiff will attempt to run a
** graphical diff command that you have setup. If the choosen command
** is not yet configured, the internal textual diff command will be
** used.
**
** If -i is supplied for either diff or gdiff, the internal textual
** diff command will be executed.
**
** Here are a few external diff command settings, for example:
**
**   %fossil config diff-command=diff
**
**   %fossil config gdiff-command=tkdiff
**   %fossil config gdiff-command=eskill22
**   %fossil config gdiff-command=tortoisemerge
**   %fossil config gdiff-command=meld
**   %fossil config gdiff-command=xxdiff
**   %fossil config gdiff-command=kdiff3
*/
void diff_cmd(void){
  const char *zFile;
  Blob cmd;
  Blob fname;
  int i, internalDiff;
  char *zV1 = 0;
  char *zV2 = 0;
  
  internalDiff = find_option("internal","i",0)!=0;
  
  if( g.argc<3 ){
    usage("?OPTIONS? FILE");
  }
  db_must_be_within_tree();
  
  if( internalDiff==0 ){
    const char *zExternalCommand;
    if( strcmp(g.argv[1], "diff")==0 ){
      zExternalCommand = db_global_get("diff-command", 0);
    }else{
      zExternalCommand = db_global_get("gdiff-command", 0);
    }
    if( zExternalCommand==0 ){
      internalDiff=1;
    }
    blob_zero(&cmd);
    blob_appendf(&cmd, "%s ", zExternalCommand);
  }
  for(i=2; i<g.argc-1; i++){
    const char *z = g.argv[i];
    if( (strcmp(z,"-v")==0 || strcmp(z,"--version")==0) && i<g.argc-2 ){
      if( zV1==0 ){
        zV1 = g.argv[i+1];
      }else if( zV2==0 ){
        zV2 = g.argv[i+1];
      }else{
        fossil_panic("too many versions");
      }
    }else{
      if( internalDiff==0 ){
        blob_appendf(&cmd, "%s ", z);
      }
    }
  }
  zFile = g.argv[g.argc-1];
  if( !file_tree_name(zFile, &fname) ){
    fossil_panic("unknown file: %s", zFile);
  }
  if( zV1==0 ){
    int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);
    Blob record;
    Blob vname;
    int cnt = 0;

    if( rid==0 ){
      fossil_panic("no history for file: %b", &fname);
    }
    blob_zero(&vname);
    do{
      blob_reset(&vname);
      blob_appendf(&vname, "%s~%d", zFile, cnt++);
    }while( access(blob_str(&vname),0)==0 );
    content_get(rid, &record);
    if( internalDiff==1 ){
      Blob current;
      Blob out;
      blob_zero(&current);
      blob_read_from_file(&current, zFile);
      blob_zero(&out);
      unified_diff(&record, &current, 5, &out);
      printf("%s\n", blob_str(&out));
      blob_reset(&current);
      blob_reset(&out);
    }else{
      blob_write_to_file(&record, blob_str(&vname));
      blob_reset(&record);
      shell_escape(&cmd, blob_str(&vname));
      blob_appendf(&cmd, " ");
      shell_escape(&cmd, zFile);
      system(blob_str(&cmd));
      unlink(blob_str(&vname));
      blob_reset(&vname);
      blob_reset(&cmd);
    }
  }else{
    fossil_panic("not yet implemented");
  }
  blob_reset(&fname);
}