|
| 1 | +// Copyright (C)2024 LordOfScripts |
| 2 | + |
| 3 | + |
| 4 | +Package bucketfs implements a Bit-Bucket Virtual File System which serves as |
| 5 | +a hybrid bridge between vfs/dummy and vfs/memfs. It is much more suitable for |
| 6 | +testing as well as for implementing Dry-Run capabilities than the default |
| 7 | +DummyFS implementation. |
| 8 | + |
| 9 | +# Use Case(s) |
| 10 | + |
| 11 | +Let's say you wrote an application like WipeChromium which helps cleaning up |
| 12 | +the immense amounts of information your Internet browser keeps. This is |
| 13 | +information that not only occupies a lot of space (and grows uncontrollably) |
| 14 | +but also may contain privacy-sensitive information. |
| 15 | + |
| 16 | +During development you may have introduced bugs, imagine what would happen |
| 17 | +if suddently due to a typo your application wipes out your entire HOME directory! |
| 18 | +It is disastrous, right? |
| 19 | + |
| 20 | +Or perhaps it is already well tested (deployment phase) but your end-user may |
| 21 | +not be confident about what the application would do in his/her system or |
| 22 | +her/his setup. Maybe they would feel at ease by first doing a Dry Run and see |
| 23 | +console notifications about each of those sensitive filesystem operations like |
| 24 | +Remove, RemoveAll, Mkdir, Rename, Symlink, ReadDir, etc. |
| 25 | + |
| 26 | +## Advantages over DummyFS |
| 27 | + |
| 28 | +The default DummyFS operates by throwing a user-specified error (or nil) on |
| 29 | +every single operation. The filesystem itself does nothing else, not traceability. |
| 30 | +The DummyFS does not fulfill the use case requirements. |
| 31 | + |
| 32 | +* Is aware of Symbolic links, files & directories. |
| 33 | + |
| 34 | +## Advantages over MemFS |
| 35 | + |
| 36 | +With MemFS you have to replicate into memory. Each of those files and directories |
| 37 | +may occupy significant space in memory. Now, I run on a Raspberry Pi with only |
| 38 | +1GB of RAM, it is important to me. |
| 39 | + |
| 40 | +Sometimes you only need to state that the filesystem object is there without |
| 41 | +actually storing any data other than the name. The MemFS is an overkill for |
| 42 | +the use case above. |
| 43 | + |
| 44 | +# How it Works |
| 45 | + |
| 46 | +As stated above, the BitBucketFS is a hybrid between a simplistic DummyFS and |
| 47 | +a quite functional MemFS. This filesystem informs you what it is doing and |
| 48 | +has the capability of pretending everything is fine, or being selective about |
| 49 | +what is fine or not. It has two modes of operation: Silent & Hybrid. |
| 50 | + |
| 51 | +## Silent Mode |
| 52 | + |
| 53 | +In Silent Mode any supported filesystem operation would result in an informational |
| 54 | +message printed on the console without producing any error whatsoever, regardless |
| 55 | +of whether the filesystem object (file or directory) exists or not. You create |
| 56 | +a VFS in Silent Mode like this: |
| 57 | + |
| 58 | + fs := bucketfs.Create() |
| 59 | + fs.Remove("/home/Documents") |
| 60 | + |
| 61 | +And an operation like the one we used after creation will print: |
| 62 | + |
| 63 | + ⚡ Remove /home/Documents |
| 64 | + |
| 65 | +But your precious directory is still there! All operations in this mode do just |
| 66 | +that, they print an informational message and pretend all is good. This is |
| 67 | +quite useful for a Dry Run. |
| 68 | + |
| 69 | +In summary, for silent mode ALL operations: |
| 70 | + |
| 71 | + - print the name of the operation and the primary parameter |
| 72 | + - return nil (no error) and possibly a dummy descriptor. |
| 73 | + - on Read*() operations nothing is actually read |
| 74 | + - on Write() operations nothing is actually written, only file size grows. |
| 75 | + - after Close() is called on a file descriptor, nothing is persisted; therefore, |
| 76 | + the size will be zero again. |
| 77 | + |
| 78 | +# Bucket VFS |
| 79 | + |
| 80 | +The *BitBucket Virtual File System* packageded `bucketfs` in |
| 81 | +version `v1.2.0` by LordOfScripts. It makes the Go VFS a very functional suite |
| 82 | +of pure GO Virtual File Systems. |
| 83 | + |
| 84 | +## Hybrid Mode |
| 85 | + |
| 86 | +Maybe you need something approaching more like the real OS but without the |
| 87 | +overhead of MemFS. You create a BitBucketFS in hybrid mode like this: |
| 88 | + |
| 89 | + ErrBadThingHappened := errors.New("Bad thing happened!") |
| 90 | + fs := bucketfs.CreateWithError(ErrBadThingHappened) |
| 91 | + |
| 92 | +Or alternatively, you can do it this way too with fluent API: |
| 93 | + |
| 94 | + ErrBadThingHappened := errors.New("Bad thing happened!") |
| 95 | + fs := bucketfs.Create().WithError(ErrBadThingHappened) |
| 96 | + |
| 97 | +At this point the BitBucket filesystem is empty, it knows no files or directories. |
| 98 | +Therefore any Rename, Remove*, Symlink, Open, ReadDir operation will result in |
| 99 | +either an os.PathError or os.LinkError with a wrapped ErrBadThingHappened. |
| 100 | + |
| 101 | +So, let's say you want it to recognized certain FAKE files and/or directories |
| 102 | +as existent. Internally only a map with these names are stored. |
| 103 | + |
| 104 | + fs.WithDirectories([]string{"/home/.cache", "/home/Documents"}) |
| 105 | + fs.WithFiles([]string{"/home/Documents/test.doc", /home/Documents/test1.txt"}) |
| 106 | + |
| 107 | +Those two methods are also part of the fluent API; therefore you could do |
| 108 | +this too: |
| 109 | + |
| 110 | + ErrBadThingHappened := errors.New("Bad thing happened!") |
| 111 | + fs := bucketfs.Create(). |
| 112 | + WithError(ErrBadThingHappened). |
| 113 | + WithDirectories([]string{...}). |
| 114 | + WithFiles([]string{...}) |
| 115 | + |
| 116 | +Now that we have a BitBucketFS in hybrid mode with a few FAKE files & directories, |
| 117 | +the supported filesystem operations would depend on whether the object exists |
| 118 | +as FAKE. For example: |
| 119 | + |
| 120 | + fs.Mkdir("/home/Downloads") |
| 121 | + |
| 122 | +would NOT produce an error and will add the named directory to the FAKE list. |
| 123 | +However, this other operation: |
| 124 | + |
| 125 | + fs.Mkdir("/home/Documents") |
| 126 | + |
| 127 | +would produce an os.PathError with a wrapped bucketfs.ErrDirExists error. |
| 128 | + |
| 129 | +There are two versions of a BitBucketFS file node: |
| 130 | + |
| 131 | + - Minimal: is only aware whether the node is symbolic link, file or directory |
| 132 | + - Functional: is fully aware of the os.FileMode including (but not enforced) |
| 133 | + (Unix) permissions and size. |
0 commit comments