Open hannahilea opened 1 year ago
The difficulty with this idea is that it requires a completely separate set of code to process the Manifest.toml file and then populate a new Pkg.API.PackageInfo Dictionary so that the rest of the code can use the information. And Pkg already does all that work already when it reads the Project.toml and Manifest.toml, so it's duplicative.
Reading the documentation on Pkg.instantiate, I interpret it as saying that if the Manifest.toml file is present it will not do any re-resolution. If the version of Julia in use is incompatible with items in the Manifest, that is an edge case and it would be interesting to know what Pkg will do in that situation. Possibly that is a case we don't support at this time.
If Pkg.instantiate is combined with Pkg.activate(; temp=true)
then I think we can get the effect called for here, where the Manifest is instantiated within a fresh environment, the SBOM is created and the users own environment is untouched.
I've got a version of this idea in the tests now. I created a set of dummy packages and use a manifest to pull them in and create an SBOM. Shows it can be done.
I wrote a bunch of code around inspection of Manifest.toml
using Pkg
utilities without instantiating a project. The only item it needs is using Pkg
. In my use case I wasn't using private registries, but there were several "develop" packages in the local file system. It works in Julia 1.6 and I just tested it on Julia 1.11 and works fine.
using Pkg
function inspect_julia_project_dir(julia_project_dir_in)
global julia_project_dir = realpath(abspath(julia_project_dir_in))
global manifest_path = abspath(joinpath(julia_project_dir, "Manifest.toml"))
global manifest_dict = Pkg.TOML.parsefile(manifest_path)
global project_dict = Pkg.TOML.parsefile(joinpath(julia_project_dir, "Project.toml"))
global application = get(project_dict, "name", basename(julia_project_dir))
end
function pkgdir_from_manifest(package_name::String)
if package_name == application
return julia_project_dir
end
if !haskey(manifest_dict, package_name)
error("No such package \"$package_name\" found in $manifest_path")
end
if length(manifest_dict[package_name]) != 1
error("Ambiguous entry list for \"$package_name\" in $manifest_path")
end
package_dict = manifest_dict[package_name][1]
if haskey(package_dict, "path")
return abspath(joinpath(julia_project_dir, package_dict["path"]))
end
if haskey(package_dict, "uuid") && haskey(package_dict, "git-tree-sha1")
return Pkg.Operations.find_installed(package_name,
Pkg.Types.UUID(package_dict["uuid"]),
Pkg.Types.SHA1(package_dict["git-tree-sha1"]))
end
if haskey(package_dict, "uuid")
return abspath(joinpath(dirname(Base.find_package(package_name)), ".."))
end
@show package_dict
error("Missing info for \"$package_name\" in $manifest_path: " *
"Need uuid and git-tree-sha1 or path to look up the path to $package_name")
return ""
end
## Usage
# inspect_julia_project_dir("path/to/julia/Project")
#
# pkgdir_from_manifest("SomePackage")
# "/Users/username/.julia/packages/SomePackage/abcd1"
The current example of SBOM generation for a package involves creating a new environment, adding just that package to it, and then constructing an SBOM from there.
Rather than instantiating an environment and then constructing an SBOM from that environment, it would be nice to provide an entrypoint that works directly from the Manifest.toml, without doing any amount of environment resolution (which may re-resolve the provided Manifest.toml in a way that introduces changes, especially if the Julia version from the original manifest and the current environment are different).