Fossil SCM
Provide a link to the reverse annotation for an /fdiff of two versions of the same file. Improvements to the description of a reverse annotation.
Commit
f52a544942a7fae8a31ef6290f392ef011f0e8e695f8a590c7624ca9b00e2b55
Parent
1f378f9e31f084b…
2 files changed
+16
-5
+26
+16
-5
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -2084,10 +2084,12 @@ | ||
| 2084 | 2084 | short int iVers; /* Level at which tag was set */ |
| 2085 | 2085 | } *aOrig; |
| 2086 | 2086 | int nOrig; /* Number of elements in aOrig[] */ |
| 2087 | 2087 | int nVers; /* Number of versions analyzed */ |
| 2088 | 2088 | int bMoreToDo; /* True if the limit was reached */ |
| 2089 | + int origId; /* RID for the zOrigin version */ | |
| 2090 | + int showId; /* RID for the version being analyzed */ | |
| 2089 | 2091 | struct AnnVers { |
| 2090 | 2092 | const char *zFUuid; /* File being analyzed */ |
| 2091 | 2093 | const char *zMUuid; /* Check-in containing the file */ |
| 2092 | 2094 | const char *zDate; /* Date of the check-in */ |
| 2093 | 2095 | const char *zBgColor; /* Suggested background color */ |
| @@ -2246,27 +2248,27 @@ | ||
| 2246 | 2248 | origid = zOrigin ? name_to_typed_rid(zOrigin, "ci") : 0; |
| 2247 | 2249 | |
| 2248 | 2250 | /* Compute all direct ancestors of the check-in being analyzed into |
| 2249 | 2251 | ** the "ancestor" table. */ |
| 2250 | 2252 | if( origid ){ |
| 2251 | - PathNode *p; | |
| 2253 | + PathNode *pPath; | |
| 2252 | 2254 | Blob sql; |
| 2253 | 2255 | int gen = 0; |
| 2254 | 2256 | char *zSep = "VALUES"; |
| 2255 | - p = path_shortest(cid, origid, 1, 0); | |
| 2257 | + pPath = path_shortest(cid, origid, 1, 0); | |
| 2256 | 2258 | db_multi_exec( |
| 2257 | 2259 | "CREATE TEMP TABLE IF NOT EXISTS ancestor(" |
| 2258 | 2260 | " rid INT UNIQUE," |
| 2259 | 2261 | " generation INTEGER PRIMARY KEY" |
| 2260 | 2262 | ");" |
| 2261 | 2263 | "DELETE FROM ancestor;" |
| 2262 | 2264 | ); |
| 2263 | 2265 | blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1); |
| 2264 | - while( p ){ | |
| 2265 | - blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, p->rid, ++gen); | |
| 2266 | + while( pPath ){ | |
| 2267 | + blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, pPath->rid,++gen); | |
| 2266 | 2268 | zSep = ","; |
| 2267 | - p = p->u.pTo; | |
| 2269 | + pPath = pPath->u.pTo; | |
| 2268 | 2270 | } |
| 2269 | 2271 | path_reset(); |
| 2270 | 2272 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 2271 | 2273 | blob_reset(&sql); |
| 2272 | 2274 | }else{ |
| @@ -2309,10 +2311,12 @@ | ||
| 2309 | 2311 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2310 | 2312 | } |
| 2311 | 2313 | blob_to_utf8_no_bom(&toAnnotate, 0); |
| 2312 | 2314 | annotation_start(p, &toAnnotate, annFlags); |
| 2313 | 2315 | p->bMoreToDo = origid!=0; |
| 2316 | + p->origId = origid; | |
| 2317 | + p->showId = cid; | |
| 2314 | 2318 | } |
| 2315 | 2319 | p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0])); |
| 2316 | 2320 | p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0)); |
| 2317 | 2321 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2318 | 2322 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| @@ -2479,13 +2483,20 @@ | ||
| 2479 | 2483 | @ w.style.display = x ? "block" : "none"; |
| 2480 | 2484 | @ } |
| 2481 | 2485 | @ </script> |
| 2482 | 2486 | |
| 2483 | 2487 | if( !ann.bMoreToDo ){ |
| 2488 | + assert( ann.origId==0 ); /* bMoreToDo always set for a point-to-point */ | |
| 2484 | 2489 | @ <h2>Origin for each line in |
| 2485 | 2490 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2486 | 2491 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2> |
| 2492 | + }else if( ann.origId>0 ){ | |
| 2493 | + @ <h2>Lines of | |
| 2494 | + @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> | |
| 2495 | + @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a> | |
| 2496 | + @ that are changed by the sequence of edits moving toward | |
| 2497 | + @ check-in %z(href("%R/info/%!S",zOrigin))%S(zOrigin)</a>:</h2> | |
| 2487 | 2498 | }else{ |
| 2488 | 2499 | @ <h2>Lines added by the %d(ann.nVers) most recent ancestors of |
| 2489 | 2500 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2490 | 2501 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2> |
| 2491 | 2502 | } |
| 2492 | 2503 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2084,10 +2084,12 @@ | |
| 2084 | short int iVers; /* Level at which tag was set */ |
| 2085 | } *aOrig; |
| 2086 | int nOrig; /* Number of elements in aOrig[] */ |
| 2087 | int nVers; /* Number of versions analyzed */ |
| 2088 | int bMoreToDo; /* True if the limit was reached */ |
| 2089 | struct AnnVers { |
| 2090 | const char *zFUuid; /* File being analyzed */ |
| 2091 | const char *zMUuid; /* Check-in containing the file */ |
| 2092 | const char *zDate; /* Date of the check-in */ |
| 2093 | const char *zBgColor; /* Suggested background color */ |
| @@ -2246,27 +2248,27 @@ | |
| 2246 | origid = zOrigin ? name_to_typed_rid(zOrigin, "ci") : 0; |
| 2247 | |
| 2248 | /* Compute all direct ancestors of the check-in being analyzed into |
| 2249 | ** the "ancestor" table. */ |
| 2250 | if( origid ){ |
| 2251 | PathNode *p; |
| 2252 | Blob sql; |
| 2253 | int gen = 0; |
| 2254 | char *zSep = "VALUES"; |
| 2255 | p = path_shortest(cid, origid, 1, 0); |
| 2256 | db_multi_exec( |
| 2257 | "CREATE TEMP TABLE IF NOT EXISTS ancestor(" |
| 2258 | " rid INT UNIQUE," |
| 2259 | " generation INTEGER PRIMARY KEY" |
| 2260 | ");" |
| 2261 | "DELETE FROM ancestor;" |
| 2262 | ); |
| 2263 | blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1); |
| 2264 | while( p ){ |
| 2265 | blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, p->rid, ++gen); |
| 2266 | zSep = ","; |
| 2267 | p = p->u.pTo; |
| 2268 | } |
| 2269 | path_reset(); |
| 2270 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 2271 | blob_reset(&sql); |
| 2272 | }else{ |
| @@ -2309,10 +2311,12 @@ | |
| 2309 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2310 | } |
| 2311 | blob_to_utf8_no_bom(&toAnnotate, 0); |
| 2312 | annotation_start(p, &toAnnotate, annFlags); |
| 2313 | p->bMoreToDo = origid!=0; |
| 2314 | } |
| 2315 | p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0])); |
| 2316 | p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0)); |
| 2317 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2318 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| @@ -2479,13 +2483,20 @@ | |
| 2479 | @ w.style.display = x ? "block" : "none"; |
| 2480 | @ } |
| 2481 | @ </script> |
| 2482 | |
| 2483 | if( !ann.bMoreToDo ){ |
| 2484 | @ <h2>Origin for each line in |
| 2485 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2486 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2> |
| 2487 | }else{ |
| 2488 | @ <h2>Lines added by the %d(ann.nVers) most recent ancestors of |
| 2489 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2490 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2> |
| 2491 | } |
| 2492 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -2084,10 +2084,12 @@ | |
| 2084 | short int iVers; /* Level at which tag was set */ |
| 2085 | } *aOrig; |
| 2086 | int nOrig; /* Number of elements in aOrig[] */ |
| 2087 | int nVers; /* Number of versions analyzed */ |
| 2088 | int bMoreToDo; /* True if the limit was reached */ |
| 2089 | int origId; /* RID for the zOrigin version */ |
| 2090 | int showId; /* RID for the version being analyzed */ |
| 2091 | struct AnnVers { |
| 2092 | const char *zFUuid; /* File being analyzed */ |
| 2093 | const char *zMUuid; /* Check-in containing the file */ |
| 2094 | const char *zDate; /* Date of the check-in */ |
| 2095 | const char *zBgColor; /* Suggested background color */ |
| @@ -2246,27 +2248,27 @@ | |
| 2248 | origid = zOrigin ? name_to_typed_rid(zOrigin, "ci") : 0; |
| 2249 | |
| 2250 | /* Compute all direct ancestors of the check-in being analyzed into |
| 2251 | ** the "ancestor" table. */ |
| 2252 | if( origid ){ |
| 2253 | PathNode *pPath; |
| 2254 | Blob sql; |
| 2255 | int gen = 0; |
| 2256 | char *zSep = "VALUES"; |
| 2257 | pPath = path_shortest(cid, origid, 1, 0); |
| 2258 | db_multi_exec( |
| 2259 | "CREATE TEMP TABLE IF NOT EXISTS ancestor(" |
| 2260 | " rid INT UNIQUE," |
| 2261 | " generation INTEGER PRIMARY KEY" |
| 2262 | ");" |
| 2263 | "DELETE FROM ancestor;" |
| 2264 | ); |
| 2265 | blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1); |
| 2266 | while( pPath ){ |
| 2267 | blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, pPath->rid,++gen); |
| 2268 | zSep = ","; |
| 2269 | pPath = pPath->u.pTo; |
| 2270 | } |
| 2271 | path_reset(); |
| 2272 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 2273 | blob_reset(&sql); |
| 2274 | }else{ |
| @@ -2309,10 +2311,12 @@ | |
| 2311 | fossil_fatal("unable to retrieve content of artifact #%d", rid); |
| 2312 | } |
| 2313 | blob_to_utf8_no_bom(&toAnnotate, 0); |
| 2314 | annotation_start(p, &toAnnotate, annFlags); |
| 2315 | p->bMoreToDo = origid!=0; |
| 2316 | p->origId = origid; |
| 2317 | p->showId = cid; |
| 2318 | } |
| 2319 | p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0])); |
| 2320 | p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0)); |
| 2321 | p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); |
| 2322 | p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); |
| @@ -2479,13 +2483,20 @@ | |
| 2483 | @ w.style.display = x ? "block" : "none"; |
| 2484 | @ } |
| 2485 | @ </script> |
| 2486 | |
| 2487 | if( !ann.bMoreToDo ){ |
| 2488 | assert( ann.origId==0 ); /* bMoreToDo always set for a point-to-point */ |
| 2489 | @ <h2>Origin for each line in |
| 2490 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2491 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2> |
| 2492 | }else if( ann.origId>0 ){ |
| 2493 | @ <h2>Lines of |
| 2494 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2495 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a> |
| 2496 | @ that are changed by the sequence of edits moving toward |
| 2497 | @ check-in %z(href("%R/info/%!S",zOrigin))%S(zOrigin)</a>:</h2> |
| 2498 | }else{ |
| 2499 | @ <h2>Lines added by the %d(ann.nVers) most recent ancestors of |
| 2500 | @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a> |
| 2501 | @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2> |
| 2502 | } |
| 2503 |
+26
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1561,12 +1561,38 @@ | ||
| 1561 | 1561 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1562 | 1562 | if( P("from") && P("to") ){ |
| 1563 | 1563 | v1 = artifact_from_ci_and_filename(0, "from"); |
| 1564 | 1564 | v2 = artifact_from_ci_and_filename(0, "to"); |
| 1565 | 1565 | }else{ |
| 1566 | + Stmt q; | |
| 1566 | 1567 | v1 = name_to_rid_www("v1"); |
| 1567 | 1568 | v2 = name_to_rid_www("v2"); |
| 1569 | + | |
| 1570 | + /* If the two file versions being compared both have the same | |
| 1571 | + ** filename, then offer an "Annotate" link that constructs an | |
| 1572 | + ** annotation between those version. */ | |
| 1573 | + db_prepare(&q, | |
| 1574 | + "SELECT (SELECT substr(uuid,1,20) FROM blob WHERE rid=a.mid)," | |
| 1575 | + " (SELECT substr(uuid,1,20) FROM blob WHERE rid=b.mid)," | |
| 1576 | + " (SELECT name FROM filename WHERE filename.fnid=a.fnid)" | |
| 1577 | + " FROM mlink a, mlink b" | |
| 1578 | + " WHERE a.fid=%d" | |
| 1579 | + " AND b.fid=%d" | |
| 1580 | + " AND a.fnid=b.fnid" | |
| 1581 | + " AND a.fid!=a.pid" | |
| 1582 | + " AND b.fid!=b.pid", | |
| 1583 | + v1, v2 | |
| 1584 | + ); | |
| 1585 | + if( db_step(&q)==SQLITE_ROW ){ | |
| 1586 | + const char *zOrig = db_column_text(&q, 0); | |
| 1587 | + const char *zCkin = db_column_text(&q, 1); | |
| 1588 | + const char *zFN = db_column_text(&q, 2); | |
| 1589 | + style_submenu_element("Annotate", | |
| 1590 | + "%R/annotate?origin=%s&checkin=%s&filename=%T", | |
| 1591 | + zOrig, zCkin, zFN); | |
| 1592 | + } | |
| 1593 | + db_finalize(&q); | |
| 1568 | 1594 | } |
| 1569 | 1595 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1570 | 1596 | zRe = P("regex"); |
| 1571 | 1597 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1572 | 1598 | if( verbose ) objdescFlags |= OBJDESC_DETAIL; |
| 1573 | 1599 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1561,12 +1561,38 @@ | |
| 1561 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1562 | if( P("from") && P("to") ){ |
| 1563 | v1 = artifact_from_ci_and_filename(0, "from"); |
| 1564 | v2 = artifact_from_ci_and_filename(0, "to"); |
| 1565 | }else{ |
| 1566 | v1 = name_to_rid_www("v1"); |
| 1567 | v2 = name_to_rid_www("v2"); |
| 1568 | } |
| 1569 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1570 | zRe = P("regex"); |
| 1571 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1572 | if( verbose ) objdescFlags |= OBJDESC_DETAIL; |
| 1573 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1561,12 +1561,38 @@ | |
| 1561 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1562 | if( P("from") && P("to") ){ |
| 1563 | v1 = artifact_from_ci_and_filename(0, "from"); |
| 1564 | v2 = artifact_from_ci_and_filename(0, "to"); |
| 1565 | }else{ |
| 1566 | Stmt q; |
| 1567 | v1 = name_to_rid_www("v1"); |
| 1568 | v2 = name_to_rid_www("v2"); |
| 1569 | |
| 1570 | /* If the two file versions being compared both have the same |
| 1571 | ** filename, then offer an "Annotate" link that constructs an |
| 1572 | ** annotation between those version. */ |
| 1573 | db_prepare(&q, |
| 1574 | "SELECT (SELECT substr(uuid,1,20) FROM blob WHERE rid=a.mid)," |
| 1575 | " (SELECT substr(uuid,1,20) FROM blob WHERE rid=b.mid)," |
| 1576 | " (SELECT name FROM filename WHERE filename.fnid=a.fnid)" |
| 1577 | " FROM mlink a, mlink b" |
| 1578 | " WHERE a.fid=%d" |
| 1579 | " AND b.fid=%d" |
| 1580 | " AND a.fnid=b.fnid" |
| 1581 | " AND a.fid!=a.pid" |
| 1582 | " AND b.fid!=b.pid", |
| 1583 | v1, v2 |
| 1584 | ); |
| 1585 | if( db_step(&q)==SQLITE_ROW ){ |
| 1586 | const char *zOrig = db_column_text(&q, 0); |
| 1587 | const char *zCkin = db_column_text(&q, 1); |
| 1588 | const char *zFN = db_column_text(&q, 2); |
| 1589 | style_submenu_element("Annotate", |
| 1590 | "%R/annotate?origin=%s&checkin=%s&filename=%T", |
| 1591 | zOrig, zCkin, zFN); |
| 1592 | } |
| 1593 | db_finalize(&q); |
| 1594 | } |
| 1595 | if( v1==0 || v2==0 ) fossil_redirect_home(); |
| 1596 | zRe = P("regex"); |
| 1597 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 1598 | if( verbose ) objdescFlags |= OBJDESC_DETAIL; |
| 1599 |