github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/vfs/fsck.go (about) 1 package vfs 2 3 import ( 4 "fmt" 5 6 "github.com/cozy/cozy-stack/pkg/couchdb" 7 ) 8 9 // FsckLogType is the type of a FsckLog 10 type FsckLogType string 11 12 const ( 13 // IndexMissingRoot is used when the index does not have a root object 14 IndexMissingRoot FsckLogType = "index_missing_root" 15 // IndexMissingTrash is used when the index does not have a trash folder 16 IndexMissingTrash FsckLogType = "index_missing_trash" 17 // IndexOrphanTree used when a part of the tree is detached from the main 18 // root of the index. 19 IndexOrphanTree FsckLogType = "index_orphan_tree" 20 // IndexBadFullpath used when a directory does not have the correct path 21 // field given its position in the index. 22 IndexBadFullpath FsckLogType = "index_bad_fullpath" 23 // FSMissing used when a file data is missing on the filesystem from its 24 // index entry. 25 FSMissing FsckLogType = "filesystem_missing" 26 // IndexMissing is used when the index entry is missing from a file data. 27 IndexMissing FsckLogType = "index_missing" 28 // TypeMismatch is used when a document type does not match in the index and 29 // underlying filesystem. 30 TypeMismatch FsckLogType = "type_mismatch" 31 // ContentMismatch is used when a document content checksum does not match 32 // with the one in the underlying fs. 33 ContentMismatch FsckLogType = "content_mismatch" 34 // FileMissing is used when a version is present for a file that is not in 35 // the index. 36 FileMissing FsckLogType = "file_missing" 37 // IndexFileWithPath is used when a file has a path in the index (only 38 // directories should have one). 39 IndexFileWithPath = "index_file_with_path" 40 // IndexDuplicateName is used when two files or directories have the same 41 // name inside the same folder (ie they have the same path). 42 IndexDuplicateName = "index_duplicate_name" 43 // TrashedNotInTrash is used when a file has trashed: true but its parent 44 // directory is not the trash, not is in the trash. 45 TrashedNotInTrash = "trashed_not_in_trash" 46 // NotTrashedInTrash is used when a file has trashed: false but its parent 47 // directory is the trash or a directory in the trash. 48 NotTrashedInTrash = "not_trashed_in_trash" 49 // ConflictInIndex is used when there is a conflict in CouchDB with 2 50 // branches of revisions. 51 ConflictInIndex = "conflict_in_index" 52 // ThumbnailWithNoFile is used when there is a thumbnail but not the file 53 // that was used to create it. 54 ThumbnailWithNoFile = "thumbnail_with_no_file" 55 ) 56 57 // FsckLog is a struct for an inconsistency in the VFS 58 type FsckLog struct { 59 Type FsckLogType `json:"type"` 60 FileDoc *TreeFile `json:"file_doc,omitempty"` 61 DirDoc *TreeFile `json:"dir_doc,omitempty"` 62 VersionDoc *Version `json:"version_doc,omitempty"` 63 IsFile bool `json:"is_file"` 64 IsVersion bool `json:"is_version"` 65 ContentMismatch *FsckContentMismatch `json:"content_mismatch,omitempty"` 66 ExpectedFullpath string `json:"expected_fullpath,omitempty"` 67 } 68 69 // String returns a string describing the FsckLog 70 func (f *FsckLog) String() string { 71 switch f.Type { 72 case IndexMissingRoot: 73 return "the root directory is not present in the index" 74 case IndexMissingTrash: 75 return "the trash directory is not present in the index" 76 case IndexOrphanTree: 77 if f.IsFile { 78 return "the file's parent is missing from the index: orphan file" 79 } 80 return "the directory's parent is missing from the index: orphan tree" 81 case IndexBadFullpath: 82 return "the directory does not have the correct path information given its position in the index" 83 case FSMissing: 84 if f.IsFile { 85 return "the file is present in the index but not on the filesystem" 86 } 87 return "the directory is present in the index but not on the filesystem" 88 case IndexMissing: 89 return "the document is present on the local filesystem but not in the index" 90 case TypeMismatch: 91 if f.IsFile { 92 return "it's a file in the index but a directory on the filesystem" 93 } 94 return "it's a directory in the index but a file on the filesystem" 95 case ContentMismatch: 96 return "the document content does not match the store content checksum" 97 case FileMissing: 98 return "the document is a version whose file is not present in the index" 99 case IndexFileWithPath: 100 return "the file document in CouchDB has a path field" 101 case IndexDuplicateName: 102 return "two documents have the same name inside the same folder" 103 case TrashedNotInTrash: 104 return "a file document has trashed set to true but its parent is not in the trash" 105 case NotTrashedInTrash: 106 return "a file document has trashed set tot false but its parent is in the trash" 107 case ConflictInIndex: 108 return "this document has a conflict in CouchDB between two branches of revisions" 109 case ThumbnailWithNoFile: 110 return "a thumbnail exists but its original file has been removed" 111 } 112 panic(fmt.Sprintf("bad FsckLog type: %#v", f)) 113 } 114 115 // FsckContentMismatch is a struct used by the FSCK where CouchDB and Swift 116 // haven't the same information about a file content (md5sum and size). 117 type FsckContentMismatch struct { 118 SizeIndex int64 `json:"size_index"` 119 SizeFile int64 `json:"size_file"` 120 MD5SumIndex []byte `json:"md5sum_index"` 121 MD5SumFile []byte `json:"md5sum_file"` 122 } 123 124 // Tree is returned by the BuildTree method on the indexes. It contains a 125 // pointer to the root element of the tree, a map of directories indexed by 126 // their ID, and a map of a potential list of orphan file or directories 127 // indexed by their DirID. 128 type Tree struct { 129 Root *TreeFile 130 DirsMap map[string]*TreeFile 131 Orphans map[string][]*TreeFile 132 Files map[string]struct{} 133 } 134 135 // TreeFile represent a subset of a file/directory structure that can be used 136 // in a tree-like representation of the index. 137 type TreeFile struct { 138 DirOrFileDoc 139 FilesChildren []*TreeFile `json:"children,omitempty"` 140 FilesChildrenSize int64 `json:"children_size,omitempty"` 141 DirsChildren []*TreeFile `json:"directories,omitempty"` 142 143 IsDir bool `json:"is_dir"` 144 IsOrphan bool `json:"is_orphan"` 145 HasCycle bool `json:"has_cycle"` 146 HasPath bool `json:"-"` 147 } 148 149 // AsFile returns the FileDoc part from this more complex struct 150 func (t *TreeFile) AsFile() *FileDoc { 151 if t.IsDir { 152 panic("calling AsFile on a directory") 153 } 154 _, fileDoc := t.DirOrFileDoc.Refine() 155 return fileDoc 156 } 157 158 // AsDir returns the DirDoc part from this more complex struct 159 func (t *TreeFile) AsDir() *DirDoc { 160 if !t.IsDir { 161 panic("calling AsDir on a file") 162 } 163 return t.DirDoc.Clone().(*DirDoc) 164 } 165 166 // Clone is part of the couchdb.Doc interface 167 func (t *TreeFile) Clone() couchdb.Doc { 168 panic("TreeFile must not be cloned") 169 } 170 171 var _ couchdb.Doc = &TreeFile{}