Fossil

Check-in [585360b4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Work towards including full text of deleted and added files in a diff when the -N or --new-file option is used. Ticket [e90d38c2054e9b44792eb]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:585360b47dad7384b7d5c5b7926d1beb77e9e5cd
User & Date: drh 2010-10-14 18:38:46
Context
2010-10-14
18:48
Remove a bunch of unused code. check-in: 62f8acbe user: drh tags: trunk
18:38
Work towards including full text of deleted and added files in a diff when the -N or --new-file option is used. Ticket [e90d38c2054e9b44792eb] check-in: 585360b4 user: drh tags: trunk
2010-10-12
21:42
Fix the default Makefile so that it works out-of-the-box on Linux, MacOSX, NetBSD, and Solaris. check-in: c845b287 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/blob.c.

610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  if( zFilename==0 || zFilename[0]==0
        || (zFilename[0]=='-' && zFilename[1]==0) ){
    return blob_read_from_channel(pBlob, stdin, -1);
  }
  size = file_size(zFilename);
  blob_zero(pBlob);
  if( size<0 ){
    fossil_panic("no such file: %s", zFilename);
  }
  if( size==0 ){
    return 0;
  }
  blob_resize(pBlob, size);
  in = fopen(zFilename, "rb");
  if( in==0 ){







|







610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
  if( zFilename==0 || zFilename[0]==0
        || (zFilename[0]=='-' && zFilename[1]==0) ){
    return blob_read_from_channel(pBlob, stdin, -1);
  }
  size = file_size(zFilename);
  blob_zero(pBlob);
  if( size<0 ){
    fossil_fatal("no such file: %s", zFilename);
  }
  if( size==0 ){
    return 0;
  }
  blob_resize(pBlob, size);
  in = fopen(zFilename, "rb");
  if( in==0 ){

Changes to src/diff.c.

97
98
99
100
101
102
103




104
105
106
107
108
109
110
  }
  if( j>LENGTH_MASK ){
    return 0;
  }
  a = malloc( nLine*sizeof(a[0]) );
  if( a==0 ) fossil_panic("out of memory");
  memset(a, 0, nLine*sizeof(a[0]) );





  /* Fill in the array */
  for(i=0; i<nLine; i++){
    a[i].z = z;
    for(j=0; z[j] && z[j]!='\n'; j++){}
    k = j;
    while( ignoreWS && k>0 && isspace(z[k-1]) ){ k--; }







>
>
>
>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  }
  if( j>LENGTH_MASK ){
    return 0;
  }
  a = malloc( nLine*sizeof(a[0]) );
  if( a==0 ) fossil_panic("out of memory");
  memset(a, 0, nLine*sizeof(a[0]) );
  if( n==0 ){
    *pnLine = 0;
    return a;
  }

  /* Fill in the array */
  for(i=0; i<nLine; i++){
    a[i].z = z;
    for(j=0; z[j] && z[j]!='\n'; j++){}
    k = j;
    while( ignoreWS && k>0 && isspace(z[k-1]) ){ k--; }

Changes to src/diffcmd.c.

17
18
19
20
21
22
23






24
25
26
27
28
29
30
..
51
52
53
54
55
56
57
58
59
60
61
62

63
64
65



66


67
68
69
70
71
72
73
74
75
76
77
78
...
181
182
183
184
185
186
187
188
189
190
191
192


193


194
195
196
197
198
199
200
...
233
234
235
236
237
238
239

240

241
242

243
244

245
246


247
248
249
250



251

252



253
254
255
256
257
258
259
...
290
291
292
293
294
295
296
297
298
299
300


301
302
303
304
305
306
307
...
368
369
370
371
372
373
374

375
376
377

378
379
380
381
382

383


384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
**
** This file contains code used to implement the "diff" command
*/
#include "config.h"
#include "diffcmd.h"
#include <assert.h>







/*
** This function implements a cross-platform "system()" interface.
*/
int portable_system(const char *zOrigCmd){
  int rc;
#if defined(_WIN32)
  /* On windows, we have to put double-quotes around the entire command.
................................................................................
** command zDiffCmd to do the diffing.
*/
static void diff_file(
  Blob *pFile1,             /* In memory content to compare from */
  const char *zFile2,       /* On disk content to compare to */
  const char *zName,        /* Display name of the file */
  const char *zDiffCmd,     /* Command for comparison */
  int ignoreEolWs           /* Ignore whitespace at end of lines */
){
  if( zDiffCmd==0 ){
    Blob out;      /* Diff output text */
    Blob file2;    /* Content of zFile2 */


    /* Read content of zFile2 into memory */
    blob_zero(&file2);



    blob_read_from_file(&file2, zFile2);



    /* Compute and output the differences */
    blob_zero(&out);
    text_diff(pFile1, &file2, &out, 5, ignoreEolWs);
    printf("--- %s\n+++ %s\n", zName, zName);
    printf("%s\n", blob_str(&out));

    /* Release memory resources */
    blob_reset(&file2);
    blob_reset(&out);
  }else{
    int cnt = 0;
................................................................................
** Run a diff between the version zFrom and files on disk.  zFrom might
** be NULL which means to simply show the difference between the edited
** files on disk and the check-out on which they are based.
*/
static void diff_all_against_disk(
  const char *zFrom,        /* Version to difference from */
  const char *zDiffCmd,     /* Use this diff command.  NULL for built-in */
  int ignoreEolWs           /* Ignore end-of-line whitespace */
){
  int vid;
  Blob sql;
  Stmt q;





  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 1);
  blob_zero(&sql);
  db_begin_transaction();
  if( zFrom ){
    int rid = name_to_rid(zFrom);
    if( !is_a_version(rid) ){
................................................................................
  }
  db_prepare(&q, blob_str(&sql));
  while( db_step(&q)==SQLITE_ROW ){
    const char *zPathname = db_column_text(&q,0);
    int isDeleted = db_column_int(&q, 1);
    int isChnged = db_column_int(&q,2);
    int isNew = db_column_int(&q,3);

    char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);

    if( isDeleted ){
      printf("DELETED  %s\n", zPathname);

    }else if( access(zFullName, 0) ){
      printf("MISSING  %s\n", zPathname);

    }else if( isNew ){
      printf("ADDED    %s\n", zPathname);


    }else if( isChnged==3 ){
      printf("ADDED_BY_MERGE %s\n", zPathname);
    }else{
      int srcid = db_column_int(&q, 4);



      Blob content;

      content_get(srcid, &content);



      printf("Index: %s\n======================================="
             "============================\n",
             zPathname
      );
      diff_file(&content, zFullName, zPathname, zDiffCmd, ignoreEolWs);
      blob_reset(&content);
    }
................................................................................
/*
** Output the differences between two check-ins.
*/
static void diff_all_two_versions(
  const char *zFrom,
  const char *zTo,
  const char *zDiffCmd,
  int ignoreEolWs
){
  Manifest mFrom, mTo;
  int iFrom, iTo;



  manifest_from_name(zFrom, &mFrom);
  manifest_from_name(zTo, &mTo);
  iFrom = iTo = 0;
  while( iFrom<mFrom.nFile && iTo<mTo.nFile ){
    int cmp;
    if( iFrom>=mFrom.nFile ){
................................................................................
** rather than any external diff program that might be configured using
** the "setting" command.  If no external diff program is configured, then
** the "-i" option is a no-op.  The "-i" option converts "gdiff" into "diff".
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */

  const char *zFrom;         /* Source version number */
  const char *zTo;           /* Target version number */
  const char *zDiffCmd = 0;  /* External diff command. NULL for internal diff */


  isGDiff = g.argv[1][0]=='g';
  isInternDiff = find_option("internal","i",0)!=0;
  zFrom = find_option("from", "r", 1);
  zTo = find_option("to", 0, 1);




  if( zTo==0 ){
    db_must_be_within_tree();
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc==3 ){
      diff_one_against_disk(zFrom, zDiffCmd, 0);
    }else{
      diff_all_against_disk(zFrom, zDiffCmd, 0);
    }
  }else if( zFrom==0 ){
    fossil_fatal("must use --from if --to is present");
  }else{
    db_find_and_open_repository(1);
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc==3 ){
      diff_one_two_versions(zFrom, zTo, zDiffCmd, 0);
    }else{
      diff_all_two_versions(zFrom, zTo, zDiffCmd, 0);
    }
  }
}







>
>
>
>
>
>







 







|


|
|
>



>
>
>
|
>
>




|







 







|




>
>

>
>







 







>

>


>


>


>
>


<
|
>
>
>

>
|
>
>
>







 







|



>
>







 







>



>





>

>
>









|












|



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
**
** This file contains code used to implement the "diff" command
*/
#include "config.h"
#include "diffcmd.h"
#include <assert.h>

/*
** Diff option flags
*/
#define DIFF_NEWFILE  0x01    /* Treat non-existing fails as empty files */
#define DIFF_NOEOLWS  0x02    /* Ignore whitespace at the end of lines */

/*
** This function implements a cross-platform "system()" interface.
*/
int portable_system(const char *zOrigCmd){
  int rc;
#if defined(_WIN32)
  /* On windows, we have to put double-quotes around the entire command.
................................................................................
** command zDiffCmd to do the diffing.
*/
static void diff_file(
  Blob *pFile1,             /* In memory content to compare from */
  const char *zFile2,       /* On disk content to compare to */
  const char *zName,        /* Display name of the file */
  const char *zDiffCmd,     /* Command for comparison */
  int ignoreEolWs           /* Ignore whitespace at end of line */
){
  if( zDiffCmd==0 ){
    Blob out;                 /* Diff output text */
    Blob file2;               /* Content of zFile2 */
    const char *zName2;       /* Name of zFile2 for display */

    /* Read content of zFile2 into memory */
    blob_zero(&file2);
    if( file_size(zFile2)<0 ){
      zName2 = "/dev/null";
    }else{
      blob_read_from_file(&file2, zFile2);
      zName2 = zName;
    }

    /* Compute and output the differences */
    blob_zero(&out);
    text_diff(pFile1, &file2, &out, 5, ignoreEolWs);
    printf("--- %s\n+++ %s\n", zName, zName2);
    printf("%s\n", blob_str(&out));

    /* Release memory resources */
    blob_reset(&file2);
    blob_reset(&out);
  }else{
    int cnt = 0;
................................................................................
** Run a diff between the version zFrom and files on disk.  zFrom might
** be NULL which means to simply show the difference between the edited
** files on disk and the check-out on which they are based.
*/
static void diff_all_against_disk(
  const char *zFrom,        /* Version to difference from */
  const char *zDiffCmd,     /* Use this diff command.  NULL for built-in */
  int diffFlags             /* Flags controlling diff output */
){
  int vid;
  Blob sql;
  Stmt q;
  int ignoreEolWs;          /* Ignore end-of-line whitespace */
  int asNewFile;            /* Treat non-existant files as empty files */

  ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0;
  asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 1);
  blob_zero(&sql);
  db_begin_transaction();
  if( zFrom ){
    int rid = name_to_rid(zFrom);
    if( !is_a_version(rid) ){
................................................................................
  }
  db_prepare(&q, blob_str(&sql));
  while( db_step(&q)==SQLITE_ROW ){
    const char *zPathname = db_column_text(&q,0);
    int isDeleted = db_column_int(&q, 1);
    int isChnged = db_column_int(&q,2);
    int isNew = db_column_int(&q,3);
    int srcid = db_column_int(&q, 4);
    char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
    int showDiff = 1;
    if( isDeleted ){
      printf("DELETED  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; }
    }else if( access(zFullName, 0) ){
      printf("MISSING  %s\n", zPathname);
      if( !asNewFile ){ showDiff = 0; }
    }else if( isNew ){
      printf("ADDED    %s\n", zPathname);
      srcid = 0;
      if( !asNewFile ){ showDiff = 0; }
    }else if( isChnged==3 ){
      printf("ADDED_BY_MERGE %s\n", zPathname);

      srcid = 0;
      if( !asNewFile ){ showDiff = 0; }
    }
    if( showDiff ){
      Blob content;
      if( srcid>0 ){
        content_get(srcid, &content);
      }else{
        blob_zero(&content);
      }
      printf("Index: %s\n======================================="
             "============================\n",
             zPathname
      );
      diff_file(&content, zFullName, zPathname, zDiffCmd, ignoreEolWs);
      blob_reset(&content);
    }
................................................................................
/*
** Output the differences between two check-ins.
*/
static void diff_all_two_versions(
  const char *zFrom,
  const char *zTo,
  const char *zDiffCmd,
  int diffFlags
){
  Manifest mFrom, mTo;
  int iFrom, iTo;
  int ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0 ? 1 : 0;
  /* int asNewFlag = (diffFlags & DIFF_NEWFILE)!=0 ? 1 : 0; */

  manifest_from_name(zFrom, &mFrom);
  manifest_from_name(zTo, &mTo);
  iFrom = iTo = 0;
  while( iFrom<mFrom.nFile && iTo<mTo.nFile ){
    int cmp;
    if( iFrom>=mFrom.nFile ){
................................................................................
** rather than any external diff program that might be configured using
** the "setting" command.  If no external diff program is configured, then
** the "-i" option is a no-op.  The "-i" option converts "gdiff" into "diff".
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */
  int hasNFlag;              /* True if -N or --new-file flag is used */
  const char *zFrom;         /* Source version number */
  const char *zTo;           /* Target version number */
  const char *zDiffCmd = 0;  /* External diff command. NULL for internal diff */
  int diffFlags = 0;         /* Flags to control the DIFF */

  isGDiff = g.argv[1][0]=='g';
  isInternDiff = find_option("internal","i",0)!=0;
  zFrom = find_option("from", "r", 1);
  zTo = find_option("to", 0, 1);
  hasNFlag = find_option("new-file","N",0)!=0;


  if( hasNFlag ) diffFlags |= DIFF_NEWFILE;
  if( zTo==0 ){
    db_must_be_within_tree();
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc==3 ){
      diff_one_against_disk(zFrom, zDiffCmd, 0);
    }else{
      diff_all_against_disk(zFrom, zDiffCmd, diffFlags);
    }
  }else if( zFrom==0 ){
    fossil_fatal("must use --from if --to is present");
  }else{
    db_find_and_open_repository(1);
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc==3 ){
      diff_one_two_versions(zFrom, zTo, zDiffCmd, 0);
    }else{
      diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
    }
  }
}