Signed by hanna SSH key fingerprint: SHA256:4g9cWhkAAw8gwqhJUcVbSnGEvdGwklW+1Aa/fMUu59k
assets/base.css +15 −0 crates/git/src/attributes.rs +6 −0 crates/git/src/repo.rs +26 −7 crates/web/src/repo.rs +16 −5 assets/base.css +15 −0 2268 border-top : none ; 2268 border-top : none ; 2269 border-radius : 0 0 var ( --fb-radius ) var ( --fb-radius ) ; 2269 border-radius : 0 0 var ( --fb-radius ) var ( --fb-radius ) ; 2270 } 2270 } 2271 2272 2273 . blob-image { 2274 background : var ( --fb-bg-inset ) ; 2275 border : 1px solid var ( --fb-border ) ; 2276 border-top : none ; 2277 border-radius : 0 0 var ( --fb-radius ) var ( --fb-radius ) ; 2278 overflow : hidden ; 2279 line-height : 0 ; 2280 } 2281 . blob-image img { 2282 display : block ; 2283 max-width : 100% ; 2284 margin : 0 auto ; 2285 } 2271 2286 2272 2287 2273 . blob-code { 2288 . blob-code {
crates/git/src/attributes.rs +6 −0 119 pub fn is_vendored ( & self ) -> bool { 119 pub fn is_vendored ( & self ) -> bool { 120 self . is_set ( "linguist-vendored" ) 120 self . is_set ( "linguist-vendored" ) 121 } 121 } 122 123 124 # [ must_use ] 125 pub fn is_lfs ( & self ) -> bool { 126 matches ! ( self . map. get ( "filter" ) , Some ( AttrValue :: Value ( v) ) if v == "lfs" ) 127 } 122 } 128 } 123 129 124 130
crates/git/src/repo.rs +26 −7 171 . map ( |b| parse_gitmodules ( b. content ( ) ) ) 171 . map ( |b| parse_gitmodules ( b. content ( ) ) ) 172 . unwrap_or_default ( ) ; 172 . unwrap_or_default ( ) ; 173 173 174 175 176 let attrs = self . attributes_set ( & rev. oid) . ok ( ) ; 177 let dir_prefix = path_string ( path) ; 178 174 let tree = if path. components ( ) . next ( ) . is_none ( ) { 179 let tree = if path. components ( ) . next ( ) . is_none ( ) { 175 Some ( root) 180 Some ( root) 176 } else { 181 } else { 182 let mut lfs = std:: collections:: HashSet :: new ( ) ; 187 let mut lfs = std:: collections:: HashSet :: new ( ) ; 183 if let Some ( tree) = tree { 188 if let Some ( tree) = tree { 184 for entry in & tree { 189 for entry in & tree { 185 if entry. kind ( ) == Some ( git2:: ObjectType :: Blob ) 190 let Some ( name) = entry. name ( ) else { continue } ; 186 && let Ok ( obj) = entry. to_object ( & self . inner) 191 if entry. kind ( ) != Some ( git2:: ObjectType :: Blob ) { 187 && let Some ( blob) = obj. as_blob ( ) 192 continue ; 188 && blob. size ( ) < POINTER_MAX 193 } 189 && is_lfs_pointer ( blob. content ( ) ) 194 let full = if dir_prefix. is_empty ( ) { 190 && let Some ( name) = entry. name ( ) 195 name. to_string ( ) 191 { 196 } else { 197 format ! ( "{dir_prefix}/{name}" ) 198 } ; 199 let tracked = attrs 200 . as_ref ( ) 201 . is_some_and ( |set| set. attributes ( & full) . is_lfs ( ) ) ; 202 let pointer = entry 203 . to_object ( & self . inner) 204 . ok ( ) 205 . and_then ( |o| { 206 o. as_blob ( ) 207 . map ( |b| b. size ( ) < POINTER_MAX && is_lfs_pointer ( b. content ( ) ) ) 208 } ) 209 . unwrap_or ( false ) ; 210 if tracked || pointer { 192 lfs. insert ( name. to_string ( ) ) ; 211 lfs. insert ( name. to_string ( ) ) ; 193 } 212 } 194 } 213 }
crates/web/src/repo.rs +16 −5 691 } ) 691 } ) 692 . await ?; 692 . await ?; 693 693 694 694 695 let ( blob, attr_lang) = git_read ( state, & ctx. repo. id, { 695 let ( blob, attr_lang, is_lfs) = git_read ( state, & ctx. repo. id, { 696 let rev = rev. clone ( ) ; 696 let rev = rev. clone ( ) ; 697 let path = path. clone ( ) ; 697 let path = path. clone ( ) ; 698 move |repo| { 698 move |repo| { 699 let blob = repo. blob ( & rev, FsPath :: new ( & path) ) ?; 699 let blob = repo. blob ( & rev, FsPath :: new ( & path) ) ?; 700 let attrs = repo. attributes_set ( & rev. oid) . ok ( ) ; 700 let attrs = repo. attributes_set ( & rev. oid) . ok ( ) ; 701 let lang = attrs. and_then ( |set| set. attributes ( & path) . language ( ) . map ( str:: to_string) ) ; 701 let resolved = attrs. map ( |set| set. attributes ( & path) ) ; 702 Ok ( ( blob, lang) ) 702 let lang = resolved 703 . as_ref ( ) 704 . and_then ( |a| a. language ( ) . map ( str:: to_string) ) ; 705 let is_lfs = resolved. as_ref ( ) . is_some_and ( git:: Attributes :: is_lfs) 706 || ( blob. size < 1024 707 && blob 708 . content 709 . starts_with ( b"version https://git-lfs.github.com/spec/v1" ) ) ; 710 Ok ( ( blob, lang, is_lfs) ) 703 } 711 } 704 } ) 712 } ) 705 . await ?; 713 . await ?; 710 & path, 718 & path, 711 & blob, 719 & blob, 712 attr_lang. as_deref ( ) , 720 attr_lang. as_deref ( ) , 721 is_lfs, 713 source_view, 722 source_view, 714 ) ; 723 ) ; 715 724 778 path : & str , 787 path : & str , 779 blob : & git:: Blob , 788 blob : & git:: Blob , 780 attr_lang : Option < & str > , 789 attr_lang : Option < & str > , 790 is_lfs : bool , 781 source_view : bool , 791 source_view : bool , 782 ) -> Markup { 792 ) -> Markup { 783 let base = format ! ( "/{}/{}" , ctx. owner. username, ctx. repo. path) ; 793 let base = format ! ( "/{}/{}" , ctx. owner. username, ctx. repo. path) ; 790 html ! { 800 html ! { 791 div class="blob-header" { 801 div class="blob-header" { 792 span class="muted" { ( blob. size) " bytes" } 802 span class="muted" { ( blob. size) " bytes" } 803 @if is_lfs { span class="badge lfs-pill" { "LFS" } } 793 div class="blob-actions" { 804 div class="blob-actions" { 794 @if previewable { 805 @if previewable { 795 a class=( toggle_class ( show_preview) ) href=( blob_url. clone ( ) ) { "Preview" } 806 a class=( toggle_class ( show_preview) ) href=( blob_url. clone ( ) ) { "Preview" } 802 } 813 } 803 } 814 } 804 @if is_image ( filename) { 815 @if is_image ( filename) { 805 p { img src=( raw_url) alt=( filename) style="max-width:100%" ; } 816 div class="blob-image" { img src=( raw_url) alt=( filename) ; } 806 } @else if blob. is_binary { 817 } @else if blob. is_binary { 807 div class="card" { 818 div class="card" { 808 p class="muted" { "Binary file not shown." } 819 p class="muted" { "Binary file not shown." }