Overview
SHA1 Hash: | 923d644b89211895883a8442883afed8ee02a6e9 |
---|---|
Date: | 2009-01-28 21:41:41 |
User: | drh |
Comment: | Add the ci=LABEL parameter to the "dir" webpage in order to look at just files within a single check-in. Add a Download link on the artifact and hexdump viewers. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/browse.c from [9050864c16] to [b26f9d5a29].
@@ -101,18 +101,24 @@ ** WEBPAGE: dir ** ** Query parameters: ** ** name=PATH Directory to display. Required. +** ci=LABEL Show only files in this check-in. Optional. */ void page_dir(void){ const char *zD = P("name"); int mxLen; int nCol, nRow; int cnt, i; char *zPrefix; Stmt q; + const char *zCI = P("ci"); + int rid = 0; + Blob content; + Manifest m; + const char *zSubdirLink; login_check_credentials(); if( !g.okHistory ){ login_needed(); return; } style_header("File List"); sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, @@ -119,45 +125,84 @@ pathelementFunc, 0, 0); /* If the name= parameter is an empty string, make it a NULL pointer */ if( zD && strlen(zD)==0 ){ zD = 0; } + /* If a specific check-in is requested, fetch and parse it. */ + if( zCI && (rid = name_to_rid(zCI))!=0 && content_get(rid, &content) ){ + if( !manifest_parse(&m, &content) || m.type!=CFTYPE_MANIFEST ){ + zCI = 0; + } + } + /* Compute the title of the page */ if( zD ){ Blob title; blob_zero(&title); blob_appendf(&title, "Files in directory "); hyperlinked_path(zD, &title); - @ <h2>%s(blob_str(&title))</h2> + @ <h2>%s(blob_str(&title)) blob_reset(&title); zPrefix = mprintf("%h/", zD); }else{ - @ <h2>Files in the top-level directory</h2> + @ <h2>Files in the top-level directory zPrefix = ""; + } + if( zCI ){ + char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); + char zShort[20]; + memcpy(zShort, zUuid, 10); + zShort[10] = 0; + @ of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]</h2> + zSubdirLink = mprintf("%s/dir?ci=%s&name=%T", g.zBaseURL, zUuid, zPrefix); + if( zD ){ + style_submenu_element("Top", "Top", "%s/dir?ci=%s", g.zBaseURL, zUuid); + } + }else{ + @ </h2> + zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix); } /* Compute the temporary table "localfiles" containing the names ** of all files and subdirectories in the zD[] directory. ** ** Subdirectory names begin with "/". This causes them to sort ** first and it also gives us an easy way to distinguish files ** from directories in the loop that follows. */ + db_multi_exec( + "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);" + "CREATE TEMP TABLE allfiles(x UNIQUE NOT NULL, u);" + ); + if( zCI ){ + Stmt ins; + int i; + db_prepare(&ins, "INSERT INTO allfiles VALUES(:x, :u)"); + for(i=0; i<m.nFile; i++){ + db_bind_text(&ins, ":x", m.aFile[i].zName); + db_bind_text(&ins, ":u", m.aFile[i].zUuid); + db_step(&ins); + db_reset(&ins); + } + db_finalize(&ins); + }else{ + db_multi_exec( + "INSERT INTO allfiles SELECT name, NULL FROM filename" + ); + } if( zD ){ db_multi_exec( - "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);" "INSERT OR IGNORE INTO localfiles " - " SELECT pathelement(name,%d) FROM filename" - " WHERE +name GLOB '%q/*'", + " SELECT pathelement(x,%d), u FROM allfiles" + " WHERE x GLOB '%q/*'", strlen(zD)+1, zD ); }else{ db_multi_exec( - "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);" "INSERT OR IGNORE INTO localfiles " - " SELECT pathelement(name,0) FROM filename" + " SELECT pathelement(x,0), u FROM allfiles" ); } /* Generate a multi-column table listing the contents of zD[] ** directory. @@ -164,11 +209,11 @@ */ mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles"); cnt = db_int(0, "SELECT count(*) FROM localfiles"); nCol = 4; nRow = (cnt+nCol-1)/nCol; - db_prepare(&q, "SELECT x FROM localfiles ORDER BY x"); + db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x"); @ <table border="0" width="100%%"><tr><td valign="top" width="25%%"> i = 0; while( db_step(&q)==SQLITE_ROW ){ const char *zFName; if( i==nRow ){ @@ -177,16 +222,19 @@ } i++; zFName = db_column_text(&q, 0); if( zFName[0]=='/' ){ zFName++; - @ <li><a href="%s(g.zBaseURL)/dir?name=%T(zPrefix)%T(zFName)"> + @ <li><a href="%s(zSubdirLink)%T(zFName)"> @ %h(zFName)/</a></li> + }else if( zCI ){ + const char *zUuid = db_column_text(&q, 1); + @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFName)</a> }else{ @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFName)"> @ %h(zFName)</a></li> } } db_finalize(&q); @ </td></tr></table> style_footer(); }
Modified src/info.c from [b42d745af6] to [8b65dc436f].
@@ -324,10 +324,11 @@ } } /* +** WEBPAGE: vinfo ** WEBPAGE: ci ** URL: /ci?name=RID|ARTIFACTID ** ** Return information about a baseline */ @@ -425,10 +426,11 @@ db_finalize(&q); @ </td></tr> @ <tr><th>Commands:</th> @ <td> @ <a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a> + @ | <a href="%s(g.zBaseURL)/dir?ci=%s(zShortUuid)">files</a> @ | <a href="%s(g.zBaseURL)/zip/%s(zProjName)-%s(zShortUuid).zip?uuid=%s(zUuid)"> @ ZIP archive</a> @ | <a href="%s(g.zBaseURL)/artifact/%d(rid)">manifest</a> if( g.okWrite ){ @ | <a href="%s(g.zBaseURL)/ci_edit?r=%d(rid)">edit</a> @@ -736,11 +738,12 @@ ** * date of check-in ** * Comment & user */ static void object_description( int rid, /* The artifact ID */ - int linkToView /* Add viewer link if true */ + int linkToView, /* Add viewer link if true */ + Blob *pDownloadName /* Fill with an appropriate download name */ ){ Stmt q; int cnt = 0; int nWiki = 0; db_prepare(&q, @@ -771,10 +774,13 @@ @ <a href="%s(g.zBaseURL)/finfo?name=%T(zName)">%h(zName)</a> @ uuid %s(zFuuid) part of check-in hyperlink_to_uuid(zVers); @ %w(zCom) by %h(zUser) on %s(zDate). cnt++; + if( pDownloadName && blob_size(pDownloadName)==0 ){ + blob_append(pDownloadName, zName, -1); + } } db_finalize(&q); db_prepare(&q, "SELECT substr(tagname, 6, 10000), datetime(event.mtime)," " coalesce(event.euser, event.user), uuid" @@ -798,10 +804,13 @@ } @ [<a href="%s(g.zBaseURL)/wiki?name=%t(zPagename)">%h(zPagename)</a>] @ uuid %s(zUuid) by %h(zUser) on %s(zDate). nWiki++; cnt++; + if( pDownloadName && blob_size(pDownloadName)==0 ){ + blob_append(pDownloadName, zPagename, -1); + } } db_finalize(&q); if( nWiki==0 ){ db_prepare(&q, "SELECT datetime(mtime), user, comment, uuid, type" @@ -828,17 +837,23 @@ }else{ @ Control file referencing } hyperlink_to_uuid(zUuid); @ %w(zCom) by %h(zUser) on %s(zDate). + if( pDownloadName && blob_size(pDownloadName)==0 ){ + blob_append(pDownloadName, zUuid, -1); + } cnt++; } db_finalize(&q); } if( cnt==0 ){ char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); @ Control file %s(zUuid). + if( pDownloadName && blob_size(pDownloadName)==0 ){ + blob_append(pDownloadName, zUuid, -1); + } }else if( linkToView ){ @ <a href="%s(g.zBaseURL)/artifact/%d(rid)">[view]</a> } } @@ -856,15 +871,15 @@ login_check_credentials(); if( !g.okRead ){ login_needed(); return; } style_header("Diff"); @ <h2>Differences From:</h2> @ <blockquote> - object_description(v1, 1); + object_description(v1, 1, 0); @ </blockquote> @ <h2>To:</h2> @ <blockquote> - object_description(v2, 1); + object_description(v2, 1, 0); @ </blockquote> @ <hr> @ <blockquote><pre> content_get(v1, &c1); content_get(v2, &c2); @@ -959,10 +974,11 @@ ** as preformatted text. */ void hexdump_page(void){ int rid; Blob content; + Blob downloadName; rid = name_to_rid(PD("name","0")); login_check_credentials(); if( !g.okRead ){ login_needed(); return; } if( rid==0 ){ cgi_redirect("/home"); } @@ -977,11 +993,14 @@ } } style_header("Hex Artifact Content"); @ <h2>Hexadecimal Content Of:</h2> @ <blockquote> - object_description(rid, 0); + blob_zero(&downloadName); + object_description(rid, 0, &downloadName); + style_submenu_element("Download", "Download", + "%s/raw/%T?name=%d", g.zBaseURL, blob_str(&downloadName), rid); @ </blockquote> @ <hr> content_get(rid, &content); @ <blockquote><pre> hexdump(&content); @@ -998,10 +1017,11 @@ */ void artifact_page(void){ int rid; Blob content; const char *zMime; + Blob downloadName; rid = name_to_rid(PD("name","0")); login_check_credentials(); if( !g.okRead ){ login_needed(); return; } if( rid==0 ){ cgi_redirect("/home"); } @@ -1016,11 +1036,14 @@ } } style_header("Artifact Content"); @ <h2>Content Of:</h2> @ <blockquote> - object_description(rid, 0); + blob_zero(&downloadName); + object_description(rid, 0, &downloadName); + style_submenu_element("Download", "Download", + "%s/raw/%T?name=%d", g.zTop, blob_str(&downloadName), rid); @ </blockquote> @ <hr> @ <blockquote> content_get(rid, &content); zMime = mimetype_from_content(&content);