Skip to content

Commit

Permalink
admit version number in InstallPackage
Browse files Browse the repository at this point in the history
... as discussed in issue gap-packages#60

(I did not add tests of the new functionality,
first we should discuss whether the proposed change does what we want.)
  • Loading branch information
ThomasBreuer committed May 4, 2021
1 parent 90f1346 commit 6bda0b8
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
24 changes: 21 additions & 3 deletions gap/PackageManager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,37 @@
#! Certain decisions, such as installing newer versions of packages, will be
#! confirmed by the user via an interactive shell - to avoid this
#! interactivity and use sane defaults instead, the optional second argument
#! `interactive` can be set to `false`.
#! `interactive_or_version` can be set to `false`.
#!
#! To see more information about this process while it is ongoing, see
#! `InfoPackageManager`.
#!
#! If `string` is the name of the package in question then one can specify
#! a required package version via a string as value of the optional argument
#! `interactive_or_version`, which is interpreted as described in Section
#! <Ref Sect="Version Numbers" BookName="ref"/>.
#! In particular, if `version` starts with `=` then the function will try to
#! install exactly the given version, and otherwise it will try to install
#! a version that is not smaller than the given one.
#! If a version is prescribed then no interactivity happens.
#! If an installed version satisfies the condition on the version then
#! `true` is returned without an attempt to upgrade the package.
#! If the package is not yet installed or if no installed version satisfies
#! the version condition then an upgrade is tried only if the package version
#! that is listed on the &GAP; webpages satisfies the condition.
#! (The function will not update a dev version of the package if a version
#! number is prescribed;
#! otherwise it could happen that one updates the installation and
#! afterwards notices that the version condition is still not satisfied.)
#!
#! @BeginExample
#! gap> InstallPackage("digraphs");
#! true
#! @EndExample
#!
#! @Arguments string[, interactive]
#! @Arguments string[, interactive_or_version]
#! @Returns
#! true or false
#! `true` or `false`
DeclareGlobalFunction("InstallPackage");

#! @Description
Expand Down
46 changes: 37 additions & 9 deletions gap/PackageManager.gi
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ function(string, interactive...)
"requires 1 or 2 arguments (not ",
Length(interactive) + 1, ")");
elif Length(interactive) = 1 then
if interactive[1] = true or interactive[1] = false then
if IsString( interactive[1] ) or interactive[1] = true
or interactive[1] = false then
interactive := interactive[1];
else
ErrorNoReturn("PackageManager: InstallPackage: ",
"<interactive> must be true or false");
"<interactive> must be true or false or a version string");
fi;
else
interactive := true;
Expand All @@ -72,10 +73,14 @@ end);

InstallGlobalFunction(InstallPackageFromName,
function(name, interactive...)
local urls, allinfo, info, newest, current, dirs, vc, q;
local version, urls, allinfo, info, newest, current, dirs, vc, q;

# Handle interactivity
if Length(interactive) = 1 and interactive[1] = false then
# Handle version condition and interactivity
version := true;
if Length(interactive) = 1 and IsString(interactive[1]) then
version := interactive[1];
interactive := false;
elif Length(interactive) = 1 and interactive[1] = false then
interactive := false;
else
interactive := true;
Expand All @@ -96,7 +101,17 @@ function(name, interactive...)
info := Filtered(allinfo,
x -> StartsWith(x.InstallationPath, PKGMAN_PackageDir()));
if not IsEmpty(info) then # Already installed
# Does the installed version already satisfy the prescribed version?
current := info[1]; # Highest-priority installation in user pkg directory
if version <> true and
CompareVersionNumbers( current.Version, version ) then
Info(InfoPackageManager, 2, "Version ", current.Version,
" of package \"", name, "\" is already installed");
return PKGMAN_CheckPackage(current.InstallationPath);
fi;

# Any VC installations?
# (This step is not relevant in case of a prescribed version number.)
dirs := List(info, i -> ShallowCopy(i.InstallationPath));
for vc in ["git", "hg"] do
if Filename(List(dirs, Directory), Concatenation(".", vc)) <> fail then
Expand All @@ -110,8 +125,15 @@ function(name, interactive...)

# Installed by archive only
newest := PKGMAN_DownloadPackageInfo(urls.(name));
current := info[1]; # Highest-priority installation in user pkg directory
if CompareVersionNumbers(newest.Version, current.Version, "equal") then
if version <> true then
# Update or give up, but do not ask questions.
if CompareVersionNumbers( newest.Version, version ) then
# Updating to the newest version will satisfy the version condition.
return UpdatePackage(name, interactive);
else
return false;
fi;
elif CompareVersionNumbers(newest.Version, current.Version, "equal") then
Info(InfoPackageManager, 2, "The newest version of package \"", name,
"\" is already installed");
return PKGMAN_CheckPackage(current.InstallationPath);
Expand All @@ -128,11 +150,11 @@ function(name, interactive...)
fi;

# Not installed yet
return InstallPackageFromInfo(urls.(name));
return InstallPackageFromInfo(urls.(name), version);
end);

InstallGlobalFunction(InstallPackageFromInfo,
function(info)
function(info, version...)
local formats, format, url;

# Check input
Expand All @@ -149,6 +171,12 @@ function(info)
fi;
fi;

# Check the version condition.
if Length(version) = 1 and IsString(version[1])
and not CompareVersionNumbers(info.Version, version[1]) then
return false;
fi;

# Read the information we want from it
formats := SplitString(info.ArchiveFormats, "", ", \n\r\t");
format := First(PKGMAN_ArchiveFormats, f -> f in formats);
Expand Down

0 comments on commit 6bda0b8

Please sign in to comment.