Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch annotate_links Excluding Merge-Ins
This is equivalent to a diff from 67f787dc4e to 96c3133576
2013-02-15
| ||
14:37 | Fixing annotate. It was hanging. Leaf check-in: 96c3133576 user: viriketo tags: annotate_links | |
2013-02-13
| ||
11:31 | Add a draft document describing the ticket tables and how they are generated from ticket change artifacts. check-in: d5be709c20 user: drh tags: trunk | |
03:14 | Improvements to the UTF-16 BOM detection. check-in: 81c4d78137 user: mistachkin tags: utf16Bom | |
2013-02-12
| ||
20:17 | Picking recent trunk fixes on tickets. check-in: 7a8ed6d7df user: viriketo tags: annotate_links | |
19:23 | Revised ticket processing to align with coding style guide, and for clarity of presentation. check-in: 67f787dc4e user: drh tags: trunk | |
19:09 | Fixing the rebuild of the ticket databases, so they get properly the comments included by manifests' "+comment". drh says not to be able to reproduce this issue, but here is a fix that makes all work for me. Feel free to rewrite this patch to match your taste. check-in: 9cca9398ab user: viriketo tags: trunk | |
Changes to src/checkin.c.
97 97 }else if( isRenamed ){ 98 98 blob_appendf(report, "RENAMED %s\n", zDisplayName); 99 99 } 100 100 free(zFullName); 101 101 } 102 102 blob_reset(&rewrittenPathname); 103 103 db_finalize(&q); 104 + /* -3 holds the baseline-based merges - nor cherrypick nor backout. 105 + * Now we can't report easily the baseline-based merges, because 106 + * we don't store the baseline point in vmerge */ 104 107 db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid" 105 - " WHERE id<=0"); 108 + " WHERE id<=0 AND id >= -2"); 106 109 while( db_step(&q)==SQLITE_ROW ){ 107 110 const char *zLabel = "MERGED_WITH"; 108 111 switch( db_column_int(&q, 1) ){ 109 112 case -1: zLabel = "CHERRYPICK "; break; 110 113 case -2: zLabel = "BACKOUT "; break; 111 114 } 112 115 blob_append(report, zPrefix, nPrefix); ................................................................................ 1209 1212 */ 1210 1213 if ( select_commit_files() ){ 1211 1214 blob_zero(&ans); 1212 1215 prompt_user("continue (y/N)? ", &ans); 1213 1216 cReply = blob_str(&ans)[0]; 1214 1217 if( cReply!='y' && cReply!='Y' ) fossil_exit(1);; 1215 1218 } 1219 + /* id=0 means that it introduces a new parent */ 1216 1220 isAMerge = db_exists("SELECT 1 FROM vmerge WHERE id=0"); 1217 1221 if( g.aCommitFile && isAMerge ){ 1218 - fossil_fatal("cannot do a partial commit of a merge"); 1222 + fossil_fatal("cannot do a partial commit of a graph merge"); 1219 1223 } 1220 1224 1221 1225 /* Doing "fossil mv fileA fileB; fossil add fileA; fossil commit fileA" 1222 1226 ** will generate a manifest that has two fileA entries, which is illegal. 1223 1227 ** When you think about it, the sequence above makes no sense. So detect 1224 1228 ** it and disallow it. Ticket [0ff64b0a5fc8]. 1225 1229 */
Changes to src/db.c.
2068 2068 { "editor", 0, 32, 0, "" }, 2069 2069 { "empty-dirs", 0, 40, 1, "" }, 2070 2070 { "encoding-glob", 0, 40, 1, "" }, 2071 2071 { "gdiff-command", 0, 40, 0, "gdiff" }, 2072 2072 { "gmerge-command",0, 40, 0, "" }, 2073 2073 { "http-port", 0, 16, 0, "8080" }, 2074 2074 { "https-login", 0, 0, 0, "off" }, 2075 + { "href-targets", 0, 0, 0, "on" }, 2075 2076 { "ignore-glob", 0, 40, 1, "" }, 2076 2077 { "localauth", 0, 0, 0, "off" }, 2077 2078 { "main-branch", 0, 40, 0, "trunk" }, 2078 2079 { "manifest", 0, 0, 1, "off" }, 2079 2080 #ifdef FOSSIL_ENABLE_MARKDOWN 2080 2081 { "markdown", 0, 0, 0, "off" }, 2081 2082 #endif
Changes to src/diff.c.
55 55 #define looks_like_binary(blob) (looks_like_utf8((blob)) == 0) 56 56 #endif /* INTERFACE */ 57 57 58 58 /* 59 59 ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) 60 60 */ 61 61 #define LENGTH_MASK_SZ 13 62 +#define TABLENGTH 4 62 63 #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) 63 64 64 65 /* 65 66 ** Information about each line of a file being diffed. 66 67 ** 67 68 ** The lower LENGTH_MASK_SZ bits of the hash (DLine.h) are the length 68 69 ** of the line. If any line is longer than LENGTH_MASK characters, ................................................................................ 616 617 for(j=0; j<m; j++){ 617 618 if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); 618 619 appendDiffLine(pOut, ' ', &B[b+j], html, 0); 619 620 } 620 621 } 621 622 } 622 623 624 +static int maxwidth; 625 + 623 626 /* 624 627 ** Status of a single output line 625 628 */ 626 629 typedef struct SbsLine SbsLine; 627 630 struct SbsLine { 628 631 char *zLine; /* The output line under construction */ 629 632 int n; /* Index of next unused slot in the zLine[] */ ................................................................................ 657 660 int i; /* Number of input characters consumed */ 658 661 int j; /* Number of output characters generated */ 659 662 int k; /* Cursor position */ 660 663 int needEndSpan = 0; 661 664 const char *zIn = pLine->z; 662 665 char *z = &p->zLine[p->n]; 663 666 int w = p->width; 667 + 664 668 int colorize = p->escHtml; 665 669 if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){ 666 670 colorize = 0; 667 671 } 668 - for(i=j=k=0; k<w && i<n; i++, k++){ 672 + 673 + /* In the case w == 0, we want to calculate the output line 674 + * width (k), but not write anything to 'z', because it has 675 + * a buffer of limited size. */ 676 + for(i=j=k=0; (w == 0 || k<w) && i<n; i++, k++){ 669 677 char c = zIn[i]; 670 678 if( colorize ){ 671 679 if( i==p->iStart ){ 672 680 int x = strlen(p->zStart); 673 - memcpy(z+j, p->zStart, x); 681 + if (w != 0) 682 + memcpy(z+j, p->zStart, x); 674 683 j += x; 675 684 needEndSpan = 1; 676 685 if( p->iStart2 ){ 677 686 p->iStart = p->iStart2; 678 687 p->zStart = p->zStart2; 679 688 p->iStart2 = 0; 680 689 } 681 690 }else if( i==p->iEnd ){ 682 - memcpy(z+j, "</span>", 7); 691 + if (w != 0) 692 + memcpy(z+j, "</span>", 7); 683 693 j += 7; 684 694 needEndSpan = 0; 685 695 if( p->iEnd2 ){ 686 696 p->iEnd = p->iEnd2; 687 697 p->iEnd2 = 0; 688 698 } 689 699 } 690 700 } 691 701 if( c=='\t' ){ 692 - z[j++] = ' '; 693 - while( (k&7)!=7 && k<w ){ z[j++] = ' '; k++; } 702 + if (w != 0) 703 + z[j++] = ' '; 704 + while( (k%TABLENGTH)!=0 && (w == 0 || k<w) ){ 705 + if (w != 0) 706 + z[j++] = ' '; 707 + k++; 708 + } 694 709 }else if( c=='\r' || c=='\f' ){ 695 - z[j++] = ' '; 710 + if (w != 0) 711 + z[j++] = ' '; 696 712 }else if( c=='<' && p->escHtml ){ 697 - memcpy(&z[j], "<", 4); 698 - j += 4; 713 + if (w != 0) { 714 + memcpy(&z[j], "<", 4); 715 + j += 4; 716 + } 699 717 }else if( c=='&' && p->escHtml ){ 700 - memcpy(&z[j], "&", 5); 701 - j += 5; 718 + if (w != 0) { 719 + memcpy(&z[j], "&", 5); 720 + j += 5; 721 + } 702 722 }else if( c=='>' && p->escHtml ){ 703 - memcpy(&z[j], ">", 4); 704 - j += 4; 723 + if (w != 0) { 724 + memcpy(&z[j], ">", 4); 725 + j += 4; 726 + } 705 727 }else if( c=='"' && p->escHtml ){ 706 - memcpy(&z[j], """, 6); 707 - j += 6; 728 + if (w != 0) { 729 + memcpy(&z[j], """, 6); 730 + j += 6; 731 + } 708 732 }else{ 709 - z[j++] = c; 733 + if (w != 0) { 734 + z[j++] = c; 735 + } 710 736 if( (c&0xc0)==0x80 ) k--; 711 737 } 712 738 } 713 739 if( needEndSpan ){ 714 - memcpy(&z[j], "</span>", 7); 715 - j += 7; 740 + if (w != 0) { 741 + memcpy(&z[j], "</span>", 7); 742 + j += 7; 743 + } 716 744 } 745 + 746 + if (k > maxwidth) 747 + maxwidth = k; 748 + 717 749 if( (flags & SBS_PAD)!=0 ){ 718 750 while( k<w ){ k++; z[j++] = ' '; } 719 751 } 720 752 if( flags & SBS_NEWLINE ){ 721 753 z[j++] = '\n'; 722 754 } 723 755 p->n += j; ................................................................................ 1239 1271 int nChunk = 0; /* Number of chunks of diff output seen so far */ 1240 1272 SbsLine s; /* Output line buffer */ 1241 1273 int nContext; /* Lines of context above and below each change */ 1242 1274 int showDivider = 0; /* True to show the divider */ 1243 1275 1244 1276 memset(&s, 0, sizeof(s)); 1245 1277 s.width = diff_width(diffFlags); 1278 + if( s.width == 0 ) { /* May Autocalculate */ 1279 + Blob dump; 1280 + maxwidth = -1; /* The webserver may call sbsDiff more than once per process */ 1281 + blob_zero(&dump); 1282 + sbsDiff(p, &dump, pRe, diffFlags | DIFF_WIDTH_MASK); 1283 + s.width = maxwidth; 1284 + blob_reset(&dump); 1285 + } 1246 1286 s.zLine = fossil_malloc( 15*s.width + 200 ); 1247 1287 if( s.zLine==0 ) return; 1248 1288 nContext = diff_context_lines(diffFlags); 1249 1289 s.escHtml = (diffFlags & DIFF_HTML)!=0; 1250 1290 s.pRe = pRe; 1251 1291 s.iStart = -1; 1252 1292 s.iStart2 = 0; ................................................................................ 1861 1901 1862 1902 /* 1863 1903 ** Extract the width of columns for side-by-side diff. Supply an 1864 1904 ** appropriate default if no width is given. 1865 1905 */ 1866 1906 int diff_width(u64 diffFlags){ 1867 1907 int w = (diffFlags & DIFF_WIDTH_MASK)/(DIFF_CONTEXT_MASK+1); 1868 - if( w==0 ) w = 80; 1869 1908 return w; 1870 1909 } 1871 1910 1872 1911 /* 1873 1912 ** Generate a report of the differences between files pA and pB. 1874 1913 ** If pOut is not NULL then a unified diff is appended there. It 1875 1914 ** is assumed that pOut has already been initialized. If pOut is ................................................................................ 2173 2212 /* 2174 2213 ** Compute a complete annotation on a file. The file is identified 2175 2214 ** by its filename number (filename.fnid) and the baseline in which 2176 2215 ** it was checked in (mlink.mid). 2177 2216 */ 2178 2217 static void annotate_file( 2179 2218 Annotator *p, /* The annotator */ 2180 - int fnid, /* The name of the file to be annotated */ 2219 + const char *zFilename,/* The name of the file to be annotated */ 2220 + int fnid, /* The file name id of the file to be annotated */ 2181 2221 int mid, /* Use the version of the file in this check-in */ 2182 2222 int webLabel, /* Use web-style annotations if true */ 2183 2223 int iLimit, /* Limit the number of levels if greater than zero */ 2184 2224 int annFlags /* Flags to alter the annotation */ 2185 2225 ){ 2186 2226 Blob toAnnotate; /* Text of the final (mid) version of the file */ 2187 2227 Blob step; /* Text of previous revision */ 2188 2228 int rid; /* Artifact ID of the file being annotated */ 2189 2229 char *zLabel; /* Label to apply to a line */ 2190 2230 Stmt q; /* Query returning all ancestor versions */ 2191 2231 int cnt = 0; /* Number of versions examined */ 2232 + const char *zInfoTarget; /* String for target info window */ 2233 + const char *zDiffTarget; /* String for target diff window */ 2234 + 2235 + zInfoTarget = db_get_boolean("href-targets", 1) ? "target='infowindow'" : ""; 2236 + zDiffTarget = db_get_boolean("href-targets", 1) ? "target='diffwindow'" : ""; 2192 2237 2193 2238 /* Initialize the annotation */ 2194 2239 rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid); 2195 2240 if( rid==0 ){ 2196 2241 fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid); 2197 2242 } 2198 2243 if( !content_get(rid, &toAnnotate) ){ ................................................................................ 2199 2244 fossil_panic("unable to retrieve content of artifact #%d", rid); 2200 2245 } 2201 2246 if( iLimit<=0 ) iLimit = 1000000000; 2202 2247 annotation_start(p, &toAnnotate); 2203 2248 2204 2249 db_prepare(&q, 2205 2250 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.%s)," 2251 + " (SELECT uuid FROM blob WHERE rid=mlink.fid)," 2252 + " (SELECT uuid FROM blob WHERE rid=mlink.pid)," 2206 2253 " date(event.mtime)," 2207 2254 " coalesce(event.euser,event.user)," 2208 2255 " mlink.pid" 2209 2256 " FROM mlink, event" 2210 2257 " WHERE mlink.fid=:rid" 2211 2258 " AND event.objid=mlink.mid" 2212 2259 " ORDER BY event.mtime", ................................................................................ 2213 2260 (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid" 2214 2261 ); 2215 2262 2216 2263 db_bind_int(&q, ":rid", rid); 2217 2264 if( iLimit==0 ) iLimit = 1000000000; 2218 2265 while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){ 2219 2266 const char *zUuid = db_column_text(&q, 0); 2220 - const char *zDate = db_column_text(&q, 1); 2221 - const char *zUser = db_column_text(&q, 2); 2222 - int prevId = db_column_int(&q, 3); 2267 + const char *zUuidFile = db_column_text(&q, 1); 2268 + const char *zUuidParentFile = db_column_text(&q, 2); 2269 + const char *zDate = db_column_text(&q, 3); 2270 + const char *zUser = db_column_text(&q, 4); 2271 + int prevId = db_column_int(&q, 5); 2223 2272 if( webLabel ){ 2224 - zLabel = mprintf( 2225 - "<a href='%R/info/%s' target='infowindow'>%.10s</a> %s %13.13s", 2226 - zUuid, zUuid, zDate, zUser 2227 - ); 2273 + if (zUuidParentFile) { 2274 + zLabel = mprintf( 2275 + "<a href='%R/info/%s' %s>%.10s</a> " 2276 + "<a href='%R/fdiff?v1=%s&v2=%s' %s>d</a> " 2277 + "%s %13.13s", 2278 + zUuid, zInfoTarget, zUuid, 2279 + zUuidParentFile, zUuidFile, zDiffTarget, 2280 + zDate, zUser); 2281 + }else{ 2282 + zLabel = mprintf( 2283 + "<a href='%R/info/%s' %s>%.10s</a> " 2284 + "%s %13.13s", 2285 + zUuid, zInfoTarget, zUuid, 2286 + zDate, zUser); 2287 + } 2228 2288 }else{ 2229 2289 zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser); 2230 2290 } 2231 2291 p->nVers++; 2232 2292 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) ); 2233 2293 p->azVers[p->nVers-1] = zLabel; 2234 2294 content_get(rid, &step); ................................................................................ 2269 2329 if( mid==0 || fnid==0 ){ fossil_redirect_home(); } 2270 2330 iLimit = atoi(PD("limit","-1")); 2271 2331 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ 2272 2332 fossil_redirect_home(); 2273 2333 } 2274 2334 style_header("File Annotation"); 2275 2335 if( P("filevers") ) annFlags |= ANN_FILE_VERS; 2276 - annotate_file(&ann, fnid, mid, g.perm.Hyperlink, iLimit, annFlags); 2336 + annotate_file(&ann, P("filename"), fnid, mid, g.perm.Hyperlink, iLimit, annFlags); 2277 2337 if( P("log") ){ 2278 2338 int i; 2279 2339 @ <h2>Versions analyzed:</h2> 2280 2340 @ <ol> 2281 2341 for(i=0; i<ann.nVers; i++){ 2282 2342 @ <li><tt>%s(ann.azVers[i])</tt></li> 2283 2343 } ................................................................................ 2360 2420 " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid" 2361 2421 " ORDER BY ancestor.generation ASC LIMIT 1", 2362 2422 fid, fnid); 2363 2423 if( mid==0 ){ 2364 2424 fossil_panic("unable to find manifest"); 2365 2425 } 2366 2426 if( fileVers ) annFlags |= ANN_FILE_VERS; 2367 - annotate_file(&ann, fnid, mid, 0, iLimit, annFlags); 2427 + annotate_file(&ann, zFilename, fnid, mid, 0, iLimit, annFlags); 2368 2428 if( showLog ){ 2369 2429 for(i=0; i<ann.nVers; i++){ 2370 2430 printf("version %3d: %s\n", i+1, ann.azVers[i]); 2371 2431 } 2372 2432 printf("---------------------------------------------------\n"); 2373 2433 } 2374 2434 for(i=0; i<ann.nOrig; i++){ 2375 2435 fossil_print("%s: %.*s\n", 2376 2436 ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); 2377 2437 } 2378 2438 }
Changes to src/diffcmd.c.
48 48 char *z = 0; 49 49 if( diffFlags & DIFF_BRIEF ){ 50 50 /* no-op */ 51 51 }else if( diffFlags & DIFF_SIDEBYSIDE ){ 52 52 int w = diff_width(diffFlags); 53 53 int n1 = strlen(zLeft); 54 54 int x; 55 - if( n1>w*2 ) n1 = w*2; 56 - x = w*2+17 - (n1+2); 55 + if (w > 0) { 56 + if( n1>w*2 ) n1 = w*2; 57 + x = w*2+17 - (n1+2); 58 + }else{ 59 + /* Autocalculate width 60 + * We can't know the width in advance, so we'll make it 61 + * output three = around the name */ 62 + x = 6; 63 + } 57 64 z = mprintf("%.*c %.*s %.*c\n", 58 65 x/2, '=', n1, zLeft, (x+1)/2, '='); 59 66 }else{ 60 67 z = mprintf("--- %s\n+++ %s\n", zLeft, zRight); 61 68 } 62 69 fossil_print("%s", z); 63 70 fossil_free(z);
Changes to src/doc.c.
186 186 { "mpeg", 4, "video/mpeg" }, 187 187 { "mpg", 3, "video/mpeg" }, 188 188 { "mpga", 4, "audio/mpeg" }, 189 189 { "ms", 2, "application/x-troff-ms" }, 190 190 { "msh", 3, "model/mesh" }, 191 191 { "nc", 2, "application/x-netcdf" }, 192 192 { "oda", 3, "application/oda" }, 193 + { "odp", 3, "application/vnd.oasis.opendocument.presentation" }, 194 + { "ods", 3, "application/vnd.oasis.opendocument.spreadsheet" }, 195 + { "odt", 3, "application/vnd.oasis.opendocument.text" }, 193 196 { "ogg", 3, "application/ogg" }, 194 197 { "ogm", 3, "application/ogg" }, 195 198 { "pbm", 3, "image/x-portable-bitmap" }, 196 199 { "pdb", 3, "chemical/x-pdb" }, 197 200 { "pdf", 3, "application/pdf" }, 198 201 { "pgm", 3, "image/x-portable-graymap" }, 199 202 { "pgn", 3, "application/x-chess-pgn" },
Changes to src/info.c.
405 405 if( showDiff==0 ){ 406 406 diffFlags = 0; /* Zero means do not show any diff */ 407 407 }else{ 408 408 int x; 409 409 if( sideBySide ){ 410 410 diffFlags = DIFF_SIDEBYSIDE | DIFF_IGNORE_EOLWS; 411 411 412 - /* "dw" query parameter determines width of each column */ 413 - x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1); 412 + /* "dw" query parameter determines width of each column 413 + * 0 means autocalculate. */ 414 + x = atoi(PD("dw","0"))*(DIFF_CONTEXT_MASK+1); 414 415 if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK; 415 416 diffFlags += x; 416 417 }else{ 417 418 diffFlags = DIFF_INLINE | DIFF_IGNORE_EOLWS; 418 419 } 419 420 420 421 /* "dc" query parameter determines lines of context */ ................................................................................ 648 649 } 649 650 @ </td></tr> 650 651 @ <tr><th>Other Links:</th> 651 652 @ <td> 652 653 @ %z(href("%R/dir?ci=%S",zUuid))files</a> 653 654 @ | %z(href("%R/fileage?name=%S",zUuid))file ages</a> 654 655 @ | %z(href("%R/artifact/%S",zUuid))manifest</a> 656 + @ | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)"> 657 + @ vdiff to parent branch</a> 655 658 if( g.perm.Write ){ 656 659 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> 657 660 } 658 661 @ </td> 659 662 @ </tr> 660 663 } 661 664 @ </table> ................................................................................ 873 876 ** Output a description of a check-in 874 877 */ 875 878 static void checkin_description(int rid){ 876 879 Stmt q; 877 880 db_prepare(&q, 878 881 "SELECT datetime(mtime), coalesce(euser,user)," 879 882 " coalesce(ecomment,comment), uuid," 883 + " coalesce((SELECT value FROM tagxref" 884 + " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid),'trunk')," 880 885 " (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref" 881 886 " WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid" 882 887 " AND tagxref.rid=blob.rid AND tagxref.tagtype>0)" 883 888 " FROM event, blob" 884 889 " WHERE event.objid=%d AND type='ci'" 885 890 " AND blob.rid=%d", 886 - rid, rid 891 + TAG_BRANCH, rid, rid 887 892 ); 888 893 while( db_step(&q)==SQLITE_ROW ){ 889 894 const char *zDate = db_column_text(&q, 0); 890 895 const char *zUser = db_column_text(&q, 1); 891 896 const char *zUuid = db_column_text(&q, 3); 897 + const char *zBranch = db_column_text(&q, 4); 892 898 const char *zTagList = db_column_text(&q, 4); 893 899 Blob comment; 894 900 int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS; 895 901 if( db_get_boolean("timeline-block-markup", 0)==0 ){ 896 902 wikiFlags |= WIKI_NOBLOCK; 897 903 } 898 904 hyperlink_to_uuid(zUuid); 905 + @ on branch <a href="%R/timeline?r=%s(zBranch)&nd&c=%T(zDate)"> 906 + @ %s(zBranch)</a> - 899 907 blob_zero(&comment); 900 908 db_column_blob(&q, 2, &comment); 901 909 wiki_convert(&comment, 0, wikiFlags); 902 910 blob_reset(&comment); 903 911 @ (user: 904 912 hyperlink_to_user(zUser,zDate,","); 905 913 if( zTagList && zTagList[0] && g.perm.Hyperlink ){ ................................................................................ 972 980 pFrom = vdiff_parse_manifest("from", &ridFrom); 973 981 if( pFrom==0 ) return; 974 982 sideBySide = atoi(PD("sbs","1")); 975 983 showDetail = atoi(PD("detail","0")); 976 984 if( !showDetail && sideBySide ) showDetail = 1; 977 985 zFrom = P("from"); 978 986 zTo = P("to"); 979 - if( !sideBySide ){ 980 - style_submenu_element("Side-by-side Diff", "sbsdiff", 981 - "%R/vdiff?from=%T&to=%T&detail=%d&sbs=1", 982 - zFrom, zTo, showDetail); 983 - }else{ 987 + if (showDetail){ 988 + style_submenu_element("Abstract", "abstract", 989 + "%s/vdiff?from=%T&to=%T&detail=0&sbs=0", 990 + g.zTop, zFrom, zTo); 991 + } 992 + if( !showDetail || sideBySide ){ 984 993 style_submenu_element("Unified Diff", "udiff", 985 - "%R/vdiff?from=%T&to=%T&detail=%d&sbs=0", 986 - zFrom, zTo, showDetail); 994 + "%R/vdiff?from=%T&to=%T&detail=1&sbs=0", 995 + zFrom, zTo); 987 996 } 997 + if (!sideBySide){ 998 + style_submenu_element("Side-by-side Diff", "sbsdiff", 999 + "%R/vdiff?from=%T&to=%T&detail=1&sbs=1", 1000 + zFrom, zTo); 1001 + } 1002 + style_submenu_element("Patch", "patch", 1003 + "%s/vpatch?from=%T&to=%T", 1004 + g.zTop, zFrom, zTo); 988 1005 style_submenu_element("Invert", "invert", 989 1006 "%R/vdiff?from=%T&to=%T&detail=%d&sbs=%d", 990 1007 zTo, zFrom, showDetail, sideBySide); 991 1008 style_header("Check-in Differences"); 992 1009 @ <h2>Difference From:</h2><blockquote> 993 1010 checkin_description(ridFrom); 994 1011 @ </blockquote><h2>To:</h2><blockquote>
Changes to src/merge.c.
628 628 } 629 629 630 630 /* 631 631 ** Clean up the mid and pid VFILE entries. Then commit the changes. 632 632 */ 633 633 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); 634 634 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(%d,%d)", 635 - pickFlag ? -1 : (backoutFlag ? -2 : 0), mid); 635 + pickFlag ? -1 : (backoutFlag ? -2 : (zPivot ? -3 : 0)), mid); 636 636 if( pickFlag ){ 637 637 /* For a cherry-pick merge, make the default check-in comment the same 638 638 ** as the check-in comment on the check-in that is being merged in. */ 639 639 db_multi_exec( 640 640 "REPLACE INTO vvar(name,value)" 641 641 " SELECT 'ci-comment', coalesce(ecomment,comment) FROM event" 642 642 " WHERE type='ci' AND objid=%d", 643 643 mid 644 644 ); 645 645 } 646 646 undo_finish(); 647 647 db_end_transaction(nochangeFlag); 648 648 }
Changes to src/name.c.
110 110 rid = db_int(0, 111 111 "SELECT objid FROM event" 112 112 " WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'" 113 113 " ORDER BY mtime DESC LIMIT 1", 114 114 &zTag[5], zType); 115 115 return rid; 116 116 } 117 + 118 + if( memcmp(zTag, "pbranch:", 8)==0 ){ 119 + int branchRid = symbolic_name_to_rid(&zTag[8], zType); 120 + if (branchRid == 0) return 0; 121 + rid = get_parent_branch_rid(branchRid); 122 + return rid; 123 + } 124 + 117 125 if( fossil_isdate(zTag) ){ 118 126 rid = db_int(0, 119 127 "SELECT objid FROM event" 120 128 " WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'" 121 129 " ORDER BY mtime DESC LIMIT 1", 122 130 zTag, zType); 123 131 if( rid) return rid; ................................................................................ 520 528 db_column_text(&q, 2)); 521 529 fossil_print(" "); 522 530 comment_print(db_column_text(&q,4), 10, 78); 523 531 } 524 532 db_finalize(&q); 525 533 } 526 534 } 535 + 536 +int get_parent_branch_rid(int ridRequested){ 537 + Stmt s; 538 + const char *branchName; /* Name of the branch requested at rid */ 539 + const char *parentBranchName; /* Name of the parent branch */ 540 + int rid; 541 + 542 + /* Get the name of the current branch */ 543 + branchName = db_text(0, 544 + "SELECT value FROM tagxref" 545 + " WHERE tagid=%d" 546 + " AND tagxref.tagtype>0" 547 + " AND rid=%d", 548 + TAG_BRANCH, ridRequested); 549 + 550 + if ( !branchName ) 551 + return 0; 552 + 553 + /* Find the name of the branch this was forked from */ 554 + db_prepare(&s, 555 + "SELECT pid, tagxref.value FROM plink JOIN tagxref" 556 + " WHERE cid=:rid" 557 + " AND isprim=1" 558 + " AND tagxref.tagid=%d" 559 + " AND tagxref.tagtype>0" 560 + " AND tagxref.rid=pid", 561 + TAG_BRANCH); 562 + 563 + rid = ridRequested; 564 + while( rid > 0 ) { 565 + db_bind_int(&s, ":rid", rid); 566 + if ( db_step(&s) == SQLITE_ROW ) { 567 + rid = db_column_int(&s, 0); 568 + parentBranchName = db_column_text(&s, 1); 569 + if ( !parentBranchName ) { 570 + rid = 0; 571 + break; 572 + } 573 + 574 + if ( fossil_strcmp(parentBranchName, branchName) ) { 575 + parentBranchName = fossil_strdup(parentBranchName); 576 + break; 577 + } 578 + }else{ 579 + rid = 0; 580 + break; 581 + } 582 + db_reset(&s); 583 + } 584 + db_finalize(&s); 585 + 586 + if (rid == 0) 587 + return 0; 588 + 589 + /* Find the last checkin coming from the parent branch */ 590 + db_prepare(&s, 591 + "SELECT pid, tagxref.value FROM plink JOIN tagxref" 592 + " WHERE cid=:rid" 593 + " AND tagxref.tagid=%d" 594 + " AND tagxref.tagtype>0" 595 + " AND tagxref.rid=pid ORDER BY isprim ASC", 596 + TAG_BRANCH); 597 + 598 + rid = ridRequested; 599 + while( rid > 0 ) { 600 + db_bind_int(&s, ":rid", rid); 601 + int found = 0; 602 + while ( db_step(&s) == SQLITE_ROW ) { 603 + const char *branchNamePid; /* Branch name of the pid */ 604 + 605 + ++found; 606 + rid = db_column_int(&s, 0); 607 + branchNamePid = db_column_text(&s, 1); 608 + if ( !branchNamePid ) { 609 + break; 610 + } 611 + if ( fossil_strcmp(parentBranchName, branchNamePid)==0 ) { 612 + /* Found the last merge from the parent branch */ 613 + db_finalize(&s); 614 + return rid; 615 + } 616 + } 617 + 618 + if (found == 0) { 619 + break; 620 + } 621 + db_reset(&s); 622 + } 623 + db_finalize(&s); 624 + 625 + return 0; 626 +}
Changes to src/timeline.c.
117 117 /* 118 118 ** Hash a string and use the hash to determine a background color. 119 119 */ 120 120 char *hash_color(const char *z){ 121 121 int i; /* Loop counter */ 122 122 unsigned int h = 0; /* Hash on the branch name */ 123 123 int r, g, b; /* Values for red, green, and blue */ 124 - int h1, h2, h3, h4; /* Elements of the hash value */ 125 - int mx, mn; /* Components of HSV */ 126 124 static char zColor[10]; /* The resulting color */ 127 - static int ix[2] = {0,0}; /* Color chooser parameters */ 125 + static int whitefg = -1; 126 + int cpc = 4; /* colours per component */ 127 + int cfactor = 128/cpc; /* Factor so n*cpc < 128 */ 128 + int cmin = cfactor - 1; /* Factor so the max component is 127 129 + and the min is different than the bg */ 128 130 129 - if( ix[0]==0 ){ 130 - if( db_get_boolean("white-foreground", 0) ){ 131 - ix[0] = 140; 132 - ix[1] = 40; 133 - }else{ 134 - ix[0] = 216; 135 - ix[1] = 16; 136 - } 137 - } 138 - for(i=0; z[i]; i++ ){ 131 + if( whitefg = -1 ) 132 + whitefg = db_get_boolean("white-foreground", 0); 133 + 134 + /* Calculate the hash based on the branch name */ 135 + for( i=0; z[i]; i++ ){ 139 136 h = (h<<11) ^ (h<<1) ^ (h>>3) ^ z[i]; 140 137 } 141 - h1 = h % 6; h /= 6; 142 - h3 = h % 30; h /= 30; 143 - h4 = h % 40; h /= 40; 144 - mx = ix[0] - h3; 145 - mn = mx - h4 - ix[1]; 146 - h2 = (h%(mx - mn)) + mn; 147 - switch( h1 ){ 148 - case 0: r = mx; g = h2, b = mn; break; 149 - case 1: r = h2; g = mx, b = mn; break; 150 - case 2: r = mn; g = mx, b = h2; break; 151 - case 3: r = mn; g = h2, b = mx; break; 152 - case 4: r = h2; g = mn, b = mx; break; 153 - default: r = mx; g = mn, b = h2; break; 138 + 139 + /* 'cpc' different random values per component, between 'cmin' and 127 */ 140 + r = cmin + (h % cpc) * cfactor; h /= cpc; 141 + g = cmin + (h % cpc) * cfactor; h /= cpc; 142 + b = cmin + (h % cpc) * cfactor; h /= cpc; 143 + 144 + /* In case of blackfg, get the inverse effect */ 145 + if( !whitefg ) 146 + { 147 + r = 255 - r; 148 + g = 255 - g; 149 + b = 255 - b; 154 150 } 155 151 sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b); 156 152 return zColor; 157 153 } 158 154 159 155 /* 160 156 ** COMMAND: test-hash-color ................................................................................ 200 196 int suppressCnt = 0; 201 197 char zPrevDate[20]; 202 198 GraphContext *pGraph = 0; 203 199 int prevWasDivider = 0; /* True if previous output row was <hr> */ 204 200 int fchngQueryInit = 0; /* True if fchngQuery is initialized */ 205 201 Stmt fchngQuery; /* Query for file changes on check-ins */ 206 202 static Stmt qbranch; 203 + const char *zDiffTarget; /* String for the target diff window */ 207 204 int pendingEndTr = 0; /* True if a </td></tr> is needed */ 208 205 209 206 zPrevDate[0] = 0; 210 207 mxWikiLen = db_get_int("timeline-max-comment", 0); 208 + zDiffTarget = db_get_boolean("href-targets", 1) ? 209 + "target='diffwindow'": ""; 211 210 if( tmFlags & TIMELINE_GRAPH ){ 212 211 pGraph = graph_init(); 213 212 /* style is not moved to css, because this is 214 213 ** a technical div for the timeline graph 215 214 */ 216 215 @ <div id="canvas" style="position:relative;height:0px;width:0px;" 217 216 @ onclick="clickOnGraph(event)"></div> ................................................................................ 445 444 const char *zNew = db_column_text(&fchngQuery, 3); 446 445 if( !inUl ){ 447 446 @ <ul class="filelist"> 448 447 inUl = 1; 449 448 } 450 449 if( isNew ){ 451 450 @ <li> %h(zFilename) (new file) 452 - @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) 451 + @ %z(xhref(zDiffTarget,"%R/artifact/%S",zNew)) 453 452 @ [view]</a></li> 454 453 }else if( isDel ){ 455 454 @ <li> %h(zFilename) (deleted)</li> 456 455 }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ 457 456 @ <li> %h(zOldName) → %h(zFilename) 458 - @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) 457 + @ %z(xhref(zDiffTarget,"%R/artifact/%S",zNew)) 459 458 @ [view]</a></li> 460 459 }else{ 461 460 if( zOldName!=0 ){ 462 461 @ <li> %h(zOldName) → %h(zFilename) 463 462 }else{ 464 463 @ <li> %h(zFilename) 465 464 } 466 - @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew)) 465 + @ %z(xhref(zDiffTarget,"%R/fdiff?v1=%S&v2=%S",zOld,zNew)) 467 466 @ [diff]</a></li> 468 467 } 469 468 } 470 469 db_reset(&fchngQuery); 471 470 if( inUl ){ 472 471 @ </ul> 473 472 }