Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Improved formatting for command-line side-by-side diff. Extend command-line side-by-side diff to all diff operations, including stash diffs. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
ab47cc73d7d95c78cf2e796654e536fb |
| User & Date: | drh 2011-10-21 23:44:14.026 |
Context
|
2011-10-22
| ||
| 03:37 | Rework the side-by-side diff so that it handles tab characters. Fix an off-by-one error in the line numbers of side-by-side diffs. ... (check-in: 8670373321 user: drh tags: trunk) | |
|
2011-10-21
| ||
| 23:44 | Improved formatting for command-line side-by-side diff. Extend command-line side-by-side diff to all diff operations, including stash diffs. ... (check-in: ab47cc73d7 user: drh tags: trunk) | |
| 21:55 | Merge the side-by-side diff spacing bug fix into trunk. ... (check-in: 54e730c339 user: drh tags: trunk) | |
Changes
Changes to src/diff.c.
| ︙ | ︙ | |||
387 388 389 390 391 392 393 |
nb += R[r+i*3];
}
/*
* If the patch changes an empty file or results in an empty file,
* the block header must use 0,0 as position indicator and not 1,0.
* Otherwise, patch would be confused and may reject the diff.
*/
| | < < | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
nb += R[r+i*3];
}
/*
* If the patch changes an empty file or results in an empty file,
* the block header must use 0,0 as position indicator and not 1,0.
* Otherwise, patch would be confused and may reject the diff.
*/
if( r>0 ) blob_appendf(pOut,"%.*c\n", width*2+16, '.');
/* Show the initial common area */
a += skip;
b += skip;
m = R[r] - skip;
for(j=0; j<m; j++){
blob_appendf(pOut, "%6d ", a+j);
|
| ︙ | ︙ | |||
696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
expandEdit(p, p->nEdit+3);
if( p->aEdit ){
p->aEdit[p->nEdit++] = 0;
p->aEdit[p->nEdit++] = 0;
p->aEdit[p->nEdit++] = 0;
}
}
/*
** Generate a report of the differences between files pA and pB.
** If pOut is not NULL then a unified diff is appended there. It
** is assumed that pOut has already been initialized. If pOut is
** NULL, then a pointer to an array of integers is returned.
** The integers come in triples. For each triple,
| > > > > > > > > > > > > > > > > > > > > | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 |
expandEdit(p, p->nEdit+3);
if( p->aEdit ){
p->aEdit[p->nEdit++] = 0;
p->aEdit[p->nEdit++] = 0;
p->aEdit[p->nEdit++] = 0;
}
}
/*
** Extract the number of lines of context from diffFlags. Supply an
** appropriate default if no context width is specified.
*/
int diff_context_lines(int diffFlags){
int n = diffFlags & DIFF_CONTEXT_MASK;
if( n==0 ) n = 5;
return n;
}
/*
** Extract the width of columns for side-by-side diff. Supply an
** appropriate default if no width is given.
*/
int diff_width(int diffFlags){
int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1);
if( w==0 ) w = 80;
return w;
}
/*
** Generate a report of the differences between files pA and pB.
** If pOut is not NULL then a unified diff is appended there. It
** is assumed that pOut has already been initialized. If pOut is
** NULL, then a pointer to an array of integers is returned.
** The integers come in triples. For each triple,
|
| ︙ | ︙ | |||
721 722 723 724 725 726 727 |
Blob *pOut, /* Write diff here if not NULL */
int diffFlags /* DIFF_* flags defined above */
){
int ignoreEolWs; /* Ignore whitespace at the end of lines */
int nContext; /* Amount of context to display */
DContext c;
| | < | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
Blob *pOut, /* Write diff here if not NULL */
int diffFlags /* DIFF_* flags defined above */
){
int ignoreEolWs; /* Ignore whitespace at the end of lines */
int nContext; /* Amount of context to display */
DContext c;
nContext = diff_context_lines(diffFlags);
ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
/* Prepare the input files */
memset(&c, 0, sizeof(c));
c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
&c.nFrom, ignoreEolWs);
c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
|
| ︙ | ︙ | |||
746 747 748 749 750 751 752 |
/* Compute the difference */
diff_all(&c);
if( pOut ){
/* Compute a context or side-by-side diff into pOut */
if( diffFlags & DIFF_SIDEBYSIDE ){
| < | | 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 |
/* Compute the difference */
diff_all(&c);
if( pOut ){
/* Compute a context or side-by-side diff into pOut */
if( diffFlags & DIFF_SIDEBYSIDE ){
int width = diff_width(diffFlags);
sbsDiff(&c, pOut, nContext, width);
}else{
contextDiff(&c, pOut, nContext);
}
free(c.aFrom);
free(c.aTo);
free(c.aEdit);
|
| ︙ | ︙ | |||
971 972 973 974 975 976 977 978 979 980 981 982 983 |
for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
}
/* free(R); */
blob_reset(&b);
}
}
/*
** COMMAND: test-udiff
*/
void test_udiff_cmd(void){
Blob a, b, out;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < | < < | | | 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]);
}
/* free(R); */
blob_reset(&b);
}
}
/*
** Process diff-related command-line options and return an appropriate
** "diffFlags" integer.
**
** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
** --context|-c N N lines of context. DIFF_CONTEXT_MASK
** --width|-W N N character lines. DIFF_WIDTH_MASK
*/
int diff_options(void){
int diffFlags = 0;
const char *z;
int f;
if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE;
if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){
if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK;
diffFlags |= f;
}
if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){
f *= DIFF_CONTEXT_MASK+1;
if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
diffFlags |= f;
}
return diffFlags;
}
/*
** COMMAND: test-udiff
**
** Print the difference between two files. The usual diff options apply.
*/
void test_udiff_cmd(void){
Blob a, b, out;
int diffFlag = diff_options();
if( g.argc!=4 ) usage("FILE1 FILE2");
blob_read_from_file(&a, g.argv[2]);
blob_read_from_file(&b, g.argv[3]);
blob_zero(&out);
text_diff(&a, &b, &out, diffFlag);
blob_write_to_file(&out, "-");
}
/**************************************************************************
** The basic difference engine is above. What follows is the annotation
** engine. Both are in the same file since they share many components.
*/
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
33 34 35 36 37 38 39 |
}else{
vprintf(zFormat, ap);
}
va_end(ap);
}
/*
| | | > > | > > > | > > > > > > > > > > > > > > > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
}else{
vprintf(zFormat, ap);
}
va_end(ap);
}
/*
** Print the "Index:" message that patches wants to see at the top of a diff.
*/
void diff_print_index(const char *zFile, int diffFlags){
if( (diffFlags & DIFF_SIDEBYSIDE)==0 ){
char *z = mprintf("Index: %s\n%.66c\n", zFile, '=');
diff_printf("%s", z);
fossil_free(z);
}
}
/*
** Print the +++/--- filename lines for a diff operation.
*/
void diff_print_filenames(const char *zLeft, const char *zRight, int diffFlags){
char *z = 0;
if( diffFlags & DIFF_SIDEBYSIDE ){
int w = diff_width(diffFlags);
int n1 = strlen(zLeft);
int x;
if( n1>w*2 ) n1 = w*2;
x = w*2+17 - (n1+2);
z = mprintf("%.*c %.*s %.*c\n",
x/2, '=', n1, zLeft, (x+1)/2, '=');
}else{
z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
}
diff_printf("%s", z);
fossil_free(z);
}
/*
** Show the difference between two files, one in memory and one on disk.
**
** The difference is the set of edits needed to transform pFile1 into
** zFile2. The content of pFile1 is in memory. zFile2 exists on disk.
|
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
zName2 = zName;
}
/* Compute and output the differences */
blob_zero(&out);
text_diff(pFile1, &file2, &out, diffFlags);
if( blob_size(&out) ){
| | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
zName2 = zName;
}
/* Compute and output the differences */
blob_zero(&out);
text_diff(pFile1, &file2, &out, diffFlags);
if( blob_size(&out) ){
diff_print_filenames(zName, zName2, diffFlags);
diff_printf("%s\n", blob_str(&out));
}
/* Release memory resources */
blob_reset(&file2);
blob_reset(&out);
}else{
|
| ︙ | ︙ | |||
137 138 139 140 141 142 143 |
int diffFlags /* Diff flags */
){
if( zDiffCmd==0 ){
Blob out; /* Diff output text */
blob_zero(&out);
text_diff(pFile1, pFile2, &out, diffFlags);
| | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
int diffFlags /* Diff flags */
){
if( zDiffCmd==0 ){
Blob out; /* Diff output text */
blob_zero(&out);
text_diff(pFile1, pFile2, &out, diffFlags);
diff_print_filenames(zName, zName, diffFlags);
diff_printf("%s\n", blob_str(&out));
/* Release memory resources */
blob_reset(&out);
}else{
Blob cmd;
char zTemp1[300];
|
| ︙ | ︙ | |||
279 280 281 282 283 284 285 |
diff_printf("ADDED_BY_MERGE %s\n", zPathname);
srcid = 0;
if( !asNewFile ){ showDiff = 0; }
}
if( showDiff ){
Blob content;
if( !isLink != !file_wd_islink(zFullName) ){
| | | | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
diff_printf("ADDED_BY_MERGE %s\n", zPathname);
srcid = 0;
if( !asNewFile ){ showDiff = 0; }
}
if( showDiff ){
Blob content;
if( !isLink != !file_wd_islink(zFullName) ){
diff_print_index(zPathname, diffFlags);
diff_print_filenames(zPathname, zPathname, diffFlags);
diff_printf("cannot compute difference between symlink and regular file\n");
continue;
}
if( srcid>0 ){
content_get(srcid, &content);
}else{
blob_zero(&content);
}
diff_print_index(zPathname, diffFlags);
diff_file(&content, zFullName, zPathname, zDiffCmd, diffFlags);
blob_reset(&content);
}
free(zToFree);
}
db_finalize(&q);
db_end_transaction(1); /* ROLLBACK */
|
| ︙ | ︙ | |||
319 320 321 322 323 324 325 |
Blob v1, v2;
int isLink1, isLink2;
file_tree_name(zFileTreeName, &fname, 1);
zName = blob_str(&fname);
historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, 0);
historical_version_of_file(zTo, zName, &v2, &isLink2, 0, 0);
if( isLink1 != isLink2 ){
| | | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
Blob v1, v2;
int isLink1, isLink2;
file_tree_name(zFileTreeName, &fname, 1);
zName = blob_str(&fname);
historical_version_of_file(zFrom, zName, &v1, &isLink1, 0, 0);
historical_version_of_file(zTo, zName, &v2, &isLink2, 0, 0);
if( isLink1 != isLink2 ){
diff_print_filenames(zName, zName, diffFlags);
diff_printf("cannot compute difference between symlink and regular file\n");
}else{
diff_file_mem(&v1, &v2, zName, zDiffCmd, diffFlags);
}
blob_reset(&v1);
blob_reset(&v2);
blob_reset(&fname);
|
| ︙ | ︙ | |||
342 343 344 345 346 347 348 |
struct ManifestFile *pTo,
const char *zDiffCmd,
int diffFlags
){
Blob f1, f2;
int rid;
const char *zName = pFrom ? pFrom->zName : pTo->zName;
| | | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
struct ManifestFile *pTo,
const char *zDiffCmd,
int diffFlags
){
Blob f1, f2;
int rid;
const char *zName = pFrom ? pFrom->zName : pTo->zName;
diff_print_index(zName, diffFlags);
if( pFrom ){
rid = uuid_to_rid(pFrom->zUuid, 0);
content_get(rid, &f1);
}else{
blob_zero(&f1);
}
if( pTo ){
|
| ︙ | ︙ | |||
461 462 463 464 465 466 467 | 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 */ | < > < < < | | < < < < < < < < | | | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
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 */
int f;
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);
diffFlags = diff_options();
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 ){
for(f=2; f<g.argc; ++f){
diff_one_against_disk(zFrom, zDiffCmd, diffFlags, g.argv[f]);
}
}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(0, 0);
verify_all_options();
if( !isInternDiff ){
zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
}
if( g.argc>=3 ){
for(f=2; f<g.argc; ++f){
diff_one_two_versions(zFrom, zTo, zDiffCmd, diffFlags, g.argv[f]);
}
}else{
diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
}
}
}
|
| ︙ | ︙ |
Changes to src/printf.c.
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
break;
case etPERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case etCHARX:
| | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
break;
case etPERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case etCHARX:
c = buf[0] = va_arg(ap,int);
if( precision>=0 ){
for(idx=1; idx<precision; idx++) buf[idx] = c;
length = precision;
}else{
length =1;
}
bufpt = buf;
|
| ︙ | ︙ |
Changes to src/stash.c.
| ︙ | ︙ | |||
264 265 266 267 268 269 270 |
nConflict);
}
}
/*
** Show the diffs associate with a single stash.
*/
| | | | | | | | | | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
nConflict);
}
}
/*
** Show the diffs associate with a single stash.
*/
static void stash_diff(int stashid, const char *zDiffCmd, int diffFlags){
Stmt q;
Blob empty;
blob_zero(&empty);
db_prepare(&q,
"SELECT rid, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile WHERE stashid=%d",
stashid
);
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
int isRemoved = db_column_int(&q, 1);
int isLink = db_column_int(&q, 3);
const char *zOrig = db_column_text(&q, 4);
const char *zNew = db_column_text(&q, 5);
char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
Blob delta;
if( rid==0 ){
db_ephemeral_blob(&q, 6, &delta);
fossil_print("ADDED %s\n", zNew);
diff_print_index(zNew, diffFlags);
diff_file_mem(&empty, &delta, zNew, zDiffCmd, diffFlags);
}else if( isRemoved ){
fossil_print("DELETE %s\n", zOrig);
if( file_wd_islink(zOPath) ){
blob_read_link(&delta, zOPath);
}else{
blob_read_from_file(&delta, zOPath);
}
diff_print_index(zNew, diffFlags);
diff_file_mem(&delta, &empty, zOrig, zDiffCmd, diffFlags);
}else{
Blob a, b, disk;
int isOrigLink = file_wd_islink(zOPath);
db_ephemeral_blob(&q, 6, &delta);
if( isOrigLink ){
blob_read_link(&disk, zOPath);
}else{
blob_read_from_file(&disk, zOPath);
}
fossil_print("CHANGED %s\n", zNew);
if( !isOrigLink != !isLink ){
diff_print_index(zNew, diffFlags);
diff_print_filenames(zOrig, zNew, diffFlags);
printf("cannot compute difference between symlink and regular file\n");
}else{
content_get(rid, &a);
blob_delta_apply(&a, &delta, &b);
diff_file_mem(&disk, &b, zNew, zDiffCmd, diffFlags);
blob_reset(&a);
blob_reset(&b);
}
blob_reset(&disk);
}
blob_reset(&delta);
}
|
| ︙ | ︙ | |||
524 525 526 527 528 529 530 531 532 |
db_multi_exec("UPDATE vfile SET mtime=0 WHERE pathname IN "
"(SELECT origname FROM stashfile WHERE stashid=%d)",
stashid);
undo_finish();
}else
if( memcmp(zCmd, "diff", nCmd)==0 ){
const char *zDiffCmd = db_get("diff-command", 0);
if( g.argc>4 ) usage("diff STASHID");
stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
| > | > | | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
db_multi_exec("UPDATE vfile SET mtime=0 WHERE pathname IN "
"(SELECT origname FROM stashfile WHERE stashid=%d)",
stashid);
undo_finish();
}else
if( memcmp(zCmd, "diff", nCmd)==0 ){
const char *zDiffCmd = db_get("diff-command", 0);
int diffFlags = diff_options();
if( g.argc>4 ) usage("diff STASHID");
stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
stash_diff(stashid, zDiffCmd, diffFlags);
}else
if( memcmp(zCmd, "gdiff", nCmd)==0 ){
const char *zDiffCmd = db_get("gdiff-command", 0);
int diffFlags = diff_options();
if( g.argc>4 ) usage("diff STASHID");
stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
stash_diff(stashid, zDiffCmd, diffFlags);
}else
{
usage("SUBCOMMAND ARGS...");
}
db_end_transaction(0);
}
|