unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
From: "Nicolò Balzarotti" <anothersms@gmail.com>
To: zimoun <zimon.toutoune@gmail.com>, "Ludovic Courtès" <ludo@gnu.org>
Cc: 45972@debbugs.gnu.org
Subject: [bug#45972] Julia importer?
Date: Sat, 30 Jan 2021 21:13:14 +0100	[thread overview]
Message-ID: <8735yi9o9x.fsf@guixSD.i-did-not-set--mail-host-address--so-tickle-me> (raw)
In-Reply-To: <86pn1mfpp1.fsf@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1108 bytes --]

zimoun <zimon.toutoune@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.


[-- Attachment #2: julia import.jl --]
[-- Type: text/plain, Size: 5358 bytes --]

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)))

  reply	other threads:[~2021-01-30 20:14 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-18 23:47 [bug#45972] [PATCH] Add julia-json with dependencies Nicolò Balzarotti
2021-01-26 21:33 ` Ludovic Courtès
2021-01-26 23:23   ` Nicolò Balzarotti
2021-01-27 22:40     ` Ludovic Courtès
2021-01-28  0:30       ` Nicolò Balzarotti
2021-01-28 13:10         ` Ludovic Courtès
2021-01-28 15:37           ` Nicolò Balzarotti
2021-01-30 14:10             ` bug#45972: " Ludovic Courtès
2021-01-30 14:46         ` [bug#45972] Julia importer? zimoun
2021-01-30 20:13           ` Nicolò Balzarotti [this message]
2021-01-30 21:42             ` Nicolò Balzarotti
2021-01-31 19:35             ` zimoun
2021-01-31 20:00               ` Nicolò Balzarotti
2021-02-01  7:22                 ` zimoun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8735yi9o9x.fsf@guixSD.i-did-not-set--mail-host-address--so-tickle-me \
    --to=anothersms@gmail.com \
    --cc=45972@debbugs.gnu.org \
    --cc=ludo@gnu.org \
    --cc=zimon.toutoune@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).