mirror of
https://github.com/ScoopInstaller/Scoop.git
synced 2025-10-30 06:07:56 +00:00
Compare commits
3 Commits
9a6cdc7328
...
persistenc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2f1e8eeb1 | ||
|
|
2bcf54422a | ||
|
|
2f850502e8 |
42
lib/core.ps1
42
lib/core.ps1
@@ -285,7 +285,47 @@ function isFileLocked([string]$path) {
|
||||
}
|
||||
|
||||
function is_directory([String] $path) {
|
||||
return (Test-Path $path) -and (Get-Item $path) -is [System.IO.DirectoryInfo]
|
||||
return (Test-Path $path) -and (Get-Item -Path $path) -is [System.IO.DirectoryInfo]
|
||||
}
|
||||
|
||||
function is_junction([String] $path) {
|
||||
return (Test-Path $path) -and (Get-Item -Path $path).LinkType -eq 'Junction'
|
||||
}
|
||||
|
||||
function create_junction([String] $link, [String] $target) {
|
||||
if (!(Test-Path $link) -and (is_directory $target)) {
|
||||
New-Item -ItemType Junction -Path (Split-Path -Path $link) -Name (Split-Path -Leaf $link) -Target $target | Out-Null
|
||||
$dirInfo = New-Object System.IO.DirectoryInfo($link)
|
||||
$dirInfo.Attributes = $dirInfo.Attributes -bor [System.IO.FileAttributes]::ReadOnly
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function remove_junction([String] $link) {
|
||||
if(is_junction $link) {
|
||||
$dirInfo = New-Object System.IO.DirectoryInfo($link)
|
||||
$dirInfo.Attributes = $dirInfo.Attributes -band (-bnot [System.IO.FileAttributes]::ReadOnly)
|
||||
$dirInfo.Delete()
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function create_hardlink([String] $link, [String] $target) {
|
||||
if (!(Test-Path $link) -and (Test-Path $target) -and !(is_directory $target)) {
|
||||
New-Item -ItemType HardLink -Path (Split-Path -Path $link) -Name (Split-Path -Leaf $link) -Target $target | Out-Null
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function remove_hardlink([String] $link) {
|
||||
if ((Test-Path $link) -and !(is_directory $link)) {
|
||||
Remove-Item -Path $link | Out-Null
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function movedir($from, $to) {
|
||||
|
||||
127
lib/install.ps1
127
lib/install.ps1
@@ -927,14 +927,9 @@ function link_current($versiondir) {
|
||||
abort "Error: Version 'current' is not allowed!"
|
||||
}
|
||||
|
||||
if(test-path $currentdir) {
|
||||
# remove the junction
|
||||
attrib -R /L $currentdir
|
||||
& "$env:COMSPEC" /c rmdir $currentdir
|
||||
}
|
||||
|
||||
& "$env:COMSPEC" /c mklink /j $currentdir $versiondir | out-null
|
||||
attrib $currentdir +R /L
|
||||
# recreate new junction
|
||||
remove_junction $currentdir | Out-Null
|
||||
create_junction $currentdir $versiondir | Out-Null
|
||||
return $currentdir
|
||||
}
|
||||
|
||||
@@ -950,11 +945,7 @@ function unlink_current($versiondir) {
|
||||
if(test-path $currentdir) {
|
||||
write-host "Unlinking $(friendly_path $currentdir)"
|
||||
|
||||
# remove read-only attribute on link
|
||||
attrib $currentdir -R /L
|
||||
|
||||
# remove the junction
|
||||
& "$env:COMSPEC" /c "rmdir $currentdir"
|
||||
remove_junction $currentdir | Out-Null
|
||||
return $currentdir
|
||||
}
|
||||
return $versiondir
|
||||
@@ -1144,56 +1135,76 @@ function persist_def($persist) {
|
||||
|
||||
function persist_data($manifest, $original_dir, $persist_dir) {
|
||||
$persist = $manifest.persist
|
||||
if($persist) {
|
||||
$persist_dir = ensure $persist_dir
|
||||
if(!$persist) {
|
||||
return
|
||||
}
|
||||
$persist_dir = ensure $persist_dir
|
||||
|
||||
if ($persist -is [String]) {
|
||||
$persist = @($persist);
|
||||
}
|
||||
if ($persist -is [String]) {
|
||||
persist_data_old $persist $original_dir $persist_dir
|
||||
return
|
||||
}
|
||||
|
||||
if ($persist -is [Array]) {
|
||||
$persist | ForEach-Object {
|
||||
$source, $target = persist_def $_
|
||||
|
||||
write-host "Persisting $source"
|
||||
|
||||
$source = $source.TrimEnd("/").TrimEnd("\\")
|
||||
|
||||
$source = fullpath "$dir\$source"
|
||||
$target = fullpath "$persist_dir\$target"
|
||||
|
||||
# if we have had persist data in the store, just create link and go
|
||||
if (Test-Path $target) {
|
||||
# if there is also a source data, rename it (to keep a original backup)
|
||||
if (Test-Path $source) {
|
||||
Move-Item -Force $source "$source.original"
|
||||
}
|
||||
# we don't have persist data in the store, move the source to target, then create link
|
||||
} elseif (Test-Path $source) {
|
||||
# ensure target parent folder exist
|
||||
$null = ensure (Split-Path -Path $target)
|
||||
Move-Item $source $target
|
||||
# we don't have neither source nor target data! we need to crate an empty target,
|
||||
# but we can't make a judgement that the data should be a file or directory...
|
||||
# so we create a directory by default. to avoid this, use pre_install
|
||||
# to create the source file before persisting (DON'T use post_install)
|
||||
} else {
|
||||
$target = New-Object System.IO.DirectoryInfo($target)
|
||||
ensure $target | Out-Null
|
||||
if($_ -is [Object]) {
|
||||
persist_data_new $_ $original_dir $persist_dir
|
||||
}
|
||||
|
||||
# create link
|
||||
if (is_directory $target) {
|
||||
# target is a directory, create junction
|
||||
& "$env:COMSPEC" /c "mklink /j `"$source`" `"$target`"" | out-null
|
||||
attrib $source +R /L
|
||||
} else {
|
||||
# target is a file, create hard link
|
||||
& "$env:COMSPEC" /c "mklink /h `"$source`" `"$target`"" | out-null
|
||||
if ($_ -is [String]) {
|
||||
persist_data_old $_ $original_dir $persist_dir
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function persist_data_new($persist, $original_dir, $persist_dir) {
|
||||
# TODO
|
||||
}
|
||||
|
||||
function persist_data_old($persist, $original_dir, $persist_dir) {
|
||||
if(!$persist) {
|
||||
return
|
||||
}
|
||||
|
||||
$source, $target = persist_def $persist
|
||||
|
||||
write-host "Persisting $source"
|
||||
|
||||
$source = $source.TrimEnd("/").TrimEnd("\\")
|
||||
|
||||
$source = fullpath "$dir\$source"
|
||||
$target = fullpath "$persist_dir\$target"
|
||||
|
||||
# if we have had persist data in the store, just create link and go
|
||||
if (Test-Path $target) {
|
||||
# if there is also a source data, rename it (to keep a original backup)
|
||||
if (Test-Path $source) {
|
||||
Move-Item -Force $source "$source.original"
|
||||
}
|
||||
# we don't have persist data in the store, move the source to target, then create link
|
||||
} elseif (Test-Path $source) {
|
||||
# ensure target parent folder exist
|
||||
$null = ensure (Split-Path -Path $target)
|
||||
Move-Item $source $target
|
||||
# we don't have neither source nor target data! we need to crate an empty target,
|
||||
# but we can't make a judgement that the data should be a file or directory...
|
||||
# so we create a directory by default. to avoid this, use pre_install
|
||||
# to create the source file before persisting (DON'T use post_install)
|
||||
} else {
|
||||
$target = New-Object System.IO.DirectoryInfo($target)
|
||||
ensure $target | Out-Null
|
||||
}
|
||||
|
||||
# create link
|
||||
if (is_directory $target) {
|
||||
# target is a directory, create junction
|
||||
create_junction $source $target | Out-Null
|
||||
} else {
|
||||
# target is a file, create hard link
|
||||
create_hardlink $source $target | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function unlink_persist_data($dir) {
|
||||
# unlink all junction / hard link in the directory
|
||||
Get-ChildItem -Recurse $dir | ForEach-Object {
|
||||
@@ -1202,13 +1213,9 @@ function unlink_persist_data($dir) {
|
||||
$filepath = $file.FullName
|
||||
# directory (junction)
|
||||
if ($file -is [System.IO.DirectoryInfo]) {
|
||||
# remove read-only attribute on the link
|
||||
attrib -R /L $filepath
|
||||
# remove the junction
|
||||
& "$env:COMSPEC" /c "rmdir /s /q $filepath"
|
||||
remove_junction | Out-Null
|
||||
} else {
|
||||
# remove the hard link
|
||||
& "$env:COMSPEC" /c "del $filepath"
|
||||
remove_hardlink $filepath | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
schema.json
76
schema.json
@@ -202,6 +202,80 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"persist": {
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "Deprecated, use object representation instead.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Deprecated, use object representation instead.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||
},
|
||||
"minItems": 1,
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"minItems": 1,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "file"
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"encoding",
|
||||
"content"
|
||||
]
|
||||
},
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"target": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"file",
|
||||
"directory",
|
||||
"folder"
|
||||
]
|
||||
},
|
||||
"encoding": {
|
||||
"enum": [
|
||||
"utf-8",
|
||||
"ascii",
|
||||
"byte"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"copy",
|
||||
"merge",
|
||||
"link",
|
||||
"update"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"checkver": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -407,7 +481,7 @@
|
||||
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
|
||||
},
|
||||
"persist": {
|
||||
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
|
||||
"$ref": "#/definitions/persist"
|
||||
},
|
||||
"checkver": {
|
||||
"$ref": "#/definitions/checkver"
|
||||
|
||||
@@ -6,21 +6,104 @@
|
||||
$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).directory.parent.FullName
|
||||
$isUnix = is_unix
|
||||
|
||||
describe "is_directory" -Tag 'Scoop' {
|
||||
describe "directory/junction/hardlink handling" -Tag 'Scoop' {
|
||||
beforeall {
|
||||
$working_dir = setup_working "is_directory"
|
||||
}
|
||||
|
||||
it "is_directory recognize directories" {
|
||||
it "is_directory recognizes directories" {
|
||||
is_directory "$working_dir\i_am_a_directory" | should -be $true
|
||||
}
|
||||
it "is_directory recognize files" {
|
||||
|
||||
it "is_directory recognizes files" {
|
||||
is_directory "$working_dir\i_am_a_file.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "is_directory is falsey on unknown path" {
|
||||
is_directory "$working_dir\i_do_not_exist" | should -be $false
|
||||
}
|
||||
|
||||
it "create_junction recognizes directories and creates junction" {
|
||||
create_junction "$working_dir\i_am_a_junction" "$working_dir\i_am_a_directory" | should -be $true
|
||||
Test-Path "$working_dir\i_am_a_junction" | should -be $true
|
||||
}
|
||||
|
||||
it "create_junction recognizes existing target" {
|
||||
create_junction "$working_dir\i_am_a_junction" "$working_dir\i_am_a_directory" | should -be $false
|
||||
}
|
||||
|
||||
it "create_junction recognizes files" {
|
||||
create_junction "$working_dir\i_am_a_junction_file.txt" "$working_dir\i_am_a_file.txt" | should -be $false
|
||||
Test-Path "$working_dir\i_am_a_junction_file.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "create_junction is falsey on unknown path" {
|
||||
create_junction "$working_dir\i_am_a_junction" "$working_dir\i_do_not_exist" | should -be $false
|
||||
}
|
||||
|
||||
it "is_junction recognizes junctions" {
|
||||
is_junction "$working_dir\i_am_a_junction" | should -be $true
|
||||
}
|
||||
|
||||
it "is_junction recognizes directories" {
|
||||
is_junction "$working_dir\i_am_a_directory" | should -be $false
|
||||
}
|
||||
|
||||
it "is_junction recognizes files" {
|
||||
is_junction "$working_dir\i_am_a_file.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "is_junction is falsey on unknown path" {
|
||||
is_junction "$working_dir\i_do_not_exist" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_junction recognizes junctions" {
|
||||
remove_junction "$working_dir\i_am_a_junction" | should -be $true
|
||||
Test-Path "$working_dir\i_am_a_junction" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_junction recognizes directories" {
|
||||
remove_junction "$working_dir\i_am_a_directory" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_junction recognizes files" {
|
||||
remove_junction "$working_dir\i_am_a_file.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_junction is falsey on unknown path" {
|
||||
remove_junction "$working_dir\i_do_not_exist" | should -be $false
|
||||
}
|
||||
|
||||
it "create_hardlink recognizes files and creates hardlink" {
|
||||
create_hardlink "$working_dir\i_am_a_hardlinked_file.txt" "$working_dir\i_am_a_file.txt" | should -be $true
|
||||
Test-Path "$working_dir\i_am_a_hardlinked_file.txt" | should -be $true
|
||||
}
|
||||
|
||||
it "create_hardlink recognizes existing target" {
|
||||
create_hardlink "$working_dir\i_am_a_hardlinked_file.txt" "$working_dir\i_am_a_file.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "create_hardlink recognizes directories" {
|
||||
create_hardlink "$working_dir\i_am_a_hardlinked_directory" "$working_dir\i_am_a_directory" | should -be $false
|
||||
Test-Path "$working_dir\i_am_a_hardlinked_directory" | should -be $false
|
||||
}
|
||||
|
||||
it "create_hardlink is falsey on unknown path" {
|
||||
create_hardlink "$working_dir\i_do_not_exist.txt" "$working_dir\i_do_not_exist.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_hardlink recognizes hardlinks/files" {
|
||||
remove_hardlink "$working_dir\i_am_a_hardlinked_file.txt" | should -be $true
|
||||
Test-Path "$working_dir\i_am_a_hardlinked_file.txt" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_hardlink recognizes directories" {
|
||||
remove_hardlink "$working_dir\i_am_a_directory" | should -be $false
|
||||
}
|
||||
|
||||
it "remove_hardlink is falsey on unknown path" {
|
||||
remove_hardlink "$working_dir\i_do_not_exist" | should -be $false
|
||||
}
|
||||
}
|
||||
|
||||
describe "movedir" -Tag 'Scoop' {
|
||||
|
||||
Reference in New Issue
Block a user