Fossil SCM
Hyperlinks to directory browser pages on the pathname in the title of the file history viewer, finfo.
Commit
a20dcb5c26addae8473d1eb93f44f00c7dbe2c37
Parent
8c3ec00311d4641…
2 files changed
+32
-20
+7
-1
+32
-20
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -65,10 +65,39 @@ | ||
| 65 | 65 | zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]); |
| 66 | 66 | sqlite3_result_text(context, zOut, i-n+1, sqlite3_free); |
| 67 | 67 | } |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | +/* | |
| 71 | +** Given a pathname which is a relative path from the root of | |
| 72 | +** the repository to a file or directory, compute a string which | |
| 73 | +** is an HTML rendering of that path with hyperlinks on each | |
| 74 | +** directory component of the path where the hyperlink redirects | |
| 75 | +** to the "dir" page for the directory. | |
| 76 | +** | |
| 77 | +** There is no hyperlink on the file element of the path. | |
| 78 | +** | |
| 79 | +** The computed string is appended to the pOut blob. pOut should | |
| 80 | +** have already been initialized. | |
| 81 | +*/ | |
| 82 | +void hyperlinked_path(const char *zPath, Blob *pOut){ | |
| 83 | + int i, j; | |
| 84 | + char *zSep = ""; | |
| 85 | + | |
| 86 | + for(i=0; zPath[i]; i=j){ | |
| 87 | + for(j=i; zPath[j] && zPath[j]!='/'; j++){} | |
| 88 | + if( zPath[j] ){ | |
| 89 | + blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", | |
| 90 | + zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]); | |
| 91 | + }else{ | |
| 92 | + blob_appendf(pOut, "%s%h", zSep, &zPath[i]); | |
| 93 | + } | |
| 94 | + zSep = "/"; | |
| 95 | + while( zPath[j]=='/' ){ j++; } | |
| 96 | + } | |
| 97 | +} | |
| 98 | + | |
| 70 | 99 | |
| 71 | 100 | /* |
| 72 | 101 | ** WEBPAGE: dir |
| 73 | 102 | ** |
| 74 | 103 | ** Query parameters: |
| @@ -92,35 +121,18 @@ | ||
| 92 | 121 | /* If the name= parameter is an empty string, make it a NULL pointer */ |
| 93 | 122 | if( zD && strlen(zD)==0 ){ zD = 0; } |
| 94 | 123 | |
| 95 | 124 | /* Compute the title of the page */ |
| 96 | 125 | if( zD ){ |
| 97 | - int i, j; | |
| 98 | - char *zCopy; | |
| 99 | 126 | Blob title; |
| 100 | 127 | |
| 101 | 128 | blob_zero(&title); |
| 102 | - zCopy = sqlite3_mprintf("%s/", zD); | |
| 103 | - blob_appendf(&title, | |
| 104 | - "Files in directory <a href=\"%s/dir\"><i>root</i></a>", | |
| 105 | - g.zBaseURL | |
| 106 | - ); | |
| 107 | - for(i=0; zD[i]; i=j){ | |
| 108 | - for(j=i; zD[j] && zD[j]!='/'; j++){} | |
| 109 | - if( zD[j] ){ | |
| 110 | - zCopy[j] = 0; | |
| 111 | - blob_appendf(&title, "/<a href=\"%s/dir?name=%T\">%h</a>", | |
| 112 | - g.zBaseURL, zCopy, &zCopy[i]); | |
| 113 | - zCopy[j] = '/'; | |
| 114 | - }else{ | |
| 115 | - blob_appendf(&title, "/%h", &zCopy[i]); | |
| 116 | - } | |
| 117 | - while( zD[j]=='/' ){ j++; } | |
| 118 | - } | |
| 129 | + blob_appendf(&title, "Files in directory "); | |
| 130 | + hyperlinked_path(zD, &title); | |
| 119 | 131 | @ <h2>%s(blob_str(&title))</h2> |
| 120 | 132 | blob_reset(&title); |
| 121 | - zPrefix = zCopy; | |
| 133 | + zPrefix = mprintf("%h/", zD); | |
| 122 | 134 | }else{ |
| 123 | 135 | @ <h2>Files in the top-level directory</h2> |
| 124 | 136 | zPrefix = ""; |
| 125 | 137 | } |
| 126 | 138 | |
| 127 | 139 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -65,10 +65,39 @@ | |
| 65 | zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]); |
| 66 | sqlite3_result_text(context, zOut, i-n+1, sqlite3_free); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | |
| 71 | /* |
| 72 | ** WEBPAGE: dir |
| 73 | ** |
| 74 | ** Query parameters: |
| @@ -92,35 +121,18 @@ | |
| 92 | /* If the name= parameter is an empty string, make it a NULL pointer */ |
| 93 | if( zD && strlen(zD)==0 ){ zD = 0; } |
| 94 | |
| 95 | /* Compute the title of the page */ |
| 96 | if( zD ){ |
| 97 | int i, j; |
| 98 | char *zCopy; |
| 99 | Blob title; |
| 100 | |
| 101 | blob_zero(&title); |
| 102 | zCopy = sqlite3_mprintf("%s/", zD); |
| 103 | blob_appendf(&title, |
| 104 | "Files in directory <a href=\"%s/dir\"><i>root</i></a>", |
| 105 | g.zBaseURL |
| 106 | ); |
| 107 | for(i=0; zD[i]; i=j){ |
| 108 | for(j=i; zD[j] && zD[j]!='/'; j++){} |
| 109 | if( zD[j] ){ |
| 110 | zCopy[j] = 0; |
| 111 | blob_appendf(&title, "/<a href=\"%s/dir?name=%T\">%h</a>", |
| 112 | g.zBaseURL, zCopy, &zCopy[i]); |
| 113 | zCopy[j] = '/'; |
| 114 | }else{ |
| 115 | blob_appendf(&title, "/%h", &zCopy[i]); |
| 116 | } |
| 117 | while( zD[j]=='/' ){ j++; } |
| 118 | } |
| 119 | @ <h2>%s(blob_str(&title))</h2> |
| 120 | blob_reset(&title); |
| 121 | zPrefix = zCopy; |
| 122 | }else{ |
| 123 | @ <h2>Files in the top-level directory</h2> |
| 124 | zPrefix = ""; |
| 125 | } |
| 126 | |
| 127 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -65,10 +65,39 @@ | |
| 65 | zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]); |
| 66 | sqlite3_result_text(context, zOut, i-n+1, sqlite3_free); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | /* |
| 71 | ** Given a pathname which is a relative path from the root of |
| 72 | ** the repository to a file or directory, compute a string which |
| 73 | ** is an HTML rendering of that path with hyperlinks on each |
| 74 | ** directory component of the path where the hyperlink redirects |
| 75 | ** to the "dir" page for the directory. |
| 76 | ** |
| 77 | ** There is no hyperlink on the file element of the path. |
| 78 | ** |
| 79 | ** The computed string is appended to the pOut blob. pOut should |
| 80 | ** have already been initialized. |
| 81 | */ |
| 82 | void hyperlinked_path(const char *zPath, Blob *pOut){ |
| 83 | int i, j; |
| 84 | char *zSep = ""; |
| 85 | |
| 86 | for(i=0; zPath[i]; i=j){ |
| 87 | for(j=i; zPath[j] && zPath[j]!='/'; j++){} |
| 88 | if( zPath[j] ){ |
| 89 | blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", |
| 90 | zSep, g.zBaseURL, j, zPath, j-i, &zPath[i]); |
| 91 | }else{ |
| 92 | blob_appendf(pOut, "%s%h", zSep, &zPath[i]); |
| 93 | } |
| 94 | zSep = "/"; |
| 95 | while( zPath[j]=='/' ){ j++; } |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | |
| 100 | /* |
| 101 | ** WEBPAGE: dir |
| 102 | ** |
| 103 | ** Query parameters: |
| @@ -92,35 +121,18 @@ | |
| 121 | /* If the name= parameter is an empty string, make it a NULL pointer */ |
| 122 | if( zD && strlen(zD)==0 ){ zD = 0; } |
| 123 | |
| 124 | /* Compute the title of the page */ |
| 125 | if( zD ){ |
| 126 | Blob title; |
| 127 | |
| 128 | blob_zero(&title); |
| 129 | blob_appendf(&title, "Files in directory "); |
| 130 | hyperlinked_path(zD, &title); |
| 131 | @ <h2>%s(blob_str(&title))</h2> |
| 132 | blob_reset(&title); |
| 133 | zPrefix = mprintf("%h/", zD); |
| 134 | }else{ |
| 135 | @ <h2>Files in the top-level directory</h2> |
| 136 | zPrefix = ""; |
| 137 | } |
| 138 | |
| 139 |
+7
-1
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -445,10 +445,12 @@ | ||
| 445 | 445 | */ |
| 446 | 446 | void finfo_page(void){ |
| 447 | 447 | Stmt q; |
| 448 | 448 | const char *zFilename; |
| 449 | 449 | char zPrevDate[20]; |
| 450 | + Blob title; | |
| 451 | + | |
| 450 | 452 | login_check_credentials(); |
| 451 | 453 | if( !g.okHistory ){ login_needed(); return; } |
| 452 | 454 | style_header("File History"); |
| 453 | 455 | |
| 454 | 456 | zPrevDate[0] = 0; |
| @@ -464,11 +466,15 @@ | ||
| 464 | 466 | " AND b.rid=mlink.fid" |
| 465 | 467 | " AND event.objid=mlink.mid" |
| 466 | 468 | " ORDER BY event.mtime DESC", |
| 467 | 469 | zFilename |
| 468 | 470 | ); |
| 469 | - @ <h2>History of %h(zFilename)</h2> | |
| 471 | + blob_zero(&title); | |
| 472 | + blob_appendf(&title, "History of "); | |
| 473 | + hyperlinked_path(zFilename, &title); | |
| 474 | + @ <h2>%b(&title)</h2> | |
| 475 | + blob_reset(&title); | |
| 470 | 476 | @ <table cellspacing=0 border=0 cellpadding=0> |
| 471 | 477 | while( db_step(&q)==SQLITE_ROW ){ |
| 472 | 478 | const char *zVers = db_column_text(&q, 0); |
| 473 | 479 | const char *zUuid = db_column_text(&q, 1); |
| 474 | 480 | const char *zDate = db_column_text(&q, 2); |
| 475 | 481 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -445,10 +445,12 @@ | |
| 445 | */ |
| 446 | void finfo_page(void){ |
| 447 | Stmt q; |
| 448 | const char *zFilename; |
| 449 | char zPrevDate[20]; |
| 450 | login_check_credentials(); |
| 451 | if( !g.okHistory ){ login_needed(); return; } |
| 452 | style_header("File History"); |
| 453 | |
| 454 | zPrevDate[0] = 0; |
| @@ -464,11 +466,15 @@ | |
| 464 | " AND b.rid=mlink.fid" |
| 465 | " AND event.objid=mlink.mid" |
| 466 | " ORDER BY event.mtime DESC", |
| 467 | zFilename |
| 468 | ); |
| 469 | @ <h2>History of %h(zFilename)</h2> |
| 470 | @ <table cellspacing=0 border=0 cellpadding=0> |
| 471 | while( db_step(&q)==SQLITE_ROW ){ |
| 472 | const char *zVers = db_column_text(&q, 0); |
| 473 | const char *zUuid = db_column_text(&q, 1); |
| 474 | const char *zDate = db_column_text(&q, 2); |
| 475 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -445,10 +445,12 @@ | |
| 445 | */ |
| 446 | void finfo_page(void){ |
| 447 | Stmt q; |
| 448 | const char *zFilename; |
| 449 | char zPrevDate[20]; |
| 450 | Blob title; |
| 451 | |
| 452 | login_check_credentials(); |
| 453 | if( !g.okHistory ){ login_needed(); return; } |
| 454 | style_header("File History"); |
| 455 | |
| 456 | zPrevDate[0] = 0; |
| @@ -464,11 +466,15 @@ | |
| 466 | " AND b.rid=mlink.fid" |
| 467 | " AND event.objid=mlink.mid" |
| 468 | " ORDER BY event.mtime DESC", |
| 469 | zFilename |
| 470 | ); |
| 471 | blob_zero(&title); |
| 472 | blob_appendf(&title, "History of "); |
| 473 | hyperlinked_path(zFilename, &title); |
| 474 | @ <h2>%b(&title)</h2> |
| 475 | blob_reset(&title); |
| 476 | @ <table cellspacing=0 border=0 cellpadding=0> |
| 477 | while( db_step(&q)==SQLITE_ROW ){ |
| 478 | const char *zVers = db_column_text(&q, 0); |
| 479 | const char *zUuid = db_column_text(&q, 1); |
| 480 | const char *zDate = db_column_text(&q, 2); |
| 481 |