1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2007 Kris Bell. 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: Oct 2007: Initial version 13 14 Authors: Kris 15 16 *******************************************************************************/ 17 18 module ocean.io.vfs.LinkedFolder; 19 20 import ocean.meta.types.Qualifiers; 21 22 import ocean.io.vfs.model.Vfs; 23 24 import ocean.core.ExceptionDefinitions; 25 26 import ocean.io.vfs.VirtualFolder; 27 28 /******************************************************************************* 29 30 LinkedFolder is derived from VirtualFolder, and behaves exactly the 31 same in all but one aspect: it treats mounted folders as an ordered 32 list of alternatives to look for a file. This supports the notion of 33 file 'overrides', whereby "customized" files can be inserted into a 34 chain of alternatives. 35 36 (Overridden folders are not currently supported.) 37 38 *******************************************************************************/ 39 40 41 class LinkedFolder : VirtualFolder 42 { 43 private Link* head; 44 45 /*********************************************************************** 46 47 Linked-list of folders. 48 49 ***********************************************************************/ 50 51 private struct Link 52 { 53 Link* next; 54 VfsFolder folder; 55 56 static Link* opCall(VfsFolder folder) 57 { 58 auto p = new Link; 59 p.folder = folder; 60 return p; 61 } 62 } 63 64 /*********************************************************************** 65 66 All folder must have a name. No '.' or '/' chars are 67 permitted. 68 69 ***********************************************************************/ 70 71 this (istring name) 72 { 73 super (name); 74 } 75 76 /*********************************************************************** 77 78 Add a child folder. The child cannot 'overlap' with others 79 in the tree of the same type. Circular references across a 80 tree of virtual folders are detected and trapped. 81 82 We add the new child at the end of an ordered list, which 83 we subsequently traverse when looking up a file. 84 85 The second argument represents an optional name that the 86 mount should be known as, instead of the name exposed by 87 the provided folder (it is not an alias). 88 89 ***********************************************************************/ 90 91 final override VfsHost mount (VfsFolder folder, istring name=null) 92 { 93 // traverse to the end of the list 94 auto link = &head; 95 while (*link) 96 link = &(*link).next; 97 98 // hook up the new folder 99 *link = Link (folder); 100 101 // and let superclass deal with it 102 return super.mount (folder, name); 103 } 104 105 /*********************************************************************** 106 107 TODO: Unhook a child folder. 108 109 ***********************************************************************/ 110 111 final override VfsHost dismount (VfsFolder folder) 112 { 113 assert (0, "LinkedFolder.dismount not implemented"); 114 } 115 116 /*********************************************************************** 117 118 Return a file representation of the given path. If the 119 path-head does not refer to an immediate child folder, 120 and does not match a symbolic link, it is considered to 121 be unknown. 122 123 We scan the set of mounted folders, in the order mounted, 124 looking for a match. Where one is found, we test to see 125 that it really exists before returning the reference. 126 127 ***********************************************************************/ 128 129 final override VfsFile file (istring path) 130 { 131 auto link = head; 132 while (link) 133 { 134 //Stdout.formatln ("looking in {}", link.folder.toString); 135 try { 136 auto file = link.folder.file (path); 137 if (file.exists) 138 return file; 139 } catch (VfsException x) {} 140 link = link.next; 141 } 142 super.error ("file '"~path~"' not found"); 143 return null; 144 } 145 } 146 147 148 debug (LinkedFolder) 149 { 150 /******************************************************************************* 151 152 *******************************************************************************/ 153 154 import ocean.io.Stdout; 155 import ocean.io.vfs.FileFolder; 156 157 void main() 158 { 159 auto root = new LinkedFolder ("root"); 160 auto sub = new VirtualFolder ("sub"); 161 sub.mount (new FileFolder (r"d:/d/import/temp")); 162 sub.map (sub.file(r"temp/subtree/test.txt"), "wumpus"); 163 164 root.mount (new FileFolder (r"d:/d/import/tango")) 165 .mount (new FileFolder (r"c:/"), "windows"); 166 root.mount (sub); 167 168 auto file = root.file (r"wumpus"); 169 Stdout.formatln ("file = {}", file); 170 } 171 }