Fossil SCM
The "diff" command with no arguments now does a diff on all files in the checkout which have been edited.
Commit
c863ec1a98c424f6c1518a2f9fb72409dec32ff2
Parent
2bde9f9b3d97781…
1 file changed
+77
-9
+77
-9
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -31,17 +31,80 @@ | ||
| 31 | 31 | ** Shell-escape the given string. Append the result to a blob. |
| 32 | 32 | */ |
| 33 | 33 | static void shell_escape(Blob *pBlob, const char *zIn){ |
| 34 | 34 | int n = blob_size(pBlob); |
| 35 | 35 | int k = strlen(zIn); |
| 36 | - int i; | |
| 36 | + int i, c; | |
| 37 | 37 | char *z; |
| 38 | - blob_appendf(pBlob, "\"%s\"", zIn); | |
| 39 | - z = blob_buffer(pBlob); | |
| 40 | - for(i=n+1; i<=n+k; i++){ | |
| 41 | - if( z[i]=='"' ) z[i] = '_'; | |
| 38 | + for(i=0; (c = zIn[i])!=0; i++){ | |
| 39 | + if( isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){ | |
| 40 | + blob_appendf(pBlob, "\"%s\"", zIn); | |
| 41 | + z = blob_buffer(pBlob); | |
| 42 | + for(i=n+1; i<=n+k; i++){ | |
| 43 | + if( z[i]=='"' ) z[i] = '_'; | |
| 44 | + } | |
| 45 | + return; | |
| 46 | + } | |
| 47 | + } | |
| 48 | + blob_append(pBlob, zIn, -1); | |
| 49 | +} | |
| 50 | + | |
| 51 | +/* | |
| 52 | +** Run the fossil diff command separately for every file in the current | |
| 53 | +** checkout that has changed. | |
| 54 | +*/ | |
| 55 | +static void diff_all(int internalDiff, const char *zRevision){ | |
| 56 | + Stmt q; | |
| 57 | + Blob cmd; | |
| 58 | + int nCmdBase; | |
| 59 | + int vid; | |
| 60 | + | |
| 61 | + vid = db_lget_int("checkout", 0); | |
| 62 | + vfile_check_signature(vid); | |
| 63 | + blob_zero(&cmd); | |
| 64 | + shell_escape(&cmd, g.argv[0]); | |
| 65 | + blob_append(&cmd, " diff ", -1); | |
| 66 | + if( internalDiff ){ | |
| 67 | + blob_append(&cmd, "-i ", -1); | |
| 68 | + } | |
| 69 | + if( zRevision ){ | |
| 70 | + blob_append(&cmd, "-r ", -1); | |
| 71 | + shell_escape(&cmd, zRevision); | |
| 72 | + blob_append(&cmd, " ", 1); | |
| 73 | + } | |
| 74 | + nCmdBase = blob_size(&cmd); | |
| 75 | + db_prepare(&q, | |
| 76 | + "SELECT pathname, deleted, chnged, rid FROM vfile " | |
| 77 | + "WHERE chnged OR deleted OR rid=0 ORDER BY 1" | |
| 78 | + ); | |
| 79 | + | |
| 80 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 81 | + const char *zPathname = db_column_text(&q,0); | |
| 82 | + int isDeleted = db_column_int(&q, 1); | |
| 83 | + int isChnged = db_column_int(&q,2); | |
| 84 | + int isNew = db_column_int(&q,3)==0; | |
| 85 | + char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); | |
| 86 | + cmd.nUsed = nCmdBase; | |
| 87 | + if( isDeleted ){ | |
| 88 | + printf("DELETED %s\n", zPathname); | |
| 89 | + }else if( access(zFullName, 0) ){ | |
| 90 | + printf("MISSING %s\n", zPathname); | |
| 91 | + }else if( isNew ){ | |
| 92 | + printf("ADDED %s\n", zPathname); | |
| 93 | + }else if( isDeleted ){ | |
| 94 | + printf("DELETED %s\n", zPathname); | |
| 95 | + }else if( isChnged==3 ){ | |
| 96 | + printf("ADDED_BY_MERGE %s\n", zPathname); | |
| 97 | + }else{ | |
| 98 | + shell_escape(&cmd, zFullName); | |
| 99 | + printf("%s\n", blob_str(&cmd)); | |
| 100 | + fflush(stdout); | |
| 101 | + system(blob_str(&cmd)); | |
| 102 | + } | |
| 103 | + free(zFullName); | |
| 42 | 104 | } |
| 105 | + db_finalize(&q); | |
| 43 | 106 | } |
| 44 | 107 | |
| 45 | 108 | /* |
| 46 | 109 | ** COMMAND: diff |
| 47 | 110 | ** COMMAND: gdiff |
| @@ -69,10 +132,11 @@ | ||
| 69 | 132 | ** %fossil setting gdiff-command meld |
| 70 | 133 | ** %fossil setting gdiff-command xxdiff |
| 71 | 134 | ** %fossil setting gdiff-command kdiff3 |
| 72 | 135 | */ |
| 73 | 136 | void diff_cmd(void){ |
| 137 | + int isGDiff = g.argv[1][0]=='g'; | |
| 74 | 138 | const char *zFile, *zRevision; |
| 75 | 139 | Blob cmd; |
| 76 | 140 | Blob fname; |
| 77 | 141 | Blob vname; |
| 78 | 142 | Blob record; |
| @@ -79,19 +143,23 @@ | ||
| 79 | 143 | int cnt=0,internalDiff; |
| 80 | 144 | |
| 81 | 145 | internalDiff = find_option("internal","i",0)!=0; |
| 82 | 146 | zRevision = find_option("revision", "r", 1); |
| 83 | 147 | verify_all_options(); |
| 148 | + db_must_be_within_tree(); | |
| 84 | 149 | |
| 150 | + if( !isGDiff && g.argc==2 ){ | |
| 151 | + diff_all(internalDiff, zRevision); | |
| 152 | + return; | |
| 153 | + } | |
| 85 | 154 | if( g.argc<3 ){ |
| 86 | 155 | usage("?OPTIONS? FILE"); |
| 87 | 156 | } |
| 88 | - db_must_be_within_tree(); | |
| 89 | 157 | |
| 90 | 158 | if( internalDiff==0 ){ |
| 91 | 159 | const char *zExternalCommand; |
| 92 | - if( strcmp(g.argv[1], "diff")==0 ){ | |
| 160 | + if( !isGDiff ){ | |
| 93 | 161 | zExternalCommand = db_get("diff-command", 0); |
| 94 | 162 | }else{ |
| 95 | 163 | zExternalCommand = db_get("gdiff-command", 0); |
| 96 | 164 | } |
| 97 | 165 | if( zExternalCommand==0 ){ |
| @@ -114,13 +182,13 @@ | ||
| 114 | 182 | if( rid==0 ){ |
| 115 | 183 | fossil_panic("no history for file: %b", &fname); |
| 116 | 184 | } |
| 117 | 185 | content_get(rid, &record); |
| 118 | 186 | }else{ |
| 119 | - historical_version_of_file(zRevision, zFile, &record); | |
| 187 | + historical_version_of_file(zRevision, blob_str(&fname), &record); | |
| 120 | 188 | } |
| 121 | - if( internalDiff==1 ){ | |
| 189 | + if( internalDiff ){ | |
| 122 | 190 | Blob out; |
| 123 | 191 | Blob current; |
| 124 | 192 | blob_zero(¤t); |
| 125 | 193 | blob_read_from_file(¤t, zFile); |
| 126 | 194 | blob_zero(&out); |
| 127 | 195 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -31,17 +31,80 @@ | |
| 31 | ** Shell-escape the given string. Append the result to a blob. |
| 32 | */ |
| 33 | static void shell_escape(Blob *pBlob, const char *zIn){ |
| 34 | int n = blob_size(pBlob); |
| 35 | int k = strlen(zIn); |
| 36 | int i; |
| 37 | char *z; |
| 38 | blob_appendf(pBlob, "\"%s\"", zIn); |
| 39 | z = blob_buffer(pBlob); |
| 40 | for(i=n+1; i<=n+k; i++){ |
| 41 | if( z[i]=='"' ) z[i] = '_'; |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | /* |
| 46 | ** COMMAND: diff |
| 47 | ** COMMAND: gdiff |
| @@ -69,10 +132,11 @@ | |
| 69 | ** %fossil setting gdiff-command meld |
| 70 | ** %fossil setting gdiff-command xxdiff |
| 71 | ** %fossil setting gdiff-command kdiff3 |
| 72 | */ |
| 73 | void diff_cmd(void){ |
| 74 | const char *zFile, *zRevision; |
| 75 | Blob cmd; |
| 76 | Blob fname; |
| 77 | Blob vname; |
| 78 | Blob record; |
| @@ -79,19 +143,23 @@ | |
| 79 | int cnt=0,internalDiff; |
| 80 | |
| 81 | internalDiff = find_option("internal","i",0)!=0; |
| 82 | zRevision = find_option("revision", "r", 1); |
| 83 | verify_all_options(); |
| 84 | |
| 85 | if( g.argc<3 ){ |
| 86 | usage("?OPTIONS? FILE"); |
| 87 | } |
| 88 | db_must_be_within_tree(); |
| 89 | |
| 90 | if( internalDiff==0 ){ |
| 91 | const char *zExternalCommand; |
| 92 | if( strcmp(g.argv[1], "diff")==0 ){ |
| 93 | zExternalCommand = db_get("diff-command", 0); |
| 94 | }else{ |
| 95 | zExternalCommand = db_get("gdiff-command", 0); |
| 96 | } |
| 97 | if( zExternalCommand==0 ){ |
| @@ -114,13 +182,13 @@ | |
| 114 | if( rid==0 ){ |
| 115 | fossil_panic("no history for file: %b", &fname); |
| 116 | } |
| 117 | content_get(rid, &record); |
| 118 | }else{ |
| 119 | historical_version_of_file(zRevision, zFile, &record); |
| 120 | } |
| 121 | if( internalDiff==1 ){ |
| 122 | Blob out; |
| 123 | Blob current; |
| 124 | blob_zero(¤t); |
| 125 | blob_read_from_file(¤t, zFile); |
| 126 | blob_zero(&out); |
| 127 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -31,17 +31,80 @@ | |
| 31 | ** Shell-escape the given string. Append the result to a blob. |
| 32 | */ |
| 33 | static void shell_escape(Blob *pBlob, const char *zIn){ |
| 34 | int n = blob_size(pBlob); |
| 35 | int k = strlen(zIn); |
| 36 | int i, c; |
| 37 | char *z; |
| 38 | for(i=0; (c = zIn[i])!=0; i++){ |
| 39 | if( isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){ |
| 40 | blob_appendf(pBlob, "\"%s\"", zIn); |
| 41 | z = blob_buffer(pBlob); |
| 42 | for(i=n+1; i<=n+k; i++){ |
| 43 | if( z[i]=='"' ) z[i] = '_'; |
| 44 | } |
| 45 | return; |
| 46 | } |
| 47 | } |
| 48 | blob_append(pBlob, zIn, -1); |
| 49 | } |
| 50 | |
| 51 | /* |
| 52 | ** Run the fossil diff command separately for every file in the current |
| 53 | ** checkout that has changed. |
| 54 | */ |
| 55 | static void diff_all(int internalDiff, const char *zRevision){ |
| 56 | Stmt q; |
| 57 | Blob cmd; |
| 58 | int nCmdBase; |
| 59 | int vid; |
| 60 | |
| 61 | vid = db_lget_int("checkout", 0); |
| 62 | vfile_check_signature(vid); |
| 63 | blob_zero(&cmd); |
| 64 | shell_escape(&cmd, g.argv[0]); |
| 65 | blob_append(&cmd, " diff ", -1); |
| 66 | if( internalDiff ){ |
| 67 | blob_append(&cmd, "-i ", -1); |
| 68 | } |
| 69 | if( zRevision ){ |
| 70 | blob_append(&cmd, "-r ", -1); |
| 71 | shell_escape(&cmd, zRevision); |
| 72 | blob_append(&cmd, " ", 1); |
| 73 | } |
| 74 | nCmdBase = blob_size(&cmd); |
| 75 | db_prepare(&q, |
| 76 | "SELECT pathname, deleted, chnged, rid FROM vfile " |
| 77 | "WHERE chnged OR deleted OR rid=0 ORDER BY 1" |
| 78 | ); |
| 79 | |
| 80 | while( db_step(&q)==SQLITE_ROW ){ |
| 81 | const char *zPathname = db_column_text(&q,0); |
| 82 | int isDeleted = db_column_int(&q, 1); |
| 83 | int isChnged = db_column_int(&q,2); |
| 84 | int isNew = db_column_int(&q,3)==0; |
| 85 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 86 | cmd.nUsed = nCmdBase; |
| 87 | if( isDeleted ){ |
| 88 | printf("DELETED %s\n", zPathname); |
| 89 | }else if( access(zFullName, 0) ){ |
| 90 | printf("MISSING %s\n", zPathname); |
| 91 | }else if( isNew ){ |
| 92 | printf("ADDED %s\n", zPathname); |
| 93 | }else if( isDeleted ){ |
| 94 | printf("DELETED %s\n", zPathname); |
| 95 | }else if( isChnged==3 ){ |
| 96 | printf("ADDED_BY_MERGE %s\n", zPathname); |
| 97 | }else{ |
| 98 | shell_escape(&cmd, zFullName); |
| 99 | printf("%s\n", blob_str(&cmd)); |
| 100 | fflush(stdout); |
| 101 | system(blob_str(&cmd)); |
| 102 | } |
| 103 | free(zFullName); |
| 104 | } |
| 105 | db_finalize(&q); |
| 106 | } |
| 107 | |
| 108 | /* |
| 109 | ** COMMAND: diff |
| 110 | ** COMMAND: gdiff |
| @@ -69,10 +132,11 @@ | |
| 132 | ** %fossil setting gdiff-command meld |
| 133 | ** %fossil setting gdiff-command xxdiff |
| 134 | ** %fossil setting gdiff-command kdiff3 |
| 135 | */ |
| 136 | void diff_cmd(void){ |
| 137 | int isGDiff = g.argv[1][0]=='g'; |
| 138 | const char *zFile, *zRevision; |
| 139 | Blob cmd; |
| 140 | Blob fname; |
| 141 | Blob vname; |
| 142 | Blob record; |
| @@ -79,19 +143,23 @@ | |
| 143 | int cnt=0,internalDiff; |
| 144 | |
| 145 | internalDiff = find_option("internal","i",0)!=0; |
| 146 | zRevision = find_option("revision", "r", 1); |
| 147 | verify_all_options(); |
| 148 | db_must_be_within_tree(); |
| 149 | |
| 150 | if( !isGDiff && g.argc==2 ){ |
| 151 | diff_all(internalDiff, zRevision); |
| 152 | return; |
| 153 | } |
| 154 | if( g.argc<3 ){ |
| 155 | usage("?OPTIONS? FILE"); |
| 156 | } |
| 157 | |
| 158 | if( internalDiff==0 ){ |
| 159 | const char *zExternalCommand; |
| 160 | if( !isGDiff ){ |
| 161 | zExternalCommand = db_get("diff-command", 0); |
| 162 | }else{ |
| 163 | zExternalCommand = db_get("gdiff-command", 0); |
| 164 | } |
| 165 | if( zExternalCommand==0 ){ |
| @@ -114,13 +182,13 @@ | |
| 182 | if( rid==0 ){ |
| 183 | fossil_panic("no history for file: %b", &fname); |
| 184 | } |
| 185 | content_get(rid, &record); |
| 186 | }else{ |
| 187 | historical_version_of_file(zRevision, blob_str(&fname), &record); |
| 188 | } |
| 189 | if( internalDiff ){ |
| 190 | Blob out; |
| 191 | Blob current; |
| 192 | blob_zero(¤t); |
| 193 | blob_read_from_file(¤t, zFile); |
| 194 | blob_zero(&out); |
| 195 |