file_info.go - afero - [fork] go afero port for 9front
 (HTM) git clone https://git.drkhsh.at/afero.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       file_info.go (3487B)
       ---
            1 // Copyright © 2021 Vasily Ovchinnikov <vasily@remerge.io>.
            2 //
            3 // The code in this file is derived from afero fork github.com/Zatte/afero by Mikael Rapp
            4 // licensed under Apache License 2.0.
            5 //
            6 // Licensed under the Apache License, Version 2.0 (the "License");
            7 // you may not use this file except in compliance with the License.
            8 // You may obtain a copy of the License at
            9 // http://www.apache.org/licenses/LICENSE-2.0
           10 //
           11 // Unless required by applicable law or agreed to in writing, software
           12 // distributed under the License is distributed on an "AS IS" BASIS,
           13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           14 // See the License for the specific language governing permissions and
           15 // limitations under the License.
           16 
           17 package gcsfs
           18 
           19 import (
           20         "os"
           21         "path/filepath"
           22         "strings"
           23         "time"
           24 
           25         "cloud.google.com/go/storage"
           26 )
           27 
           28 const (
           29         folderSize = 42
           30 )
           31 
           32 type FileInfo struct {
           33         name     string
           34         size     int64
           35         updated  time.Time
           36         isDir    bool
           37         fileMode os.FileMode
           38 }
           39 
           40 func newFileInfo(name string, fs *Fs, fileMode os.FileMode) (*FileInfo, error) {
           41         res := &FileInfo{
           42                 name:     name,
           43                 size:     folderSize,
           44                 updated:  time.Time{},
           45                 isDir:    false,
           46                 fileMode: fileMode,
           47         }
           48 
           49         obj, err := fs.getObj(name)
           50         if err != nil {
           51                 return nil, err
           52         }
           53 
           54         objAttrs, err := obj.Attrs(fs.ctx)
           55         if err != nil {
           56                 if err.Error() == ErrEmptyObjectName.Error() {
           57                         // It's a root folder here, we return right away
           58                         res.name = fs.ensureTrailingSeparator(res.name)
           59                         res.isDir = true
           60                         return res, nil
           61                 } else if err.Error() == ErrObjectDoesNotExist.Error() {
           62                         // Folders do not actually "exist" in GCloud, so we have to check, if something exists with
           63                         // such a prefix
           64                         bucketName, bucketPath := fs.splitName(name)
           65                         it := fs.client.Bucket(bucketName).Objects(
           66                                 fs.ctx, &storage.Query{Delimiter: fs.separator, Prefix: bucketPath, Versions: false})
           67                         if _, err = it.Next(); err == nil {
           68                                 res.name = fs.ensureTrailingSeparator(res.name)
           69                                 res.isDir = true
           70                                 return res, nil
           71                         }
           72 
           73                         return nil, ErrFileNotFound
           74                 }
           75                 return nil, err
           76         }
           77 
           78         res.size = objAttrs.Size
           79         res.updated = objAttrs.Updated
           80 
           81         return res, nil
           82 }
           83 
           84 func newFileInfoFromAttrs(objAttrs *storage.ObjectAttrs, fileMode os.FileMode) *FileInfo {
           85         res := &FileInfo{
           86                 name:     objAttrs.Name,
           87                 size:     objAttrs.Size,
           88                 updated:  objAttrs.Updated,
           89                 isDir:    false,
           90                 fileMode: fileMode,
           91         }
           92 
           93         if res.name == "" {
           94                 if objAttrs.Prefix != "" {
           95                         // It's a virtual folder! It does not have a name, but prefix - this is how GCS API
           96                         // deals with them at the moment
           97                         res.name = objAttrs.Prefix
           98                         res.size = folderSize
           99                         res.isDir = true
          100                 }
          101         }
          102 
          103         return res
          104 }
          105 
          106 func (fi *FileInfo) Name() string {
          107         return filepath.Base(filepath.FromSlash(fi.name))
          108 }
          109 
          110 func (fi *FileInfo) Size() int64 {
          111         return fi.size
          112 }
          113 
          114 func (fi *FileInfo) Mode() os.FileMode {
          115         if fi.IsDir() {
          116                 return os.ModeDir | fi.fileMode
          117         }
          118         return fi.fileMode
          119 }
          120 
          121 func (fi *FileInfo) ModTime() time.Time {
          122         return fi.updated
          123 }
          124 
          125 func (fi *FileInfo) IsDir() bool {
          126         return fi.isDir
          127 }
          128 
          129 func (fi *FileInfo) Sys() interface{} {
          130         return nil
          131 }
          132 
          133 type ByName []*FileInfo
          134 
          135 func (a ByName) Len() int { return len(a) }
          136 func (a ByName) Swap(i, j int) {
          137         a[i].name, a[j].name = a[j].name, a[i].name
          138         a[i].size, a[j].size = a[j].size, a[i].size
          139         a[i].updated, a[j].updated = a[j].updated, a[i].updated
          140         a[i].isDir, a[j].isDir = a[j].isDir, a[i].isDir
          141 }
          142 func (a ByName) Less(i, j int) bool { return strings.Compare(a[i].Name(), a[j].Name()) == -1 }