Diff

Differences From Artifact [3cd77a5342]:

To Artifact [d0837729e0]:


   457    457   
   458    458   				if {[info exists pathinfo(package)] && [info exists pathinfo(hostname)] && [info exists pathinfo(file)]} {
   459    459   					set dir [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)]
   460    460   					foreach file [glob -nocomplain -tails -directory $dir -types {d f l} {{.,}*}] {
   461    461   						if {$file == "." || $file == ".."} {
   462    462   							continue
   463    463   						}
          464  +
          465  +						if {[string match "*.APPFS.WHITEOUT" $file]} {
          466  +							set remove [string range $file 0 end-15]
          467  +							set idx [lsearch -exact $retval $remove]
          468  +							if {$idx != -1} {
          469  +								set retval [lreplace $retval $idx $idx]
          470  +							}
          471  +							continue
          472  +						}
   464    473   
   465    474   						if {[lsearch -exact $retval $file] != -1} {
   466    475   							continue
   467    476   						}
   468    477   
   469    478   						lappend retval $file
   470    479   					}
................................................................................
   527    536   					if {[info exists pathinfo(package_sha1)] && $pathinfo(package_sha1) != ""} {
   528    537   						set retval(type) directory
   529    538   						set retval(childcount) 2;
   530    539   					}
   531    540   				}
   532    541   			}
   533    542   			"files" {
   534         -
   535    543   				set retval(packaged) 1
   536    544   
   537    545   				set localpath [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)]
   538    546   
   539    547   				set retval(localpath) $localpath
   540    548   
   541         -				if {[file exists $localpath]} {
   542         -					catch {
   543         -						file lstat $localpath localpathinfo
   544         -						set retval(time) $localpathinfo(mtime)
   545         -
   546         -						switch -- $localpathinfo(type) {
   547         -							"directory" {
   548         -								set retval(type) "directory"
   549         -								set retval(childcount) 2
   550         -							}
   551         -							"file" {
   552         -								set retval(type) "file"
   553         -								set retval(size) $localpathinfo(size)
   554         -								if {[file executable $localpath]} {
   555         -									set retval(perms) "x"
   556         -								} else {
   557         -									set retval(perms) ""
          549  +				if {![file exists "${localpath}.APPFS.WHITEOUT"]} {
          550  +					if {[file exists $localpath]} {
          551  +						set retval(is_localfile) 1
          552  +						catch {
          553  +							file lstat $localpath localpathinfo
          554  +							set retval(time) $localpathinfo(mtime)
          555  +
          556  +							switch -- $localpathinfo(type) {
          557  +								"directory" {
          558  +									set retval(type) "directory"
          559  +									set retval(childcount) 2
          560  +								}
          561  +								"file" {
          562  +									set retval(type) "file"
          563  +									set retval(size) $localpathinfo(size)
          564  +									if {[file executable $localpath]} {
          565  +										set retval(perms) "x"
          566  +									} else {
          567  +										set retval(perms) ""
          568  +									}
          569  +								}
          570  +								"link" {
          571  +									set retval(type) "symlink"
          572  +									set retval(source) [file readlink $localpath]
   558    573   								}
   559    574   							}
   560         -							"link" {
   561         -								set retval(type) "symlink"
   562         -								set retval(source) [file readlink $localpath]
   563         -							}
   564         -						}
   565         -					} err
   566         -				} else {
   567         -					set work [split $pathinfo(file) "/"]
   568         -					set directory [join [lrange $work 0 end-1] "/"]
   569         -					set file [lindex $work end]
   570         -					::appfs::db eval {SELECT type, time, source, size, perms FROM files WHERE package_sha1 = $pathinfo(package_sha1) AND file_directory = $directory AND file_name = $file;} retval {}
   571         -					unset -nocomplain retval(*)
          575  +						} err
          576  +					} else {
          577  +						set retval(is_remotefile) 1
          578  +
          579  +						set work [split $pathinfo(file) "/"]
          580  +						set directory [join [lrange $work 0 end-1] "/"]
          581  +						set file [lindex $work end]
          582  +						::appfs::db eval {SELECT type, time, source, size, perms FROM files WHERE package_sha1 = $pathinfo(package_sha1) AND file_directory = $directory AND file_name = $file;} retval {}
          583  +						unset -nocomplain retval(*)
          584  +					}
   572    585   				}
   573    586   
   574    587   			}
   575    588   		}
   576    589   
   577    590   		if {![info exists retval(type)]} {
   578    591   			return -code error "No such file or directory"
................................................................................
   586    599   
   587    600   		if {$pathinfo(_type) != "files"} {
   588    601   			return -code error "invalid type"
   589    602   		}
   590    603   
   591    604   		set localpath [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)]
   592    605   
   593         -		if {[file exists $localpath]} {
          606  +		if {$mode == "create"} {
          607  +			file delete -- "${localpath}.APPFS.WHITEOUT"
          608  +
   594    609   			return $localpath
   595    610   		}
   596    611   
   597         -		if {$mode == "create"} {
          612  +		if {[file exists $localpath]} {
   598    613   			return $localpath
   599    614   		}
   600    615   
   601    616   		set work [split $pathinfo(file) "/"]
   602    617   		set directory [join [lrange $work 0 end-1] "/"]
   603    618   		set file [lindex $work end]
   604    619   		::appfs::db eval {SELECT file_sha1, perms FROM files WHERE package_sha1 = $pathinfo(package_sha1) AND file_name = $file AND file_directory = $directory;} pkgpathinfo {}
................................................................................
   665    680   		set dirname [file dirname $filename]
   666    681   
   667    682   		file mkdir $dirname
   668    683   
   669    684   		return $filename
   670    685   	}
   671    686   
   672         -	proc prepare_to_create {path} {
   673         -		if {[exists $path] != ""} {
   674         -			return -code error "File already exists"
   675         -		}
   676         -
   677         -		set filename [openpath $path "create"]
   678         -
   679         -		set dirname [file dirname $filename]
   680         -
   681         -		file mkdir $dirname
   682         -
   683         -		return $filename
   684         -	}
   685         -
   686    687   	proc localpath {path} {
   687    688   		array set pathinfo [_parsepath $path]
   688    689   
   689    690   		if {$pathinfo(_type) != "files"} {
   690    691   			return -code error "invalid type"
   691    692   		}
   692    693   
   693    694   		set localpath [_localpath $pathinfo(package) $pathinfo(hostname) $pathinfo(file)]
   694    695   
   695    696   		return $localpath
   696    697   	}
          698  +
          699  +	proc _delete_files_except_whiteout {path} {
          700  +		foreach file [glob -nocomplain -directory $path {{.,}*}] {
          701  +			if {[string match "*/.." $file] || [string match "*/." $file]} {
          702  +				continue
          703  +			}
          704  +
          705  +			if {[file isdirectory $file]} {
          706  +				_delete_files_except_whiteout $file
          707  +			}
          708  +
          709  +			if {[string match "*.APPFS.WHITEOUT" $file]} {
          710  +				continue
          711  +			}
          712  +
          713  +			catch {
          714  +				file delete -- $file
          715  +			}
          716  +		}
          717  +	}
          718  +
          719  +	proc unlinkpath {path} {
          720  +		array set pathattrs [exists $path]
          721  +
          722  +		if {![info exists pathattrs(packaged)]} {
          723  +			return -code error "invalid type"
          724  +		}
          725  +
          726  +		set localpath $pathattrs(localpath)
          727  +
          728  +		set whiteout 0
          729  +		set isdirectory 0
          730  +		if {[info exists pathattrs(is_localfile)]} {
          731  +			if {[file isdirectory $localpath]} {
          732  +				set isdirectory 1
          733  +				set whiteout 1
          734  +				_delete_files_except_whiteout $localpath
          735  +			} else {
          736  +				file delete -force -- $localpath
          737  +			}
          738  +		} elseif {[info exists pathattrs(is_remotefile)]} {
          739  +			if {$pathattrs(type) == "directory"} {
          740  +				set isdirectory 1
          741  +			}
          742  +
          743  +			set whiteout 1
          744  +		} else {
          745  +			return -code error "Unknown if file is remote or local !?"
          746  +		}
          747  +
          748  +		if {$isdirectory} {
          749  +			set children [getchildren $path]
          750  +			if {$children != [list]} {
          751  +				return -code error "Asked to delete non-empty directory"
          752  +			}
          753  +		}
          754  +
          755  +		if {$whiteout} {
          756  +			set whiteoutfile "${localpath}.APPFS.WHITEOUT"
          757  +			set whiteoutdir [file dirname $whiteoutfile]
          758  +			file mkdir $whiteoutdir
          759  +			close [open $whiteoutfile w]
          760  +		}
          761  +	}
   697    762   }