Fossil SCM

New /file page that works like /artifact except takes a filename as an argument instead of a SHA1 hash of an artifact, and resolves to the most recent version of any file with that name.

drh 2016-11-28 16:44 trunk
Commit d95f712f2caba1e268cfd33abfcdfe7b8122e32d
1 file changed +45 -20
+45 -20
--- src/info.c
+++ src/info.c
@@ -1729,23 +1729,30 @@
17291729
}
17301730
17311731
/*
17321732
** Look for "ci" and "filename" query parameters. If found, try to
17331733
** use them to extract the record ID of an artifact for the file.
1734
+**
1735
+** Also look for "fn" as an alias for "filename". If either "filename"
1736
+** or "fn" is present but "ci" is missing, use "tip" as a default value
1737
+** for "ci".
17341738
*/
17351739
int artifact_from_ci_and_filename_www(void){
17361740
const char *zFilename;
17371741
const char *zCI;
17381742
int cirid;
17391743
Manifest *pManifest;
17401744
ManifestFile *pFile;
17411745
1742
- zCI = P("ci");
1743
- if( zCI==0 ) return 0;
17441746
zFilename = P("filename");
1745
- if( zFilename==0 ) return 0;
1746
- cirid = name_to_rid_www("ci");
1747
+ if( zFilename==0 ){
1748
+ zFilename = P("fn");
1749
+ if( zFilename==0 ) return 0;
1750
+ }
1751
+ zCI = PD("ci", "tip");
1752
+ cirid = name_to_typed_rid(zCI, "ci");
1753
+ if( cirid<=0 ) return 0;
17471754
pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
17481755
if( pManifest==0 ) return 0;
17491756
manifest_file_rewind(pManifest);
17501757
while( (pFile = manifest_file_next(pManifest,0))!=0 ){
17511758
if( fossil_strcmp(zFilename, pFile->zName)==0 ){
@@ -1840,29 +1847,37 @@
18401847
}
18411848
}
18421849
18431850
18441851
/*
1845
-** WEBPAGE: whatis
18461852
** WEBPAGE: artifact
1853
+** WEBPAGE: file
1854
+** WEBPAGE: whatis
1855
+**
1856
+** Typical usage:
18471857
**
1848
-** URL: /artifact/SHA1HASH
1849
-** URL: /artifact?ci=CHECKIN&filename=PATH
1850
-** URL: /whatis/SHA1HASH
1858
+** /artifact/SHA1HASH
1859
+** /whatis/SHA1HASH
1860
+** /file/NAME
18511861
**
18521862
** Additional query parameters:
18531863
**
18541864
** ln - show line numbers
18551865
** ln=N - highlight line number N
18561866
** ln=M-N - highlight lines M through N inclusive
18571867
** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
18581868
** verbose - show more detail in the description
18591869
** download - redirect to the download (artifact page only)
1870
+** name=SHA1HASH - Provide the SHA1HASH as a query parameter
1871
+** filename=NAME - Show information for content file NAME
1872
+** fn=NAME - "fn" is shorthand for "filename"
1873
+** ci=VERSION - The specific check-in to use for "filename=".
18601874
**
18611875
** The /artifact page show the complete content of a file
18621876
** identified by SHA1HASH as preformatted text. The
1863
-** /whatis page shows only a description of the file.
1877
+** /whatis page shows only a description of the file. The /file
1878
+** page shows the most recent version of the named file.
18641879
*/
18651880
void artifact_page(void){
18661881
int rid = 0;
18671882
Blob content;
18681883
const char *zMime;
@@ -1872,23 +1887,39 @@
18721887
int objType;
18731888
int asText;
18741889
const char *zUuid;
18751890
u32 objdescFlags = 0;
18761891
int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
1892
+ int isFile = fossil_strcmp(g.zPath,"file")==0;
18771893
const char *zLn = P("ln");
18781894
1879
- if( P("ci") && P("filename") ){
1880
- rid = artifact_from_ci_and_filename_www();
1881
- }
1895
+ rid = artifact_from_ci_and_filename_www();
18821896
if( rid==0 ){
1883
- rid = name_to_rid_www("name");
1897
+ if( fossil_strcmp(g.zPath,"file")==0 ){
1898
+ rid = db_int(0,
1899
+ "SELECT fid FROM filename, mlink, event"
1900
+ " WHERE name=%Q"
1901
+ " AND mlink.fnid=filename.fnid"
1902
+ " AND event.objid=mlink.mid"
1903
+ " ORDER BY event.mtime DESC LIMIT 1",
1904
+ PD("name","")
1905
+ );
1906
+ }else{
1907
+ rid = name_to_rid_www("name");
1908
+ }
18841909
}
18851910
18861911
login_check_credentials();
18871912
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
18881913
if( rid==0 ) fossil_redirect_home();
18891914
if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
1915
+ zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1916
+ if( g.perm.Setup ){
1917
+ @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
1918
+ }else{
1919
+ @ <h2>Artifact %s(zUuid):</h2>
1920
+ }
18901921
blob_zero(&downloadName);
18911922
objType = object_description(rid, objdescFlags, &downloadName);
18921923
if( !descOnly && P("download")!=0 ){
18931924
cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
18941925
db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
@@ -1902,16 +1933,10 @@
19021933
}else{
19031934
style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
19041935
}
19051936
}
19061937
style_header("%s", descOnly ? "Artifact Description" : "Artifact Content");
1907
- zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1908
- if( g.perm.Setup ){
1909
- @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
1910
- }else{
1911
- @ <h2>Artifact %s(zUuid):</h2>
1912
- }
19131938
if( g.perm.Admin ){
19141939
Stmt q;
19151940
db_prepare(&q,
19161941
"SELECT coalesce(user.login,rcvfrom.uid),"
19171942
" datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
@@ -1925,11 +1950,11 @@
19251950
@ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
19261951
}
19271952
db_finalize(&q);
19281953
}
19291954
style_submenu_element("Download", "%R/raw/%T?name=%s",
1930
- blob_str(&downloadName), zUuid);
1955
+ blob_str(&downloadName), zUuid);
19311956
if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
19321957
style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
19331958
}
19341959
asText = P("txt")!=0;
19351960
zMime = mimetype_from_name(blob_str(&downloadName));
19361961
--- src/info.c
+++ src/info.c
@@ -1729,23 +1729,30 @@
1729 }
1730
1731 /*
1732 ** Look for "ci" and "filename" query parameters. If found, try to
1733 ** use them to extract the record ID of an artifact for the file.
 
 
 
 
1734 */
1735 int artifact_from_ci_and_filename_www(void){
1736 const char *zFilename;
1737 const char *zCI;
1738 int cirid;
1739 Manifest *pManifest;
1740 ManifestFile *pFile;
1741
1742 zCI = P("ci");
1743 if( zCI==0 ) return 0;
1744 zFilename = P("filename");
1745 if( zFilename==0 ) return 0;
1746 cirid = name_to_rid_www("ci");
 
 
 
 
 
1747 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1748 if( pManifest==0 ) return 0;
1749 manifest_file_rewind(pManifest);
1750 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1751 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
@@ -1840,29 +1847,37 @@
1840 }
1841 }
1842
1843
1844 /*
1845 ** WEBPAGE: whatis
1846 ** WEBPAGE: artifact
 
 
 
 
1847 **
1848 ** URL: /artifact/SHA1HASH
1849 ** URL: /artifact?ci=CHECKIN&filename=PATH
1850 ** URL: /whatis/SHA1HASH
1851 **
1852 ** Additional query parameters:
1853 **
1854 ** ln - show line numbers
1855 ** ln=N - highlight line number N
1856 ** ln=M-N - highlight lines M through N inclusive
1857 ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
1858 ** verbose - show more detail in the description
1859 ** download - redirect to the download (artifact page only)
 
 
 
 
1860 **
1861 ** The /artifact page show the complete content of a file
1862 ** identified by SHA1HASH as preformatted text. The
1863 ** /whatis page shows only a description of the file.
 
1864 */
1865 void artifact_page(void){
1866 int rid = 0;
1867 Blob content;
1868 const char *zMime;
@@ -1872,23 +1887,39 @@
1872 int objType;
1873 int asText;
1874 const char *zUuid;
1875 u32 objdescFlags = 0;
1876 int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
 
1877 const char *zLn = P("ln");
1878
1879 if( P("ci") && P("filename") ){
1880 rid = artifact_from_ci_and_filename_www();
1881 }
1882 if( rid==0 ){
1883 rid = name_to_rid_www("name");
 
 
 
 
 
 
 
 
 
 
 
1884 }
1885
1886 login_check_credentials();
1887 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1888 if( rid==0 ) fossil_redirect_home();
1889 if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
 
 
 
 
 
 
1890 blob_zero(&downloadName);
1891 objType = object_description(rid, objdescFlags, &downloadName);
1892 if( !descOnly && P("download")!=0 ){
1893 cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
1894 db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
@@ -1902,16 +1933,10 @@
1902 }else{
1903 style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
1904 }
1905 }
1906 style_header("%s", descOnly ? "Artifact Description" : "Artifact Content");
1907 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1908 if( g.perm.Setup ){
1909 @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
1910 }else{
1911 @ <h2>Artifact %s(zUuid):</h2>
1912 }
1913 if( g.perm.Admin ){
1914 Stmt q;
1915 db_prepare(&q,
1916 "SELECT coalesce(user.login,rcvfrom.uid),"
1917 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
@@ -1925,11 +1950,11 @@
1925 @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
1926 }
1927 db_finalize(&q);
1928 }
1929 style_submenu_element("Download", "%R/raw/%T?name=%s",
1930 blob_str(&downloadName), zUuid);
1931 if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
1932 style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
1933 }
1934 asText = P("txt")!=0;
1935 zMime = mimetype_from_name(blob_str(&downloadName));
1936
--- src/info.c
+++ src/info.c
@@ -1729,23 +1729,30 @@
1729 }
1730
1731 /*
1732 ** Look for "ci" and "filename" query parameters. If found, try to
1733 ** use them to extract the record ID of an artifact for the file.
1734 **
1735 ** Also look for "fn" as an alias for "filename". If either "filename"
1736 ** or "fn" is present but "ci" is missing, use "tip" as a default value
1737 ** for "ci".
1738 */
1739 int artifact_from_ci_and_filename_www(void){
1740 const char *zFilename;
1741 const char *zCI;
1742 int cirid;
1743 Manifest *pManifest;
1744 ManifestFile *pFile;
1745
 
 
1746 zFilename = P("filename");
1747 if( zFilename==0 ){
1748 zFilename = P("fn");
1749 if( zFilename==0 ) return 0;
1750 }
1751 zCI = PD("ci", "tip");
1752 cirid = name_to_typed_rid(zCI, "ci");
1753 if( cirid<=0 ) return 0;
1754 pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
1755 if( pManifest==0 ) return 0;
1756 manifest_file_rewind(pManifest);
1757 while( (pFile = manifest_file_next(pManifest,0))!=0 ){
1758 if( fossil_strcmp(zFilename, pFile->zName)==0 ){
@@ -1840,29 +1847,37 @@
1847 }
1848 }
1849
1850
1851 /*
 
1852 ** WEBPAGE: artifact
1853 ** WEBPAGE: file
1854 ** WEBPAGE: whatis
1855 **
1856 ** Typical usage:
1857 **
1858 ** /artifact/SHA1HASH
1859 ** /whatis/SHA1HASH
1860 ** /file/NAME
1861 **
1862 ** Additional query parameters:
1863 **
1864 ** ln - show line numbers
1865 ** ln=N - highlight line number N
1866 ** ln=M-N - highlight lines M through N inclusive
1867 ** ln=M-N+Y-Z - highlight lines M through N and Y through Z (inclusive)
1868 ** verbose - show more detail in the description
1869 ** download - redirect to the download (artifact page only)
1870 ** name=SHA1HASH - Provide the SHA1HASH as a query parameter
1871 ** filename=NAME - Show information for content file NAME
1872 ** fn=NAME - "fn" is shorthand for "filename"
1873 ** ci=VERSION - The specific check-in to use for "filename=".
1874 **
1875 ** The /artifact page show the complete content of a file
1876 ** identified by SHA1HASH as preformatted text. The
1877 ** /whatis page shows only a description of the file. The /file
1878 ** page shows the most recent version of the named file.
1879 */
1880 void artifact_page(void){
1881 int rid = 0;
1882 Blob content;
1883 const char *zMime;
@@ -1872,23 +1887,39 @@
1887 int objType;
1888 int asText;
1889 const char *zUuid;
1890 u32 objdescFlags = 0;
1891 int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
1892 int isFile = fossil_strcmp(g.zPath,"file")==0;
1893 const char *zLn = P("ln");
1894
1895 rid = artifact_from_ci_and_filename_www();
 
 
1896 if( rid==0 ){
1897 if( fossil_strcmp(g.zPath,"file")==0 ){
1898 rid = db_int(0,
1899 "SELECT fid FROM filename, mlink, event"
1900 " WHERE name=%Q"
1901 " AND mlink.fnid=filename.fnid"
1902 " AND event.objid=mlink.mid"
1903 " ORDER BY event.mtime DESC LIMIT 1",
1904 PD("name","")
1905 );
1906 }else{
1907 rid = name_to_rid_www("name");
1908 }
1909 }
1910
1911 login_check_credentials();
1912 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1913 if( rid==0 ) fossil_redirect_home();
1914 if( descOnly || P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
1915 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1916 if( g.perm.Setup ){
1917 @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
1918 }else{
1919 @ <h2>Artifact %s(zUuid):</h2>
1920 }
1921 blob_zero(&downloadName);
1922 objType = object_description(rid, objdescFlags, &downloadName);
1923 if( !descOnly && P("download")!=0 ){
1924 cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
1925 db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
@@ -1902,16 +1933,10 @@
1933 }else{
1934 style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
1935 }
1936 }
1937 style_header("%s", descOnly ? "Artifact Description" : "Artifact Content");
 
 
 
 
 
 
1938 if( g.perm.Admin ){
1939 Stmt q;
1940 db_prepare(&q,
1941 "SELECT coalesce(user.login,rcvfrom.uid),"
1942 " datetime(rcvfrom.mtime,toLocal()), rcvfrom.ipaddr"
@@ -1925,11 +1950,11 @@
1950 @ <p>Received on %s(zDate) from %h(zUser) at %h(zIp).</p>
1951 }
1952 db_finalize(&q);
1953 }
1954 style_submenu_element("Download", "%R/raw/%T?name=%s",
1955 blob_str(&downloadName), zUuid);
1956 if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
1957 style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
1958 }
1959 asText = P("txt")!=0;
1960 zMime = mimetype_from_name(blob_str(&downloadName));
1961

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button