diff --git a/app/views/repositories/_dir_list_content.rhtml b/app/views/repositories/_dir_list_content.rhtml
index 7993181..bcffed4 100644
--- a/app/views/repositories/_dir_list_content.rhtml
+++ b/app/views/repositories/_dir_list_content.rhtml
@@ -13,7 +13,7 @@
<% end %>
<%= link_to h(entry.name),
{:action => (entry.is_dir? ? 'browse' : 'changes'), :id => @project, :path => to_path_param(entry.path), :rev => @rev},
- :class => (entry.is_dir? ? 'icon icon-folder' : 'icon icon-file')%>
+ :class => (entry.is_dir? ? 'icon icon-folder' : "icon icon-file #{Redmine::MimeType.css_class_of(entry.name)}")%>
<%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %> |
<% changeset = @project.repository.changesets.find_by_revision(entry.lastrev.identifier) if entry.lastrev && entry.lastrev.identifier %>
diff --git a/lib/redmine/mime_type.rb b/lib/redmine/mime_type.rb
index dfdfff4..f0e55cc 100644
--- a/lib/redmine/mime_type.rb
+++ b/lib/redmine/mime_type.rb
@@ -24,6 +24,7 @@ module Redmine
'text/html' => 'html,htm,xhtml',
'text/jsp' => 'jsp',
'text/x-c' => 'c,cpp,cc,h,hh',
+ 'text/x-csharp' => 'cs',
'text/x-java' => 'java',
'text/x-javascript' => 'js',
'text/x-html-template' => 'rhtml',
@@ -41,6 +42,9 @@ module Redmine
'image/tiff' => 'tiff,tif',
'image/x-ms-bmp' => 'bmp',
'image/x-xpixmap' => 'xpm',
+ 'application/pdf' => 'pdf',
+ 'application/zip' => 'zip',
+ 'application/x-gzip' => 'gz',
}.freeze
EXTENSIONS = MIME_TYPES.inject({}) do |map, (type, exts)|
@@ -55,6 +59,13 @@ module Redmine
EXTENSIONS[m[2].downcase] if m
end
+ # Returns the css class associated to
+ # the mime type of name
+ def self.css_class_of(name)
+ mime = of(name)
+ mime && mime.gsub('/', '-')
+ end
+
def self.main_mimetype_of(name)
mimetype = of(name)
mimetype.split('/').first if mimetype
diff --git a/public/images/file.png b/public/images/file.png
deleted file mode 100644
index f387dd3052a73db6663f7ce845282757b961ca87..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@bfr7Syp@G4R4eS9xo$Mu^zOL-o899Xb`CN7$
z+y@lmEbxddW?Nn{1`%>sNvT>mpLeEy&r|NqmocREihV~;CK;dW`8
zSJ8c9N8at;JM!nRFEG&ONl5BE(eZ&Hsv<4!7fYXDQ|*(C%*LbpOcrmu(yRKY`+rBu
zMnA4t&dn>;AFBFnZQXt#Mc?({sb60Y+_w&BA1KRuw`44$rjF6*2UngE}v
Bk%j;O
diff --git a/public/images/files/c.png b/public/images/files/c.png
new file mode 100644
index 0000000000000000000000000000000000000000..34a05cccf064b35701b61ba1d395048873d7b48e
GIT binary patch
literal 587
zc$@)C0<`^!P)~7
zMNw2LQirBVQoa8G3P(rY+l;L4iy+JwSqmy$9JlSkk
z&*$^Eg+c)@!R|v4gdc8+TTn&eWHO0VD&>$!B%o;;WLf4CNs=Inq9d`xA4otCWHK38
zmc{pkX`0Y=9g3oGK{}lVy~OYL|C5lQ&U^l;wrg|7w=BcA9L4-r411?K7f`@348&rw
zXD#uW)DK;H`hxO}u%=@Cj{;#u#_;bb1_KgUOT2Hp6;)MvC6P$vQP3=g1O5#aU%I!K
zZ1dc@f}YvG&*Spnplm2rIp^VdA^HydZ0X1axdms2!RKi5x-SFA4p@
zC@N|PI$ryHL@t-(!zBsf2-+sYAukhDHU_YP)WjsQrp;}0X?Bxrvf12IKW8>3t`e~W9|JS<{btTNbNT@EQIWBSNJTX8AMGXD
z-SsH|s#>j9Xf~VMtyT-YMD}5^SWHTY5->o`k|d#AE_YQd79j`%GMS7FNvG3b7^Vy9
zn0HYCJy5MyQLoqKnW|JOp-?D*<2V^msZ>BOv0ANd2n7t@{=V;sZrQ>3c})5_%ms4z
z7!qXwHHe~!QFj8aR~&*-3F?O|;#(ESIXP~Os%|~y^7c15*q5`gz2-5ol!fU92NIGT
z_ves+>+Tf3gfcL?!nimYmR}cw*|BGULzI^7!;k#3K^YO#;!+vM@N~(99+<;fdqr
zYPJm+pXYFYk;neQyXXEcTQDNQx57i`Okp9A#n?<7!{#tnKJdsF>utb@JH7dU01gfL
zEK2hoPZAnO5+je3&^i*hWM`qCW^vLK!O*?U-#IvXV?#6koWqrwnD{j&K`7N>^tR3G
z8zr1(qVOzcF#nF1&0MZ5C$l8*E^Uth0000C#5QQ<|d}62BjvZR2H60wE-&H;pyTSqH(@-Vl>|&1p(LP>kg~E
zYiz5X^`c$+%8#zC{u)yfe-5
zmgid={Z3k(ERKCKrE7DF;=x4^O+
pzO8rLO8p|Ip=x)jHOtWj`bJBmKdh_V<`47(gQu&X%Q~loCIFbEay|e6
literal 0
Hc$@0(Jd~P)VHAd+bMNh~)LLRqN>D)-jd9UvB%+hyKX5U|&4t0)fzgD-MPpQ$nHU%yoz=vI
zMGb>1Xu!6Hw$NT~@Au<4P-+{9;Uw?&oj31uzH>xX0T7Xkz!(tn|Ed9-s_FqyReC13
z(ll)vW1O{Ck5ihay12Ob2ABc@RUI;zHpaMiyRDs0r>|D4rHw{ItJSJnYjt~jTbGuW
z`X(~}?!&86q40R8<4zYw;$qi0^3ec=c&<&H;r`8W%H=Xymf^i;Wo6~<+}zx2UMzpC
z*6MZN?(FMv`n|KO3(KFiUaucP0;Z!@LcUNa%8#vGK5aZ>wDgB0Gi=t*argWJcdlMQ
z2#MpEX0wU+9&0U?N(F#OgpviU_Y{jYMsj65U3|PjwUOY}lUYj?MTiK_Il}NCVx-Eh
zDx-TzMk7se+M#W_>?A1-x}ZXw3kkyz5kW)_hkjsi@RhKadN#H$Hq)$07*qoM6N<$f}lhwPXGV_
literal 0
Hc$@~O9lw>B8WRlD)Gm}Jrz31u-X&&gn2lvjs=i{7nIaL6v2==uw+8Lcs(8j27
z;|c`rmSv@Lx!heopGP^^Ieb3f=R!%Lpp$}iMS-&P3EJ)s48wrJ_Ni0~k|c47D2nj=
z{jS6bt|kFpFf|p5cM`_&0Zh|`rfEp0(}=}lT#(6RpzAsUfxv^LSYX>WlAaN$>)*J5
z0#sE+JRUD8iT9*fz{)_^7@6P&!sEjTcD+I9Z4YjT1`wH@fV{cEvneYGFU%maIEU2s55&K(LixD|{p-uiS@?KNj
zk-Go8G$hH6g002ovPDHLkV1hVj1#|!a
literal 0
Hc$@vYep8SaFV10Q$h+;hIUPX_=v5b}%>Tm<(&j1&5;I!55C)oN0s(P%ZB
zP3Q#ahfpXKWF@S?jm4U#fv)QovMhrriclyNs6-G12#3R##4PSZ0VY(dRWJ;Lwuq{#
zAW0Gwi$yA^R4RZ!;W+L`f&%x{=D^VK#BBWL4Ys{;*!A7Q;!=dN<&D8*GzGaF4`hV4
zDbY0{NrMX>ZqF=0((gR5-zL$kC*b)!fwu{Euru|XrG<$^n#@)7i_>rCmRxnDq>$Y%gJaCkRd|tE*a2x05Pe!I^e13o69#&RQZ36s0
zB=O|K2Yi(jsMqThn}9t?f5E-)L^naZ+db$&%M$!bCdm=jv7?t_lB?3&%Ltq(>ESw?
c;MI421LCcoDG!2@;{X5v07*qoM6N<$f`UZt7XSbN
literal 0
Hc$@ZS(e|#C2>JN4>y}l*tQ*E7zP@R2CCJnkW?xa6bgk%(hgtZ
z0=~d?U3i`+Mvi4!&~+WPT1^NX#{u6&QIx+DE(oR{&T5&-ovF?@wGw)P&AtpHZa|G%V*GUUqL@@!d4V$`8=##4)ytY959JG
zdc&Kho)&AL70^i
z!PEmeeDWCB-UbK(*4JST44^tV2z_J(dn~+vBMJT97_7rzFio=~XczIv?PQ5$v%u~y
zu(bteXb5I1h2zCV{Jc2~V{{yzZipgsP6;k264$*#5q?GzCm|CPa9CKqm4b116h3Pu
z?+%Cm52plC8|5P0@igf2GV1KkCfk{Zecu=G@VNrf>s%g9c5D%@cfxVb6$nY`1IW=4
zt10QqSps_2JLp0f3I0j0u>#qA;v!+T))KEbCg|mo3q0pG{OR}p0fPds8+K~d>Hq)$
M07*qoM6N<$g1S2e3jhEB
literal 0
Hc$@C#5QQ<|d}62BjvZR2H60wE-%6;pyTSA|c6o&@eC9QG)Hj&ExYL
zO&oVL^)+cM^qd@ApywS>pwx0H@RDN}hq;7mU-SKczYQ-hnrr=;iDAQMZQ+*g=YOM=
z!QlMQEn7FbaD->uKAYgo_j9)W&$$zS*W9}m(ey0q$&7l-XEWO0Y(9M=SnhLbwy;d>@~SY$Ku*0xPvIOQeV1x7u_z-2-X>_74(yfh7C
znXL|3GZ+d2`3re2hs?MK^~*-1fljz_B$LUvK}k?BNXe#Y!m=zM!!V#}8bncK5m;8VP
zw86G*RI63?Cd%b9bX|ueNlZ|wR6rj|r_)VIP@r2imh3?SN+^{|kY%~8B{maJ@F*OK
z&VH9LwOeGt#DRjj0~v~8`>iO7!Ybi;zE$va`A^T#yW`y44;k^#O~K5*jD=qcUhPSc
zvyy~q;5H_1WT1l~cqje9yfa+l!hu6xjdOJ8s;8E^+=QQ$tw
p?%p!Hy#YapB=@+^9(46X{{RQg%9y;OKjr`c002ovPDHLkV1g7l326WT
literal 0
Hc$@ZcJ%1+b$|lEg|m$p?$2s-?aFIU^lhS4
zt=5>B*onJiX5((A#g&zdZ;7N+zyNUJY~v8{(NtqH{`+@8xk&m
zG`u_jq?FJb9n=hw%`FbbD_m;*4&fCDuR=V`pUsP7fU1Tp7Q?_nK-IQ85K85YX7gRJ
zgwtoomKC%RWTO%Skh+*{%b>T>VfXA~9;mZE6vn=~?YHE7)8Zq;mfF}l;^WAReVKbv2dyl8I
zZdsNM9oTISwn$ahzw_tMS*<#q^{;+1adq)i5#6)A{L5!4^#~!-uOE5i^$%Jv0}EmF
z8*kM!$D7UP9;w~?<@c-q)vuj615`xxpt}~#kmfz_<A+Py(u*QQK4SDbur>73_#_dcJ}^ZeMc=S%0j-@Eny|NnKHk{E$@F_r}R1v5B2
zyO9RuNgQE>~@@z2E---{jMv_2%}xn_^5rT_o{
diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css
index a8d8736..f4bd102 100644
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -665,7 +665,6 @@ vertical-align: middle;
.icon-move { background-image: url(../images/move.png); }
.icon-save { background-image: url(../images/save.png); }
.icon-cancel { background-image: url(../images/cancel.png); }
-.icon-file { background-image: url(../images/file.png); }
.icon-folder { background-image: url(../images/folder.png); }
.open .icon-folder { background-image: url(../images/folder_open.png); }
.icon-package { background-image: url(../images/package.png); }
@@ -692,6 +691,21 @@ vertical-align: middle;
.icon-report { background-image: url(../images/report.png); }
.icon-comment { background-image: url(../images/comment.png); }
+.icon-file { background-image: url(../images/files/default.png); }
+.icon-file.text-plain { background-image: url(../images/files/text.png); }
+.icon-file.text-x-c { background-image: url(../images/files/c.png); }
+.icon-file.text-x-csharp { background-image: url(../images/files/csharp.png); }
+.icon-file.text-x-php { background-image: url(../images/files/php.png); }
+.icon-file.text-x-ruby { background-image: url(../images/files/ruby.png); }
+.icon-file.text-xml { background-image: url(../images/files/xml.png); }
+.icon-file.image-gif { background-image: url(../images/files/image.png); }
+.icon-file.image-jpeg { background-image: url(../images/files/image.png); }
+.icon-file.image-png { background-image: url(../images/files/image.png); }
+.icon-file.image-tiff { background-image: url(../images/files/image.png); }
+.icon-file.application-pdf { background-image: url(../images/files/pdf.png); }
+.icon-file.application-zip { background-image: url(../images/files/zip.png); }
+.icon-file.application-x-gzip { background-image: url(../images/files/zip.png); }
+
.icon22-projects { background-image: url(../images/22x22/projects.png); }
.icon22-users { background-image: url(../images/22x22/users.png); }
.icon22-tracker { background-image: url(../images/22x22/tracker.png); }
diff --git a/test/functional/repositories_subversion_controller_test.rb b/test/functional/repositories_subversion_controller_test.rb
index c2bb403..aef8c2e 100644
--- a/test/functional/repositories_subversion_controller_test.rb
+++ b/test/functional/repositories_subversion_controller_test.rb
@@ -64,6 +64,7 @@ class RepositoriesSubversionControllerTest < Test::Unit::TestCase
entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
assert_equal 'file', entry.kind
assert_equal 'subversion_test/helloworld.c', entry.path
+ assert_tag :a, :content => 'helloworld.c', :attributes => { :class => /text\-x\-c/ }
end
def test_browse_at_given_revision
diff --git a/test/unit/lib/redmine/mime_type_test.rb b/test/unit/lib/redmine/mime_type_test.rb
new file mode 100644
index 0000000..79d0869
--- /dev/null
+++ b/test/unit/lib/redmine/mime_type_test.rb
@@ -0,0 +1,61 @@
+# Redmine - project management software
+# Copyright (C) 2006-2009 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require File.dirname(__FILE__) + '/../../../test_helper'
+
+class Redmine::MimeTypeTest < Test::Unit::TestCase
+
+ def test_of
+ to_test = {'test.unk' => nil,
+ 'test.txt' => 'text/plain',
+ 'test.c' => 'text/x-c',
+ }
+ to_test.each do |name, expected|
+ assert_equal expected, Redmine::MimeType.of(name)
+ end
+ end
+
+ def test_css_class_of
+ to_test = {'test.unk' => nil,
+ 'test.txt' => 'text-plain',
+ 'test.c' => 'text-x-c',
+ }
+ to_test.each do |name, expected|
+ assert_equal expected, Redmine::MimeType.css_class_of(name)
+ end
+ end
+
+ def test_main_mimetype_of
+ to_test = {'test.unk' => nil,
+ 'test.txt' => 'text',
+ 'test.c' => 'text',
+ }
+ to_test.each do |name, expected|
+ assert_equal expected, Redmine::MimeType.main_mimetype_of(name)
+ end
+ end
+
+ def test_is_type
+ to_test = {['text', 'test.unk'] => false,
+ ['text', 'test.txt'] => true,
+ ['text', 'test.c'] => true,
+ }
+ to_test.each do |args, expected|
+ assert_equal expected, Redmine::MimeType.is_type?(*args)
+ end
+ end
+end