Index: src/info.c ================================================================== --- src/info.c +++ src/info.c @@ -675,16 +675,18 @@ fossil_free(zUrl); } @ @ Other Links: @ - @ %z(href("%R/tree?ci=%!S",zUuid))files - @ | %z(href("%R/fileage?name=%!S",zUuid))file ages - @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders - @ | %z(href("%R/artifact/%!S",zUuid))manifest + @ %z(href("%R/tree?ci=%S",zUuid))files + @ | %z(href("%R/fileage?name=%S",zUuid))file ages + @ | %z(href("%R/tree?nofiles&type=tree&ci=%S",zUuid))folders + @ | %z(href("%R/artifact/%S",zUuid))manifest + @ | + @ changes over parent branch if( g.anon.Write ){ - @ | %z(href("%R/ci_edit?r=%!S",zUuid))edit + @ | %z(href("%R/ci_edit?r=%S",zUuid))edit } @ @ blob_reset(&projName); } @@ -919,29 +921,34 @@ static void checkin_description(int rid){ Stmt q; db_prepare(&q, "SELECT datetime(mtime), coalesce(euser,user)," " coalesce(ecomment,comment), uuid," + " coalesce((SELECT value FROM tagxref" + " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid),'trunk')," " (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref" " WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid" " AND tagxref.rid=blob.rid AND tagxref.tagtype>0)" " FROM event, blob" " WHERE event.objid=%d AND type='ci'" " AND blob.rid=%d", - rid, rid + TAG_BRANCH, rid, rid ); while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); const char *zUser = db_column_text(&q, 1); const char *zUuid = db_column_text(&q, 3); + const char *zBranch = db_column_text(&q, 4); const char *zTagList = db_column_text(&q, 4); Blob comment; int wikiFlags = WIKI_INLINE|WIKI_NOBADLINKS; if( db_get_boolean("timeline-block-markup", 0)==0 ){ wikiFlags |= WIKI_NOBLOCK; } hyperlink_to_uuid(zUuid); + @ on branch + @ %s(zBranch) - blob_zero(&comment); db_column_blob(&q, 2, &comment); wiki_convert(&comment, 0, wikiFlags); blob_reset(&comment); @ (user: Index: src/name.c ================================================================== --- src/name.c +++ src/name.c @@ -186,10 +186,19 @@ " WHERE mtime<=julianday('%qz') AND type GLOB '%q'" " ORDER BY mtime DESC LIMIT 1", &zTag[4], zType); return rid; } + + /* "parent:", as for parent branch. It returns the checkin of + the last checkin of the parent branch that has been merged in. */ + if( memcmp(zTag, "pbranch:", 8)==0 ){ + int branchRid = symbolic_name_to_rid(&zTag[8], zType); + if (branchRid == 0) return 0; + rid = get_parent_branch_rid(branchRid); + return rid; + } /* "tag:" + symbolic-name */ if( memcmp(zTag, "tag:", 4)==0 ){ rid = db_int(0, "SELECT event.objid, max(event.mtime)" @@ -1138,10 +1147,108 @@ void test_phatoms_cmd(void){ db_find_and_open_repository(0,0); describe_artifacts_to_stdout("IN (SELECT rid FROM blob WHERE size<0)", 0); } + + +/* +** It returns the checkin of the last checkin of the parent branch that has +** been merged in. +*/ +int get_parent_branch_rid(int ridRequested){ + Stmt s; + const char *branchName; /* Name of the branch requested at rid */ + const char *parentBranchName; /* Name of the parent branch */ + int rid; + + /* Get the name of the current branch */ + branchName = db_text(0, + "SELECT value FROM tagxref" + " WHERE tagid=%d" + " AND tagxref.tagtype>0" + " AND rid=%d", + TAG_BRANCH, ridRequested); + + if ( !branchName ) + return 0; + + /* Find the name of the branch this was forked from */ + db_prepare(&s, + "SELECT pid, tagxref.value FROM plink JOIN tagxref" + " WHERE cid=:rid" + " AND isprim=1" + " AND tagxref.tagid=%d" + " AND tagxref.tagtype>0" + " AND tagxref.rid=pid", + TAG_BRANCH); + + rid = ridRequested; + while( rid > 0 ) { + db_bind_int(&s, ":rid", rid); + if ( db_step(&s) == SQLITE_ROW ) { + rid = db_column_int(&s, 0); + parentBranchName = db_column_text(&s, 1); + if ( !parentBranchName ) { + rid = 0; + break; + } + + if ( fossil_strcmp(parentBranchName, branchName) ) { + parentBranchName = fossil_strdup(parentBranchName); + break; + } + }else{ + rid = 0; + break; + } + db_reset(&s); + } + db_finalize(&s); + + if (rid == 0) + return 0; + + /* Find the last checkin coming from the parent branch */ + db_prepare(&s, + "SELECT pid, tagxref.value FROM plink JOIN tagxref" + " WHERE cid=:rid" + " AND tagxref.tagid=%d" + " AND tagxref.tagtype>0" + " AND tagxref.rid=pid ORDER BY isprim ASC", + TAG_BRANCH); + + rid = ridRequested; + while( rid > 0 ) { + db_bind_int(&s, ":rid", rid); + int found = 0; + while ( db_step(&s) == SQLITE_ROW ) { + const char *branchNamePid; /* Branch name of the pid */ + + ++found; + rid = db_column_int(&s, 0); + branchNamePid = db_column_text(&s, 1); + if ( !branchNamePid ) { + break; + } + if ( fossil_strcmp(parentBranchName, branchNamePid)==0 ) { + /* Found the last merge from the parent branch */ + db_finalize(&s); + return rid; + } + } + + if (found == 0) { + break; + } + db_reset(&s); + } + db_finalize(&s); + + return 0; +} + /* Maximum number of collision examples to remember */ #define MAX_COLLIDE 25 /* ** Generate a report on the number of collisions in SHA1 hashes Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -103,40 +103,36 @@ */ char *hash_color(const char *z){ int i; /* Loop counter */ unsigned int h = 0; /* Hash on the branch name */ int r, g, b; /* Values for red, green, and blue */ - int h1, h2, h3, h4; /* Elements of the hash value */ - int mx, mn; /* Components of HSV */ static char zColor[10]; /* The resulting color */ - static int ix[2] = {0,0}; /* Color chooser parameters */ - - if( ix[0]==0 ){ - if( skin_detail_boolean("white-foreground") ){ - ix[0] = 140; - ix[1] = 40; - }else{ - ix[0] = 216; - ix[1] = 16; - } - } - for(i=0; z[i]; i++ ){ + static int whitefg = -1; + int cpc = 4; /* colours per component */ + int cfactor = 128/cpc; /* Factor so n*cpc < 128 */ + int cmin = cfactor - 1; /* Factor so the max component is 127 + and the min is different than the bg */ + + if(whitefg = -1) + whitefg = skin_detail_boolean("white-foreground"); + + /* Calculate the hash based on the branch name */ + for(i=0; z[i]; i++){ h = (h<<11) ^ (h<<1) ^ (h>>3) ^ z[i]; } - h1 = h % 6; h /= 6; - h3 = h % 30; h /= 30; - h4 = h % 40; h /= 40; - mx = ix[0] - h3; - mn = mx - h4 - ix[1]; - h2 = (h%(mx - mn)) + mn; - switch( h1 ){ - case 0: r = mx; g = h2, b = mn; break; - case 1: r = h2; g = mx, b = mn; break; - case 2: r = mn; g = mx, b = h2; break; - case 3: r = mn; g = h2, b = mx; break; - case 4: r = h2; g = mn, b = mx; break; - default: r = mx; g = mn, b = h2; break; + + /* 'cpc' different random values per component, between 'cmin' and 127 */ + r = cmin + (h % cpc) * cfactor; h /= cpc; + g = cmin + (h % cpc) * cfactor; h /= cpc; + b = cmin + (h % cpc) * cfactor; h /= cpc; + + /* In case of blackfg, get the inverse effect */ + if(!whitefg) + { + r = 255 - r; + g = 255 - g; + b = 255 - b; } sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b); return zColor; }