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{}