Attachment "full-diff.diff" to
ticket [e90d38c205]
added by
anonymous
2010-10-14 16:29:07.
ADDED motd
Index: src/diffcmd.c
===================================================================
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -51,11 +51,12 @@
** 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 *zName1, /* Display name of the file (from) */
+ const char *zName2, /* Display name of the file (to) */
const char *zDiffCmd, /* Command for comparison */
int ignoreEolWs /* Ignore whitespace at end of lines */
){
if( zDiffCmd==0 ){
Blob out; /* Diff output text */
@@ -66,11 +67,11 @@
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+++ %s\n", zName1, zName2);
printf("%s\n", blob_str(&out));
/* Release memory resources */
blob_reset(&file2);
blob_reset(&out);
@@ -158,10 +159,63 @@
blob_reset(&cmd);
}
}
/*
+** Show the difference for a newly added or deleted file.
+**
+** The difference is the set of edits needed to transform an empty file into
+** pFile or the reverse.
+**
+** fromNull determines the direction of the diff.
+**
+** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
+** command zDiffCmd to do the diffing.
+*/
+static void diff_file_removed(
+ Blob *pFile, /* Content to use */
+ 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 nullBlob;
+
+ blob_zero(&out);
+ blob_zero(&nullBlob);
+ text_diff(pFile, &nullBlob, &out, 5, ignoreEolWs);
+ printf("--- %s\n+++ /dev/null\n", zName);
+ printf("%s\n", blob_str(&out));
+
+ /* Release memory resources */
+ blob_reset(&out);
+ blob_reset(&nullBlob);
+ }else{
+ Blob cmd;
+ char zTemp[300];
+
+ /* Construct a temporary file names */
+ file_tempname(sizeof(zTemp), zTemp);
+ blob_write_to_file(pFile, zTemp);
+
+ /* Construct the external diff command */
+ blob_zero(&cmd);
+ blob_appendf(&cmd, "%s ", zDiffCmd);
+ shell_escape(&cmd, zTemp);
+ blob_append(&cmd, " /dev/null", 1);
+
+ /* Run the external diff command */
+ portable_system(blob_str(&cmd));
+
+ /* Delete the temporary file and clean up memory used */
+ unlink(zTemp);
+ blob_reset(&cmd);
+ }
+}
+
+/*
** Do a diff against a single file named in g.argv[2] from version zFrom
** against the same file on disk.
*/
static void diff_one_against_disk(
const char *zFrom, /* Name of file */
@@ -170,11 +224,11 @@
){
Blob fname;
Blob content;
file_tree_name(g.argv[2], &fname, 1);
historical_version_of_file(zFrom, blob_str(&fname), &content, 0);
- diff_file(&content, g.argv[2], g.argv[2], zDiffCmd, ignoreEolWs);
+ diff_file(&content, g.argv[2], g.argv[2], g.argv[2], zDiffCmd, ignoreEolWs);
blob_reset(&content);
blob_reset(&fname);
}
/*
@@ -183,10 +237,11 @@
** 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 fullDiff, /* Include added or remove files */
int ignoreEolWs /* Ignore end-of-line whitespace */
){
int vid;
Blob sql;
Stmt q;
@@ -236,28 +291,45 @@
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);
+ int isMissing = access(zFullName, 0);
+
+ if( fullDiff || !(isDeleted || isNew || isMissing || isChnged==3) ){
Blob content;
- content_get(srcid, &content);
+ const char *zPathnameSrc;
+ if( isNew || isChnged==3 ){
+ blob_zero(&content);
+ zPathnameSrc = "/dev/null";
+ }else{
+ int srcid = db_column_int(&q, 4);
+ content_get(srcid, &content);
+ zPathnameSrc = zPathname;
+ }
printf("Index: %s\n======================================="
"============================\n",
zPathname
);
- diff_file(&content, zFullName, zPathname, zDiffCmd, ignoreEolWs);
+ if( isDeleted || isMissing ){
+ diff_file_removed(&content, zPathname, zDiffCmd, ignoreEolWs);
+ }else{
+ diff_file(&content, zFullName, zPathnameSrc, zPathname, zDiffCmd,
+ ignoreEolWs
+ );
+ }
blob_reset(&content);
+ }else{
+ if( isDeleted ){
+ printf("DELETED %s\n", zPathname);
+ }else if( isMissing ){
+ printf("MISSING %s\n", zPathname);
+ }else if( isNew ){
+ printf("ADDED %s\n", zPathname);
+ }else if( isChnged==3){
+ printf("ADDED_BY_MERGE %s\n", zPathname);
+ }
}
free(zFullName);
}
db_finalize(&q);
db_end_transaction(1); /* ROLLBACK */
@@ -370,16 +442,18 @@
** 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 isFullDiff; /* True for full diffs */
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;
+ isFullDiff = find_option("full", "f",0)!=0;
zFrom = find_option("from", "r", 1);
zTo = find_option("to", 0, 1);
if( zTo==0 ){
db_must_be_within_tree();
@@ -388,11 +462,11 @@
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);
+ diff_all_against_disk(zFrom, zDiffCmd, isFullDiff, 0);
}
}else if( zFrom==0 ){
fossil_fatal("must use --from if --to is present");
}else{
db_find_and_open_repository(1);