GNU bug report logs - #45972
[PATCH] Add julia-json with dependencies

Previous Next

Package: guix-patches;

Reported by: Nicolò Balzarotti <anothersms <at> gmail.com>

Date: Mon, 18 Jan 2021 23:49:02 UTC

Severity: normal

Tags: patch

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Nicolò Balzarotti <anothersms <at> gmail.com>
To: zimoun <zimon.toutoune <at> gmail.com>, Ludovic Courtès <ludo <at> gnu.org>
Cc: 45972 <at> debbugs.gnu.org
Subject: [bug#45972] Julia importer?
Date: Sat, 30 Jan 2021 21:13:14 +0100
[Message part 1 (text/plain, inline)]
zimoun <zimon.toutoune <at> gmail.com> writes:

> Hi,

Hi Simon!

>>
>> (invoke-julia "using Pkg; Pkg.TOML.parsefile("Project.toml")["name"] |> println")
>
> With a bit more glue, could this be transformed into something like
> “julia->guix-package”?  And so have a Julia package importer, even if it
> fails for some cases.

Well, if you mean "Can we use Pkg.jl to generate package definitions for
us?" the answer is "probably yes, but I never investigated this".  That
line uses just Julia Base TOML.jl, which for some reason is defined
inside module Pkg.jl (and it's not top-level).

If you instead meant "Can we have a Julia importer?" some time ago I
wrote one in Julia, I've not used it in the last year, but it did work
quite well back then.  I attach it here for reference.

But before digging into Pkg3, I need to push a new set of packages which
contains julia-jllwrappers, which is needed for Julia packages which
require binary distributions to work.  After that, it will be possible
to create an importer that work "ok" even with packages depending on
.so libraries.

[import.jl (text/plain, inline)]
using Pkg
using Pkg.TOML
using LibGit2

const base = ["Base64",
              "CRC32c",
              "Dates",
              "DelimitedFiles",
              "Distributed",
              "FileWatching",
              "Future",
              "InteractiveUtils",
              "Libdl",
              "LibGit2",
              "LinearAlgebra",
              "Logging",
              "Markdown",
              "Mmap",
              "Pkg",
              "Printf",
              "Profile",
              "Random",
              "REPL",
              "Serialization",
              "SHA",
              "SharedArrays",
              "Sockets",
              "SparseArrays",
              "Statistics",
              "SuiteSparse",
              "Test",
              "Unicode",
              "UUIDs"]
const disabled = ["WinRPM", "Homebrew", "CMake",
                  "Docile", "Color", 
                  "HTTPClient", "ICU", "Calendar", "LegacyStrings",
                  "Nulls"]

registrypath = expanduser("~/.julia-old/registries/General/")
registry = joinpath(registrypath, "Registry.toml")
const register = TOML.parse(join(readlines(registry), "\n"))

jlpkgname(info) = "julia-$(lowercase(info.name))"

function getrev(path)
    versions = TOML.parse(join(readlines(path), "\n"))
    versionv = findmax(map(x -> VersionNumber(x), keys(versions) |> collect))
    (rev = versions[string(versionv[1])]["git-tree-sha1"],
     ver = versionv[1])
end

function getpackagebyuuid(uuid)
    uuid in keys(register["packages"]) || return nothing
    path = register["packages"][uuid]["path"]
    getpath(x) =  joinpath(registrypath, joinpath(path, x))
    package = TOML.parse(join(readlines(getpath("Package.toml")), "\n"))
    deppath = getpath("Deps.toml")
    isfile(deppath) || return nothing
    deps = TOML.parse(join(readlines(deppath), "\n"))
    (name = package["name"],
     uuid = package["uuid"],
     repo = package["repo"],
     deps = deps,
     vers = getrev(getpath("Versions.toml")))
end

function getpackage(wanted)
    uuid = findfirst(p -> lowercase(p["name"]) == lowercase(wanted),
                     register["packages"])
    uuid == nothing && return nothing
    return getpackagebyuuid(uuid)
end

function getdeps!(deps, vers, recursive, out)
    flat(arr::Array) = mapreduce(x -> isa(x, Array) ? flat(x) : x, append!,
                                 arr, init=[])
    v = map(p -> VersionNumber.(split(p, '-')), keys(deps) |> collect)
    valid = findall(x -> length(x) == 1 ||
                    (x[2] == v"0" && x[1] <= vers) ||
                    x[1] <= vers <= x[2], v)
    f = flat(map(x -> values(x), values(collect(values(deps))[valid])))
    push!.(Ref(out), f)
    # if recursive
    #     push!
    # end
    nothing
end

function have(info)
    file = "/home/nixo/git/guix/gnu/packages/julia-xyz.scm"
    return "(name \"" * jlpkgname(info) * "\")" in strip.(readlines(file))
end

function gethash(info)
    wd = mktempdir()
    if info.name in base ||
        info.name in disabled ||
        have(info)
        return ""
    end
    println(stderr, "Cloning $(info.name) in $wd")
    repo = LibGit2.clone(info.repo, wd)
    hash = cd(wd) do
        out = Pipe()
        try
            LibGit2.checkout!(repo,
                              string(LibGit2.GitHash(LibGit2.peel(LibGit2.GitCommit,
                                                                  LibGit2.GitTag(repo, "v" * string(info.vers.ver))))))
        catch e
            try
                LibGit2.checkout!(repo,
                                  string(LibGit2.GitHash(LibGit2.peel(LibGit2.GitCommit,
                                                                      LibGit2.GitCommit(repo, "v" * string(info.vers.ver))))))
            catch e
                # FIXME: if this happens, return the commit too and use it in the package
                println(stderr, "Failed to checkout $(e), continuing")
            end
        end
        run(pipeline(`guix hash -rx .`, stdout=out))
        readline(out)
    end
    rm(wd, recursive = true)
    hash
end

function makepackage(info; done = [])
    if info === nothing
        @warn "Could not find package (have you cloned the registry?)"
        return
    elseif info in done
        return ""
    end
    push!(done, info)
    deps = String[]
    getdeps!(info.deps, info.vers.ver, true, deps)
    # TODO: remove deps that are in base
    deps = filter(x -> x !== nothing, getpackagebyuuid.(deps))
    deplist = join(map(name -> "(\"$name\" ,$name)",
                       jlpkgname.(deps)), '\n')
    packagedeps = join(makepackage.(deps, done = done), "")
    hash = gethash(info)
    hash == "" && return ""
    """
    $packagedeps
    (define-public $(jlpkgname(info))
      (package
       (name "$(jlpkgname(info))")
       (version "$(info.vers.ver)")
       (source
          (origin
            (method git-fetch)
            (uri (git-reference
              (url "$(info.repo)")
              (commit (string-append "v" version))))
            (file-name "$(info.name)")
            (sha256
                 (base32 "$hash"))))
       (propagated-inputs `($(deplist)))
       (build-system julia-build-system)
       (home-page "$(info.repo)")
       (synopsis "")
       (description "")
       (license license:expat)))
    """
end

println.(makepackage.(getpackage.(ARGS)))

This bug report was last modified 4 years and 169 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.