diff --git a/gap/PackageManager.gd b/gap/PackageManager.gd index 4cad0c1..dddf03e 100644 --- a/gap/PackageManager.gd +++ b/gap/PackageManager.gd @@ -132,15 +132,6 @@ SetInfoLevel(InfoPackageManager, 3); #! true or false DeclareGlobalFunction("InstallPackageFromInfo"); -#! @Description -#! Attempts to download and install a package from an archive located at the -#! given URL. Returns true if the installation was successful, and -#! false otherwise. -#! @Arguments url -#! @Returns -#! true or false -DeclareGlobalFunction("InstallPackageFromArchive"); - #! @Section Removing packages #! @Description @@ -173,9 +164,6 @@ DeclareGlobalFunction("PKGMAN_RefreshPackageInfo"); DeclareGlobalFunction("PKGMAN_ValidatePackageInfo"); DeclareGlobalFunction("PKGMAN_InfoWithIndent"); -# Hidden variables -PKGMAN_ArchiveFormats := [".tar.gz", ".tar.bz2"]; - # PackageInfo must at least contain the following to pass: PKGMAN_RequiredPackageInfoFields := ["PackageName", "PackageDoc", diff --git a/gap/PackageManager.gi b/gap/PackageManager.gi index 289f404..dd8c712 100644 --- a/gap/PackageManager.gi +++ b/gap/PackageManager.gi @@ -110,97 +110,6 @@ function(info, version...) return InstallPackageFromArchive(url); end); -InstallGlobalFunction(InstallPackageFromArchive, -function(url) - local get, user_pkg_dir, url_parts, filename, path, tar, options, exec, - files, topdir, dir, movedname; - - # Download archive - Info(InfoPackageManager, 3, "Downloading archive from URL ", url, " ..."); - get := PKGMAN_DownloadURL(url); - if get.success <> true then - Info(InfoPackageManager, 1, "Could not download from ", url); - return false; - fi; - user_pkg_dir := PKGMAN_PackageDir(); - url_parts := SplitString(url, "/"); - filename := url_parts[Length(url_parts)]; - path := Filename(DirectoryTemporary(), filename); - path := Concatenation(path, ".pkgman"); # TEMP: hack till GAP #4110 is merged - FileString(path, get.result); - Info(InfoPackageManager, 2, "Saved archive to ", path); - - # Check which version of tar we are using - tar := PKGMAN_Exec(".", "tar", "--version"); - if StartsWith(tar.output, "tar (GNU tar)") then - options := "--warning=none"; - else - options := ""; - fi; - - # Check contents - exec := PKGMAN_Exec(".", "tar", options, "-tf", path); - if exec.code <> 0 then - Info(InfoPackageManager, 1, "Could not inspect tarball contents"); - return false; - fi; - files := SplitString(exec.output, "", "\n"); - topdir := Set(files, f -> SplitString(f, "/")[1]); - if Length(topdir) <> 1 then - Info(InfoPackageManager, 1, - "Archive should contain 1 directory (not ", Length(topdir), ")"); - return false; - fi; - topdir := topdir[1]; - - # Check availability of target location - dir := Filename(Directory(user_pkg_dir), topdir); - if not PKGMAN_IsValidTargetDir(dir) then - if IsDirectoryPath(dir) and IsWritableFile(dir) and IsReadableFile(dir) then - # old version installed with the same name: change dir name - movedname := Concatenation(dir, ".old"); - Info(InfoPackageManager, 1, "Appending '.old' to old version directory"); - exec := PKGMAN_Exec(".", "mv", dir, movedname); - PKGMAN_RefreshPackageInfo(); - if exec.code <> 0 then - Info(InfoPackageManager, 1, "Could not rename old package directory"); - return false; - fi; - else - return false; - fi; - fi; - - # Extract package - Info(InfoPackageManager, 2, "Extracting to ", dir, " ..."); - exec := PKGMAN_Exec(".", "tar", "xf", path, "-C", user_pkg_dir); - if exec.code <> 0 then - Info(InfoPackageManager, 1, "Extraction unsuccessful"); - return false; - fi; - Info(InfoPackageManager, 4, "Extracted successfully"); - - # Install dependencies - if PKGMAN_InstallDependencies(dir) <> true then - Info(InfoPackageManager, 1, "Dependencies not satisfied for ", topdir); - if ValueOption("keepDirectory") <> true then - PKGMAN_RemoveDir(dir); - fi; - return false; - fi; - - # Check validity - if PKGMAN_CheckPackage(dir) = false then - if ValueOption("keepDirectory") <> true then - PKGMAN_RemoveDir(dir); - fi; - return false; - fi; - PKGMAN_RefreshPackageInfo(); - - return true; -end); - BindGlobal("PKGMAN_GetPackageInfo", function(dir_or_stream) local fname, info; diff --git a/gap/archive.gd b/gap/archive.gd new file mode 100644 index 0000000..28b9e39 --- /dev/null +++ b/gap/archive.gd @@ -0,0 +1,10 @@ +#! @Description +#! Attempts to download and install a package from an archive located at the +#! given URL. Returns true if the installation was successful, and +#! false otherwise. +#! @Arguments url +#! @Returns +#! true or false +DeclareGlobalFunction("InstallPackageFromArchive"); + +PKGMAN_ArchiveFormats := [".tar.gz", ".tar.bz2"]; diff --git a/gap/archive.gi b/gap/archive.gi new file mode 100644 index 0000000..62dd5d6 --- /dev/null +++ b/gap/archive.gi @@ -0,0 +1,90 @@ +InstallGlobalFunction(InstallPackageFromArchive, +function(url) + local get, user_pkg_dir, url_parts, filename, path, tar, options, exec, + files, topdir, dir, movedname; + + # Download archive + Info(InfoPackageManager, 3, "Downloading archive from URL ", url, " ..."); + get := PKGMAN_DownloadURL(url); + if get.success <> true then + Info(InfoPackageManager, 1, "Could not download from ", url); + return false; + fi; + user_pkg_dir := PKGMAN_PackageDir(); + url_parts := SplitString(url, "/"); + filename := url_parts[Length(url_parts)]; + path := Filename(DirectoryTemporary(), filename); + path := Concatenation(path, ".pkgman"); # TEMP: hack till GAP #4110 is merged + FileString(path, get.result); + Info(InfoPackageManager, 2, "Saved archive to ", path); + + # Check which version of tar we are using + tar := PKGMAN_Exec(".", "tar", "--version"); + if StartsWith(tar.output, "tar (GNU tar)") then + options := "--warning=none"; + else + options := ""; + fi; + + # Check contents + exec := PKGMAN_Exec(".", "tar", options, "-tf", path); + if exec.code <> 0 then + Info(InfoPackageManager, 1, "Could not inspect tarball contents"); + return false; + fi; + files := SplitString(exec.output, "", "\n"); + topdir := Set(files, f -> SplitString(f, "/")[1]); + if Length(topdir) <> 1 then + Info(InfoPackageManager, 1, + "Archive should contain 1 directory (not ", Length(topdir), ")"); + return false; + fi; + topdir := topdir[1]; + + # Check availability of target location + dir := Filename(Directory(user_pkg_dir), topdir); + if not PKGMAN_IsValidTargetDir(dir) then + if IsDirectoryPath(dir) and IsWritableFile(dir) and IsReadableFile(dir) then + # old version installed with the same name: change dir name + movedname := Concatenation(dir, ".old"); + Info(InfoPackageManager, 1, "Appending '.old' to old version directory"); + exec := PKGMAN_Exec(".", "mv", dir, movedname); + PKGMAN_RefreshPackageInfo(); + if exec.code <> 0 then + Info(InfoPackageManager, 1, "Could not rename old package directory"); + return false; + fi; + else + return false; + fi; + fi; + + # Extract package + Info(InfoPackageManager, 2, "Extracting to ", dir, " ..."); + exec := PKGMAN_Exec(".", "tar", "xf", path, "-C", user_pkg_dir); + if exec.code <> 0 then + Info(InfoPackageManager, 1, "Extraction unsuccessful"); + return false; + fi; + Info(InfoPackageManager, 4, "Extracted successfully"); + + # Install dependencies + if PKGMAN_InstallDependencies(dir) <> true then + Info(InfoPackageManager, 1, "Dependencies not satisfied for ", topdir); + if ValueOption("keepDirectory") <> true then + PKGMAN_RemoveDir(dir); + fi; + return false; + fi; + + # Check validity + if PKGMAN_CheckPackage(dir) = false then + if ValueOption("keepDirectory") <> true then + PKGMAN_RemoveDir(dir); + fi; + return false; + fi; + PKGMAN_RefreshPackageInfo(); + + return true; +end); diff --git a/init.g b/init.g index c639168..f1c7152 100644 --- a/init.g +++ b/init.g @@ -5,6 +5,7 @@ # ReadPackage("PackageManager", "gap/PackageManager.gd"); +ReadPackage("PackageManager", "gap/archive.gd"); ReadPackage("PackageManager", "gap/compile.gd"); ReadPackage("PackageManager", "gap/directories.gd"); ReadPackage("PackageManager", "gap/distro.gd"); diff --git a/read.g b/read.g index 0bf8975..f8f7520 100644 --- a/read.g +++ b/read.g @@ -5,6 +5,7 @@ # ReadPackage("PackageManager", "gap/PackageManager.gi"); +ReadPackage("PackageManager", "gap/archive.gi"); ReadPackage("PackageManager", "gap/compile.gi"); ReadPackage("PackageManager", "gap/directories.gi"); ReadPackage("PackageManager", "gap/distro.gi"); diff --git a/tst/PackageManager.tst b/tst/PackageManager.tst index 231f791..4825117 100644 --- a/tst/PackageManager.tst +++ b/tst/PackageManager.tst @@ -19,15 +19,6 @@ true gap> RemovePackage("autpgrp", false); true -# Install a package from a .tar.gz archive -gap> InstallPackage("https://github.com/gap-packages/example/releases/download/v4.2.1/Example-4.2.1.tar.gz"); -true -gap> ForAny(DirectoryContents(PKGMAN_PackageDir()), -> f -> StartsWith(LowercaseString(f), "example")); -true -gap> RemovePackage("example", false); -true - # RemovePackage failure gap> RemovePackage(3); Error, PackageManager: RemovePackage: must be a string @@ -80,20 +71,6 @@ gap> InstallPackage("http://www.nothing.rubbish/PackageInfo.g"); #I Unable to download from http://www.nothing.rubbish/PackageInfo.g false -# InstallPackageFromArchive failure -gap> InstallPackage("www.gap.rubbish/somepackage.tar.gz"); -#I Could not download from www.gap.rubbish/somepackage.tar.gz -false -gap> InstallPackage("https://gap-packages.github.io/PackageManager/dummy/bad-tarball.tar.gz"); -#I Could not inspect tarball contents -false -gap> InstallPackage("https://gap-packages.github.io/PackageManager/dummy/twodirs.tar.gz"); -#I Archive should contain 1 directory (not 2) -false -gap> InstallPackage("https://gap-packages.github.io/PackageManager/dummy/badpackage.tar.gz"); -#I PackageInfo.g lacks PackageName field -false - # Check a bad package directory gap> baddir := Filename(Directory(PKGMAN_PackageDir()), "badpkg");; gap> CreateDir(baddir);; @@ -119,22 +96,6 @@ true gap> InstallPackage("https://github.com/gap-packages/toric/releases/download/v1.9.5/Toric-1.9.5.tar.gz"); true -# Updating old package that doesn't have the version number in its directory name -gap> InstallPackage("https://www.math.colostate.edu/~hulpke/transgrp/transgrp3.6.4.tar.gz"); -true -gap> oldinfo := First(PackageInfo("transgrp"), x -> x.Version = "3.6.4");; -gap> oldinfo <> fail; -true -gap> PositionSublist(oldinfo.InstallationPath, "3.6.4"); # version number not in dir name -fail -gap> UpdatePackage("transgrp", false); -#I Package already installed at target location -#I Appending '.old' to old version directory -true -gap> newinfo := PackageInfo("transgrp")[1];; -gap> CompareVersionNumbers(newinfo.Version, ">=3.6.5"); -true - # FINAL TEST # (keep this at the end of the file) gap> PKGMAN_SetCustomPackageDir(Filename(DirectoryTemporary(), "pkg/")); diff --git a/tst/archive.tst b/tst/archive.tst new file mode 100644 index 0000000..18423f7 --- /dev/null +++ b/tst/archive.tst @@ -0,0 +1,43 @@ +# Install a package from a .tar.gz archive +gap> InstallPackage("https://github.com/gap-packages/example/releases/download/v4.2.1/Example-4.2.1.tar.gz"); +true +gap> ForAny(DirectoryContents(PKGMAN_PackageDir()), +> f -> StartsWith(LowercaseString(f), "example")); +true +gap> RemovePackage("example", false); +true + +# InstallPackageFromArchive failure +gap> InstallPackage("www.gap.rubbish/somepackage.tar.gz"); +#I Could not download from www.gap.rubbish/somepackage.tar.gz +false +gap> InstallPackage("https://gap-packages.github.io/PackageManager/dummy/bad-tarball.tar.gz"); +#I Could not inspect tarball contents +false +gap> InstallPackage("https://gap-packages.github.io/PackageManager/dummy/twodirs.tar.gz"); +#I Archive should contain 1 directory (not 2) +false +gap> InstallPackage("https://gap-packages.github.io/PackageManager/dummy/badpackage.tar.gz"); +#I PackageInfo.g lacks PackageName field +false + +# Updating old package that doesn't have the version number in its directory name +gap> InstallPackage("https://www.math.colostate.edu/~hulpke/transgrp/transgrp3.6.4.tar.gz"); +true +gap> oldinfo := First(PackageInfo("transgrp"), x -> x.Version = "3.6.4");; +gap> oldinfo <> fail; +true +gap> PositionSublist(oldinfo.InstallationPath, "3.6.4"); # version number not in dir name +fail +gap> UpdatePackage("transgrp", false); +#I Package already installed at target location +#I Appending '.old' to old version directory +true +gap> newinfo := PackageInfo("transgrp")[1];; +gap> CompareVersionNumbers(newinfo.Version, ">=3.6.5"); +true +gap> RemoveDirectoryRecursively(newinfo.InstallationPath); # clean up for future tests +true +gap> PKGMAN_RefreshPackageInfo(); +gap> RemovePackage("transgrp", false); +true