Fossil SCM
Rename --ignore-space-at-eol (from Git) to -Z|--ignore-trailing-space (gnu diff). Add --ignore-all-space as well (doesn't behave exactly like GNU's option yet)
Commit
d9e79f685bf4c7c3d7c45c48bdb65a01497ff002
Parent
4e6cfaf8f85c787…
15 files changed
+11
-1
+62
-38
+62
-38
+16
-18
+16
-18
+5
-5
+5
-5
+1
-1
+6
-3
+105
-17
+1
-1
+1
-1
+1
-1
+7
-3
+7
-3
+11
-1
| --- src/config.h | ||
| +++ src/config.h | ||
| @@ -105,11 +105,21 @@ | ||
| 105 | 105 | # else |
| 106 | 106 | # define COMPILER_NAME "msc" |
| 107 | 107 | # endif |
| 108 | 108 | # elif defined(__MINGW32__) |
| 109 | 109 | # if !defined(COMPILER_VERSION) |
| 110 | -# if defined(__MINGW32_VERSION) | |
| 110 | +# if defined(__MINGW_VERSION) | |
| 111 | +# if defined(__GNUC__) | |
| 112 | +# if defined(__VERSION__) | |
| 113 | +# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc-" __VERSION__ | |
| 114 | +# else | |
| 115 | +# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc" | |
| 116 | +# endif | |
| 117 | +# else | |
| 118 | +# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) | |
| 119 | +# endif | |
| 120 | +# elif defined(__MINGW32_VERSION) | |
| 111 | 121 | # if defined(__GNUC__) |
| 112 | 122 | # if defined(__VERSION__) |
| 113 | 123 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__ |
| 114 | 124 | # else |
| 115 | 125 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc" |
| 116 | 126 |
| --- src/config.h | |
| +++ src/config.h | |
| @@ -105,11 +105,21 @@ | |
| 105 | # else |
| 106 | # define COMPILER_NAME "msc" |
| 107 | # endif |
| 108 | # elif defined(__MINGW32__) |
| 109 | # if !defined(COMPILER_VERSION) |
| 110 | # if defined(__MINGW32_VERSION) |
| 111 | # if defined(__GNUC__) |
| 112 | # if defined(__VERSION__) |
| 113 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__ |
| 114 | # else |
| 115 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc" |
| 116 |
| --- src/config.h | |
| +++ src/config.h | |
| @@ -105,11 +105,21 @@ | |
| 105 | # else |
| 106 | # define COMPILER_NAME "msc" |
| 107 | # endif |
| 108 | # elif defined(__MINGW32__) |
| 109 | # if !defined(COMPILER_VERSION) |
| 110 | # if defined(__MINGW_VERSION) |
| 111 | # if defined(__GNUC__) |
| 112 | # if defined(__VERSION__) |
| 113 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc-" __VERSION__ |
| 114 | # else |
| 115 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc" |
| 116 | # endif |
| 117 | # else |
| 118 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) |
| 119 | # endif |
| 120 | # elif defined(__MINGW32_VERSION) |
| 121 | # if defined(__GNUC__) |
| 122 | # if defined(__VERSION__) |
| 123 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__ |
| 124 | # else |
| 125 | # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc" |
| 126 |
+62
-38
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -28,12 +28,13 @@ | ||
| 28 | 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | 29 | ** of the diff output. |
| 30 | 30 | */ |
| 31 | 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | -#define DIFF_IGNORE_SOLWS ((u64)0x01000000) /* Ignore start-of-line whitespace */ | |
| 33 | +#define DIFF_STRIP_EOLCR ((u64)0x01000000) /* Strip trailing CR */ | |
| 34 | 34 | #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */ |
| 35 | +#define DIFF_IGNORE_ALLWS ((u64)0x03000000) /* Ignore all whitespace */ | |
| 35 | 36 | #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ |
| 36 | 37 | #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ |
| 37 | 38 | #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ |
| 38 | 39 | #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ |
| 39 | 40 | #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ |
| @@ -40,11 +41,10 @@ | ||
| 40 | 41 | #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ |
| 41 | 42 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 42 | 43 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 43 | 44 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 44 | 45 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | -#define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ | |
| 46 | 46 | |
| 47 | 47 | /* |
| 48 | 48 | ** These error messages are shared in multiple locations. They are defined |
| 49 | 49 | ** here for consistency. |
| 50 | 50 | */ |
| @@ -172,11 +172,11 @@ | ||
| 172 | 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | 176 | } |
| 177 | - if( diffFlags & DIFF_IGNORE_SOLWS ){ | |
| 177 | + if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ | |
| 178 | 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | 179 | if( z[s]=='\t' ){ |
| 180 | 180 | indent = ((indent+9)/8)*8; |
| 181 | 181 | }else if( z[s]==' ' ){ |
| 182 | 182 | indent++; |
| @@ -1792,11 +1792,11 @@ | ||
| 1792 | 1792 | if( diffFlags & DIFF_INVERT ){ |
| 1793 | 1793 | Blob *pTemp = pA_Blob; |
| 1794 | 1794 | pA_Blob = pB_Blob; |
| 1795 | 1795 | pB_Blob = pTemp; |
| 1796 | 1796 | } |
| 1797 | - ignoreWs = (diffFlags & (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))!=0; | |
| 1797 | + ignoreWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; | |
| 1798 | 1798 | blob_to_utf8_no_bom(pA_Blob, 0); |
| 1799 | 1799 | blob_to_utf8_no_bom(pB_Blob, 0); |
| 1800 | 1800 | |
| 1801 | 1801 | /* Prepare the input files */ |
| 1802 | 1802 | memset(&c, 0, sizeof(c)); |
| @@ -1862,28 +1862,36 @@ | ||
| 1862 | 1862 | |
| 1863 | 1863 | /* |
| 1864 | 1864 | ** Process diff-related command-line options and return an appropriate |
| 1865 | 1865 | ** "diffFlags" integer. |
| 1866 | 1866 | ** |
| 1867 | -** --brief Show filenames only DIFF_BRIEF | |
| 1868 | -** --context|-c N N lines of context. DIFF_CONTEXT_MASK | |
| 1869 | -** --html Format for HTML DIFF_HTML | |
| 1870 | -** --invert Invert the diff DIFF_INVERT | |
| 1871 | -** --ignore-space-at-eol Ignore eol-whitespaces DIFF_IGNORE_EOLWS | |
| 1872 | -** --ignore-space-at-sol Ignore sol-whitespaces DIFF_IGNORE_SOLWS | |
| 1873 | -** --linenum|-n Show line numbers DIFF_LINENO | |
| 1874 | -** --noopt Disable optimization DIFF_NOOPT | |
| 1875 | -** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE | |
| 1876 | -** --strip-trailing-cr Strip trailing CR DIFF_IGNORE_EOLCR | |
| 1877 | -** --unified Unified diff. ~DIFF_SIDEBYSIDE | |
| 1878 | -** -w Ignore all whitespaces DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS | |
| 1879 | -** --width|-W N N character lines. DIFF_WIDTH_MASK | |
| 1867 | +** --brief Show filenames only DIFF_BRIEF | |
| 1868 | +** --context|-c N N lines of context. DIFF_CONTEXT_MASK | |
| 1869 | +** --html Format for HTML DIFF_HTML | |
| 1870 | +** --invert Invert the diff DIFF_INVERT | |
| 1871 | +** --linenum|-n Show line numbers DIFF_LINENO | |
| 1872 | +** --noopt Disable optimization DIFF_NOOPT | |
| 1873 | +** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE | |
| 1874 | +** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR | |
| 1875 | +** --unified Unified diff. ~DIFF_SIDEBYSIDE | |
| 1876 | +** --width|-W N N character lines. DIFF_WIDTH_MASK | |
| 1877 | +** -w|--ignore-all-space Ignore all white space DIFF_IGNORE_ALLWS | |
| 1878 | +** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS | |
| 1880 | 1879 | */ |
| 1881 | 1880 | u64 diff_options(void){ |
| 1882 | 1881 | u64 diffFlags = 0; |
| 1883 | 1882 | const char *z; |
| 1884 | 1883 | int f; |
| 1884 | + if( find_option("strip-trailing-cr",0,0)!=0 ){ | |
| 1885 | + diffFlags = DIFF_STRIP_EOLCR; | |
| 1886 | + } | |
| 1887 | + if( find_option("ignore-trailing-space","Z",0)!=0 ){ | |
| 1888 | + diffFlags = DIFF_IGNORE_EOLWS; /* stronger than DIFF_STRIP_EOLCR */ | |
| 1889 | + } | |
| 1890 | + if( find_option("ignore-all-space","w",0)!=0 ){ | |
| 1891 | + diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ | |
| 1892 | + } | |
| 1885 | 1893 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1886 | 1894 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1887 | 1895 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 1888 | 1896 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1889 | 1897 | diffFlags |= f + DIFF_CONTEXT_EX; |
| @@ -1892,14 +1900,10 @@ | ||
| 1892 | 1900 | f *= DIFF_CONTEXT_MASK+1; |
| 1893 | 1901 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1894 | 1902 | diffFlags |= f; |
| 1895 | 1903 | } |
| 1896 | 1904 | if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; |
| 1897 | - if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS; | |
| 1898 | - if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS; | |
| 1899 | - if( find_option("strip-trailing-cr",0,0)!=0 ) diffFlags |= DIFF_STRIP_EOLCR; | |
| 1900 | - if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS); | |
| 1901 | 1905 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 1902 | 1906 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 1903 | 1907 | if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT; |
| 1904 | 1908 | if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF; |
| 1905 | 1909 | return diffFlags; |
| @@ -2001,16 +2005,16 @@ | ||
| 2001 | 2005 | /* |
| 2002 | 2006 | ** Initialize the annotation process by specifying the file that is |
| 2003 | 2007 | ** to be annotated. The annotator takes control of the input Blob and |
| 2004 | 2008 | ** will release it when it is finished with it. |
| 2005 | 2009 | */ |
| 2006 | -static int annotation_start(Annotator *p, Blob *pInput){ | |
| 2010 | +static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){ | |
| 2007 | 2011 | int i; |
| 2008 | 2012 | |
| 2009 | 2013 | memset(p, 0, sizeof(*p)); |
| 2010 | 2014 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, |
| 2011 | - 0); | |
| 2015 | + diffFlags); | |
| 2012 | 2016 | if( p->c.aTo==0 ){ |
| 2013 | 2017 | return 1; |
| 2014 | 2018 | } |
| 2015 | 2019 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2016 | 2020 | for(i=0; i<p->c.nTo; i++){ |
| @@ -2028,17 +2032,17 @@ | ||
| 2028 | 2032 | ** being annotated. Do another step of the annotation. Return true |
| 2029 | 2033 | ** if additional annotation is required. zPName is the tag to insert |
| 2030 | 2034 | ** on each line of the file being annotated that was contributed by |
| 2031 | 2035 | ** pParent. Memory to hold zPName is leaked. |
| 2032 | 2036 | */ |
| 2033 | -static int annotation_step(Annotator *p, Blob *pParent, int iVers){ | |
| 2037 | +static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){ | |
| 2034 | 2038 | int i, j; |
| 2035 | 2039 | int lnTo; |
| 2036 | 2040 | |
| 2037 | 2041 | /* Prepare the parent file to be diffed */ |
| 2038 | 2042 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 2039 | - &p->c.nFrom, 0); | |
| 2043 | + &p->c.nFrom, diffFlags); | |
| 2040 | 2044 | if( p->c.aFrom==0 ){ |
| 2041 | 2045 | return 1; |
| 2042 | 2046 | } |
| 2043 | 2047 | |
| 2044 | 2048 | /* Compute the differences going from pParent to the file being |
| @@ -2085,11 +2089,12 @@ | ||
| 2085 | 2089 | static void annotate_file( |
| 2086 | 2090 | Annotator *p, /* The annotator */ |
| 2087 | 2091 | int fnid, /* The name of the file to be annotated */ |
| 2088 | 2092 | int mid, /* Use the version of the file in this check-in */ |
| 2089 | 2093 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 2090 | - int annFlags /* Flags to alter the annotation */ | |
| 2094 | + int annFlags, /* Flags to alter the annotation */ | |
| 2095 | + u64 diffFlags /* Flags to alter the whitespace handling */ | |
| 2091 | 2096 | ){ |
| 2092 | 2097 | Blob toAnnotate; /* Text of the final (mid) version of the file */ |
| 2093 | 2098 | Blob step; /* Text of previous revision */ |
| 2094 | 2099 | int rid; /* Artifact ID of the file being annotated */ |
| 2095 | 2100 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -2103,11 +2108,11 @@ | ||
| 2103 | 2108 | } |
| 2104 | 2109 | if( !content_get(rid, &toAnnotate) ){ |
| 2105 | 2110 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2106 | 2111 | } |
| 2107 | 2112 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2108 | - annotation_start(p, &toAnnotate); | |
| 2113 | + annotation_start(p, &toAnnotate, diffFlags); | |
| 2109 | 2114 | db_begin_transaction(); |
| 2110 | 2115 | db_multi_exec( |
| 2111 | 2116 | "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" |
| 2112 | 2117 | "DELETE FROM vseen;" |
| 2113 | 2118 | ); |
| @@ -2137,11 +2142,11 @@ | ||
| 2137 | 2142 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2138 | 2143 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| 2139 | 2144 | p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); |
| 2140 | 2145 | if( p->nVers ){ |
| 2141 | 2146 | content_get(rid, &step); |
| 2142 | - annotation_step(p, &step, p->nVers-1); | |
| 2147 | + annotation_step(p, &step, p->nVers-1, diffFlags); | |
| 2143 | 2148 | blob_reset(&step); |
| 2144 | 2149 | } |
| 2145 | 2150 | p->nVers++; |
| 2146 | 2151 | db_bind_int(&ins, ":rid", rid); |
| 2147 | 2152 | db_step(&ins); |
| @@ -2177,10 +2182,11 @@ | ||
| 2177 | 2182 | } |
| 2178 | 2183 | |
| 2179 | 2184 | /* |
| 2180 | 2185 | ** WEBPAGE: annotate |
| 2181 | 2186 | ** WEBPAGE: blame |
| 2187 | +** WEBPAGE: praise | |
| 2182 | 2188 | ** |
| 2183 | 2189 | ** Query parameters: |
| 2184 | 2190 | ** |
| 2185 | 2191 | ** checkin=ID The manifest ID at which to start the annotation |
| 2186 | 2192 | ** filename=FILENAME The filename. |
| @@ -2193,17 +2199,19 @@ | ||
| 2193 | 2199 | int fnid; |
| 2194 | 2200 | int i; |
| 2195 | 2201 | int iLimit; /* Depth limit */ |
| 2196 | 2202 | int annFlags = ANN_FILE_ANCEST; |
| 2197 | 2203 | int showLog = 0; /* True to display the log */ |
| 2204 | + int ignoreWs = 0; /* Ignore whitespace */ | |
| 2205 | + u64 diffFlags = DIFF_STRIP_EOLCR; /* diff flags for ignore whitespace */ | |
| 2198 | 2206 | const char *zFilename; /* Name of file to annotate */ |
| 2199 | 2207 | const char *zCI; /* The check-in containing zFilename */ |
| 2200 | 2208 | Annotator ann; |
| 2201 | 2209 | HQuery url; |
| 2202 | 2210 | struct AnnVers *p; |
| 2203 | 2211 | unsigned clr1, clr2, clr; |
| 2204 | - int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */ | |
| 2212 | + int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */ | |
| 2205 | 2213 | |
| 2206 | 2214 | /* Gather query parameters */ |
| 2207 | 2215 | showLog = atoi(PD("log","1")); |
| 2208 | 2216 | login_check_credentials(); |
| 2209 | 2217 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -2212,17 +2220,19 @@ | ||
| 2212 | 2220 | zFilename = P("filename"); |
| 2213 | 2221 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2214 | 2222 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 2215 | 2223 | iLimit = atoi(PD("limit","20")); |
| 2216 | 2224 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 2225 | + ignoreWs = P("w")!=0; | |
| 2226 | + if( ignoreWs ) diffFlags |= DIFF_IGNORE_ALLWS; | |
| 2217 | 2227 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 2218 | 2228 | fossil_redirect_home(); |
| 2219 | 2229 | } |
| 2220 | 2230 | |
| 2221 | 2231 | /* compute the annotation */ |
| 2222 | 2232 | compute_direct_ancestors(mid, 10000000); |
| 2223 | - annotate_file(&ann, fnid, mid, iLimit, annFlags); | |
| 2233 | + annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); | |
| 2224 | 2234 | zCI = ann.aVers[0].zMUuid; |
| 2225 | 2235 | |
| 2226 | 2236 | /* generate the web page */ |
| 2227 | 2237 | style_header("Annotation For %h", zFilename); |
| 2228 | 2238 | if( bBlame ){ |
| @@ -2234,10 +2244,18 @@ | ||
| 2234 | 2244 | url_add_parameter(&url, "filename", zFilename); |
| 2235 | 2245 | if( iLimit!=20 ){ |
| 2236 | 2246 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2237 | 2247 | } |
| 2238 | 2248 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2249 | + if( ignoreWs ){ | |
| 2250 | + url_add_parameter(&url, "w", ""); | |
| 2251 | + style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", | |
| 2252 | + "%s", url_render(&url, "w", 0, 0, 0)); | |
| 2253 | + }else{ | |
| 2254 | + style_submenu_element("Ignore Whitespace", "Ignore Whitespace", | |
| 2255 | + "%s", url_render(&url, "w", "", 0, 0)); | |
| 2256 | + } | |
| 2239 | 2257 | if( showLog ){ |
| 2240 | 2258 | style_submenu_element("Hide Log", "Hide Log", |
| 2241 | 2259 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2242 | 2260 | }else{ |
| 2243 | 2261 | style_submenu_element("Show Log", "Show Log", |
| @@ -2347,22 +2365,25 @@ | ||
| 2347 | 2365 | } |
| 2348 | 2366 | |
| 2349 | 2367 | /* |
| 2350 | 2368 | ** COMMAND: annotate |
| 2351 | 2369 | ** COMMAND: blame |
| 2370 | +** COMMAND: praise | |
| 2352 | 2371 | ** |
| 2353 | -** %fossil (annotate|blame) ?OPTIONS? FILENAME | |
| 2372 | +** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME | |
| 2354 | 2373 | ** |
| 2355 | 2374 | ** Output the text of a file with markings to show when each line of |
| 2356 | 2375 | ** the file was last modified. The "annotate" command shows line numbers |
| 2357 | -** and omits the username. The "blame" command shows the user who made each | |
| 2358 | -** checkin and omits the line number. | |
| 2376 | +** and omits the username. The "blame" and "praise" commands show the user | |
| 2377 | +** who made each checkin and omits the line number. | |
| 2359 | 2378 | ** |
| 2360 | 2379 | ** Options: |
| 2361 | -** --filevers Show file version numbers rather than check-in versions | |
| 2362 | -** -l|--log List all versions analyzed | |
| 2363 | -** -n|--limit N Only look backwards in time by N versions | |
| 2380 | +** --filevers Show file version numbers rather than check-in versions | |
| 2381 | +** -l|--log List all versions analyzed | |
| 2382 | +** -n|--limit N Only look backwards in time by N versions | |
| 2383 | +** -w|--ignore-all-space Ignore white space when comparing lines | |
| 2384 | +** -Z|--ignore-trailing-space Ignore whitespace at line end | |
| 2364 | 2385 | ** |
| 2365 | 2386 | ** See also: info, finfo, timeline |
| 2366 | 2387 | */ |
| 2367 | 2388 | void annotate_cmd(void){ |
| 2368 | 2389 | int fnid; /* Filename ID */ |
| @@ -2374,19 +2395,22 @@ | ||
| 2374 | 2395 | Annotator ann; /* The annotation of the file */ |
| 2375 | 2396 | int i; /* Loop counter */ |
| 2376 | 2397 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2377 | 2398 | int iLimit; /* How far back in time to look */ |
| 2378 | 2399 | int showLog; /* True to show the log */ |
| 2400 | + u64 diffFlags = DIFF_STRIP_EOLCR;/* Flags to control whitespace handling */ | |
| 2379 | 2401 | int fileVers; /* Show file version instead of check-in versions */ |
| 2380 | 2402 | int annFlags = 0; /* Flags to control annotation properties */ |
| 2381 | 2403 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2382 | 2404 | |
| 2383 | - bBlame = g.argv[1][0]=='b'; | |
| 2405 | + bBlame = g.argv[1][0]!='a'; | |
| 2384 | 2406 | zLimit = find_option("limit","n",1); |
| 2385 | 2407 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2386 | 2408 | iLimit = atoi(zLimit); |
| 2387 | 2409 | showLog = find_option("log","l",0)!=0; |
| 2410 | + if( find_option("ignore-trailing-space","Z",0)!=0 ) diffFlags = DIFF_IGNORE_EOLWS; | |
| 2411 | + if( find_option("w",0,0)!=0 ) diffFlags |= DIFF_IGNORE_ALLWS; | |
| 2388 | 2412 | fileVers = find_option("filevers",0,0)!=0; |
| 2389 | 2413 | db_must_be_within_tree(); |
| 2390 | 2414 | if( g.argc<3 ) { |
| 2391 | 2415 | usage("FILENAME"); |
| 2392 | 2416 | } |
| @@ -2412,11 +2436,11 @@ | ||
| 2412 | 2436 | fid, fnid); |
| 2413 | 2437 | if( mid==0 ){ |
| 2414 | 2438 | fossil_fatal("unable to find manifest"); |
| 2415 | 2439 | } |
| 2416 | 2440 | annFlags |= ANN_FILE_ANCEST; |
| 2417 | - annotate_file(&ann, fnid, mid, iLimit, annFlags); | |
| 2441 | + annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); | |
| 2418 | 2442 | if( showLog ){ |
| 2419 | 2443 | struct AnnVers *p; |
| 2420 | 2444 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2421 | 2445 | fossil_print("version %3d: %s %.10s file %.10s\n", |
| 2422 | 2446 | i+1, p->zDate, p->zMUuid, p->zFUuid); |
| 2423 | 2447 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -28,12 +28,13 @@ | |
| 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | ** of the diff output. |
| 30 | */ |
| 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | #define DIFF_IGNORE_SOLWS ((u64)0x01000000) /* Ignore start-of-line whitespace */ |
| 34 | #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */ |
| 35 | #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ |
| 36 | #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ |
| 37 | #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ |
| 38 | #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ |
| 39 | #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ |
| @@ -40,11 +41,10 @@ | |
| 40 | #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ |
| 41 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 42 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 43 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 44 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | #define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ |
| 46 | |
| 47 | /* |
| 48 | ** These error messages are shared in multiple locations. They are defined |
| 49 | ** here for consistency. |
| 50 | */ |
| @@ -172,11 +172,11 @@ | |
| 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | } |
| 177 | if( diffFlags & DIFF_IGNORE_SOLWS ){ |
| 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | if( z[s]=='\t' ){ |
| 180 | indent = ((indent+9)/8)*8; |
| 181 | }else if( z[s]==' ' ){ |
| 182 | indent++; |
| @@ -1792,11 +1792,11 @@ | |
| 1792 | if( diffFlags & DIFF_INVERT ){ |
| 1793 | Blob *pTemp = pA_Blob; |
| 1794 | pA_Blob = pB_Blob; |
| 1795 | pB_Blob = pTemp; |
| 1796 | } |
| 1797 | ignoreWs = (diffFlags & (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))!=0; |
| 1798 | blob_to_utf8_no_bom(pA_Blob, 0); |
| 1799 | blob_to_utf8_no_bom(pB_Blob, 0); |
| 1800 | |
| 1801 | /* Prepare the input files */ |
| 1802 | memset(&c, 0, sizeof(c)); |
| @@ -1862,28 +1862,36 @@ | |
| 1862 | |
| 1863 | /* |
| 1864 | ** Process diff-related command-line options and return an appropriate |
| 1865 | ** "diffFlags" integer. |
| 1866 | ** |
| 1867 | ** --brief Show filenames only DIFF_BRIEF |
| 1868 | ** --context|-c N N lines of context. DIFF_CONTEXT_MASK |
| 1869 | ** --html Format for HTML DIFF_HTML |
| 1870 | ** --invert Invert the diff DIFF_INVERT |
| 1871 | ** --ignore-space-at-eol Ignore eol-whitespaces DIFF_IGNORE_EOLWS |
| 1872 | ** --ignore-space-at-sol Ignore sol-whitespaces DIFF_IGNORE_SOLWS |
| 1873 | ** --linenum|-n Show line numbers DIFF_LINENO |
| 1874 | ** --noopt Disable optimization DIFF_NOOPT |
| 1875 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1876 | ** --strip-trailing-cr Strip trailing CR DIFF_IGNORE_EOLCR |
| 1877 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1878 | ** -w Ignore all whitespaces DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS |
| 1879 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1880 | */ |
| 1881 | u64 diff_options(void){ |
| 1882 | u64 diffFlags = 0; |
| 1883 | const char *z; |
| 1884 | int f; |
| 1885 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1886 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1887 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 1888 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1889 | diffFlags |= f + DIFF_CONTEXT_EX; |
| @@ -1892,14 +1900,10 @@ | |
| 1892 | f *= DIFF_CONTEXT_MASK+1; |
| 1893 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1894 | diffFlags |= f; |
| 1895 | } |
| 1896 | if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; |
| 1897 | if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS; |
| 1898 | if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS; |
| 1899 | if( find_option("strip-trailing-cr",0,0)!=0 ) diffFlags |= DIFF_STRIP_EOLCR; |
| 1900 | if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS); |
| 1901 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 1902 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 1903 | if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT; |
| 1904 | if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF; |
| 1905 | return diffFlags; |
| @@ -2001,16 +2005,16 @@ | |
| 2001 | /* |
| 2002 | ** Initialize the annotation process by specifying the file that is |
| 2003 | ** to be annotated. The annotator takes control of the input Blob and |
| 2004 | ** will release it when it is finished with it. |
| 2005 | */ |
| 2006 | static int annotation_start(Annotator *p, Blob *pInput){ |
| 2007 | int i; |
| 2008 | |
| 2009 | memset(p, 0, sizeof(*p)); |
| 2010 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, |
| 2011 | 0); |
| 2012 | if( p->c.aTo==0 ){ |
| 2013 | return 1; |
| 2014 | } |
| 2015 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2016 | for(i=0; i<p->c.nTo; i++){ |
| @@ -2028,17 +2032,17 @@ | |
| 2028 | ** being annotated. Do another step of the annotation. Return true |
| 2029 | ** if additional annotation is required. zPName is the tag to insert |
| 2030 | ** on each line of the file being annotated that was contributed by |
| 2031 | ** pParent. Memory to hold zPName is leaked. |
| 2032 | */ |
| 2033 | static int annotation_step(Annotator *p, Blob *pParent, int iVers){ |
| 2034 | int i, j; |
| 2035 | int lnTo; |
| 2036 | |
| 2037 | /* Prepare the parent file to be diffed */ |
| 2038 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 2039 | &p->c.nFrom, 0); |
| 2040 | if( p->c.aFrom==0 ){ |
| 2041 | return 1; |
| 2042 | } |
| 2043 | |
| 2044 | /* Compute the differences going from pParent to the file being |
| @@ -2085,11 +2089,12 @@ | |
| 2085 | static void annotate_file( |
| 2086 | Annotator *p, /* The annotator */ |
| 2087 | int fnid, /* The name of the file to be annotated */ |
| 2088 | int mid, /* Use the version of the file in this check-in */ |
| 2089 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 2090 | int annFlags /* Flags to alter the annotation */ |
| 2091 | ){ |
| 2092 | Blob toAnnotate; /* Text of the final (mid) version of the file */ |
| 2093 | Blob step; /* Text of previous revision */ |
| 2094 | int rid; /* Artifact ID of the file being annotated */ |
| 2095 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -2103,11 +2108,11 @@ | |
| 2103 | } |
| 2104 | if( !content_get(rid, &toAnnotate) ){ |
| 2105 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2106 | } |
| 2107 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2108 | annotation_start(p, &toAnnotate); |
| 2109 | db_begin_transaction(); |
| 2110 | db_multi_exec( |
| 2111 | "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" |
| 2112 | "DELETE FROM vseen;" |
| 2113 | ); |
| @@ -2137,11 +2142,11 @@ | |
| 2137 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2138 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| 2139 | p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); |
| 2140 | if( p->nVers ){ |
| 2141 | content_get(rid, &step); |
| 2142 | annotation_step(p, &step, p->nVers-1); |
| 2143 | blob_reset(&step); |
| 2144 | } |
| 2145 | p->nVers++; |
| 2146 | db_bind_int(&ins, ":rid", rid); |
| 2147 | db_step(&ins); |
| @@ -2177,10 +2182,11 @@ | |
| 2177 | } |
| 2178 | |
| 2179 | /* |
| 2180 | ** WEBPAGE: annotate |
| 2181 | ** WEBPAGE: blame |
| 2182 | ** |
| 2183 | ** Query parameters: |
| 2184 | ** |
| 2185 | ** checkin=ID The manifest ID at which to start the annotation |
| 2186 | ** filename=FILENAME The filename. |
| @@ -2193,17 +2199,19 @@ | |
| 2193 | int fnid; |
| 2194 | int i; |
| 2195 | int iLimit; /* Depth limit */ |
| 2196 | int annFlags = ANN_FILE_ANCEST; |
| 2197 | int showLog = 0; /* True to display the log */ |
| 2198 | const char *zFilename; /* Name of file to annotate */ |
| 2199 | const char *zCI; /* The check-in containing zFilename */ |
| 2200 | Annotator ann; |
| 2201 | HQuery url; |
| 2202 | struct AnnVers *p; |
| 2203 | unsigned clr1, clr2, clr; |
| 2204 | int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */ |
| 2205 | |
| 2206 | /* Gather query parameters */ |
| 2207 | showLog = atoi(PD("log","1")); |
| 2208 | login_check_credentials(); |
| 2209 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -2212,17 +2220,19 @@ | |
| 2212 | zFilename = P("filename"); |
| 2213 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2214 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 2215 | iLimit = atoi(PD("limit","20")); |
| 2216 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 2217 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 2218 | fossil_redirect_home(); |
| 2219 | } |
| 2220 | |
| 2221 | /* compute the annotation */ |
| 2222 | compute_direct_ancestors(mid, 10000000); |
| 2223 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2224 | zCI = ann.aVers[0].zMUuid; |
| 2225 | |
| 2226 | /* generate the web page */ |
| 2227 | style_header("Annotation For %h", zFilename); |
| 2228 | if( bBlame ){ |
| @@ -2234,10 +2244,18 @@ | |
| 2234 | url_add_parameter(&url, "filename", zFilename); |
| 2235 | if( iLimit!=20 ){ |
| 2236 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2237 | } |
| 2238 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2239 | if( showLog ){ |
| 2240 | style_submenu_element("Hide Log", "Hide Log", |
| 2241 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2242 | }else{ |
| 2243 | style_submenu_element("Show Log", "Show Log", |
| @@ -2347,22 +2365,25 @@ | |
| 2347 | } |
| 2348 | |
| 2349 | /* |
| 2350 | ** COMMAND: annotate |
| 2351 | ** COMMAND: blame |
| 2352 | ** |
| 2353 | ** %fossil (annotate|blame) ?OPTIONS? FILENAME |
| 2354 | ** |
| 2355 | ** Output the text of a file with markings to show when each line of |
| 2356 | ** the file was last modified. The "annotate" command shows line numbers |
| 2357 | ** and omits the username. The "blame" command shows the user who made each |
| 2358 | ** checkin and omits the line number. |
| 2359 | ** |
| 2360 | ** Options: |
| 2361 | ** --filevers Show file version numbers rather than check-in versions |
| 2362 | ** -l|--log List all versions analyzed |
| 2363 | ** -n|--limit N Only look backwards in time by N versions |
| 2364 | ** |
| 2365 | ** See also: info, finfo, timeline |
| 2366 | */ |
| 2367 | void annotate_cmd(void){ |
| 2368 | int fnid; /* Filename ID */ |
| @@ -2374,19 +2395,22 @@ | |
| 2374 | Annotator ann; /* The annotation of the file */ |
| 2375 | int i; /* Loop counter */ |
| 2376 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2377 | int iLimit; /* How far back in time to look */ |
| 2378 | int showLog; /* True to show the log */ |
| 2379 | int fileVers; /* Show file version instead of check-in versions */ |
| 2380 | int annFlags = 0; /* Flags to control annotation properties */ |
| 2381 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2382 | |
| 2383 | bBlame = g.argv[1][0]=='b'; |
| 2384 | zLimit = find_option("limit","n",1); |
| 2385 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2386 | iLimit = atoi(zLimit); |
| 2387 | showLog = find_option("log","l",0)!=0; |
| 2388 | fileVers = find_option("filevers",0,0)!=0; |
| 2389 | db_must_be_within_tree(); |
| 2390 | if( g.argc<3 ) { |
| 2391 | usage("FILENAME"); |
| 2392 | } |
| @@ -2412,11 +2436,11 @@ | |
| 2412 | fid, fnid); |
| 2413 | if( mid==0 ){ |
| 2414 | fossil_fatal("unable to find manifest"); |
| 2415 | } |
| 2416 | annFlags |= ANN_FILE_ANCEST; |
| 2417 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2418 | if( showLog ){ |
| 2419 | struct AnnVers *p; |
| 2420 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2421 | fossil_print("version %3d: %s %.10s file %.10s\n", |
| 2422 | i+1, p->zDate, p->zMUuid, p->zFUuid); |
| 2423 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -28,12 +28,13 @@ | |
| 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | ** of the diff output. |
| 30 | */ |
| 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | #define DIFF_STRIP_EOLCR ((u64)0x01000000) /* Strip trailing CR */ |
| 34 | #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */ |
| 35 | #define DIFF_IGNORE_ALLWS ((u64)0x03000000) /* Ignore all whitespace */ |
| 36 | #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ |
| 37 | #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ |
| 38 | #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ |
| 39 | #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ |
| 40 | #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ |
| @@ -40,11 +41,10 @@ | |
| 41 | #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ |
| 42 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 43 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 44 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 45 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 46 | |
| 47 | /* |
| 48 | ** These error messages are shared in multiple locations. They are defined |
| 49 | ** here for consistency. |
| 50 | */ |
| @@ -172,11 +172,11 @@ | |
| 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | } |
| 177 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | if( z[s]=='\t' ){ |
| 180 | indent = ((indent+9)/8)*8; |
| 181 | }else if( z[s]==' ' ){ |
| 182 | indent++; |
| @@ -1792,11 +1792,11 @@ | |
| 1792 | if( diffFlags & DIFF_INVERT ){ |
| 1793 | Blob *pTemp = pA_Blob; |
| 1794 | pA_Blob = pB_Blob; |
| 1795 | pB_Blob = pTemp; |
| 1796 | } |
| 1797 | ignoreWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; |
| 1798 | blob_to_utf8_no_bom(pA_Blob, 0); |
| 1799 | blob_to_utf8_no_bom(pB_Blob, 0); |
| 1800 | |
| 1801 | /* Prepare the input files */ |
| 1802 | memset(&c, 0, sizeof(c)); |
| @@ -1862,28 +1862,36 @@ | |
| 1862 | |
| 1863 | /* |
| 1864 | ** Process diff-related command-line options and return an appropriate |
| 1865 | ** "diffFlags" integer. |
| 1866 | ** |
| 1867 | ** --brief Show filenames only DIFF_BRIEF |
| 1868 | ** --context|-c N N lines of context. DIFF_CONTEXT_MASK |
| 1869 | ** --html Format for HTML DIFF_HTML |
| 1870 | ** --invert Invert the diff DIFF_INVERT |
| 1871 | ** --linenum|-n Show line numbers DIFF_LINENO |
| 1872 | ** --noopt Disable optimization DIFF_NOOPT |
| 1873 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1874 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| 1875 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1876 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1877 | ** -w|--ignore-all-space Ignore all white space DIFF_IGNORE_ALLWS |
| 1878 | ** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS |
| 1879 | */ |
| 1880 | u64 diff_options(void){ |
| 1881 | u64 diffFlags = 0; |
| 1882 | const char *z; |
| 1883 | int f; |
| 1884 | if( find_option("strip-trailing-cr",0,0)!=0 ){ |
| 1885 | diffFlags = DIFF_STRIP_EOLCR; |
| 1886 | } |
| 1887 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| 1888 | diffFlags = DIFF_IGNORE_EOLWS; /* stronger than DIFF_STRIP_EOLCR */ |
| 1889 | } |
| 1890 | if( find_option("ignore-all-space","w",0)!=0 ){ |
| 1891 | diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ |
| 1892 | } |
| 1893 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1894 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1895 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 1896 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1897 | diffFlags |= f + DIFF_CONTEXT_EX; |
| @@ -1892,14 +1900,10 @@ | |
| 1900 | f *= DIFF_CONTEXT_MASK+1; |
| 1901 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1902 | diffFlags |= f; |
| 1903 | } |
| 1904 | if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; |
| 1905 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 1906 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 1907 | if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT; |
| 1908 | if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF; |
| 1909 | return diffFlags; |
| @@ -2001,16 +2005,16 @@ | |
| 2005 | /* |
| 2006 | ** Initialize the annotation process by specifying the file that is |
| 2007 | ** to be annotated. The annotator takes control of the input Blob and |
| 2008 | ** will release it when it is finished with it. |
| 2009 | */ |
| 2010 | static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){ |
| 2011 | int i; |
| 2012 | |
| 2013 | memset(p, 0, sizeof(*p)); |
| 2014 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, |
| 2015 | diffFlags); |
| 2016 | if( p->c.aTo==0 ){ |
| 2017 | return 1; |
| 2018 | } |
| 2019 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2020 | for(i=0; i<p->c.nTo; i++){ |
| @@ -2028,17 +2032,17 @@ | |
| 2032 | ** being annotated. Do another step of the annotation. Return true |
| 2033 | ** if additional annotation is required. zPName is the tag to insert |
| 2034 | ** on each line of the file being annotated that was contributed by |
| 2035 | ** pParent. Memory to hold zPName is leaked. |
| 2036 | */ |
| 2037 | static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){ |
| 2038 | int i, j; |
| 2039 | int lnTo; |
| 2040 | |
| 2041 | /* Prepare the parent file to be diffed */ |
| 2042 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 2043 | &p->c.nFrom, diffFlags); |
| 2044 | if( p->c.aFrom==0 ){ |
| 2045 | return 1; |
| 2046 | } |
| 2047 | |
| 2048 | /* Compute the differences going from pParent to the file being |
| @@ -2085,11 +2089,12 @@ | |
| 2089 | static void annotate_file( |
| 2090 | Annotator *p, /* The annotator */ |
| 2091 | int fnid, /* The name of the file to be annotated */ |
| 2092 | int mid, /* Use the version of the file in this check-in */ |
| 2093 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 2094 | int annFlags, /* Flags to alter the annotation */ |
| 2095 | u64 diffFlags /* Flags to alter the whitespace handling */ |
| 2096 | ){ |
| 2097 | Blob toAnnotate; /* Text of the final (mid) version of the file */ |
| 2098 | Blob step; /* Text of previous revision */ |
| 2099 | int rid; /* Artifact ID of the file being annotated */ |
| 2100 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -2103,11 +2108,11 @@ | |
| 2108 | } |
| 2109 | if( !content_get(rid, &toAnnotate) ){ |
| 2110 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2111 | } |
| 2112 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2113 | annotation_start(p, &toAnnotate, diffFlags); |
| 2114 | db_begin_transaction(); |
| 2115 | db_multi_exec( |
| 2116 | "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" |
| 2117 | "DELETE FROM vseen;" |
| 2118 | ); |
| @@ -2137,11 +2142,11 @@ | |
| 2142 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2143 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| 2144 | p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); |
| 2145 | if( p->nVers ){ |
| 2146 | content_get(rid, &step); |
| 2147 | annotation_step(p, &step, p->nVers-1, diffFlags); |
| 2148 | blob_reset(&step); |
| 2149 | } |
| 2150 | p->nVers++; |
| 2151 | db_bind_int(&ins, ":rid", rid); |
| 2152 | db_step(&ins); |
| @@ -2177,10 +2182,11 @@ | |
| 2182 | } |
| 2183 | |
| 2184 | /* |
| 2185 | ** WEBPAGE: annotate |
| 2186 | ** WEBPAGE: blame |
| 2187 | ** WEBPAGE: praise |
| 2188 | ** |
| 2189 | ** Query parameters: |
| 2190 | ** |
| 2191 | ** checkin=ID The manifest ID at which to start the annotation |
| 2192 | ** filename=FILENAME The filename. |
| @@ -2193,17 +2199,19 @@ | |
| 2199 | int fnid; |
| 2200 | int i; |
| 2201 | int iLimit; /* Depth limit */ |
| 2202 | int annFlags = ANN_FILE_ANCEST; |
| 2203 | int showLog = 0; /* True to display the log */ |
| 2204 | int ignoreWs = 0; /* Ignore whitespace */ |
| 2205 | u64 diffFlags = DIFF_STRIP_EOLCR; /* diff flags for ignore whitespace */ |
| 2206 | const char *zFilename; /* Name of file to annotate */ |
| 2207 | const char *zCI; /* The check-in containing zFilename */ |
| 2208 | Annotator ann; |
| 2209 | HQuery url; |
| 2210 | struct AnnVers *p; |
| 2211 | unsigned clr1, clr2, clr; |
| 2212 | int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */ |
| 2213 | |
| 2214 | /* Gather query parameters */ |
| 2215 | showLog = atoi(PD("log","1")); |
| 2216 | login_check_credentials(); |
| 2217 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -2212,17 +2220,19 @@ | |
| 2220 | zFilename = P("filename"); |
| 2221 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2222 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 2223 | iLimit = atoi(PD("limit","20")); |
| 2224 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 2225 | ignoreWs = P("w")!=0; |
| 2226 | if( ignoreWs ) diffFlags |= DIFF_IGNORE_ALLWS; |
| 2227 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 2228 | fossil_redirect_home(); |
| 2229 | } |
| 2230 | |
| 2231 | /* compute the annotation */ |
| 2232 | compute_direct_ancestors(mid, 10000000); |
| 2233 | annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); |
| 2234 | zCI = ann.aVers[0].zMUuid; |
| 2235 | |
| 2236 | /* generate the web page */ |
| 2237 | style_header("Annotation For %h", zFilename); |
| 2238 | if( bBlame ){ |
| @@ -2234,10 +2244,18 @@ | |
| 2244 | url_add_parameter(&url, "filename", zFilename); |
| 2245 | if( iLimit!=20 ){ |
| 2246 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2247 | } |
| 2248 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2249 | if( ignoreWs ){ |
| 2250 | url_add_parameter(&url, "w", ""); |
| 2251 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 2252 | "%s", url_render(&url, "w", 0, 0, 0)); |
| 2253 | }else{ |
| 2254 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 2255 | "%s", url_render(&url, "w", "", 0, 0)); |
| 2256 | } |
| 2257 | if( showLog ){ |
| 2258 | style_submenu_element("Hide Log", "Hide Log", |
| 2259 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2260 | }else{ |
| 2261 | style_submenu_element("Show Log", "Show Log", |
| @@ -2347,22 +2365,25 @@ | |
| 2365 | } |
| 2366 | |
| 2367 | /* |
| 2368 | ** COMMAND: annotate |
| 2369 | ** COMMAND: blame |
| 2370 | ** COMMAND: praise |
| 2371 | ** |
| 2372 | ** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME |
| 2373 | ** |
| 2374 | ** Output the text of a file with markings to show when each line of |
| 2375 | ** the file was last modified. The "annotate" command shows line numbers |
| 2376 | ** and omits the username. The "blame" and "praise" commands show the user |
| 2377 | ** who made each checkin and omits the line number. |
| 2378 | ** |
| 2379 | ** Options: |
| 2380 | ** --filevers Show file version numbers rather than check-in versions |
| 2381 | ** -l|--log List all versions analyzed |
| 2382 | ** -n|--limit N Only look backwards in time by N versions |
| 2383 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 2384 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 2385 | ** |
| 2386 | ** See also: info, finfo, timeline |
| 2387 | */ |
| 2388 | void annotate_cmd(void){ |
| 2389 | int fnid; /* Filename ID */ |
| @@ -2374,19 +2395,22 @@ | |
| 2395 | Annotator ann; /* The annotation of the file */ |
| 2396 | int i; /* Loop counter */ |
| 2397 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2398 | int iLimit; /* How far back in time to look */ |
| 2399 | int showLog; /* True to show the log */ |
| 2400 | u64 diffFlags = DIFF_STRIP_EOLCR;/* Flags to control whitespace handling */ |
| 2401 | int fileVers; /* Show file version instead of check-in versions */ |
| 2402 | int annFlags = 0; /* Flags to control annotation properties */ |
| 2403 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2404 | |
| 2405 | bBlame = g.argv[1][0]!='a'; |
| 2406 | zLimit = find_option("limit","n",1); |
| 2407 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2408 | iLimit = atoi(zLimit); |
| 2409 | showLog = find_option("log","l",0)!=0; |
| 2410 | if( find_option("ignore-trailing-space","Z",0)!=0 ) diffFlags = DIFF_IGNORE_EOLWS; |
| 2411 | if( find_option("w",0,0)!=0 ) diffFlags |= DIFF_IGNORE_ALLWS; |
| 2412 | fileVers = find_option("filevers",0,0)!=0; |
| 2413 | db_must_be_within_tree(); |
| 2414 | if( g.argc<3 ) { |
| 2415 | usage("FILENAME"); |
| 2416 | } |
| @@ -2412,11 +2436,11 @@ | |
| 2436 | fid, fnid); |
| 2437 | if( mid==0 ){ |
| 2438 | fossil_fatal("unable to find manifest"); |
| 2439 | } |
| 2440 | annFlags |= ANN_FILE_ANCEST; |
| 2441 | annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); |
| 2442 | if( showLog ){ |
| 2443 | struct AnnVers *p; |
| 2444 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2445 | fossil_print("version %3d: %s %.10s file %.10s\n", |
| 2446 | i+1, p->zDate, p->zMUuid, p->zFUuid); |
| 2447 |
+62
-38
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -28,12 +28,13 @@ | ||
| 28 | 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | 29 | ** of the diff output. |
| 30 | 30 | */ |
| 31 | 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | -#define DIFF_IGNORE_SOLWS ((u64)0x01000000) /* Ignore start-of-line whitespace */ | |
| 33 | +#define DIFF_STRIP_EOLCR ((u64)0x01000000) /* Strip trailing CR */ | |
| 34 | 34 | #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */ |
| 35 | +#define DIFF_IGNORE_ALLWS ((u64)0x03000000) /* Ignore all whitespace */ | |
| 35 | 36 | #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ |
| 36 | 37 | #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ |
| 37 | 38 | #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ |
| 38 | 39 | #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ |
| 39 | 40 | #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ |
| @@ -40,11 +41,10 @@ | ||
| 40 | 41 | #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ |
| 41 | 42 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 42 | 43 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 43 | 44 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 44 | 45 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | -#define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ | |
| 46 | 46 | |
| 47 | 47 | /* |
| 48 | 48 | ** These error messages are shared in multiple locations. They are defined |
| 49 | 49 | ** here for consistency. |
| 50 | 50 | */ |
| @@ -172,11 +172,11 @@ | ||
| 172 | 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | 176 | } |
| 177 | - if( diffFlags & DIFF_IGNORE_SOLWS ){ | |
| 177 | + if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ | |
| 178 | 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | 179 | if( z[s]=='\t' ){ |
| 180 | 180 | indent = ((indent+9)/8)*8; |
| 181 | 181 | }else if( z[s]==' ' ){ |
| 182 | 182 | indent++; |
| @@ -1792,11 +1792,11 @@ | ||
| 1792 | 1792 | if( diffFlags & DIFF_INVERT ){ |
| 1793 | 1793 | Blob *pTemp = pA_Blob; |
| 1794 | 1794 | pA_Blob = pB_Blob; |
| 1795 | 1795 | pB_Blob = pTemp; |
| 1796 | 1796 | } |
| 1797 | - ignoreWs = (diffFlags & (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))!=0; | |
| 1797 | + ignoreWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; | |
| 1798 | 1798 | blob_to_utf8_no_bom(pA_Blob, 0); |
| 1799 | 1799 | blob_to_utf8_no_bom(pB_Blob, 0); |
| 1800 | 1800 | |
| 1801 | 1801 | /* Prepare the input files */ |
| 1802 | 1802 | memset(&c, 0, sizeof(c)); |
| @@ -1862,28 +1862,36 @@ | ||
| 1862 | 1862 | |
| 1863 | 1863 | /* |
| 1864 | 1864 | ** Process diff-related command-line options and return an appropriate |
| 1865 | 1865 | ** "diffFlags" integer. |
| 1866 | 1866 | ** |
| 1867 | -** --brief Show filenames only DIFF_BRIEF | |
| 1868 | -** --context|-c N N lines of context. DIFF_CONTEXT_MASK | |
| 1869 | -** --html Format for HTML DIFF_HTML | |
| 1870 | -** --invert Invert the diff DIFF_INVERT | |
| 1871 | -** --ignore-space-at-eol Ignore eol-whitespaces DIFF_IGNORE_EOLWS | |
| 1872 | -** --ignore-space-at-sol Ignore sol-whitespaces DIFF_IGNORE_SOLWS | |
| 1873 | -** --linenum|-n Show line numbers DIFF_LINENO | |
| 1874 | -** --noopt Disable optimization DIFF_NOOPT | |
| 1875 | -** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE | |
| 1876 | -** --strip-trailing-cr Strip trailing CR DIFF_IGNORE_EOLCR | |
| 1877 | -** --unified Unified diff. ~DIFF_SIDEBYSIDE | |
| 1878 | -** -w Ignore all whitespaces DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS | |
| 1879 | -** --width|-W N N character lines. DIFF_WIDTH_MASK | |
| 1867 | +** --brief Show filenames only DIFF_BRIEF | |
| 1868 | +** --context|-c N N lines of context. DIFF_CONTEXT_MASK | |
| 1869 | +** --html Format for HTML DIFF_HTML | |
| 1870 | +** --invert Invert the diff DIFF_INVERT | |
| 1871 | +** --linenum|-n Show line numbers DIFF_LINENO | |
| 1872 | +** --noopt Disable optimization DIFF_NOOPT | |
| 1873 | +** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE | |
| 1874 | +** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR | |
| 1875 | +** --unified Unified diff. ~DIFF_SIDEBYSIDE | |
| 1876 | +** --width|-W N N character lines. DIFF_WIDTH_MASK | |
| 1877 | +** -w|--ignore-all-space Ignore all white space DIFF_IGNORE_ALLWS | |
| 1878 | +** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS | |
| 1880 | 1879 | */ |
| 1881 | 1880 | u64 diff_options(void){ |
| 1882 | 1881 | u64 diffFlags = 0; |
| 1883 | 1882 | const char *z; |
| 1884 | 1883 | int f; |
| 1884 | + if( find_option("strip-trailing-cr",0,0)!=0 ){ | |
| 1885 | + diffFlags = DIFF_STRIP_EOLCR; | |
| 1886 | + } | |
| 1887 | + if( find_option("ignore-trailing-space","Z",0)!=0 ){ | |
| 1888 | + diffFlags = DIFF_IGNORE_EOLWS; /* stronger than DIFF_STRIP_EOLCR */ | |
| 1889 | + } | |
| 1890 | + if( find_option("ignore-all-space","w",0)!=0 ){ | |
| 1891 | + diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ | |
| 1892 | + } | |
| 1885 | 1893 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1886 | 1894 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1887 | 1895 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 1888 | 1896 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1889 | 1897 | diffFlags |= f + DIFF_CONTEXT_EX; |
| @@ -1892,14 +1900,10 @@ | ||
| 1892 | 1900 | f *= DIFF_CONTEXT_MASK+1; |
| 1893 | 1901 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1894 | 1902 | diffFlags |= f; |
| 1895 | 1903 | } |
| 1896 | 1904 | if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; |
| 1897 | - if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS; | |
| 1898 | - if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS; | |
| 1899 | - if( find_option("strip-trailing-cr",0,0)!=0 ) diffFlags |= DIFF_STRIP_EOLCR; | |
| 1900 | - if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS); | |
| 1901 | 1905 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 1902 | 1906 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 1903 | 1907 | if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT; |
| 1904 | 1908 | if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF; |
| 1905 | 1909 | return diffFlags; |
| @@ -2001,16 +2005,16 @@ | ||
| 2001 | 2005 | /* |
| 2002 | 2006 | ** Initialize the annotation process by specifying the file that is |
| 2003 | 2007 | ** to be annotated. The annotator takes control of the input Blob and |
| 2004 | 2008 | ** will release it when it is finished with it. |
| 2005 | 2009 | */ |
| 2006 | -static int annotation_start(Annotator *p, Blob *pInput){ | |
| 2010 | +static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){ | |
| 2007 | 2011 | int i; |
| 2008 | 2012 | |
| 2009 | 2013 | memset(p, 0, sizeof(*p)); |
| 2010 | 2014 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, |
| 2011 | - 0); | |
| 2015 | + diffFlags); | |
| 2012 | 2016 | if( p->c.aTo==0 ){ |
| 2013 | 2017 | return 1; |
| 2014 | 2018 | } |
| 2015 | 2019 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2016 | 2020 | for(i=0; i<p->c.nTo; i++){ |
| @@ -2028,17 +2032,17 @@ | ||
| 2028 | 2032 | ** being annotated. Do another step of the annotation. Return true |
| 2029 | 2033 | ** if additional annotation is required. zPName is the tag to insert |
| 2030 | 2034 | ** on each line of the file being annotated that was contributed by |
| 2031 | 2035 | ** pParent. Memory to hold zPName is leaked. |
| 2032 | 2036 | */ |
| 2033 | -static int annotation_step(Annotator *p, Blob *pParent, int iVers){ | |
| 2037 | +static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){ | |
| 2034 | 2038 | int i, j; |
| 2035 | 2039 | int lnTo; |
| 2036 | 2040 | |
| 2037 | 2041 | /* Prepare the parent file to be diffed */ |
| 2038 | 2042 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 2039 | - &p->c.nFrom, 0); | |
| 2043 | + &p->c.nFrom, diffFlags); | |
| 2040 | 2044 | if( p->c.aFrom==0 ){ |
| 2041 | 2045 | return 1; |
| 2042 | 2046 | } |
| 2043 | 2047 | |
| 2044 | 2048 | /* Compute the differences going from pParent to the file being |
| @@ -2085,11 +2089,12 @@ | ||
| 2085 | 2089 | static void annotate_file( |
| 2086 | 2090 | Annotator *p, /* The annotator */ |
| 2087 | 2091 | int fnid, /* The name of the file to be annotated */ |
| 2088 | 2092 | int mid, /* Use the version of the file in this check-in */ |
| 2089 | 2093 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 2090 | - int annFlags /* Flags to alter the annotation */ | |
| 2094 | + int annFlags, /* Flags to alter the annotation */ | |
| 2095 | + u64 diffFlags /* Flags to alter the whitespace handling */ | |
| 2091 | 2096 | ){ |
| 2092 | 2097 | Blob toAnnotate; /* Text of the final (mid) version of the file */ |
| 2093 | 2098 | Blob step; /* Text of previous revision */ |
| 2094 | 2099 | int rid; /* Artifact ID of the file being annotated */ |
| 2095 | 2100 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -2103,11 +2108,11 @@ | ||
| 2103 | 2108 | } |
| 2104 | 2109 | if( !content_get(rid, &toAnnotate) ){ |
| 2105 | 2110 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2106 | 2111 | } |
| 2107 | 2112 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2108 | - annotation_start(p, &toAnnotate); | |
| 2113 | + annotation_start(p, &toAnnotate, diffFlags); | |
| 2109 | 2114 | db_begin_transaction(); |
| 2110 | 2115 | db_multi_exec( |
| 2111 | 2116 | "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" |
| 2112 | 2117 | "DELETE FROM vseen;" |
| 2113 | 2118 | ); |
| @@ -2137,11 +2142,11 @@ | ||
| 2137 | 2142 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2138 | 2143 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| 2139 | 2144 | p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); |
| 2140 | 2145 | if( p->nVers ){ |
| 2141 | 2146 | content_get(rid, &step); |
| 2142 | - annotation_step(p, &step, p->nVers-1); | |
| 2147 | + annotation_step(p, &step, p->nVers-1, diffFlags); | |
| 2143 | 2148 | blob_reset(&step); |
| 2144 | 2149 | } |
| 2145 | 2150 | p->nVers++; |
| 2146 | 2151 | db_bind_int(&ins, ":rid", rid); |
| 2147 | 2152 | db_step(&ins); |
| @@ -2177,10 +2182,11 @@ | ||
| 2177 | 2182 | } |
| 2178 | 2183 | |
| 2179 | 2184 | /* |
| 2180 | 2185 | ** WEBPAGE: annotate |
| 2181 | 2186 | ** WEBPAGE: blame |
| 2187 | +** WEBPAGE: praise | |
| 2182 | 2188 | ** |
| 2183 | 2189 | ** Query parameters: |
| 2184 | 2190 | ** |
| 2185 | 2191 | ** checkin=ID The manifest ID at which to start the annotation |
| 2186 | 2192 | ** filename=FILENAME The filename. |
| @@ -2193,17 +2199,19 @@ | ||
| 2193 | 2199 | int fnid; |
| 2194 | 2200 | int i; |
| 2195 | 2201 | int iLimit; /* Depth limit */ |
| 2196 | 2202 | int annFlags = ANN_FILE_ANCEST; |
| 2197 | 2203 | int showLog = 0; /* True to display the log */ |
| 2204 | + int ignoreWs = 0; /* Ignore whitespace */ | |
| 2205 | + u64 diffFlags = DIFF_STRIP_EOLCR; /* diff flags for ignore whitespace */ | |
| 2198 | 2206 | const char *zFilename; /* Name of file to annotate */ |
| 2199 | 2207 | const char *zCI; /* The check-in containing zFilename */ |
| 2200 | 2208 | Annotator ann; |
| 2201 | 2209 | HQuery url; |
| 2202 | 2210 | struct AnnVers *p; |
| 2203 | 2211 | unsigned clr1, clr2, clr; |
| 2204 | - int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */ | |
| 2212 | + int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */ | |
| 2205 | 2213 | |
| 2206 | 2214 | /* Gather query parameters */ |
| 2207 | 2215 | showLog = atoi(PD("log","1")); |
| 2208 | 2216 | login_check_credentials(); |
| 2209 | 2217 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -2212,17 +2220,19 @@ | ||
| 2212 | 2220 | zFilename = P("filename"); |
| 2213 | 2221 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2214 | 2222 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 2215 | 2223 | iLimit = atoi(PD("limit","20")); |
| 2216 | 2224 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 2225 | + ignoreWs = P("w")!=0; | |
| 2226 | + if( ignoreWs ) diffFlags |= DIFF_IGNORE_ALLWS; | |
| 2217 | 2227 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 2218 | 2228 | fossil_redirect_home(); |
| 2219 | 2229 | } |
| 2220 | 2230 | |
| 2221 | 2231 | /* compute the annotation */ |
| 2222 | 2232 | compute_direct_ancestors(mid, 10000000); |
| 2223 | - annotate_file(&ann, fnid, mid, iLimit, annFlags); | |
| 2233 | + annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); | |
| 2224 | 2234 | zCI = ann.aVers[0].zMUuid; |
| 2225 | 2235 | |
| 2226 | 2236 | /* generate the web page */ |
| 2227 | 2237 | style_header("Annotation For %h", zFilename); |
| 2228 | 2238 | if( bBlame ){ |
| @@ -2234,10 +2244,18 @@ | ||
| 2234 | 2244 | url_add_parameter(&url, "filename", zFilename); |
| 2235 | 2245 | if( iLimit!=20 ){ |
| 2236 | 2246 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2237 | 2247 | } |
| 2238 | 2248 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2249 | + if( ignoreWs ){ | |
| 2250 | + url_add_parameter(&url, "w", ""); | |
| 2251 | + style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", | |
| 2252 | + "%s", url_render(&url, "w", 0, 0, 0)); | |
| 2253 | + }else{ | |
| 2254 | + style_submenu_element("Ignore Whitespace", "Ignore Whitespace", | |
| 2255 | + "%s", url_render(&url, "w", "", 0, 0)); | |
| 2256 | + } | |
| 2239 | 2257 | if( showLog ){ |
| 2240 | 2258 | style_submenu_element("Hide Log", "Hide Log", |
| 2241 | 2259 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2242 | 2260 | }else{ |
| 2243 | 2261 | style_submenu_element("Show Log", "Show Log", |
| @@ -2347,22 +2365,25 @@ | ||
| 2347 | 2365 | } |
| 2348 | 2366 | |
| 2349 | 2367 | /* |
| 2350 | 2368 | ** COMMAND: annotate |
| 2351 | 2369 | ** COMMAND: blame |
| 2370 | +** COMMAND: praise | |
| 2352 | 2371 | ** |
| 2353 | -** %fossil (annotate|blame) ?OPTIONS? FILENAME | |
| 2372 | +** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME | |
| 2354 | 2373 | ** |
| 2355 | 2374 | ** Output the text of a file with markings to show when each line of |
| 2356 | 2375 | ** the file was last modified. The "annotate" command shows line numbers |
| 2357 | -** and omits the username. The "blame" command shows the user who made each | |
| 2358 | -** checkin and omits the line number. | |
| 2376 | +** and omits the username. The "blame" and "praise" commands show the user | |
| 2377 | +** who made each checkin and omits the line number. | |
| 2359 | 2378 | ** |
| 2360 | 2379 | ** Options: |
| 2361 | -** --filevers Show file version numbers rather than check-in versions | |
| 2362 | -** -l|--log List all versions analyzed | |
| 2363 | -** -n|--limit N Only look backwards in time by N versions | |
| 2380 | +** --filevers Show file version numbers rather than check-in versions | |
| 2381 | +** -l|--log List all versions analyzed | |
| 2382 | +** -n|--limit N Only look backwards in time by N versions | |
| 2383 | +** -w|--ignore-all-space Ignore white space when comparing lines | |
| 2384 | +** -Z|--ignore-trailing-space Ignore whitespace at line end | |
| 2364 | 2385 | ** |
| 2365 | 2386 | ** See also: info, finfo, timeline |
| 2366 | 2387 | */ |
| 2367 | 2388 | void annotate_cmd(void){ |
| 2368 | 2389 | int fnid; /* Filename ID */ |
| @@ -2374,19 +2395,22 @@ | ||
| 2374 | 2395 | Annotator ann; /* The annotation of the file */ |
| 2375 | 2396 | int i; /* Loop counter */ |
| 2376 | 2397 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2377 | 2398 | int iLimit; /* How far back in time to look */ |
| 2378 | 2399 | int showLog; /* True to show the log */ |
| 2400 | + u64 diffFlags = DIFF_STRIP_EOLCR;/* Flags to control whitespace handling */ | |
| 2379 | 2401 | int fileVers; /* Show file version instead of check-in versions */ |
| 2380 | 2402 | int annFlags = 0; /* Flags to control annotation properties */ |
| 2381 | 2403 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2382 | 2404 | |
| 2383 | - bBlame = g.argv[1][0]=='b'; | |
| 2405 | + bBlame = g.argv[1][0]!='a'; | |
| 2384 | 2406 | zLimit = find_option("limit","n",1); |
| 2385 | 2407 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2386 | 2408 | iLimit = atoi(zLimit); |
| 2387 | 2409 | showLog = find_option("log","l",0)!=0; |
| 2410 | + if( find_option("ignore-trailing-space","Z",0)!=0 ) diffFlags = DIFF_IGNORE_EOLWS; | |
| 2411 | + if( find_option("w",0,0)!=0 ) diffFlags |= DIFF_IGNORE_ALLWS; | |
| 2388 | 2412 | fileVers = find_option("filevers",0,0)!=0; |
| 2389 | 2413 | db_must_be_within_tree(); |
| 2390 | 2414 | if( g.argc<3 ) { |
| 2391 | 2415 | usage("FILENAME"); |
| 2392 | 2416 | } |
| @@ -2412,11 +2436,11 @@ | ||
| 2412 | 2436 | fid, fnid); |
| 2413 | 2437 | if( mid==0 ){ |
| 2414 | 2438 | fossil_fatal("unable to find manifest"); |
| 2415 | 2439 | } |
| 2416 | 2440 | annFlags |= ANN_FILE_ANCEST; |
| 2417 | - annotate_file(&ann, fnid, mid, iLimit, annFlags); | |
| 2441 | + annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); | |
| 2418 | 2442 | if( showLog ){ |
| 2419 | 2443 | struct AnnVers *p; |
| 2420 | 2444 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2421 | 2445 | fossil_print("version %3d: %s %.10s file %.10s\n", |
| 2422 | 2446 | i+1, p->zDate, p->zMUuid, p->zFUuid); |
| 2423 | 2447 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -28,12 +28,13 @@ | |
| 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | ** of the diff output. |
| 30 | */ |
| 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | #define DIFF_IGNORE_SOLWS ((u64)0x01000000) /* Ignore start-of-line whitespace */ |
| 34 | #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */ |
| 35 | #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ |
| 36 | #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ |
| 37 | #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ |
| 38 | #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ |
| 39 | #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ |
| @@ -40,11 +41,10 @@ | |
| 40 | #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ |
| 41 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 42 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 43 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 44 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | #define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ |
| 46 | |
| 47 | /* |
| 48 | ** These error messages are shared in multiple locations. They are defined |
| 49 | ** here for consistency. |
| 50 | */ |
| @@ -172,11 +172,11 @@ | |
| 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | } |
| 177 | if( diffFlags & DIFF_IGNORE_SOLWS ){ |
| 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | if( z[s]=='\t' ){ |
| 180 | indent = ((indent+9)/8)*8; |
| 181 | }else if( z[s]==' ' ){ |
| 182 | indent++; |
| @@ -1792,11 +1792,11 @@ | |
| 1792 | if( diffFlags & DIFF_INVERT ){ |
| 1793 | Blob *pTemp = pA_Blob; |
| 1794 | pA_Blob = pB_Blob; |
| 1795 | pB_Blob = pTemp; |
| 1796 | } |
| 1797 | ignoreWs = (diffFlags & (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))!=0; |
| 1798 | blob_to_utf8_no_bom(pA_Blob, 0); |
| 1799 | blob_to_utf8_no_bom(pB_Blob, 0); |
| 1800 | |
| 1801 | /* Prepare the input files */ |
| 1802 | memset(&c, 0, sizeof(c)); |
| @@ -1862,28 +1862,36 @@ | |
| 1862 | |
| 1863 | /* |
| 1864 | ** Process diff-related command-line options and return an appropriate |
| 1865 | ** "diffFlags" integer. |
| 1866 | ** |
| 1867 | ** --brief Show filenames only DIFF_BRIEF |
| 1868 | ** --context|-c N N lines of context. DIFF_CONTEXT_MASK |
| 1869 | ** --html Format for HTML DIFF_HTML |
| 1870 | ** --invert Invert the diff DIFF_INVERT |
| 1871 | ** --ignore-space-at-eol Ignore eol-whitespaces DIFF_IGNORE_EOLWS |
| 1872 | ** --ignore-space-at-sol Ignore sol-whitespaces DIFF_IGNORE_SOLWS |
| 1873 | ** --linenum|-n Show line numbers DIFF_LINENO |
| 1874 | ** --noopt Disable optimization DIFF_NOOPT |
| 1875 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1876 | ** --strip-trailing-cr Strip trailing CR DIFF_IGNORE_EOLCR |
| 1877 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1878 | ** -w Ignore all whitespaces DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS |
| 1879 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1880 | */ |
| 1881 | u64 diff_options(void){ |
| 1882 | u64 diffFlags = 0; |
| 1883 | const char *z; |
| 1884 | int f; |
| 1885 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1886 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1887 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 1888 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1889 | diffFlags |= f + DIFF_CONTEXT_EX; |
| @@ -1892,14 +1900,10 @@ | |
| 1892 | f *= DIFF_CONTEXT_MASK+1; |
| 1893 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1894 | diffFlags |= f; |
| 1895 | } |
| 1896 | if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; |
| 1897 | if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS; |
| 1898 | if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS; |
| 1899 | if( find_option("strip-trailing-cr",0,0)!=0 ) diffFlags |= DIFF_STRIP_EOLCR; |
| 1900 | if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS); |
| 1901 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 1902 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 1903 | if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT; |
| 1904 | if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF; |
| 1905 | return diffFlags; |
| @@ -2001,16 +2005,16 @@ | |
| 2001 | /* |
| 2002 | ** Initialize the annotation process by specifying the file that is |
| 2003 | ** to be annotated. The annotator takes control of the input Blob and |
| 2004 | ** will release it when it is finished with it. |
| 2005 | */ |
| 2006 | static int annotation_start(Annotator *p, Blob *pInput){ |
| 2007 | int i; |
| 2008 | |
| 2009 | memset(p, 0, sizeof(*p)); |
| 2010 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, |
| 2011 | 0); |
| 2012 | if( p->c.aTo==0 ){ |
| 2013 | return 1; |
| 2014 | } |
| 2015 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2016 | for(i=0; i<p->c.nTo; i++){ |
| @@ -2028,17 +2032,17 @@ | |
| 2028 | ** being annotated. Do another step of the annotation. Return true |
| 2029 | ** if additional annotation is required. zPName is the tag to insert |
| 2030 | ** on each line of the file being annotated that was contributed by |
| 2031 | ** pParent. Memory to hold zPName is leaked. |
| 2032 | */ |
| 2033 | static int annotation_step(Annotator *p, Blob *pParent, int iVers){ |
| 2034 | int i, j; |
| 2035 | int lnTo; |
| 2036 | |
| 2037 | /* Prepare the parent file to be diffed */ |
| 2038 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 2039 | &p->c.nFrom, 0); |
| 2040 | if( p->c.aFrom==0 ){ |
| 2041 | return 1; |
| 2042 | } |
| 2043 | |
| 2044 | /* Compute the differences going from pParent to the file being |
| @@ -2085,11 +2089,12 @@ | |
| 2085 | static void annotate_file( |
| 2086 | Annotator *p, /* The annotator */ |
| 2087 | int fnid, /* The name of the file to be annotated */ |
| 2088 | int mid, /* Use the version of the file in this check-in */ |
| 2089 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 2090 | int annFlags /* Flags to alter the annotation */ |
| 2091 | ){ |
| 2092 | Blob toAnnotate; /* Text of the final (mid) version of the file */ |
| 2093 | Blob step; /* Text of previous revision */ |
| 2094 | int rid; /* Artifact ID of the file being annotated */ |
| 2095 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -2103,11 +2108,11 @@ | |
| 2103 | } |
| 2104 | if( !content_get(rid, &toAnnotate) ){ |
| 2105 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2106 | } |
| 2107 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2108 | annotation_start(p, &toAnnotate); |
| 2109 | db_begin_transaction(); |
| 2110 | db_multi_exec( |
| 2111 | "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" |
| 2112 | "DELETE FROM vseen;" |
| 2113 | ); |
| @@ -2137,11 +2142,11 @@ | |
| 2137 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2138 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| 2139 | p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); |
| 2140 | if( p->nVers ){ |
| 2141 | content_get(rid, &step); |
| 2142 | annotation_step(p, &step, p->nVers-1); |
| 2143 | blob_reset(&step); |
| 2144 | } |
| 2145 | p->nVers++; |
| 2146 | db_bind_int(&ins, ":rid", rid); |
| 2147 | db_step(&ins); |
| @@ -2177,10 +2182,11 @@ | |
| 2177 | } |
| 2178 | |
| 2179 | /* |
| 2180 | ** WEBPAGE: annotate |
| 2181 | ** WEBPAGE: blame |
| 2182 | ** |
| 2183 | ** Query parameters: |
| 2184 | ** |
| 2185 | ** checkin=ID The manifest ID at which to start the annotation |
| 2186 | ** filename=FILENAME The filename. |
| @@ -2193,17 +2199,19 @@ | |
| 2193 | int fnid; |
| 2194 | int i; |
| 2195 | int iLimit; /* Depth limit */ |
| 2196 | int annFlags = ANN_FILE_ANCEST; |
| 2197 | int showLog = 0; /* True to display the log */ |
| 2198 | const char *zFilename; /* Name of file to annotate */ |
| 2199 | const char *zCI; /* The check-in containing zFilename */ |
| 2200 | Annotator ann; |
| 2201 | HQuery url; |
| 2202 | struct AnnVers *p; |
| 2203 | unsigned clr1, clr2, clr; |
| 2204 | int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */ |
| 2205 | |
| 2206 | /* Gather query parameters */ |
| 2207 | showLog = atoi(PD("log","1")); |
| 2208 | login_check_credentials(); |
| 2209 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -2212,17 +2220,19 @@ | |
| 2212 | zFilename = P("filename"); |
| 2213 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2214 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 2215 | iLimit = atoi(PD("limit","20")); |
| 2216 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 2217 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 2218 | fossil_redirect_home(); |
| 2219 | } |
| 2220 | |
| 2221 | /* compute the annotation */ |
| 2222 | compute_direct_ancestors(mid, 10000000); |
| 2223 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2224 | zCI = ann.aVers[0].zMUuid; |
| 2225 | |
| 2226 | /* generate the web page */ |
| 2227 | style_header("Annotation For %h", zFilename); |
| 2228 | if( bBlame ){ |
| @@ -2234,10 +2244,18 @@ | |
| 2234 | url_add_parameter(&url, "filename", zFilename); |
| 2235 | if( iLimit!=20 ){ |
| 2236 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2237 | } |
| 2238 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2239 | if( showLog ){ |
| 2240 | style_submenu_element("Hide Log", "Hide Log", |
| 2241 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2242 | }else{ |
| 2243 | style_submenu_element("Show Log", "Show Log", |
| @@ -2347,22 +2365,25 @@ | |
| 2347 | } |
| 2348 | |
| 2349 | /* |
| 2350 | ** COMMAND: annotate |
| 2351 | ** COMMAND: blame |
| 2352 | ** |
| 2353 | ** %fossil (annotate|blame) ?OPTIONS? FILENAME |
| 2354 | ** |
| 2355 | ** Output the text of a file with markings to show when each line of |
| 2356 | ** the file was last modified. The "annotate" command shows line numbers |
| 2357 | ** and omits the username. The "blame" command shows the user who made each |
| 2358 | ** checkin and omits the line number. |
| 2359 | ** |
| 2360 | ** Options: |
| 2361 | ** --filevers Show file version numbers rather than check-in versions |
| 2362 | ** -l|--log List all versions analyzed |
| 2363 | ** -n|--limit N Only look backwards in time by N versions |
| 2364 | ** |
| 2365 | ** See also: info, finfo, timeline |
| 2366 | */ |
| 2367 | void annotate_cmd(void){ |
| 2368 | int fnid; /* Filename ID */ |
| @@ -2374,19 +2395,22 @@ | |
| 2374 | Annotator ann; /* The annotation of the file */ |
| 2375 | int i; /* Loop counter */ |
| 2376 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2377 | int iLimit; /* How far back in time to look */ |
| 2378 | int showLog; /* True to show the log */ |
| 2379 | int fileVers; /* Show file version instead of check-in versions */ |
| 2380 | int annFlags = 0; /* Flags to control annotation properties */ |
| 2381 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2382 | |
| 2383 | bBlame = g.argv[1][0]=='b'; |
| 2384 | zLimit = find_option("limit","n",1); |
| 2385 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2386 | iLimit = atoi(zLimit); |
| 2387 | showLog = find_option("log","l",0)!=0; |
| 2388 | fileVers = find_option("filevers",0,0)!=0; |
| 2389 | db_must_be_within_tree(); |
| 2390 | if( g.argc<3 ) { |
| 2391 | usage("FILENAME"); |
| 2392 | } |
| @@ -2412,11 +2436,11 @@ | |
| 2412 | fid, fnid); |
| 2413 | if( mid==0 ){ |
| 2414 | fossil_fatal("unable to find manifest"); |
| 2415 | } |
| 2416 | annFlags |= ANN_FILE_ANCEST; |
| 2417 | annotate_file(&ann, fnid, mid, iLimit, annFlags); |
| 2418 | if( showLog ){ |
| 2419 | struct AnnVers *p; |
| 2420 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2421 | fossil_print("version %3d: %s %.10s file %.10s\n", |
| 2422 | i+1, p->zDate, p->zMUuid, p->zFUuid); |
| 2423 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -28,12 +28,13 @@ | |
| 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | ** of the diff output. |
| 30 | */ |
| 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | #define DIFF_STRIP_EOLCR ((u64)0x01000000) /* Strip trailing CR */ |
| 34 | #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */ |
| 35 | #define DIFF_IGNORE_ALLWS ((u64)0x03000000) /* Ignore all whitespace */ |
| 36 | #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */ |
| 37 | #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */ |
| 38 | #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */ |
| 39 | #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */ |
| 40 | #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */ |
| @@ -40,11 +41,10 @@ | |
| 41 | #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */ |
| 42 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 43 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 44 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 45 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 46 | |
| 47 | /* |
| 48 | ** These error messages are shared in multiple locations. They are defined |
| 49 | ** here for consistency. |
| 50 | */ |
| @@ -172,11 +172,11 @@ | |
| 172 | if( diffFlags & DIFF_IGNORE_EOLWS ){ |
| 173 | while( k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 174 | }else if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 175 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 176 | } |
| 177 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 178 | while( s<k && fossil_isspace(z[s]) ){ |
| 179 | if( z[s]=='\t' ){ |
| 180 | indent = ((indent+9)/8)*8; |
| 181 | }else if( z[s]==' ' ){ |
| 182 | indent++; |
| @@ -1792,11 +1792,11 @@ | |
| 1792 | if( diffFlags & DIFF_INVERT ){ |
| 1793 | Blob *pTemp = pA_Blob; |
| 1794 | pA_Blob = pB_Blob; |
| 1795 | pB_Blob = pTemp; |
| 1796 | } |
| 1797 | ignoreWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; |
| 1798 | blob_to_utf8_no_bom(pA_Blob, 0); |
| 1799 | blob_to_utf8_no_bom(pB_Blob, 0); |
| 1800 | |
| 1801 | /* Prepare the input files */ |
| 1802 | memset(&c, 0, sizeof(c)); |
| @@ -1862,28 +1862,36 @@ | |
| 1862 | |
| 1863 | /* |
| 1864 | ** Process diff-related command-line options and return an appropriate |
| 1865 | ** "diffFlags" integer. |
| 1866 | ** |
| 1867 | ** --brief Show filenames only DIFF_BRIEF |
| 1868 | ** --context|-c N N lines of context. DIFF_CONTEXT_MASK |
| 1869 | ** --html Format for HTML DIFF_HTML |
| 1870 | ** --invert Invert the diff DIFF_INVERT |
| 1871 | ** --linenum|-n Show line numbers DIFF_LINENO |
| 1872 | ** --noopt Disable optimization DIFF_NOOPT |
| 1873 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1874 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| 1875 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1876 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1877 | ** -w|--ignore-all-space Ignore all white space DIFF_IGNORE_ALLWS |
| 1878 | ** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS |
| 1879 | */ |
| 1880 | u64 diff_options(void){ |
| 1881 | u64 diffFlags = 0; |
| 1882 | const char *z; |
| 1883 | int f; |
| 1884 | if( find_option("strip-trailing-cr",0,0)!=0 ){ |
| 1885 | diffFlags = DIFF_STRIP_EOLCR; |
| 1886 | } |
| 1887 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| 1888 | diffFlags = DIFF_IGNORE_EOLWS; /* stronger than DIFF_STRIP_EOLCR */ |
| 1889 | } |
| 1890 | if( find_option("ignore-all-space","w",0)!=0 ){ |
| 1891 | diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ |
| 1892 | } |
| 1893 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1894 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1895 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 1896 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1897 | diffFlags |= f + DIFF_CONTEXT_EX; |
| @@ -1892,14 +1900,10 @@ | |
| 1900 | f *= DIFF_CONTEXT_MASK+1; |
| 1901 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1902 | diffFlags |= f; |
| 1903 | } |
| 1904 | if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; |
| 1905 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 1906 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 1907 | if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT; |
| 1908 | if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF; |
| 1909 | return diffFlags; |
| @@ -2001,16 +2005,16 @@ | |
| 2005 | /* |
| 2006 | ** Initialize the annotation process by specifying the file that is |
| 2007 | ** to be annotated. The annotator takes control of the input Blob and |
| 2008 | ** will release it when it is finished with it. |
| 2009 | */ |
| 2010 | static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){ |
| 2011 | int i; |
| 2012 | |
| 2013 | memset(p, 0, sizeof(*p)); |
| 2014 | p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo, |
| 2015 | diffFlags); |
| 2016 | if( p->c.aTo==0 ){ |
| 2017 | return 1; |
| 2018 | } |
| 2019 | p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); |
| 2020 | for(i=0; i<p->c.nTo; i++){ |
| @@ -2028,17 +2032,17 @@ | |
| 2032 | ** being annotated. Do another step of the annotation. Return true |
| 2033 | ** if additional annotation is required. zPName is the tag to insert |
| 2034 | ** on each line of the file being annotated that was contributed by |
| 2035 | ** pParent. Memory to hold zPName is leaked. |
| 2036 | */ |
| 2037 | static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){ |
| 2038 | int i, j; |
| 2039 | int lnTo; |
| 2040 | |
| 2041 | /* Prepare the parent file to be diffed */ |
| 2042 | p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), |
| 2043 | &p->c.nFrom, diffFlags); |
| 2044 | if( p->c.aFrom==0 ){ |
| 2045 | return 1; |
| 2046 | } |
| 2047 | |
| 2048 | /* Compute the differences going from pParent to the file being |
| @@ -2085,11 +2089,12 @@ | |
| 2089 | static void annotate_file( |
| 2090 | Annotator *p, /* The annotator */ |
| 2091 | int fnid, /* The name of the file to be annotated */ |
| 2092 | int mid, /* Use the version of the file in this check-in */ |
| 2093 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 2094 | int annFlags, /* Flags to alter the annotation */ |
| 2095 | u64 diffFlags /* Flags to alter the whitespace handling */ |
| 2096 | ){ |
| 2097 | Blob toAnnotate; /* Text of the final (mid) version of the file */ |
| 2098 | Blob step; /* Text of previous revision */ |
| 2099 | int rid; /* Artifact ID of the file being annotated */ |
| 2100 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -2103,11 +2108,11 @@ | |
| 2108 | } |
| 2109 | if( !content_get(rid, &toAnnotate) ){ |
| 2110 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2111 | } |
| 2112 | if( iLimit<=0 ) iLimit = 1000000000; |
| 2113 | annotation_start(p, &toAnnotate, diffFlags); |
| 2114 | db_begin_transaction(); |
| 2115 | db_multi_exec( |
| 2116 | "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" |
| 2117 | "DELETE FROM vseen;" |
| 2118 | ); |
| @@ -2137,11 +2142,11 @@ | |
| 2142 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2143 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| 2144 | p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); |
| 2145 | if( p->nVers ){ |
| 2146 | content_get(rid, &step); |
| 2147 | annotation_step(p, &step, p->nVers-1, diffFlags); |
| 2148 | blob_reset(&step); |
| 2149 | } |
| 2150 | p->nVers++; |
| 2151 | db_bind_int(&ins, ":rid", rid); |
| 2152 | db_step(&ins); |
| @@ -2177,10 +2182,11 @@ | |
| 2182 | } |
| 2183 | |
| 2184 | /* |
| 2185 | ** WEBPAGE: annotate |
| 2186 | ** WEBPAGE: blame |
| 2187 | ** WEBPAGE: praise |
| 2188 | ** |
| 2189 | ** Query parameters: |
| 2190 | ** |
| 2191 | ** checkin=ID The manifest ID at which to start the annotation |
| 2192 | ** filename=FILENAME The filename. |
| @@ -2193,17 +2199,19 @@ | |
| 2199 | int fnid; |
| 2200 | int i; |
| 2201 | int iLimit; /* Depth limit */ |
| 2202 | int annFlags = ANN_FILE_ANCEST; |
| 2203 | int showLog = 0; /* True to display the log */ |
| 2204 | int ignoreWs = 0; /* Ignore whitespace */ |
| 2205 | u64 diffFlags = DIFF_STRIP_EOLCR; /* diff flags for ignore whitespace */ |
| 2206 | const char *zFilename; /* Name of file to annotate */ |
| 2207 | const char *zCI; /* The check-in containing zFilename */ |
| 2208 | Annotator ann; |
| 2209 | HQuery url; |
| 2210 | struct AnnVers *p; |
| 2211 | unsigned clr1, clr2, clr; |
| 2212 | int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */ |
| 2213 | |
| 2214 | /* Gather query parameters */ |
| 2215 | showLog = atoi(PD("log","1")); |
| 2216 | login_check_credentials(); |
| 2217 | if( !g.perm.Read ){ login_needed(); return; } |
| @@ -2212,17 +2220,19 @@ | |
| 2220 | zFilename = P("filename"); |
| 2221 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); |
| 2222 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 2223 | iLimit = atoi(PD("limit","20")); |
| 2224 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 2225 | ignoreWs = P("w")!=0; |
| 2226 | if( ignoreWs ) diffFlags |= DIFF_IGNORE_ALLWS; |
| 2227 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 2228 | fossil_redirect_home(); |
| 2229 | } |
| 2230 | |
| 2231 | /* compute the annotation */ |
| 2232 | compute_direct_ancestors(mid, 10000000); |
| 2233 | annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); |
| 2234 | zCI = ann.aVers[0].zMUuid; |
| 2235 | |
| 2236 | /* generate the web page */ |
| 2237 | style_header("Annotation For %h", zFilename); |
| 2238 | if( bBlame ){ |
| @@ -2234,10 +2244,18 @@ | |
| 2244 | url_add_parameter(&url, "filename", zFilename); |
| 2245 | if( iLimit!=20 ){ |
| 2246 | url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); |
| 2247 | } |
| 2248 | url_add_parameter(&url, "log", showLog ? "1" : "0"); |
| 2249 | if( ignoreWs ){ |
| 2250 | url_add_parameter(&url, "w", ""); |
| 2251 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 2252 | "%s", url_render(&url, "w", 0, 0, 0)); |
| 2253 | }else{ |
| 2254 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 2255 | "%s", url_render(&url, "w", "", 0, 0)); |
| 2256 | } |
| 2257 | if( showLog ){ |
| 2258 | style_submenu_element("Hide Log", "Hide Log", |
| 2259 | "%s", url_render(&url, "log", "0", 0, 0)); |
| 2260 | }else{ |
| 2261 | style_submenu_element("Show Log", "Show Log", |
| @@ -2347,22 +2365,25 @@ | |
| 2365 | } |
| 2366 | |
| 2367 | /* |
| 2368 | ** COMMAND: annotate |
| 2369 | ** COMMAND: blame |
| 2370 | ** COMMAND: praise |
| 2371 | ** |
| 2372 | ** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME |
| 2373 | ** |
| 2374 | ** Output the text of a file with markings to show when each line of |
| 2375 | ** the file was last modified. The "annotate" command shows line numbers |
| 2376 | ** and omits the username. The "blame" and "praise" commands show the user |
| 2377 | ** who made each checkin and omits the line number. |
| 2378 | ** |
| 2379 | ** Options: |
| 2380 | ** --filevers Show file version numbers rather than check-in versions |
| 2381 | ** -l|--log List all versions analyzed |
| 2382 | ** -n|--limit N Only look backwards in time by N versions |
| 2383 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 2384 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 2385 | ** |
| 2386 | ** See also: info, finfo, timeline |
| 2387 | */ |
| 2388 | void annotate_cmd(void){ |
| 2389 | int fnid; /* Filename ID */ |
| @@ -2374,19 +2395,22 @@ | |
| 2395 | Annotator ann; /* The annotation of the file */ |
| 2396 | int i; /* Loop counter */ |
| 2397 | const char *zLimit; /* The value to the -n|--limit option */ |
| 2398 | int iLimit; /* How far back in time to look */ |
| 2399 | int showLog; /* True to show the log */ |
| 2400 | u64 diffFlags = DIFF_STRIP_EOLCR;/* Flags to control whitespace handling */ |
| 2401 | int fileVers; /* Show file version instead of check-in versions */ |
| 2402 | int annFlags = 0; /* Flags to control annotation properties */ |
| 2403 | int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ |
| 2404 | |
| 2405 | bBlame = g.argv[1][0]!='a'; |
| 2406 | zLimit = find_option("limit","n",1); |
| 2407 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 2408 | iLimit = atoi(zLimit); |
| 2409 | showLog = find_option("log","l",0)!=0; |
| 2410 | if( find_option("ignore-trailing-space","Z",0)!=0 ) diffFlags = DIFF_IGNORE_EOLWS; |
| 2411 | if( find_option("w",0,0)!=0 ) diffFlags |= DIFF_IGNORE_ALLWS; |
| 2412 | fileVers = find_option("filevers",0,0)!=0; |
| 2413 | db_must_be_within_tree(); |
| 2414 | if( g.argc<3 ) { |
| 2415 | usage("FILENAME"); |
| 2416 | } |
| @@ -2412,11 +2436,11 @@ | |
| 2436 | fid, fnid); |
| 2437 | if( mid==0 ){ |
| 2438 | fossil_fatal("unable to find manifest"); |
| 2439 | } |
| 2440 | annFlags |= ANN_FILE_ANCEST; |
| 2441 | annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags); |
| 2442 | if( showLog ){ |
| 2443 | struct AnnVers *p; |
| 2444 | for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){ |
| 2445 | fossil_print("version %3d: %s %.10s file %.10s\n", |
| 2446 | i+1, p->zDate, p->zMUuid, p->zFUuid); |
| 2447 |
+16
-18
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -1089,28 +1089,26 @@ | ||
| 1089 | 1089 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1090 | 1090 | ** as binary when considering if they should be used with external diff program. |
| 1091 | 1091 | ** This option overrides the "binary-glob" setting. |
| 1092 | 1092 | ** |
| 1093 | 1093 | ** Options: |
| 1094 | -** --binary PATTERN Treat files that match the glob PATTERN as binary | |
| 1095 | -** --branch BRANCH Show diff of all changes on BRANCH | |
| 1096 | -** --brief Show filenames only | |
| 1097 | -** --context|-c N Use N lines of context | |
| 1098 | -** --diff-binary BOOL Include binary files when using external commands | |
| 1099 | -** --from|-r VERSION select VERSION as source for the diff | |
| 1100 | -** --ignore-space-at-eol Ignore changes to end-of-line whitespace | |
| 1101 | -** --ignore-space-at-sol Ignore changes to start-of-line whitespace | |
| 1102 | -** --internal|-i use internal diff logic | |
| 1103 | -** --side-by-side|-y side-by-side diff | |
| 1104 | -** --strip-trailing-cr Strip trailing CR | |
| 1105 | -** --tk Launch a Tcl/Tk GUI for display | |
| 1106 | -** --to VERSION select VERSION as target for the diff | |
| 1107 | -** --unified unified diff | |
| 1108 | -** -v|--verbose output complete text of added or deleted files | |
| 1109 | -** -w Ignore changes to start-of-line and end-of-line | |
| 1110 | -** whitespace | |
| 1111 | -** -W|--width Width of lines in side-by-side diff | |
| 1094 | +** --binary PATTERN Treat files that match the glob PATTERN as binary | |
| 1095 | +** --branch BRANCH Show diff of all changes on BRANCH | |
| 1096 | +** --brief Show filenames only | |
| 1097 | +** --context|-c N Use N lines of context | |
| 1098 | +** --diff-binary BOOL Include binary files when using external commands | |
| 1099 | +** --from|-r VERSION select VERSION as source for the diff | |
| 1100 | +** --internal|-i use internal diff logic | |
| 1101 | +** --side-by-side|-y side-by-side diff | |
| 1102 | +** --strip-trailing-cr Strip trailing CR | |
| 1103 | +** --tk Launch a Tcl/Tk GUI for display | |
| 1104 | +** --to VERSION select VERSION as target for the diff | |
| 1105 | +** --unified unified diff | |
| 1106 | +** -v|--verbose output complete text of added or deleted files | |
| 1107 | +** -w|--ignore-all-space Ignore white space when comparing lines | |
| 1108 | +** -W|--width <num> Width of lines in side-by-side diff | |
| 1109 | +** -Z|--ignore-trailing-space Ignore whitespace at line end | |
| 1112 | 1110 | */ |
| 1113 | 1111 | void diff_cmd(void){ |
| 1114 | 1112 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 1115 | 1113 | int isInternDiff; /* True for internal diff */ |
| 1116 | 1114 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 1117 | 1115 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -1089,28 +1089,26 @@ | |
| 1089 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1090 | ** as binary when considering if they should be used with external diff program. |
| 1091 | ** This option overrides the "binary-glob" setting. |
| 1092 | ** |
| 1093 | ** Options: |
| 1094 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 1095 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 1096 | ** --brief Show filenames only |
| 1097 | ** --context|-c N Use N lines of context |
| 1098 | ** --diff-binary BOOL Include binary files when using external commands |
| 1099 | ** --from|-r VERSION select VERSION as source for the diff |
| 1100 | ** --ignore-space-at-eol Ignore changes to end-of-line whitespace |
| 1101 | ** --ignore-space-at-sol Ignore changes to start-of-line whitespace |
| 1102 | ** --internal|-i use internal diff logic |
| 1103 | ** --side-by-side|-y side-by-side diff |
| 1104 | ** --strip-trailing-cr Strip trailing CR |
| 1105 | ** --tk Launch a Tcl/Tk GUI for display |
| 1106 | ** --to VERSION select VERSION as target for the diff |
| 1107 | ** --unified unified diff |
| 1108 | ** -v|--verbose output complete text of added or deleted files |
| 1109 | ** -w Ignore changes to start-of-line and end-of-line |
| 1110 | ** whitespace |
| 1111 | ** -W|--width Width of lines in side-by-side diff |
| 1112 | */ |
| 1113 | void diff_cmd(void){ |
| 1114 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 1115 | int isInternDiff; /* True for internal diff */ |
| 1116 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 1117 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -1089,28 +1089,26 @@ | |
| 1089 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1090 | ** as binary when considering if they should be used with external diff program. |
| 1091 | ** This option overrides the "binary-glob" setting. |
| 1092 | ** |
| 1093 | ** Options: |
| 1094 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 1095 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 1096 | ** --brief Show filenames only |
| 1097 | ** --context|-c N Use N lines of context |
| 1098 | ** --diff-binary BOOL Include binary files when using external commands |
| 1099 | ** --from|-r VERSION select VERSION as source for the diff |
| 1100 | ** --internal|-i use internal diff logic |
| 1101 | ** --side-by-side|-y side-by-side diff |
| 1102 | ** --strip-trailing-cr Strip trailing CR |
| 1103 | ** --tk Launch a Tcl/Tk GUI for display |
| 1104 | ** --to VERSION select VERSION as target for the diff |
| 1105 | ** --unified unified diff |
| 1106 | ** -v|--verbose output complete text of added or deleted files |
| 1107 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 1108 | ** -W|--width <num> Width of lines in side-by-side diff |
| 1109 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 1110 | */ |
| 1111 | void diff_cmd(void){ |
| 1112 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 1113 | int isInternDiff; /* True for internal diff */ |
| 1114 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 1115 |
+16
-18
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -1089,28 +1089,26 @@ | ||
| 1089 | 1089 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1090 | 1090 | ** as binary when considering if they should be used with external diff program. |
| 1091 | 1091 | ** This option overrides the "binary-glob" setting. |
| 1092 | 1092 | ** |
| 1093 | 1093 | ** Options: |
| 1094 | -** --binary PATTERN Treat files that match the glob PATTERN as binary | |
| 1095 | -** --branch BRANCH Show diff of all changes on BRANCH | |
| 1096 | -** --brief Show filenames only | |
| 1097 | -** --context|-c N Use N lines of context | |
| 1098 | -** --diff-binary BOOL Include binary files when using external commands | |
| 1099 | -** --from|-r VERSION select VERSION as source for the diff | |
| 1100 | -** --ignore-space-at-eol Ignore changes to end-of-line whitespace | |
| 1101 | -** --ignore-space-at-sol Ignore changes to start-of-line whitespace | |
| 1102 | -** --internal|-i use internal diff logic | |
| 1103 | -** --side-by-side|-y side-by-side diff | |
| 1104 | -** --strip-trailing-cr Strip trailing CR | |
| 1105 | -** --tk Launch a Tcl/Tk GUI for display | |
| 1106 | -** --to VERSION select VERSION as target for the diff | |
| 1107 | -** --unified unified diff | |
| 1108 | -** -v|--verbose output complete text of added or deleted files | |
| 1109 | -** -w Ignore changes to start-of-line and end-of-line | |
| 1110 | -** whitespace | |
| 1111 | -** -W|--width Width of lines in side-by-side diff | |
| 1094 | +** --binary PATTERN Treat files that match the glob PATTERN as binary | |
| 1095 | +** --branch BRANCH Show diff of all changes on BRANCH | |
| 1096 | +** --brief Show filenames only | |
| 1097 | +** --context|-c N Use N lines of context | |
| 1098 | +** --diff-binary BOOL Include binary files when using external commands | |
| 1099 | +** --from|-r VERSION select VERSION as source for the diff | |
| 1100 | +** --internal|-i use internal diff logic | |
| 1101 | +** --side-by-side|-y side-by-side diff | |
| 1102 | +** --strip-trailing-cr Strip trailing CR | |
| 1103 | +** --tk Launch a Tcl/Tk GUI for display | |
| 1104 | +** --to VERSION select VERSION as target for the diff | |
| 1105 | +** --unified unified diff | |
| 1106 | +** -v|--verbose output complete text of added or deleted files | |
| 1107 | +** -w|--ignore-all-space Ignore white space when comparing lines | |
| 1108 | +** -W|--width <num> Width of lines in side-by-side diff | |
| 1109 | +** -Z|--ignore-trailing-space Ignore whitespace at line end | |
| 1112 | 1110 | */ |
| 1113 | 1111 | void diff_cmd(void){ |
| 1114 | 1112 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 1115 | 1113 | int isInternDiff; /* True for internal diff */ |
| 1116 | 1114 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 1117 | 1115 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -1089,28 +1089,26 @@ | |
| 1089 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1090 | ** as binary when considering if they should be used with external diff program. |
| 1091 | ** This option overrides the "binary-glob" setting. |
| 1092 | ** |
| 1093 | ** Options: |
| 1094 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 1095 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 1096 | ** --brief Show filenames only |
| 1097 | ** --context|-c N Use N lines of context |
| 1098 | ** --diff-binary BOOL Include binary files when using external commands |
| 1099 | ** --from|-r VERSION select VERSION as source for the diff |
| 1100 | ** --ignore-space-at-eol Ignore changes to end-of-line whitespace |
| 1101 | ** --ignore-space-at-sol Ignore changes to start-of-line whitespace |
| 1102 | ** --internal|-i use internal diff logic |
| 1103 | ** --side-by-side|-y side-by-side diff |
| 1104 | ** --strip-trailing-cr Strip trailing CR |
| 1105 | ** --tk Launch a Tcl/Tk GUI for display |
| 1106 | ** --to VERSION select VERSION as target for the diff |
| 1107 | ** --unified unified diff |
| 1108 | ** -v|--verbose output complete text of added or deleted files |
| 1109 | ** -w Ignore changes to start-of-line and end-of-line |
| 1110 | ** whitespace |
| 1111 | ** -W|--width Width of lines in side-by-side diff |
| 1112 | */ |
| 1113 | void diff_cmd(void){ |
| 1114 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 1115 | int isInternDiff; /* True for internal diff */ |
| 1116 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 1117 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -1089,28 +1089,26 @@ | |
| 1089 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1090 | ** as binary when considering if they should be used with external diff program. |
| 1091 | ** This option overrides the "binary-glob" setting. |
| 1092 | ** |
| 1093 | ** Options: |
| 1094 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 1095 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 1096 | ** --brief Show filenames only |
| 1097 | ** --context|-c N Use N lines of context |
| 1098 | ** --diff-binary BOOL Include binary files when using external commands |
| 1099 | ** --from|-r VERSION select VERSION as source for the diff |
| 1100 | ** --internal|-i use internal diff logic |
| 1101 | ** --side-by-side|-y side-by-side diff |
| 1102 | ** --strip-trailing-cr Strip trailing CR |
| 1103 | ** --tk Launch a Tcl/Tk GUI for display |
| 1104 | ** --to VERSION select VERSION as target for the diff |
| 1105 | ** --unified unified diff |
| 1106 | ** -v|--verbose output complete text of added or deleted files |
| 1107 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 1108 | ** -W|--width <num> Width of lines in side-by-side diff |
| 1109 | ** -Z|--ignore-trailing-space Ignore whitespace at line end |
| 1110 | */ |
| 1111 | void diff_cmd(void){ |
| 1112 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 1113 | int isInternDiff; /* True for internal diff */ |
| 1114 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 1115 |
+5
-5
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -460,11 +460,11 @@ | ||
| 460 | 460 | }else{ |
| 461 | 461 | diffFlags = DIFF_INLINE; |
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | if( P("w") ){ |
| 465 | - diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); | |
| 465 | + diffFlags |= DIFF_IGNORE_ALLWS; | |
| 466 | 466 | } |
| 467 | 467 | /* "dc" query parameter determines lines of context */ |
| 468 | 468 | x = atoi(PD("dc","7")); |
| 469 | 469 | if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; |
| 470 | 470 | diffFlags += x; |
| @@ -678,11 +678,11 @@ | ||
| 678 | 678 | verboseFlag = !verboseFlag; |
| 679 | 679 | zPage = "ci"; |
| 680 | 680 | zPageHide = "vinfo"; |
| 681 | 681 | } |
| 682 | 682 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 683 | - zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; | |
| 683 | + zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; | |
| 684 | 684 | if( verboseFlag ){ |
| 685 | 685 | @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) |
| 686 | 686 | @ Hide Diffs</a> |
| 687 | 687 | if( sideBySide ){ |
| 688 | 688 | @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) |
| @@ -988,11 +988,11 @@ | ||
| 988 | 988 | zTo = P("to"); |
| 989 | 989 | if(zGlob && !*zGlob){ |
| 990 | 990 | zGlob = NULL; |
| 991 | 991 | } |
| 992 | 992 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 993 | - zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; | |
| 993 | + zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; | |
| 994 | 994 | if( sideBySide || verboseFlag ){ |
| 995 | 995 | style_submenu_element("Hide Diff", "hidediff", |
| 996 | 996 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 997 | 997 | zFrom, zTo, |
| 998 | 998 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| @@ -1382,13 +1382,13 @@ | ||
| 1382 | 1382 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1383 | 1383 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1384 | 1384 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1385 | 1385 | |
| 1386 | 1386 | style_header("Diff"); |
| 1387 | - zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; | |
| 1387 | + zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; | |
| 1388 | 1388 | if( *zW ){ |
| 1389 | - diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); | |
| 1389 | + diffFlags |= DIFF_IGNORE_ALLWS; | |
| 1390 | 1390 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1391 | 1391 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1392 | 1392 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1393 | 1393 | }else{ |
| 1394 | 1394 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1395 | 1395 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -460,11 +460,11 @@ | |
| 460 | }else{ |
| 461 | diffFlags = DIFF_INLINE; |
| 462 | } |
| 463 | |
| 464 | if( P("w") ){ |
| 465 | diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); |
| 466 | } |
| 467 | /* "dc" query parameter determines lines of context */ |
| 468 | x = atoi(PD("dc","7")); |
| 469 | if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; |
| 470 | diffFlags += x; |
| @@ -678,11 +678,11 @@ | |
| 678 | verboseFlag = !verboseFlag; |
| 679 | zPage = "ci"; |
| 680 | zPageHide = "vinfo"; |
| 681 | } |
| 682 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 683 | zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; |
| 684 | if( verboseFlag ){ |
| 685 | @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) |
| 686 | @ Hide Diffs</a> |
| 687 | if( sideBySide ){ |
| 688 | @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) |
| @@ -988,11 +988,11 @@ | |
| 988 | zTo = P("to"); |
| 989 | if(zGlob && !*zGlob){ |
| 990 | zGlob = NULL; |
| 991 | } |
| 992 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 993 | zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; |
| 994 | if( sideBySide || verboseFlag ){ |
| 995 | style_submenu_element("Hide Diff", "hidediff", |
| 996 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 997 | zFrom, zTo, |
| 998 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| @@ -1382,13 +1382,13 @@ | |
| 1382 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1383 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1384 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1385 | |
| 1386 | style_header("Diff"); |
| 1387 | zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; |
| 1388 | if( *zW ){ |
| 1389 | diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); |
| 1390 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1391 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1392 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1393 | }else{ |
| 1394 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1395 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -460,11 +460,11 @@ | |
| 460 | }else{ |
| 461 | diffFlags = DIFF_INLINE; |
| 462 | } |
| 463 | |
| 464 | if( P("w") ){ |
| 465 | diffFlags |= DIFF_IGNORE_ALLWS; |
| 466 | } |
| 467 | /* "dc" query parameter determines lines of context */ |
| 468 | x = atoi(PD("dc","7")); |
| 469 | if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; |
| 470 | diffFlags += x; |
| @@ -678,11 +678,11 @@ | |
| 678 | verboseFlag = !verboseFlag; |
| 679 | zPage = "ci"; |
| 680 | zPageHide = "vinfo"; |
| 681 | } |
| 682 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 683 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 684 | if( verboseFlag ){ |
| 685 | @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) |
| 686 | @ Hide Diffs</a> |
| 687 | if( sideBySide ){ |
| 688 | @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) |
| @@ -988,11 +988,11 @@ | |
| 988 | zTo = P("to"); |
| 989 | if(zGlob && !*zGlob){ |
| 990 | zGlob = NULL; |
| 991 | } |
| 992 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 993 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 994 | if( sideBySide || verboseFlag ){ |
| 995 | style_submenu_element("Hide Diff", "hidediff", |
| 996 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 997 | zFrom, zTo, |
| 998 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| @@ -1382,13 +1382,13 @@ | |
| 1382 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1383 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1384 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1385 | |
| 1386 | style_header("Diff"); |
| 1387 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1388 | if( *zW ){ |
| 1389 | diffFlags |= DIFF_IGNORE_ALLWS; |
| 1390 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1391 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1392 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1393 | }else{ |
| 1394 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1395 |
+5
-5
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -460,11 +460,11 @@ | ||
| 460 | 460 | }else{ |
| 461 | 461 | diffFlags = DIFF_INLINE; |
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | if( P("w") ){ |
| 465 | - diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); | |
| 465 | + diffFlags |= DIFF_IGNORE_ALLWS; | |
| 466 | 466 | } |
| 467 | 467 | /* "dc" query parameter determines lines of context */ |
| 468 | 468 | x = atoi(PD("dc","7")); |
| 469 | 469 | if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; |
| 470 | 470 | diffFlags += x; |
| @@ -678,11 +678,11 @@ | ||
| 678 | 678 | verboseFlag = !verboseFlag; |
| 679 | 679 | zPage = "ci"; |
| 680 | 680 | zPageHide = "vinfo"; |
| 681 | 681 | } |
| 682 | 682 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 683 | - zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; | |
| 683 | + zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; | |
| 684 | 684 | if( verboseFlag ){ |
| 685 | 685 | @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) |
| 686 | 686 | @ Hide Diffs</a> |
| 687 | 687 | if( sideBySide ){ |
| 688 | 688 | @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) |
| @@ -988,11 +988,11 @@ | ||
| 988 | 988 | zTo = P("to"); |
| 989 | 989 | if(zGlob && !*zGlob){ |
| 990 | 990 | zGlob = NULL; |
| 991 | 991 | } |
| 992 | 992 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 993 | - zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; | |
| 993 | + zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; | |
| 994 | 994 | if( sideBySide || verboseFlag ){ |
| 995 | 995 | style_submenu_element("Hide Diff", "hidediff", |
| 996 | 996 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 997 | 997 | zFrom, zTo, |
| 998 | 998 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| @@ -1382,13 +1382,13 @@ | ||
| 1382 | 1382 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1383 | 1383 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1384 | 1384 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1385 | 1385 | |
| 1386 | 1386 | style_header("Diff"); |
| 1387 | - zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; | |
| 1387 | + zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; | |
| 1388 | 1388 | if( *zW ){ |
| 1389 | - diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); | |
| 1389 | + diffFlags |= DIFF_IGNORE_ALLWS; | |
| 1390 | 1390 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1391 | 1391 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1392 | 1392 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1393 | 1393 | }else{ |
| 1394 | 1394 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1395 | 1395 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -460,11 +460,11 @@ | |
| 460 | }else{ |
| 461 | diffFlags = DIFF_INLINE; |
| 462 | } |
| 463 | |
| 464 | if( P("w") ){ |
| 465 | diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); |
| 466 | } |
| 467 | /* "dc" query parameter determines lines of context */ |
| 468 | x = atoi(PD("dc","7")); |
| 469 | if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; |
| 470 | diffFlags += x; |
| @@ -678,11 +678,11 @@ | |
| 678 | verboseFlag = !verboseFlag; |
| 679 | zPage = "ci"; |
| 680 | zPageHide = "vinfo"; |
| 681 | } |
| 682 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 683 | zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; |
| 684 | if( verboseFlag ){ |
| 685 | @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) |
| 686 | @ Hide Diffs</a> |
| 687 | if( sideBySide ){ |
| 688 | @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) |
| @@ -988,11 +988,11 @@ | |
| 988 | zTo = P("to"); |
| 989 | if(zGlob && !*zGlob){ |
| 990 | zGlob = NULL; |
| 991 | } |
| 992 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 993 | zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; |
| 994 | if( sideBySide || verboseFlag ){ |
| 995 | style_submenu_element("Hide Diff", "hidediff", |
| 996 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 997 | zFrom, zTo, |
| 998 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| @@ -1382,13 +1382,13 @@ | |
| 1382 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1383 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1384 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1385 | |
| 1386 | style_header("Diff"); |
| 1387 | zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":""; |
| 1388 | if( *zW ){ |
| 1389 | diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS); |
| 1390 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1391 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1392 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1393 | }else{ |
| 1394 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1395 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -460,11 +460,11 @@ | |
| 460 | }else{ |
| 461 | diffFlags = DIFF_INLINE; |
| 462 | } |
| 463 | |
| 464 | if( P("w") ){ |
| 465 | diffFlags |= DIFF_IGNORE_ALLWS; |
| 466 | } |
| 467 | /* "dc" query parameter determines lines of context */ |
| 468 | x = atoi(PD("dc","7")); |
| 469 | if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; |
| 470 | diffFlags += x; |
| @@ -678,11 +678,11 @@ | |
| 678 | verboseFlag = !verboseFlag; |
| 679 | zPage = "ci"; |
| 680 | zPageHide = "vinfo"; |
| 681 | } |
| 682 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 683 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 684 | if( verboseFlag ){ |
| 685 | @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName)) |
| 686 | @ Hide Diffs</a> |
| 687 | if( sideBySide ){ |
| 688 | @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW)) |
| @@ -988,11 +988,11 @@ | |
| 988 | zTo = P("to"); |
| 989 | if(zGlob && !*zGlob){ |
| 990 | zGlob = NULL; |
| 991 | } |
| 992 | diffFlags = construct_diff_flags(verboseFlag, sideBySide); |
| 993 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 994 | if( sideBySide || verboseFlag ){ |
| 995 | style_submenu_element("Hide Diff", "hidediff", |
| 996 | "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s", |
| 997 | zFrom, zTo, |
| 998 | zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW); |
| @@ -1382,13 +1382,13 @@ | |
| 1382 | zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); |
| 1383 | zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); |
| 1384 | diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; |
| 1385 | |
| 1386 | style_header("Diff"); |
| 1387 | zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; |
| 1388 | if( *zW ){ |
| 1389 | diffFlags |= DIFF_IGNORE_ALLWS; |
| 1390 | style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes", |
| 1391 | "%s/fdiff?v1=%T&v2=%T&sbs=%d", |
| 1392 | g.zTop, P("v1"), P("v2"), sideBySide); |
| 1393 | }else{ |
| 1394 | style_submenu_element("Ignore Whitespace", "Ignore Whitespace", |
| 1395 |
+1
-1
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -798,11 +798,11 @@ | ||
| 798 | 798 | writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n" |
| 799 | 799 | writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n" |
| 800 | 800 | } |
| 801 | 801 | |
| 802 | 802 | set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS |
| 803 | -lappend MINGW_SQLITE_OPTIONS -D_HAVE_SQLITE_CONFIG_H | |
| 803 | +lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H | |
| 804 | 804 | lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H |
| 805 | 805 | lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE |
| 806 | 806 | |
| 807 | 807 | set j " \\\n " |
| 808 | 808 | writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n" |
| 809 | 809 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -798,11 +798,11 @@ | |
| 798 | writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n" |
| 799 | writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n" |
| 800 | } |
| 801 | |
| 802 | set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS |
| 803 | lappend MINGW_SQLITE_OPTIONS -D_HAVE_SQLITE_CONFIG_H |
| 804 | lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H |
| 805 | lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE |
| 806 | |
| 807 | set j " \\\n " |
| 808 | writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n" |
| 809 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -798,11 +798,11 @@ | |
| 798 | writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n" |
| 799 | writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n" |
| 800 | } |
| 801 | |
| 802 | set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS |
| 803 | lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H |
| 804 | lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H |
| 805 | lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE |
| 806 | |
| 807 | set j " \\\n " |
| 808 | writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n" |
| 809 |
+6
-3
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -1182,10 +1182,11 @@ | ||
| 1182 | 1182 | ** itself by 2 spaces. |
| 1183 | 1183 | ** |
| 1184 | 1184 | ** * For each "Goto", if the jump destination is earlier in the program |
| 1185 | 1185 | ** and ends on one of: |
| 1186 | 1186 | ** Yield SeekGt SeekLt RowSetRead Rewind |
| 1187 | +** or if the P1 parameter is one instead of zero, | |
| 1187 | 1188 | ** then indent all opcodes between the earlier instruction |
| 1188 | 1189 | ** and "Goto" by 2 spaces. |
| 1189 | 1190 | */ |
| 1190 | 1191 | static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ |
| 1191 | 1192 | const char *zSql; /* The text of the SQL statement */ |
| @@ -1229,11 +1230,13 @@ | ||
| 1229 | 1230 | p->nIndent = iOp+1; |
| 1230 | 1231 | |
| 1231 | 1232 | if( str_in_array(zOp, azNext) ){ |
| 1232 | 1233 | for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; |
| 1233 | 1234 | } |
| 1234 | - if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){ | |
| 1235 | + if( str_in_array(zOp, azGoto) && p2op<p->nIndent | |
| 1236 | + && (abYield[p2op] || sqlite3_column_int(pSql, 2)) | |
| 1237 | + ){ | |
| 1235 | 1238 | for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2; |
| 1236 | 1239 | } |
| 1237 | 1240 | } |
| 1238 | 1241 | |
| 1239 | 1242 | p->iIndent = 0; |
| @@ -3815,12 +3818,12 @@ | ||
| 3815 | 3818 | "Enter \".help\" for usage hints.\n", |
| 3816 | 3819 | sqlite3_libversion(), sqlite3_sourceid() |
| 3817 | 3820 | ); |
| 3818 | 3821 | if( warnInmemoryDb ){ |
| 3819 | 3822 | printf("Connected to a "); |
| 3820 | - printBold("transient in-memory database."); | |
| 3821 | - printf("\nUse \".open FILENAME\" to reopen on a " | |
| 3823 | + printBold("transient in-memory database"); | |
| 3824 | + printf(".\nUse \".open FILENAME\" to reopen on a " | |
| 3822 | 3825 | "persistent database.\n"); |
| 3823 | 3826 | } |
| 3824 | 3827 | zHome = find_home_dir(); |
| 3825 | 3828 | if( zHome ){ |
| 3826 | 3829 | nHistory = strlen30(zHome) + 20; |
| 3827 | 3830 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -1182,10 +1182,11 @@ | |
| 1182 | ** itself by 2 spaces. |
| 1183 | ** |
| 1184 | ** * For each "Goto", if the jump destination is earlier in the program |
| 1185 | ** and ends on one of: |
| 1186 | ** Yield SeekGt SeekLt RowSetRead Rewind |
| 1187 | ** then indent all opcodes between the earlier instruction |
| 1188 | ** and "Goto" by 2 spaces. |
| 1189 | */ |
| 1190 | static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ |
| 1191 | const char *zSql; /* The text of the SQL statement */ |
| @@ -1229,11 +1230,13 @@ | |
| 1229 | p->nIndent = iOp+1; |
| 1230 | |
| 1231 | if( str_in_array(zOp, azNext) ){ |
| 1232 | for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; |
| 1233 | } |
| 1234 | if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){ |
| 1235 | for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2; |
| 1236 | } |
| 1237 | } |
| 1238 | |
| 1239 | p->iIndent = 0; |
| @@ -3815,12 +3818,12 @@ | |
| 3815 | "Enter \".help\" for usage hints.\n", |
| 3816 | sqlite3_libversion(), sqlite3_sourceid() |
| 3817 | ); |
| 3818 | if( warnInmemoryDb ){ |
| 3819 | printf("Connected to a "); |
| 3820 | printBold("transient in-memory database."); |
| 3821 | printf("\nUse \".open FILENAME\" to reopen on a " |
| 3822 | "persistent database.\n"); |
| 3823 | } |
| 3824 | zHome = find_home_dir(); |
| 3825 | if( zHome ){ |
| 3826 | nHistory = strlen30(zHome) + 20; |
| 3827 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -1182,10 +1182,11 @@ | |
| 1182 | ** itself by 2 spaces. |
| 1183 | ** |
| 1184 | ** * For each "Goto", if the jump destination is earlier in the program |
| 1185 | ** and ends on one of: |
| 1186 | ** Yield SeekGt SeekLt RowSetRead Rewind |
| 1187 | ** or if the P1 parameter is one instead of zero, |
| 1188 | ** then indent all opcodes between the earlier instruction |
| 1189 | ** and "Goto" by 2 spaces. |
| 1190 | */ |
| 1191 | static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ |
| 1192 | const char *zSql; /* The text of the SQL statement */ |
| @@ -1229,11 +1230,13 @@ | |
| 1230 | p->nIndent = iOp+1; |
| 1231 | |
| 1232 | if( str_in_array(zOp, azNext) ){ |
| 1233 | for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; |
| 1234 | } |
| 1235 | if( str_in_array(zOp, azGoto) && p2op<p->nIndent |
| 1236 | && (abYield[p2op] || sqlite3_column_int(pSql, 2)) |
| 1237 | ){ |
| 1238 | for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2; |
| 1239 | } |
| 1240 | } |
| 1241 | |
| 1242 | p->iIndent = 0; |
| @@ -3815,12 +3818,12 @@ | |
| 3818 | "Enter \".help\" for usage hints.\n", |
| 3819 | sqlite3_libversion(), sqlite3_sourceid() |
| 3820 | ); |
| 3821 | if( warnInmemoryDb ){ |
| 3822 | printf("Connected to a "); |
| 3823 | printBold("transient in-memory database"); |
| 3824 | printf(".\nUse \".open FILENAME\" to reopen on a " |
| 3825 | "persistent database.\n"); |
| 3826 | } |
| 3827 | zHome = find_home_dir(); |
| 3828 | if( zHome ){ |
| 3829 | nHistory = strlen30(zHome) + 20; |
| 3830 |
+105
-17
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -73,12 +73,45 @@ | ||
| 73 | 73 | # define _FILE_OFFSET_BITS 64 |
| 74 | 74 | # endif |
| 75 | 75 | # define _LARGEFILE_SOURCE 1 |
| 76 | 76 | #endif |
| 77 | 77 | |
| 78 | +/* | |
| 79 | +** For MinGW, check to see if we can include the header file containing its | |
| 80 | +** version information, among other things. Normally, this internal MinGW | |
| 81 | +** header file would [only] be included automatically by other MinGW header | |
| 82 | +** files; however, the contained version information is now required by this | |
| 83 | +** header file to work around binary compatibility issues (see below) and | |
| 84 | +** this is the only known way to reliably obtain it. This entire #if block | |
| 85 | +** would be completely unnecessary if there was any other way of detecting | |
| 86 | +** MinGW via their preprocessor (e.g. if they customized their GCC to define | |
| 87 | +** some MinGW-specific macros). When compiling for MinGW, either the | |
| 88 | +** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be | |
| 89 | +** defined; otherwise, detection of conditions specific to MinGW will be | |
| 90 | +** disabled. | |
| 91 | +*/ | |
| 92 | +#if defined(_HAVE_MINGW_H) | |
| 93 | +# include "mingw.h" | |
| 94 | +#elif defined(_HAVE__MINGW_H) | |
| 95 | +# include "_mingw.h" | |
| 96 | +#endif | |
| 97 | + | |
| 98 | +/* | |
| 99 | +** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T | |
| 100 | +** define is required to maintain binary compatibility with the MSVC runtime | |
| 101 | +** library in use (e.g. for Windows XP). | |
| 102 | +*/ | |
| 103 | +#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ | |
| 104 | + defined(_WIN32) && !defined(_WIN64) && \ | |
| 105 | + defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ | |
| 106 | + defined(__MSVCRT__) | |
| 107 | +# define _USE_32BIT_TIME_T | |
| 108 | +#endif | |
| 109 | + | |
| 78 | 110 | /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear |
| 79 | -** first in QNX. | |
| 111 | +** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for | |
| 112 | +** MinGW. | |
| 80 | 113 | */ |
| 81 | 114 | /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ |
| 82 | 115 | /************** Begin file sqlite3.h *****************************************/ |
| 83 | 116 | /* |
| 84 | 117 | ** 2001 September 15 |
| @@ -189,11 +222,11 @@ | ||
| 189 | 222 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 190 | 223 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 191 | 224 | */ |
| 192 | 225 | #define SQLITE_VERSION "3.8.4" |
| 193 | 226 | #define SQLITE_VERSION_NUMBER 3008004 |
| 194 | -#define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042" | |
| 227 | +#define SQLITE_SOURCE_ID "2014-03-06 13:38:37 0a4200f95cf46ad620b9fd91f4444114a0c74730" | |
| 195 | 228 | |
| 196 | 229 | /* |
| 197 | 230 | ** CAPI3REF: Run-Time Library Version Numbers |
| 198 | 231 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 199 | 232 | ** |
| @@ -36451,12 +36484,29 @@ | ||
| 36451 | 36484 | ** Interfaces for opening a shared library, finding entry points |
| 36452 | 36485 | ** within the shared library, and closing the shared library. |
| 36453 | 36486 | */ |
| 36454 | 36487 | static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |
| 36455 | 36488 | HANDLE h; |
| 36489 | +#if defined(__CYGWIN__) | |
| 36490 | + int nFull = pVfs->mxPathname+1; | |
| 36491 | + char *zFull = sqlite3MallocZero( nFull ); | |
| 36492 | + void *zConverted = 0; | |
| 36493 | + if( zFull==0 ){ | |
| 36494 | + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); | |
| 36495 | + return 0; | |
| 36496 | + } | |
| 36497 | + if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ | |
| 36498 | + sqlite3_free(zFull); | |
| 36499 | + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); | |
| 36500 | + return 0; | |
| 36501 | + } | |
| 36502 | + zConverted = winConvertFromUtf8Filename(zFull); | |
| 36503 | + sqlite3_free(zFull); | |
| 36504 | +#else | |
| 36456 | 36505 | void *zConverted = winConvertFromUtf8Filename(zFilename); |
| 36457 | 36506 | UNUSED_PARAMETER(pVfs); |
| 36507 | +#endif | |
| 36458 | 36508 | if( zConverted==0 ){ |
| 36459 | 36509 | OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); |
| 36460 | 36510 | return 0; |
| 36461 | 36511 | } |
| 36462 | 36512 | if( osIsNT() ){ |
| @@ -55338,11 +55388,11 @@ | ||
| 55338 | 55388 | assert( pIdxKey->default_rc==1 |
| 55339 | 55389 | || pIdxKey->default_rc==0 |
| 55340 | 55390 | || pIdxKey->default_rc==-1 |
| 55341 | 55391 | ); |
| 55342 | 55392 | }else{ |
| 55343 | - xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */ | |
| 55393 | + xRecordCompare = 0; /* All keys are integers */ | |
| 55344 | 55394 | } |
| 55345 | 55395 | |
| 55346 | 55396 | rc = moveToRoot(pCur); |
| 55347 | 55397 | if( rc ){ |
| 55348 | 55398 | return rc; |
| @@ -62528,10 +62578,14 @@ | ||
| 62528 | 62578 | ** sqlite3MemRelease() were called from here. With -O2, this jumps |
| 62529 | 62579 | ** to 6.6 percent. The test case is inserting 1000 rows into a table |
| 62530 | 62580 | ** with no indexes using a single prepared INSERT statement, bind() |
| 62531 | 62581 | ** and reset(). Inserts are grouped into a transaction. |
| 62532 | 62582 | */ |
| 62583 | + testcase( p->flags & MEM_Agg ); | |
| 62584 | + testcase( p->flags & MEM_Dyn ); | |
| 62585 | + testcase( p->flags & MEM_Frame ); | |
| 62586 | + testcase( p->flags & MEM_RowSet ); | |
| 62533 | 62587 | if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ |
| 62534 | 62588 | sqlite3VdbeMemRelease(p); |
| 62535 | 62589 | }else if( p->zMalloc ){ |
| 62536 | 62590 | sqlite3DbFree(db, p->zMalloc); |
| 62537 | 62591 | p->zMalloc = 0; |
| @@ -64256,31 +64310,36 @@ | ||
| 64256 | 64310 | break; |
| 64257 | 64311 | } |
| 64258 | 64312 | case 1: { /* 1-byte signed integer */ |
| 64259 | 64313 | pMem->u.i = ONE_BYTE_INT(buf); |
| 64260 | 64314 | pMem->flags = MEM_Int; |
| 64315 | + testcase( pMem->u.i<0 ); | |
| 64261 | 64316 | return 1; |
| 64262 | 64317 | } |
| 64263 | 64318 | case 2: { /* 2-byte signed integer */ |
| 64264 | 64319 | pMem->u.i = TWO_BYTE_INT(buf); |
| 64265 | 64320 | pMem->flags = MEM_Int; |
| 64321 | + testcase( pMem->u.i<0 ); | |
| 64266 | 64322 | return 2; |
| 64267 | 64323 | } |
| 64268 | 64324 | case 3: { /* 3-byte signed integer */ |
| 64269 | 64325 | pMem->u.i = THREE_BYTE_INT(buf); |
| 64270 | 64326 | pMem->flags = MEM_Int; |
| 64327 | + testcase( pMem->u.i<0 ); | |
| 64271 | 64328 | return 3; |
| 64272 | 64329 | } |
| 64273 | 64330 | case 4: { /* 4-byte signed integer */ |
| 64274 | 64331 | y = FOUR_BYTE_UINT(buf); |
| 64275 | 64332 | pMem->u.i = (i64)*(int*)&y; |
| 64276 | 64333 | pMem->flags = MEM_Int; |
| 64334 | + testcase( pMem->u.i<0 ); | |
| 64277 | 64335 | return 4; |
| 64278 | 64336 | } |
| 64279 | 64337 | case 5: { /* 6-byte signed integer */ |
| 64280 | 64338 | pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); |
| 64281 | 64339 | pMem->flags = MEM_Int; |
| 64340 | + testcase( pMem->u.i<0 ); | |
| 64282 | 64341 | return 6; |
| 64283 | 64342 | } |
| 64284 | 64343 | case 6: /* 8-byte signed integer */ |
| 64285 | 64344 | case 7: { /* IEEE floating point */ |
| 64286 | 64345 | #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) |
| @@ -64299,10 +64358,11 @@ | ||
| 64299 | 64358 | y = FOUR_BYTE_UINT(buf+4); |
| 64300 | 64359 | x = (x<<32) | y; |
| 64301 | 64360 | if( serial_type==6 ){ |
| 64302 | 64361 | pMem->u.i = *(i64*)&x; |
| 64303 | 64362 | pMem->flags = MEM_Int; |
| 64363 | + testcase( pMem->u.i<0 ); | |
| 64304 | 64364 | }else{ |
| 64305 | 64365 | assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); |
| 64306 | 64366 | swapMixedEndianFloat(x); |
| 64307 | 64367 | memcpy(&pMem->r, &x, sizeof(x)); |
| 64308 | 64368 | pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; |
| @@ -64644,24 +64704,30 @@ | ||
| 64644 | 64704 | u32 y; |
| 64645 | 64705 | assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); |
| 64646 | 64706 | switch( serial_type ){ |
| 64647 | 64707 | case 0: |
| 64648 | 64708 | case 1: |
| 64709 | + testcase( aKey[0]&0x80 ); | |
| 64649 | 64710 | return ONE_BYTE_INT(aKey); |
| 64650 | 64711 | case 2: |
| 64712 | + testcase( aKey[0]&0x80 ); | |
| 64651 | 64713 | return TWO_BYTE_INT(aKey); |
| 64652 | 64714 | case 3: |
| 64715 | + testcase( aKey[0]&0x80 ); | |
| 64653 | 64716 | return THREE_BYTE_INT(aKey); |
| 64654 | 64717 | case 4: { |
| 64718 | + testcase( aKey[0]&0x80 ); | |
| 64655 | 64719 | y = FOUR_BYTE_UINT(aKey); |
| 64656 | 64720 | return (i64)*(int*)&y; |
| 64657 | 64721 | } |
| 64658 | 64722 | case 5: { |
| 64723 | + testcase( aKey[0]&0x80 ); | |
| 64659 | 64724 | return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); |
| 64660 | 64725 | } |
| 64661 | 64726 | case 6: { |
| 64662 | 64727 | u64 x = FOUR_BYTE_UINT(aKey); |
| 64728 | + testcase( aKey[0]&0x80 ); | |
| 64663 | 64729 | x = (x<<32) | FOUR_BYTE_UINT(aKey+4); |
| 64664 | 64730 | return (i64)*(i64*)&x; |
| 64665 | 64731 | } |
| 64666 | 64732 | } |
| 64667 | 64733 | |
| @@ -64725,10 +64791,11 @@ | ||
| 64725 | 64791 | u32 serial_type; |
| 64726 | 64792 | |
| 64727 | 64793 | /* RHS is an integer */ |
| 64728 | 64794 | if( pRhs->flags & MEM_Int ){ |
| 64729 | 64795 | serial_type = aKey1[idx1]; |
| 64796 | + testcase( serial_type==12 ); | |
| 64730 | 64797 | if( serial_type>=12 ){ |
| 64731 | 64798 | rc = +1; |
| 64732 | 64799 | }else if( serial_type==0 ){ |
| 64733 | 64800 | rc = -1; |
| 64734 | 64801 | }else if( serial_type==7 ){ |
| @@ -64775,16 +64842,19 @@ | ||
| 64775 | 64842 | } |
| 64776 | 64843 | |
| 64777 | 64844 | /* RHS is a string */ |
| 64778 | 64845 | else if( pRhs->flags & MEM_Str ){ |
| 64779 | 64846 | getVarint32(&aKey1[idx1], serial_type); |
| 64847 | + testcase( serial_type==12 ); | |
| 64780 | 64848 | if( serial_type<12 ){ |
| 64781 | 64849 | rc = -1; |
| 64782 | 64850 | }else if( !(serial_type & 0x01) ){ |
| 64783 | 64851 | rc = +1; |
| 64784 | 64852 | }else{ |
| 64785 | 64853 | mem1.n = (serial_type - 12) / 2; |
| 64854 | + testcase( (d1+mem1.n)==(unsigned)nKey1 ); | |
| 64855 | + testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); | |
| 64786 | 64856 | if( (d1+mem1.n) > (unsigned)nKey1 ){ |
| 64787 | 64857 | rc = 1; /* Corruption */ |
| 64788 | 64858 | }else if( pKeyInfo->aColl[i] ){ |
| 64789 | 64859 | mem1.enc = pKeyInfo->enc; |
| 64790 | 64860 | mem1.db = pKeyInfo->db; |
| @@ -64800,14 +64870,17 @@ | ||
| 64800 | 64870 | } |
| 64801 | 64871 | |
| 64802 | 64872 | /* RHS is a blob */ |
| 64803 | 64873 | else if( pRhs->flags & MEM_Blob ){ |
| 64804 | 64874 | getVarint32(&aKey1[idx1], serial_type); |
| 64875 | + testcase( serial_type==12 ); | |
| 64805 | 64876 | if( serial_type<12 || (serial_type & 0x01) ){ |
| 64806 | 64877 | rc = -1; |
| 64807 | 64878 | }else{ |
| 64808 | 64879 | int nStr = (serial_type - 12) / 2; |
| 64880 | + testcase( (d1+nStr)==(unsigned)nKey1 ); | |
| 64881 | + testcase( (d1+nStr+1)==(unsigned)nKey1 ); | |
| 64809 | 64882 | if( (d1+nStr) > (unsigned)nKey1 ){ |
| 64810 | 64883 | rc = 1; /* Corruption */ |
| 64811 | 64884 | }else{ |
| 64812 | 64885 | int nCmp = MIN(nStr, pRhs->n); |
| 64813 | 64886 | rc = memcmp(&aKey1[d1], pRhs->z, nCmp); |
| @@ -64877,33 +64950,39 @@ | ||
| 64877 | 64950 | |
| 64878 | 64951 | assert( bSkip==0 ); |
| 64879 | 64952 | switch( serial_type ){ |
| 64880 | 64953 | case 1: { /* 1-byte signed integer */ |
| 64881 | 64954 | lhs = ONE_BYTE_INT(aKey); |
| 64955 | + testcase( lhs<0 ); | |
| 64882 | 64956 | break; |
| 64883 | 64957 | } |
| 64884 | 64958 | case 2: { /* 2-byte signed integer */ |
| 64885 | 64959 | lhs = TWO_BYTE_INT(aKey); |
| 64960 | + testcase( lhs<0 ); | |
| 64886 | 64961 | break; |
| 64887 | 64962 | } |
| 64888 | 64963 | case 3: { /* 3-byte signed integer */ |
| 64889 | 64964 | lhs = THREE_BYTE_INT(aKey); |
| 64965 | + testcase( lhs<0 ); | |
| 64890 | 64966 | break; |
| 64891 | 64967 | } |
| 64892 | 64968 | case 4: { /* 4-byte signed integer */ |
| 64893 | 64969 | y = FOUR_BYTE_UINT(aKey); |
| 64894 | 64970 | lhs = (i64)*(int*)&y; |
| 64971 | + testcase( lhs<0 ); | |
| 64895 | 64972 | break; |
| 64896 | 64973 | } |
| 64897 | 64974 | case 5: { /* 6-byte signed integer */ |
| 64898 | 64975 | lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); |
| 64976 | + testcase( lhs<0 ); | |
| 64899 | 64977 | break; |
| 64900 | 64978 | } |
| 64901 | 64979 | case 6: { /* 8-byte signed integer */ |
| 64902 | 64980 | x = FOUR_BYTE_UINT(aKey); |
| 64903 | 64981 | x = (x<<32) | FOUR_BYTE_UINT(aKey+4); |
| 64904 | 64982 | lhs = *(i64*)&x; |
| 64983 | + testcase( lhs<0 ); | |
| 64905 | 64984 | break; |
| 64906 | 64985 | } |
| 64907 | 64986 | case 8: |
| 64908 | 64987 | lhs = 0; |
| 64909 | 64988 | break; |
| @@ -65036,13 +65115,15 @@ | ||
| 65036 | 65115 | p->r2 = 1; |
| 65037 | 65116 | } |
| 65038 | 65117 | if( (flags & MEM_Int) ){ |
| 65039 | 65118 | return vdbeRecordCompareInt; |
| 65040 | 65119 | } |
| 65041 | - if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0 | |
| 65042 | - && p->pKeyInfo->aColl[0]==0 | |
| 65043 | - ){ | |
| 65120 | + testcase( flags & MEM_Real ); | |
| 65121 | + testcase( flags & MEM_Null ); | |
| 65122 | + testcase( flags & MEM_Blob ); | |
| 65123 | + if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ | |
| 65124 | + assert( flags & MEM_Str ); | |
| 65044 | 65125 | return vdbeRecordCompareString; |
| 65045 | 65126 | } |
| 65046 | 65127 | } |
| 65047 | 65128 | |
| 65048 | 65129 | return sqlite3VdbeRecordCompare; |
| @@ -66945,11 +67026,11 @@ | ||
| 66945 | 67026 | ** value of the cell. This macro verifies that shallow copies are |
| 66946 | 67027 | ** not misused. A shallow copy of a string or blob just copies a |
| 66947 | 67028 | ** pointer to the string or blob, not the content. If the original |
| 66948 | 67029 | ** is changed while the copy is still in use, the string or blob might |
| 66949 | 67030 | ** be changed out from under the copy. This macro verifies that nothing |
| 66950 | -** like that every happens. | |
| 67031 | +** like that ever happens. | |
| 66951 | 67032 | */ |
| 66952 | 67033 | #ifdef SQLITE_DEBUG |
| 66953 | 67034 | # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) |
| 66954 | 67035 | #else |
| 66955 | 67036 | # define memAboutToChange(P,M) |
| @@ -67677,10 +67758,15 @@ | ||
| 67677 | 67758 | ** |
| 67678 | 67759 | ** An unconditional jump to address P2. |
| 67679 | 67760 | ** The next instruction executed will be |
| 67680 | 67761 | ** the one at index P2 from the beginning of |
| 67681 | 67762 | ** the program. |
| 67763 | +** | |
| 67764 | +** The P1 parameter is not actually used by this opcode. However, it | |
| 67765 | +** is sometimes set to 1 instead of 0 as a hint to the command-line shell | |
| 67766 | +** that this Goto is the bottom of a loop and that the lines from P2 down | |
| 67767 | +** to the current line should be indented for EXPLAIN output. | |
| 67682 | 67768 | */ |
| 67683 | 67769 | case OP_Goto: { /* jump */ |
| 67684 | 67770 | pc = pOp->p2 - 1; |
| 67685 | 67771 | |
| 67686 | 67772 | /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, |
| @@ -69172,12 +69258,12 @@ | ||
| 69172 | 69258 | |
| 69173 | 69259 | /* Opcode: Once P1 P2 * * * |
| 69174 | 69260 | ** |
| 69175 | 69261 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 69176 | 69262 | ** set the flag and fall through to the next instruction. In other words, |
| 69177 | -** this opcode causes all following up codes up through P2 (but not including | |
| 69178 | -** P2) to run just once and skipped on subsequent times through the loop. | |
| 69263 | +** this opcode causes all following opcodes up through P2 (but not including | |
| 69264 | +** P2) to run just once and to be skipped on subsequent times through the loop. | |
| 69179 | 69265 | */ |
| 69180 | 69266 | case OP_Once: { /* jump */ |
| 69181 | 69267 | assert( pOp->p1<p->nOnceFlag ); |
| 69182 | 69268 | VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); |
| 69183 | 69269 | if( p->aOnceFlag[pOp->p1] ){ |
| @@ -83266,11 +83352,14 @@ | ||
| 83266 | 83352 | VdbeCoverage(v); |
| 83267 | 83353 | callStatGet(v, regStat4, STAT_GET_NEQ, regEq); |
| 83268 | 83354 | callStatGet(v, regStat4, STAT_GET_NLT, regLt); |
| 83269 | 83355 | callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); |
| 83270 | 83356 | sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); |
| 83271 | - VdbeCoverage(v); | |
| 83357 | + /* We know that the regSampleRowid row exists because it was read by | |
| 83358 | + ** the previous loop. Thus the not-found jump of seekOp will never | |
| 83359 | + ** be taken */ | |
| 83360 | + VdbeCoverageNeverTaken(v); | |
| 83272 | 83361 | #ifdef SQLITE_ENABLE_STAT3 |
| 83273 | 83362 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
| 83274 | 83363 | pIdx->aiColumn[0], regSample); |
| 83275 | 83364 | #else |
| 83276 | 83365 | for(i=0; i<nCol; i++){ |
| @@ -83280,11 +83369,11 @@ | ||
| 83280 | 83369 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample); |
| 83281 | 83370 | #endif |
| 83282 | 83371 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); |
| 83283 | 83372 | sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); |
| 83284 | 83373 | sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); |
| 83285 | - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); | |
| 83374 | + sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */ | |
| 83286 | 83375 | sqlite3VdbeJumpHere(v, addrIsNull); |
| 83287 | 83376 | } |
| 83288 | 83377 | #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ |
| 83289 | 83378 | |
| 83290 | 83379 | /* End of analysis */ |
| @@ -93446,17 +93535,17 @@ | ||
| 93446 | 93535 | |
| 93447 | 93536 | /* |
| 93448 | 93537 | ** Compute the affinity string for table pTab, if it has not already been |
| 93449 | 93538 | ** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. |
| 93450 | 93539 | ** |
| 93451 | -** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values and | |
| 93540 | +** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and | |
| 93452 | 93541 | ** if iReg>0 then code an OP_Affinity opcode that will set the affinities |
| 93453 | 93542 | ** for register iReg and following. Or if affinities exists and iReg==0, |
| 93454 | 93543 | ** then just set the P4 operand of the previous opcode (which should be |
| 93455 | 93544 | ** an OP_MakeRecord) to the affinity string. |
| 93456 | 93545 | ** |
| 93457 | -** A column affinity string has one character column: | |
| 93546 | +** A column affinity string has one character per column: | |
| 93458 | 93547 | ** |
| 93459 | 93548 | ** Character Column affinity |
| 93460 | 93549 | ** ------------------------------ |
| 93461 | 93550 | ** 'a' TEXT |
| 93462 | 93551 | ** 'b' NONE |
| @@ -93493,14 +93582,13 @@ | ||
| 93493 | 93582 | } |
| 93494 | 93583 | } |
| 93495 | 93584 | |
| 93496 | 93585 | /* |
| 93497 | 93586 | ** Return non-zero if the table pTab in database iDb or any of its indices |
| 93498 | -** have been opened at any point in the VDBE program beginning at location | |
| 93499 | -** iStartAddr throught the end of the program. This is used to see if | |
| 93587 | +** have been opened at any point in the VDBE program. This is used to see if | |
| 93500 | 93588 | ** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can |
| 93501 | -** run without using temporary table for the results of the SELECT. | |
| 93589 | +** run without using a temporary table for the results of the SELECT. | |
| 93502 | 93590 | */ |
| 93503 | 93591 | static int readsTable(Parse *p, int iDb, Table *pTab){ |
| 93504 | 93592 | Vdbe *v = sqlite3GetVdbe(p); |
| 93505 | 93593 | int i; |
| 93506 | 93594 | int iEnd = sqlite3VdbeCurrentAddr(v); |
| @@ -112351,17 +112439,17 @@ | ||
| 112351 | 112439 | } |
| 112352 | 112440 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ |
| 112353 | 112441 | pRangeEnd = pLoop->aLTerm[j++]; |
| 112354 | 112442 | nExtraReg = 1; |
| 112355 | 112443 | if( pRangeStart==0 |
| 112356 | - && (pRangeEnd->wtFlags & TERM_VNULL)==0 | |
| 112357 | 112444 | && (j = pIdx->aiColumn[nEq])>=0 |
| 112358 | 112445 | && pIdx->pTable->aCol[j].notNull==0 |
| 112359 | 112446 | ){ |
| 112360 | 112447 | bSeekPastNull = 1; |
| 112361 | 112448 | } |
| 112362 | 112449 | } |
| 112450 | + assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); | |
| 112363 | 112451 | |
| 112364 | 112452 | /* Generate code to evaluate all constraint terms using == or IN |
| 112365 | 112453 | ** and store the values of those terms in an array of registers |
| 112366 | 112454 | ** starting at regBase. |
| 112367 | 112455 | */ |
| 112368 | 112456 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -73,12 +73,45 @@ | |
| 73 | # define _FILE_OFFSET_BITS 64 |
| 74 | # endif |
| 75 | # define _LARGEFILE_SOURCE 1 |
| 76 | #endif |
| 77 | |
| 78 | /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear |
| 79 | ** first in QNX. |
| 80 | */ |
| 81 | /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ |
| 82 | /************** Begin file sqlite3.h *****************************************/ |
| 83 | /* |
| 84 | ** 2001 September 15 |
| @@ -189,11 +222,11 @@ | |
| 189 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 190 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 191 | */ |
| 192 | #define SQLITE_VERSION "3.8.4" |
| 193 | #define SQLITE_VERSION_NUMBER 3008004 |
| 194 | #define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042" |
| 195 | |
| 196 | /* |
| 197 | ** CAPI3REF: Run-Time Library Version Numbers |
| 198 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 199 | ** |
| @@ -36451,12 +36484,29 @@ | |
| 36451 | ** Interfaces for opening a shared library, finding entry points |
| 36452 | ** within the shared library, and closing the shared library. |
| 36453 | */ |
| 36454 | static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |
| 36455 | HANDLE h; |
| 36456 | void *zConverted = winConvertFromUtf8Filename(zFilename); |
| 36457 | UNUSED_PARAMETER(pVfs); |
| 36458 | if( zConverted==0 ){ |
| 36459 | OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); |
| 36460 | return 0; |
| 36461 | } |
| 36462 | if( osIsNT() ){ |
| @@ -55338,11 +55388,11 @@ | |
| 55338 | assert( pIdxKey->default_rc==1 |
| 55339 | || pIdxKey->default_rc==0 |
| 55340 | || pIdxKey->default_rc==-1 |
| 55341 | ); |
| 55342 | }else{ |
| 55343 | xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */ |
| 55344 | } |
| 55345 | |
| 55346 | rc = moveToRoot(pCur); |
| 55347 | if( rc ){ |
| 55348 | return rc; |
| @@ -62528,10 +62578,14 @@ | |
| 62528 | ** sqlite3MemRelease() were called from here. With -O2, this jumps |
| 62529 | ** to 6.6 percent. The test case is inserting 1000 rows into a table |
| 62530 | ** with no indexes using a single prepared INSERT statement, bind() |
| 62531 | ** and reset(). Inserts are grouped into a transaction. |
| 62532 | */ |
| 62533 | if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ |
| 62534 | sqlite3VdbeMemRelease(p); |
| 62535 | }else if( p->zMalloc ){ |
| 62536 | sqlite3DbFree(db, p->zMalloc); |
| 62537 | p->zMalloc = 0; |
| @@ -64256,31 +64310,36 @@ | |
| 64256 | break; |
| 64257 | } |
| 64258 | case 1: { /* 1-byte signed integer */ |
| 64259 | pMem->u.i = ONE_BYTE_INT(buf); |
| 64260 | pMem->flags = MEM_Int; |
| 64261 | return 1; |
| 64262 | } |
| 64263 | case 2: { /* 2-byte signed integer */ |
| 64264 | pMem->u.i = TWO_BYTE_INT(buf); |
| 64265 | pMem->flags = MEM_Int; |
| 64266 | return 2; |
| 64267 | } |
| 64268 | case 3: { /* 3-byte signed integer */ |
| 64269 | pMem->u.i = THREE_BYTE_INT(buf); |
| 64270 | pMem->flags = MEM_Int; |
| 64271 | return 3; |
| 64272 | } |
| 64273 | case 4: { /* 4-byte signed integer */ |
| 64274 | y = FOUR_BYTE_UINT(buf); |
| 64275 | pMem->u.i = (i64)*(int*)&y; |
| 64276 | pMem->flags = MEM_Int; |
| 64277 | return 4; |
| 64278 | } |
| 64279 | case 5: { /* 6-byte signed integer */ |
| 64280 | pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); |
| 64281 | pMem->flags = MEM_Int; |
| 64282 | return 6; |
| 64283 | } |
| 64284 | case 6: /* 8-byte signed integer */ |
| 64285 | case 7: { /* IEEE floating point */ |
| 64286 | #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) |
| @@ -64299,10 +64358,11 @@ | |
| 64299 | y = FOUR_BYTE_UINT(buf+4); |
| 64300 | x = (x<<32) | y; |
| 64301 | if( serial_type==6 ){ |
| 64302 | pMem->u.i = *(i64*)&x; |
| 64303 | pMem->flags = MEM_Int; |
| 64304 | }else{ |
| 64305 | assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); |
| 64306 | swapMixedEndianFloat(x); |
| 64307 | memcpy(&pMem->r, &x, sizeof(x)); |
| 64308 | pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; |
| @@ -64644,24 +64704,30 @@ | |
| 64644 | u32 y; |
| 64645 | assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); |
| 64646 | switch( serial_type ){ |
| 64647 | case 0: |
| 64648 | case 1: |
| 64649 | return ONE_BYTE_INT(aKey); |
| 64650 | case 2: |
| 64651 | return TWO_BYTE_INT(aKey); |
| 64652 | case 3: |
| 64653 | return THREE_BYTE_INT(aKey); |
| 64654 | case 4: { |
| 64655 | y = FOUR_BYTE_UINT(aKey); |
| 64656 | return (i64)*(int*)&y; |
| 64657 | } |
| 64658 | case 5: { |
| 64659 | return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); |
| 64660 | } |
| 64661 | case 6: { |
| 64662 | u64 x = FOUR_BYTE_UINT(aKey); |
| 64663 | x = (x<<32) | FOUR_BYTE_UINT(aKey+4); |
| 64664 | return (i64)*(i64*)&x; |
| 64665 | } |
| 64666 | } |
| 64667 | |
| @@ -64725,10 +64791,11 @@ | |
| 64725 | u32 serial_type; |
| 64726 | |
| 64727 | /* RHS is an integer */ |
| 64728 | if( pRhs->flags & MEM_Int ){ |
| 64729 | serial_type = aKey1[idx1]; |
| 64730 | if( serial_type>=12 ){ |
| 64731 | rc = +1; |
| 64732 | }else if( serial_type==0 ){ |
| 64733 | rc = -1; |
| 64734 | }else if( serial_type==7 ){ |
| @@ -64775,16 +64842,19 @@ | |
| 64775 | } |
| 64776 | |
| 64777 | /* RHS is a string */ |
| 64778 | else if( pRhs->flags & MEM_Str ){ |
| 64779 | getVarint32(&aKey1[idx1], serial_type); |
| 64780 | if( serial_type<12 ){ |
| 64781 | rc = -1; |
| 64782 | }else if( !(serial_type & 0x01) ){ |
| 64783 | rc = +1; |
| 64784 | }else{ |
| 64785 | mem1.n = (serial_type - 12) / 2; |
| 64786 | if( (d1+mem1.n) > (unsigned)nKey1 ){ |
| 64787 | rc = 1; /* Corruption */ |
| 64788 | }else if( pKeyInfo->aColl[i] ){ |
| 64789 | mem1.enc = pKeyInfo->enc; |
| 64790 | mem1.db = pKeyInfo->db; |
| @@ -64800,14 +64870,17 @@ | |
| 64800 | } |
| 64801 | |
| 64802 | /* RHS is a blob */ |
| 64803 | else if( pRhs->flags & MEM_Blob ){ |
| 64804 | getVarint32(&aKey1[idx1], serial_type); |
| 64805 | if( serial_type<12 || (serial_type & 0x01) ){ |
| 64806 | rc = -1; |
| 64807 | }else{ |
| 64808 | int nStr = (serial_type - 12) / 2; |
| 64809 | if( (d1+nStr) > (unsigned)nKey1 ){ |
| 64810 | rc = 1; /* Corruption */ |
| 64811 | }else{ |
| 64812 | int nCmp = MIN(nStr, pRhs->n); |
| 64813 | rc = memcmp(&aKey1[d1], pRhs->z, nCmp); |
| @@ -64877,33 +64950,39 @@ | |
| 64877 | |
| 64878 | assert( bSkip==0 ); |
| 64879 | switch( serial_type ){ |
| 64880 | case 1: { /* 1-byte signed integer */ |
| 64881 | lhs = ONE_BYTE_INT(aKey); |
| 64882 | break; |
| 64883 | } |
| 64884 | case 2: { /* 2-byte signed integer */ |
| 64885 | lhs = TWO_BYTE_INT(aKey); |
| 64886 | break; |
| 64887 | } |
| 64888 | case 3: { /* 3-byte signed integer */ |
| 64889 | lhs = THREE_BYTE_INT(aKey); |
| 64890 | break; |
| 64891 | } |
| 64892 | case 4: { /* 4-byte signed integer */ |
| 64893 | y = FOUR_BYTE_UINT(aKey); |
| 64894 | lhs = (i64)*(int*)&y; |
| 64895 | break; |
| 64896 | } |
| 64897 | case 5: { /* 6-byte signed integer */ |
| 64898 | lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); |
| 64899 | break; |
| 64900 | } |
| 64901 | case 6: { /* 8-byte signed integer */ |
| 64902 | x = FOUR_BYTE_UINT(aKey); |
| 64903 | x = (x<<32) | FOUR_BYTE_UINT(aKey+4); |
| 64904 | lhs = *(i64*)&x; |
| 64905 | break; |
| 64906 | } |
| 64907 | case 8: |
| 64908 | lhs = 0; |
| 64909 | break; |
| @@ -65036,13 +65115,15 @@ | |
| 65036 | p->r2 = 1; |
| 65037 | } |
| 65038 | if( (flags & MEM_Int) ){ |
| 65039 | return vdbeRecordCompareInt; |
| 65040 | } |
| 65041 | if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0 |
| 65042 | && p->pKeyInfo->aColl[0]==0 |
| 65043 | ){ |
| 65044 | return vdbeRecordCompareString; |
| 65045 | } |
| 65046 | } |
| 65047 | |
| 65048 | return sqlite3VdbeRecordCompare; |
| @@ -66945,11 +67026,11 @@ | |
| 66945 | ** value of the cell. This macro verifies that shallow copies are |
| 66946 | ** not misused. A shallow copy of a string or blob just copies a |
| 66947 | ** pointer to the string or blob, not the content. If the original |
| 66948 | ** is changed while the copy is still in use, the string or blob might |
| 66949 | ** be changed out from under the copy. This macro verifies that nothing |
| 66950 | ** like that every happens. |
| 66951 | */ |
| 66952 | #ifdef SQLITE_DEBUG |
| 66953 | # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) |
| 66954 | #else |
| 66955 | # define memAboutToChange(P,M) |
| @@ -67677,10 +67758,15 @@ | |
| 67677 | ** |
| 67678 | ** An unconditional jump to address P2. |
| 67679 | ** The next instruction executed will be |
| 67680 | ** the one at index P2 from the beginning of |
| 67681 | ** the program. |
| 67682 | */ |
| 67683 | case OP_Goto: { /* jump */ |
| 67684 | pc = pOp->p2 - 1; |
| 67685 | |
| 67686 | /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, |
| @@ -69172,12 +69258,12 @@ | |
| 69172 | |
| 69173 | /* Opcode: Once P1 P2 * * * |
| 69174 | ** |
| 69175 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 69176 | ** set the flag and fall through to the next instruction. In other words, |
| 69177 | ** this opcode causes all following up codes up through P2 (but not including |
| 69178 | ** P2) to run just once and skipped on subsequent times through the loop. |
| 69179 | */ |
| 69180 | case OP_Once: { /* jump */ |
| 69181 | assert( pOp->p1<p->nOnceFlag ); |
| 69182 | VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); |
| 69183 | if( p->aOnceFlag[pOp->p1] ){ |
| @@ -83266,11 +83352,14 @@ | |
| 83266 | VdbeCoverage(v); |
| 83267 | callStatGet(v, regStat4, STAT_GET_NEQ, regEq); |
| 83268 | callStatGet(v, regStat4, STAT_GET_NLT, regLt); |
| 83269 | callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); |
| 83270 | sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); |
| 83271 | VdbeCoverage(v); |
| 83272 | #ifdef SQLITE_ENABLE_STAT3 |
| 83273 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
| 83274 | pIdx->aiColumn[0], regSample); |
| 83275 | #else |
| 83276 | for(i=0; i<nCol; i++){ |
| @@ -83280,11 +83369,11 @@ | |
| 83280 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample); |
| 83281 | #endif |
| 83282 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); |
| 83283 | sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); |
| 83284 | sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); |
| 83285 | sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); |
| 83286 | sqlite3VdbeJumpHere(v, addrIsNull); |
| 83287 | } |
| 83288 | #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ |
| 83289 | |
| 83290 | /* End of analysis */ |
| @@ -93446,17 +93535,17 @@ | |
| 93446 | |
| 93447 | /* |
| 93448 | ** Compute the affinity string for table pTab, if it has not already been |
| 93449 | ** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. |
| 93450 | ** |
| 93451 | ** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values and |
| 93452 | ** if iReg>0 then code an OP_Affinity opcode that will set the affinities |
| 93453 | ** for register iReg and following. Or if affinities exists and iReg==0, |
| 93454 | ** then just set the P4 operand of the previous opcode (which should be |
| 93455 | ** an OP_MakeRecord) to the affinity string. |
| 93456 | ** |
| 93457 | ** A column affinity string has one character column: |
| 93458 | ** |
| 93459 | ** Character Column affinity |
| 93460 | ** ------------------------------ |
| 93461 | ** 'a' TEXT |
| 93462 | ** 'b' NONE |
| @@ -93493,14 +93582,13 @@ | |
| 93493 | } |
| 93494 | } |
| 93495 | |
| 93496 | /* |
| 93497 | ** Return non-zero if the table pTab in database iDb or any of its indices |
| 93498 | ** have been opened at any point in the VDBE program beginning at location |
| 93499 | ** iStartAddr throught the end of the program. This is used to see if |
| 93500 | ** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can |
| 93501 | ** run without using temporary table for the results of the SELECT. |
| 93502 | */ |
| 93503 | static int readsTable(Parse *p, int iDb, Table *pTab){ |
| 93504 | Vdbe *v = sqlite3GetVdbe(p); |
| 93505 | int i; |
| 93506 | int iEnd = sqlite3VdbeCurrentAddr(v); |
| @@ -112351,17 +112439,17 @@ | |
| 112351 | } |
| 112352 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ |
| 112353 | pRangeEnd = pLoop->aLTerm[j++]; |
| 112354 | nExtraReg = 1; |
| 112355 | if( pRangeStart==0 |
| 112356 | && (pRangeEnd->wtFlags & TERM_VNULL)==0 |
| 112357 | && (j = pIdx->aiColumn[nEq])>=0 |
| 112358 | && pIdx->pTable->aCol[j].notNull==0 |
| 112359 | ){ |
| 112360 | bSeekPastNull = 1; |
| 112361 | } |
| 112362 | } |
| 112363 | |
| 112364 | /* Generate code to evaluate all constraint terms using == or IN |
| 112365 | ** and store the values of those terms in an array of registers |
| 112366 | ** starting at regBase. |
| 112367 | */ |
| 112368 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -73,12 +73,45 @@ | |
| 73 | # define _FILE_OFFSET_BITS 64 |
| 74 | # endif |
| 75 | # define _LARGEFILE_SOURCE 1 |
| 76 | #endif |
| 77 | |
| 78 | /* |
| 79 | ** For MinGW, check to see if we can include the header file containing its |
| 80 | ** version information, among other things. Normally, this internal MinGW |
| 81 | ** header file would [only] be included automatically by other MinGW header |
| 82 | ** files; however, the contained version information is now required by this |
| 83 | ** header file to work around binary compatibility issues (see below) and |
| 84 | ** this is the only known way to reliably obtain it. This entire #if block |
| 85 | ** would be completely unnecessary if there was any other way of detecting |
| 86 | ** MinGW via their preprocessor (e.g. if they customized their GCC to define |
| 87 | ** some MinGW-specific macros). When compiling for MinGW, either the |
| 88 | ** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be |
| 89 | ** defined; otherwise, detection of conditions specific to MinGW will be |
| 90 | ** disabled. |
| 91 | */ |
| 92 | #if defined(_HAVE_MINGW_H) |
| 93 | # include "mingw.h" |
| 94 | #elif defined(_HAVE__MINGW_H) |
| 95 | # include "_mingw.h" |
| 96 | #endif |
| 97 | |
| 98 | /* |
| 99 | ** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T |
| 100 | ** define is required to maintain binary compatibility with the MSVC runtime |
| 101 | ** library in use (e.g. for Windows XP). |
| 102 | */ |
| 103 | #if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ |
| 104 | defined(_WIN32) && !defined(_WIN64) && \ |
| 105 | defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ |
| 106 | defined(__MSVCRT__) |
| 107 | # define _USE_32BIT_TIME_T |
| 108 | #endif |
| 109 | |
| 110 | /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear |
| 111 | ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for |
| 112 | ** MinGW. |
| 113 | */ |
| 114 | /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ |
| 115 | /************** Begin file sqlite3.h *****************************************/ |
| 116 | /* |
| 117 | ** 2001 September 15 |
| @@ -189,11 +222,11 @@ | |
| 222 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 223 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 224 | */ |
| 225 | #define SQLITE_VERSION "3.8.4" |
| 226 | #define SQLITE_VERSION_NUMBER 3008004 |
| 227 | #define SQLITE_SOURCE_ID "2014-03-06 13:38:37 0a4200f95cf46ad620b9fd91f4444114a0c74730" |
| 228 | |
| 229 | /* |
| 230 | ** CAPI3REF: Run-Time Library Version Numbers |
| 231 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 232 | ** |
| @@ -36451,12 +36484,29 @@ | |
| 36484 | ** Interfaces for opening a shared library, finding entry points |
| 36485 | ** within the shared library, and closing the shared library. |
| 36486 | */ |
| 36487 | static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |
| 36488 | HANDLE h; |
| 36489 | #if defined(__CYGWIN__) |
| 36490 | int nFull = pVfs->mxPathname+1; |
| 36491 | char *zFull = sqlite3MallocZero( nFull ); |
| 36492 | void *zConverted = 0; |
| 36493 | if( zFull==0 ){ |
| 36494 | OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); |
| 36495 | return 0; |
| 36496 | } |
| 36497 | if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ |
| 36498 | sqlite3_free(zFull); |
| 36499 | OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); |
| 36500 | return 0; |
| 36501 | } |
| 36502 | zConverted = winConvertFromUtf8Filename(zFull); |
| 36503 | sqlite3_free(zFull); |
| 36504 | #else |
| 36505 | void *zConverted = winConvertFromUtf8Filename(zFilename); |
| 36506 | UNUSED_PARAMETER(pVfs); |
| 36507 | #endif |
| 36508 | if( zConverted==0 ){ |
| 36509 | OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); |
| 36510 | return 0; |
| 36511 | } |
| 36512 | if( osIsNT() ){ |
| @@ -55338,11 +55388,11 @@ | |
| 55388 | assert( pIdxKey->default_rc==1 |
| 55389 | || pIdxKey->default_rc==0 |
| 55390 | || pIdxKey->default_rc==-1 |
| 55391 | ); |
| 55392 | }else{ |
| 55393 | xRecordCompare = 0; /* All keys are integers */ |
| 55394 | } |
| 55395 | |
| 55396 | rc = moveToRoot(pCur); |
| 55397 | if( rc ){ |
| 55398 | return rc; |
| @@ -62528,10 +62578,14 @@ | |
| 62578 | ** sqlite3MemRelease() were called from here. With -O2, this jumps |
| 62579 | ** to 6.6 percent. The test case is inserting 1000 rows into a table |
| 62580 | ** with no indexes using a single prepared INSERT statement, bind() |
| 62581 | ** and reset(). Inserts are grouped into a transaction. |
| 62582 | */ |
| 62583 | testcase( p->flags & MEM_Agg ); |
| 62584 | testcase( p->flags & MEM_Dyn ); |
| 62585 | testcase( p->flags & MEM_Frame ); |
| 62586 | testcase( p->flags & MEM_RowSet ); |
| 62587 | if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ |
| 62588 | sqlite3VdbeMemRelease(p); |
| 62589 | }else if( p->zMalloc ){ |
| 62590 | sqlite3DbFree(db, p->zMalloc); |
| 62591 | p->zMalloc = 0; |
| @@ -64256,31 +64310,36 @@ | |
| 64310 | break; |
| 64311 | } |
| 64312 | case 1: { /* 1-byte signed integer */ |
| 64313 | pMem->u.i = ONE_BYTE_INT(buf); |
| 64314 | pMem->flags = MEM_Int; |
| 64315 | testcase( pMem->u.i<0 ); |
| 64316 | return 1; |
| 64317 | } |
| 64318 | case 2: { /* 2-byte signed integer */ |
| 64319 | pMem->u.i = TWO_BYTE_INT(buf); |
| 64320 | pMem->flags = MEM_Int; |
| 64321 | testcase( pMem->u.i<0 ); |
| 64322 | return 2; |
| 64323 | } |
| 64324 | case 3: { /* 3-byte signed integer */ |
| 64325 | pMem->u.i = THREE_BYTE_INT(buf); |
| 64326 | pMem->flags = MEM_Int; |
| 64327 | testcase( pMem->u.i<0 ); |
| 64328 | return 3; |
| 64329 | } |
| 64330 | case 4: { /* 4-byte signed integer */ |
| 64331 | y = FOUR_BYTE_UINT(buf); |
| 64332 | pMem->u.i = (i64)*(int*)&y; |
| 64333 | pMem->flags = MEM_Int; |
| 64334 | testcase( pMem->u.i<0 ); |
| 64335 | return 4; |
| 64336 | } |
| 64337 | case 5: { /* 6-byte signed integer */ |
| 64338 | pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); |
| 64339 | pMem->flags = MEM_Int; |
| 64340 | testcase( pMem->u.i<0 ); |
| 64341 | return 6; |
| 64342 | } |
| 64343 | case 6: /* 8-byte signed integer */ |
| 64344 | case 7: { /* IEEE floating point */ |
| 64345 | #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) |
| @@ -64299,10 +64358,11 @@ | |
| 64358 | y = FOUR_BYTE_UINT(buf+4); |
| 64359 | x = (x<<32) | y; |
| 64360 | if( serial_type==6 ){ |
| 64361 | pMem->u.i = *(i64*)&x; |
| 64362 | pMem->flags = MEM_Int; |
| 64363 | testcase( pMem->u.i<0 ); |
| 64364 | }else{ |
| 64365 | assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); |
| 64366 | swapMixedEndianFloat(x); |
| 64367 | memcpy(&pMem->r, &x, sizeof(x)); |
| 64368 | pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; |
| @@ -64644,24 +64704,30 @@ | |
| 64704 | u32 y; |
| 64705 | assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); |
| 64706 | switch( serial_type ){ |
| 64707 | case 0: |
| 64708 | case 1: |
| 64709 | testcase( aKey[0]&0x80 ); |
| 64710 | return ONE_BYTE_INT(aKey); |
| 64711 | case 2: |
| 64712 | testcase( aKey[0]&0x80 ); |
| 64713 | return TWO_BYTE_INT(aKey); |
| 64714 | case 3: |
| 64715 | testcase( aKey[0]&0x80 ); |
| 64716 | return THREE_BYTE_INT(aKey); |
| 64717 | case 4: { |
| 64718 | testcase( aKey[0]&0x80 ); |
| 64719 | y = FOUR_BYTE_UINT(aKey); |
| 64720 | return (i64)*(int*)&y; |
| 64721 | } |
| 64722 | case 5: { |
| 64723 | testcase( aKey[0]&0x80 ); |
| 64724 | return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); |
| 64725 | } |
| 64726 | case 6: { |
| 64727 | u64 x = FOUR_BYTE_UINT(aKey); |
| 64728 | testcase( aKey[0]&0x80 ); |
| 64729 | x = (x<<32) | FOUR_BYTE_UINT(aKey+4); |
| 64730 | return (i64)*(i64*)&x; |
| 64731 | } |
| 64732 | } |
| 64733 | |
| @@ -64725,10 +64791,11 @@ | |
| 64791 | u32 serial_type; |
| 64792 | |
| 64793 | /* RHS is an integer */ |
| 64794 | if( pRhs->flags & MEM_Int ){ |
| 64795 | serial_type = aKey1[idx1]; |
| 64796 | testcase( serial_type==12 ); |
| 64797 | if( serial_type>=12 ){ |
| 64798 | rc = +1; |
| 64799 | }else if( serial_type==0 ){ |
| 64800 | rc = -1; |
| 64801 | }else if( serial_type==7 ){ |
| @@ -64775,16 +64842,19 @@ | |
| 64842 | } |
| 64843 | |
| 64844 | /* RHS is a string */ |
| 64845 | else if( pRhs->flags & MEM_Str ){ |
| 64846 | getVarint32(&aKey1[idx1], serial_type); |
| 64847 | testcase( serial_type==12 ); |
| 64848 | if( serial_type<12 ){ |
| 64849 | rc = -1; |
| 64850 | }else if( !(serial_type & 0x01) ){ |
| 64851 | rc = +1; |
| 64852 | }else{ |
| 64853 | mem1.n = (serial_type - 12) / 2; |
| 64854 | testcase( (d1+mem1.n)==(unsigned)nKey1 ); |
| 64855 | testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); |
| 64856 | if( (d1+mem1.n) > (unsigned)nKey1 ){ |
| 64857 | rc = 1; /* Corruption */ |
| 64858 | }else if( pKeyInfo->aColl[i] ){ |
| 64859 | mem1.enc = pKeyInfo->enc; |
| 64860 | mem1.db = pKeyInfo->db; |
| @@ -64800,14 +64870,17 @@ | |
| 64870 | } |
| 64871 | |
| 64872 | /* RHS is a blob */ |
| 64873 | else if( pRhs->flags & MEM_Blob ){ |
| 64874 | getVarint32(&aKey1[idx1], serial_type); |
| 64875 | testcase( serial_type==12 ); |
| 64876 | if( serial_type<12 || (serial_type & 0x01) ){ |
| 64877 | rc = -1; |
| 64878 | }else{ |
| 64879 | int nStr = (serial_type - 12) / 2; |
| 64880 | testcase( (d1+nStr)==(unsigned)nKey1 ); |
| 64881 | testcase( (d1+nStr+1)==(unsigned)nKey1 ); |
| 64882 | if( (d1+nStr) > (unsigned)nKey1 ){ |
| 64883 | rc = 1; /* Corruption */ |
| 64884 | }else{ |
| 64885 | int nCmp = MIN(nStr, pRhs->n); |
| 64886 | rc = memcmp(&aKey1[d1], pRhs->z, nCmp); |
| @@ -64877,33 +64950,39 @@ | |
| 64950 | |
| 64951 | assert( bSkip==0 ); |
| 64952 | switch( serial_type ){ |
| 64953 | case 1: { /* 1-byte signed integer */ |
| 64954 | lhs = ONE_BYTE_INT(aKey); |
| 64955 | testcase( lhs<0 ); |
| 64956 | break; |
| 64957 | } |
| 64958 | case 2: { /* 2-byte signed integer */ |
| 64959 | lhs = TWO_BYTE_INT(aKey); |
| 64960 | testcase( lhs<0 ); |
| 64961 | break; |
| 64962 | } |
| 64963 | case 3: { /* 3-byte signed integer */ |
| 64964 | lhs = THREE_BYTE_INT(aKey); |
| 64965 | testcase( lhs<0 ); |
| 64966 | break; |
| 64967 | } |
| 64968 | case 4: { /* 4-byte signed integer */ |
| 64969 | y = FOUR_BYTE_UINT(aKey); |
| 64970 | lhs = (i64)*(int*)&y; |
| 64971 | testcase( lhs<0 ); |
| 64972 | break; |
| 64973 | } |
| 64974 | case 5: { /* 6-byte signed integer */ |
| 64975 | lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); |
| 64976 | testcase( lhs<0 ); |
| 64977 | break; |
| 64978 | } |
| 64979 | case 6: { /* 8-byte signed integer */ |
| 64980 | x = FOUR_BYTE_UINT(aKey); |
| 64981 | x = (x<<32) | FOUR_BYTE_UINT(aKey+4); |
| 64982 | lhs = *(i64*)&x; |
| 64983 | testcase( lhs<0 ); |
| 64984 | break; |
| 64985 | } |
| 64986 | case 8: |
| 64987 | lhs = 0; |
| 64988 | break; |
| @@ -65036,13 +65115,15 @@ | |
| 65115 | p->r2 = 1; |
| 65116 | } |
| 65117 | if( (flags & MEM_Int) ){ |
| 65118 | return vdbeRecordCompareInt; |
| 65119 | } |
| 65120 | testcase( flags & MEM_Real ); |
| 65121 | testcase( flags & MEM_Null ); |
| 65122 | testcase( flags & MEM_Blob ); |
| 65123 | if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ |
| 65124 | assert( flags & MEM_Str ); |
| 65125 | return vdbeRecordCompareString; |
| 65126 | } |
| 65127 | } |
| 65128 | |
| 65129 | return sqlite3VdbeRecordCompare; |
| @@ -66945,11 +67026,11 @@ | |
| 67026 | ** value of the cell. This macro verifies that shallow copies are |
| 67027 | ** not misused. A shallow copy of a string or blob just copies a |
| 67028 | ** pointer to the string or blob, not the content. If the original |
| 67029 | ** is changed while the copy is still in use, the string or blob might |
| 67030 | ** be changed out from under the copy. This macro verifies that nothing |
| 67031 | ** like that ever happens. |
| 67032 | */ |
| 67033 | #ifdef SQLITE_DEBUG |
| 67034 | # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) |
| 67035 | #else |
| 67036 | # define memAboutToChange(P,M) |
| @@ -67677,10 +67758,15 @@ | |
| 67758 | ** |
| 67759 | ** An unconditional jump to address P2. |
| 67760 | ** The next instruction executed will be |
| 67761 | ** the one at index P2 from the beginning of |
| 67762 | ** the program. |
| 67763 | ** |
| 67764 | ** The P1 parameter is not actually used by this opcode. However, it |
| 67765 | ** is sometimes set to 1 instead of 0 as a hint to the command-line shell |
| 67766 | ** that this Goto is the bottom of a loop and that the lines from P2 down |
| 67767 | ** to the current line should be indented for EXPLAIN output. |
| 67768 | */ |
| 67769 | case OP_Goto: { /* jump */ |
| 67770 | pc = pOp->p2 - 1; |
| 67771 | |
| 67772 | /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, |
| @@ -69172,12 +69258,12 @@ | |
| 69258 | |
| 69259 | /* Opcode: Once P1 P2 * * * |
| 69260 | ** |
| 69261 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 69262 | ** set the flag and fall through to the next instruction. In other words, |
| 69263 | ** this opcode causes all following opcodes up through P2 (but not including |
| 69264 | ** P2) to run just once and to be skipped on subsequent times through the loop. |
| 69265 | */ |
| 69266 | case OP_Once: { /* jump */ |
| 69267 | assert( pOp->p1<p->nOnceFlag ); |
| 69268 | VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); |
| 69269 | if( p->aOnceFlag[pOp->p1] ){ |
| @@ -83266,11 +83352,14 @@ | |
| 83352 | VdbeCoverage(v); |
| 83353 | callStatGet(v, regStat4, STAT_GET_NEQ, regEq); |
| 83354 | callStatGet(v, regStat4, STAT_GET_NLT, regLt); |
| 83355 | callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); |
| 83356 | sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); |
| 83357 | /* We know that the regSampleRowid row exists because it was read by |
| 83358 | ** the previous loop. Thus the not-found jump of seekOp will never |
| 83359 | ** be taken */ |
| 83360 | VdbeCoverageNeverTaken(v); |
| 83361 | #ifdef SQLITE_ENABLE_STAT3 |
| 83362 | sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, |
| 83363 | pIdx->aiColumn[0], regSample); |
| 83364 | #else |
| 83365 | for(i=0; i<nCol; i++){ |
| @@ -83280,11 +83369,11 @@ | |
| 83369 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample); |
| 83370 | #endif |
| 83371 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); |
| 83372 | sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); |
| 83373 | sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); |
| 83374 | sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */ |
| 83375 | sqlite3VdbeJumpHere(v, addrIsNull); |
| 83376 | } |
| 83377 | #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ |
| 83378 | |
| 83379 | /* End of analysis */ |
| @@ -93446,17 +93535,17 @@ | |
| 93535 | |
| 93536 | /* |
| 93537 | ** Compute the affinity string for table pTab, if it has not already been |
| 93538 | ** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. |
| 93539 | ** |
| 93540 | ** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and |
| 93541 | ** if iReg>0 then code an OP_Affinity opcode that will set the affinities |
| 93542 | ** for register iReg and following. Or if affinities exists and iReg==0, |
| 93543 | ** then just set the P4 operand of the previous opcode (which should be |
| 93544 | ** an OP_MakeRecord) to the affinity string. |
| 93545 | ** |
| 93546 | ** A column affinity string has one character per column: |
| 93547 | ** |
| 93548 | ** Character Column affinity |
| 93549 | ** ------------------------------ |
| 93550 | ** 'a' TEXT |
| 93551 | ** 'b' NONE |
| @@ -93493,14 +93582,13 @@ | |
| 93582 | } |
| 93583 | } |
| 93584 | |
| 93585 | /* |
| 93586 | ** Return non-zero if the table pTab in database iDb or any of its indices |
| 93587 | ** have been opened at any point in the VDBE program. This is used to see if |
| 93588 | ** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can |
| 93589 | ** run without using a temporary table for the results of the SELECT. |
| 93590 | */ |
| 93591 | static int readsTable(Parse *p, int iDb, Table *pTab){ |
| 93592 | Vdbe *v = sqlite3GetVdbe(p); |
| 93593 | int i; |
| 93594 | int iEnd = sqlite3VdbeCurrentAddr(v); |
| @@ -112351,17 +112439,17 @@ | |
| 112439 | } |
| 112440 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ |
| 112441 | pRangeEnd = pLoop->aLTerm[j++]; |
| 112442 | nExtraReg = 1; |
| 112443 | if( pRangeStart==0 |
| 112444 | && (j = pIdx->aiColumn[nEq])>=0 |
| 112445 | && pIdx->pTable->aCol[j].notNull==0 |
| 112446 | ){ |
| 112447 | bSeekPastNull = 1; |
| 112448 | } |
| 112449 | } |
| 112450 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 112451 | |
| 112452 | /* Generate code to evaluate all constraint terms using == or IN |
| 112453 | ** and store the values of those terms in an array of registers |
| 112454 | ** starting at regBase. |
| 112455 | */ |
| 112456 |
+1
-1
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -107,11 +107,11 @@ | ||
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | 110 | #define SQLITE_VERSION "3.8.4" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3008004 |
| 112 | -#define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042" | |
| 112 | +#define SQLITE_SOURCE_ID "2014-03-06 13:38:37 0a4200f95cf46ad620b9fd91f4444114a0c74730" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| 118 | 118 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.4" |
| 111 | #define SQLITE_VERSION_NUMBER 3008004 |
| 112 | #define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| 118 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.4" |
| 111 | #define SQLITE_VERSION_NUMBER 3008004 |
| 112 | #define SQLITE_SOURCE_ID "2014-03-06 13:38:37 0a4200f95cf46ad620b9fd91f4444114a0c74730" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| 118 |
+1
-1
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -1704,11 +1704,11 @@ | ||
| 1704 | 1704 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 1705 | 1705 | -DSQLITE_THREADSAFE=0 \ |
| 1706 | 1706 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 1707 | 1707 | -DSQLITE_OMIT_DEPRECATED \ |
| 1708 | 1708 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 1709 | - -D_HAVE_SQLITE_CONFIG_H \ | |
| 1709 | + -D_HAVE__MINGW_H \ | |
| 1710 | 1710 | -DSQLITE_USE_MALLOC_H \ |
| 1711 | 1711 | -DSQLITE_USE_MSIZE |
| 1712 | 1712 | |
| 1713 | 1713 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 1714 | 1714 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 1715 | 1715 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -1704,11 +1704,11 @@ | |
| 1704 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 1705 | -DSQLITE_THREADSAFE=0 \ |
| 1706 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 1707 | -DSQLITE_OMIT_DEPRECATED \ |
| 1708 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 1709 | -D_HAVE_SQLITE_CONFIG_H \ |
| 1710 | -DSQLITE_USE_MALLOC_H \ |
| 1711 | -DSQLITE_USE_MSIZE |
| 1712 | |
| 1713 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 1714 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 1715 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -1704,11 +1704,11 @@ | |
| 1704 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 1705 | -DSQLITE_THREADSAFE=0 \ |
| 1706 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 1707 | -DSQLITE_OMIT_DEPRECATED \ |
| 1708 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 1709 | -D_HAVE__MINGW_H \ |
| 1710 | -DSQLITE_USE_MALLOC_H \ |
| 1711 | -DSQLITE_USE_MSIZE |
| 1712 | |
| 1713 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 1714 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 1715 |
+1
-1
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -1704,11 +1704,11 @@ | ||
| 1704 | 1704 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 1705 | 1705 | -DSQLITE_THREADSAFE=0 \ |
| 1706 | 1706 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 1707 | 1707 | -DSQLITE_OMIT_DEPRECATED \ |
| 1708 | 1708 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 1709 | - -D_HAVE_SQLITE_CONFIG_H \ | |
| 1709 | + -D_HAVE__MINGW_H \ | |
| 1710 | 1710 | -DSQLITE_USE_MALLOC_H \ |
| 1711 | 1711 | -DSQLITE_USE_MSIZE |
| 1712 | 1712 | |
| 1713 | 1713 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 1714 | 1714 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 1715 | 1715 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -1704,11 +1704,11 @@ | |
| 1704 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 1705 | -DSQLITE_THREADSAFE=0 \ |
| 1706 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 1707 | -DSQLITE_OMIT_DEPRECATED \ |
| 1708 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 1709 | -D_HAVE_SQLITE_CONFIG_H \ |
| 1710 | -DSQLITE_USE_MALLOC_H \ |
| 1711 | -DSQLITE_USE_MSIZE |
| 1712 | |
| 1713 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 1714 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 1715 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -1704,11 +1704,11 @@ | |
| 1704 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 1705 | -DSQLITE_THREADSAFE=0 \ |
| 1706 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 1707 | -DSQLITE_OMIT_DEPRECATED \ |
| 1708 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 1709 | -D_HAVE__MINGW_H \ |
| 1710 | -DSQLITE_USE_MALLOC_H \ |
| 1711 | -DSQLITE_USE_MSIZE |
| 1712 | |
| 1713 | SHELL_OPTIONS = -Dmain=sqlite3_shell \ |
| 1714 | -DSQLITE_OMIT_LOAD_EXTENSION=1 \ |
| 1715 |
+7
-3
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -11,13 +11,17 @@ | ||
| 11 | 11 | filter links. |
| 12 | 12 | * The [/help/info | info command] now shows leaf status of the checkout. |
| 13 | 13 | * Add support for tunneling https through a http proxy (Ticket [e854101c4f]). |
| 14 | 14 | * Add option --empty to the "[/help?cmd=open | fossil open]" command. |
| 15 | 15 | * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter. |
| 16 | - * Add --ignore-space-at-sol and --ignore-space-at-eol options to [/help?cmd=diff|fossil (g)diff], | |
| 17 | - [/help?cmd=stash|fossil stash diff]. The option -w activates both of them. | |
| 18 | - * Add button "Ignore Whitespace" to /ci, /vdiff and /fdiff UI pages. | |
| 16 | + * Add -w|--ignore-all-space and -Z|--ignore-trailing-space options to | |
| 17 | + [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame], | |
| 18 | + [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff]. | |
| 19 | + * Add --strip-trailing-cr options to [/help?cmd=diff|fossil (g)diff] and | |
| 20 | + [/help?cmd=stash|fossil stash diff]. | |
| 21 | + * Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff | |
| 22 | + and /vdiff UI pages. | |
| 19 | 23 | |
| 20 | 24 | <h2>Changes For Version 1.28 (2014-01-27)</h2> |
| 21 | 25 | * Enhance [/help?cmd=/reports | /reports] to support event type filtering. |
| 22 | 26 | * When cloning a repository, the user name passed via the URL (if any) |
| 23 | 27 | is now used as the default local admin user's name. |
| 24 | 28 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -11,13 +11,17 @@ | |
| 11 | filter links. |
| 12 | * The [/help/info | info command] now shows leaf status of the checkout. |
| 13 | * Add support for tunneling https through a http proxy (Ticket [e854101c4f]). |
| 14 | * Add option --empty to the "[/help?cmd=open | fossil open]" command. |
| 15 | * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter. |
| 16 | * Add --ignore-space-at-sol and --ignore-space-at-eol options to [/help?cmd=diff|fossil (g)diff], |
| 17 | [/help?cmd=stash|fossil stash diff]. The option -w activates both of them. |
| 18 | * Add button "Ignore Whitespace" to /ci, /vdiff and /fdiff UI pages. |
| 19 | |
| 20 | <h2>Changes For Version 1.28 (2014-01-27)</h2> |
| 21 | * Enhance [/help?cmd=/reports | /reports] to support event type filtering. |
| 22 | * When cloning a repository, the user name passed via the URL (if any) |
| 23 | is now used as the default local admin user's name. |
| 24 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -11,13 +11,17 @@ | |
| 11 | filter links. |
| 12 | * The [/help/info | info command] now shows leaf status of the checkout. |
| 13 | * Add support for tunneling https through a http proxy (Ticket [e854101c4f]). |
| 14 | * Add option --empty to the "[/help?cmd=open | fossil open]" command. |
| 15 | * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter. |
| 16 | * Add -w|--ignore-all-space and -Z|--ignore-trailing-space options to |
| 17 | [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame], |
| 18 | [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff]. |
| 19 | * Add --strip-trailing-cr options to [/help?cmd=diff|fossil (g)diff] and |
| 20 | [/help?cmd=stash|fossil stash diff]. |
| 21 | * Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff |
| 22 | and /vdiff UI pages. |
| 23 | |
| 24 | <h2>Changes For Version 1.28 (2014-01-27)</h2> |
| 25 | * Enhance [/help?cmd=/reports | /reports] to support event type filtering. |
| 26 | * When cloning a repository, the user name passed via the URL (if any) |
| 27 | is now used as the default local admin user's name. |
| 28 |
+7
-3
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -11,13 +11,17 @@ | ||
| 11 | 11 | filter links. |
| 12 | 12 | * The [/help/info | info command] now shows leaf status of the checkout. |
| 13 | 13 | * Add support for tunneling https through a http proxy (Ticket [e854101c4f]). |
| 14 | 14 | * Add option --empty to the "[/help?cmd=open | fossil open]" command. |
| 15 | 15 | * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter. |
| 16 | - * Add --ignore-space-at-sol and --ignore-space-at-eol options to [/help?cmd=diff|fossil (g)diff], | |
| 17 | - [/help?cmd=stash|fossil stash diff]. The option -w activates both of them. | |
| 18 | - * Add button "Ignore Whitespace" to /ci, /vdiff and /fdiff UI pages. | |
| 16 | + * Add -w|--ignore-all-space and -Z|--ignore-trailing-space options to | |
| 17 | + [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame], | |
| 18 | + [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff]. | |
| 19 | + * Add --strip-trailing-cr options to [/help?cmd=diff|fossil (g)diff] and | |
| 20 | + [/help?cmd=stash|fossil stash diff]. | |
| 21 | + * Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff | |
| 22 | + and /vdiff UI pages. | |
| 19 | 23 | |
| 20 | 24 | <h2>Changes For Version 1.28 (2014-01-27)</h2> |
| 21 | 25 | * Enhance [/help?cmd=/reports | /reports] to support event type filtering. |
| 22 | 26 | * When cloning a repository, the user name passed via the URL (if any) |
| 23 | 27 | is now used as the default local admin user's name. |
| 24 | 28 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -11,13 +11,17 @@ | |
| 11 | filter links. |
| 12 | * The [/help/info | info command] now shows leaf status of the checkout. |
| 13 | * Add support for tunneling https through a http proxy (Ticket [e854101c4f]). |
| 14 | * Add option --empty to the "[/help?cmd=open | fossil open]" command. |
| 15 | * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter. |
| 16 | * Add --ignore-space-at-sol and --ignore-space-at-eol options to [/help?cmd=diff|fossil (g)diff], |
| 17 | [/help?cmd=stash|fossil stash diff]. The option -w activates both of them. |
| 18 | * Add button "Ignore Whitespace" to /ci, /vdiff and /fdiff UI pages. |
| 19 | |
| 20 | <h2>Changes For Version 1.28 (2014-01-27)</h2> |
| 21 | * Enhance [/help?cmd=/reports | /reports] to support event type filtering. |
| 22 | * When cloning a repository, the user name passed via the URL (if any) |
| 23 | is now used as the default local admin user's name. |
| 24 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -11,13 +11,17 @@ | |
| 11 | filter links. |
| 12 | * The [/help/info | info command] now shows leaf status of the checkout. |
| 13 | * Add support for tunneling https through a http proxy (Ticket [e854101c4f]). |
| 14 | * Add option --empty to the "[/help?cmd=open | fossil open]" command. |
| 15 | * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter. |
| 16 | * Add -w|--ignore-all-space and -Z|--ignore-trailing-space options to |
| 17 | [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame], |
| 18 | [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff]. |
| 19 | * Add --strip-trailing-cr options to [/help?cmd=diff|fossil (g)diff] and |
| 20 | [/help?cmd=stash|fossil stash diff]. |
| 21 | * Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff |
| 22 | and /vdiff UI pages. |
| 23 | |
| 24 | <h2>Changes For Version 1.28 (2014-01-27)</h2> |
| 25 | * Enhance [/help?cmd=/reports | /reports] to support event type filtering. |
| 26 | * When cloning a repository, the user name passed via the URL (if any) |
| 27 | is now used as the default local admin user's name. |
| 28 |