1""" 2 3davcmd.py 4--------- 5 6containts commands like copy, move, delete for normal 7resources and collections 8 9""" 10 11from string import split,replace,joinfields 12import urlparse 13 14from utils import create_treelist, is_prefix 15from errors import * 16 17def deltree(dc,uri,exclude={}): 18 """ delete a tree of resources 19 20 dc -- dataclass to use 21 uri -- root uri to delete 22 exclude -- an optional list of uri:error_code pairs which should not 23 be deleted. 24 25 returns dict of uri:error_code tuples from which 26 another method can create a multistatus xml element. 27 28 Also note that we only know Depth=infinity thus we don't have 29 to test for it. 30 31 """ 32 33 tlist=create_treelist(dc,uri) 34 result={} 35 36 for i in range(len(tlist),0,-1): 37 problem_uris=result.keys() 38 element=tlist[i-1] 39 40 # test here, if an element is a prefix of an uri which 41 # generated an error before. 42 # note that we walk here from childs to parents, thus 43 # we cannot delete a parent if a child made a problem. 44 # (see example in 8.6.2.1) 45 ok=1 46 for p in problem_uris: 47 if is_prefix(element,p): 48 ok=None 49 break 50 51 if not ok: continue 52 53 # here we test for the exclude list which is the other way round! 54 for p in exclude.keys(): 55 if is_prefix(p,element): 56 ok=None 57 break 58 59 if not ok: continue 60 61 # now delete stuff 62 try: 63 delone(dc,element) 64 except DAV_Error, (ec,dd): 65 result[element]=ec 66 67 return result 68 69def delone(dc,uri): 70 """ delete a single object """ 71 if dc.is_collection(uri): 72 return dc.rmcol(uri) # should be empty 73 else: 74 return dc.rm(uri) 75 76### 77### COPY 78### 79 80# helper function 81 82def copy(dc,src,dst): 83 """ only copy the element 84 85 This is just a helper method factored out from copy and 86 copytree. It will not handle the overwrite or depth header. 87 88 """ 89 90 # destination should have been deleted before 91 if dc.exists(dst): 92 raise DAV_Error, 412 93 94 # source should exist also 95 if not dc.exists(src): 96 raise DAV_NotFound 97 98 if dc.is_collection(src): 99 dc.copycol(src, dst) # an exception will be passed thru 100 else: 101 dc.copy(src, dst) # an exception will be passed thru 102 103# the main functions 104 105def copyone(dc,src,dst,overwrite=None): 106 """ copy one resource to a new destination """ 107 108 if overwrite and dc.exists(dst): 109 delres = deltree(dc, dst) 110 else: 111 delres={} 112 113 # if we cannot delete everything, then do not copy! 114 if delres: 115 return delres 116 117 try: 118 copy(dc, src, dst) # pass thru exceptions 119 except DAV_Error, (ec, dd): 120 return ec 121 122def copytree(dc,src,dst,overwrite=None): 123 """ copy a tree of resources to another location 124 125 dc -- dataclass to use 126 src -- src uri from where to copy 127 dst -- dst uri 128 overwrite -- if 1 then delete dst uri before 129 130 returns dict of uri:error_code tuples from which 131 another method can create a multistatus xml element. 132 133 """ 134 135 # first delete the destination resource 136 if overwrite and dc.exists(dst): 137 delres=deltree(dc,dst) 138 else: 139 delres={} 140 141 # if we cannot delete everything, then do not copy! 142 if delres: 143 return delres 144 145 # get the tree we have to copy 146 tlist = create_treelist(dc,src) 147 result = {} 148 149 # prepare destination URIs (get the prefix) 150 dpath = urlparse.urlparse(dst)[2] 151 152 for element in tlist: 153 problem_uris = result.keys() 154 155 # now URIs get longer and longer thus we have 156 # to test if we had a parent URI which we were not 157 # able to copy in problem_uris which is the prefix 158 # of the actual element. If it is, then we cannot 159 # copy this as well but do not generate another error. 160 ok=1 161 for p in problem_uris: 162 if is_prefix(p,element): 163 ok=None 164 break 165 166 if not ok: continue 167 168 # now create the destination URI which corresponds to 169 # the actual source URI. -> actual_dst 170 # ("subtract" the base src from the URI and prepend the 171 # dst prefix to it.) 172 esrc=replace(element,src,"") 173 actual_dst=dpath+esrc 174 175 # now copy stuff 176 try: 177 copy(dc,element,actual_dst) 178 except DAV_Error, (ec,dd): 179 result[element]=ec 180 181 return result 182 183 184### 185### MOVE 186### 187 188 189def moveone(dc,src,dst,overwrite=None): 190 """ move a single resource 191 192 This is done by first copying it and then deleting 193 the original. 194 """ 195 196 # first copy it 197 copyone(dc, src, dst, overwrite) 198 199 # then delete it 200 dc.rm(src) 201 202def movetree(dc,src,dst,overwrite=None): 203 """ move a collection 204 205 This is done by first copying it and then deleting 206 the original. 207 208 PROBLEM: if something did not copy then we have a problem 209 when deleting as the original might get deleted! 210 """ 211 212 # first copy it 213 res = copytree(dc,src,dst,overwrite) 214 215 # then delete it 216 res = deltree(dc,src,exclude=res) 217 218 return res 219 220