[ANN] SnoopPrecompile -> PrecompileTools

For those who wanted to know the details of how I generated the pull requests, here it is. It’s largely copy/pasted from MassInstallActions with as few changes as I had to make to get this to work. As the name MassInstallActions suggests, that package only handles pull request dealing with GitHub Actions. Ideally we’d refactor that package to support more general kinds of changes, but for now I just hacked the following up:

using GitHub, HTTP, Pkg

include("convertpc.jl")

const default_body = read("commitmsg.md", String)

function with_temp_dir(f::Function)
    original_directory = pwd()
    tmp_dir = mktempdir()
    atexit(() -> rm(tmp_dir; force = true, recursive = true))
    cd(tmp_dir)
    result = f(tmp_dir)
    cd(original_directory)
    rm(tmp_dir; force = true, recursive = true)
    return result
end

function git(f)
    return f("git")
end

function migrate(repo::GitHub.Repo;
                 auth::GitHub.Authorization,
                 pr_branch_name::AbstractString = "teh/precompiletools",
                 pr_title::AbstractString = "Migrate from SnoopPrecompile to PrecompileTools",
                 pr_body::AbstractString = default_body,
                 commit_message::AbstractString = "Migrate from SnoopPrecompile to PrecompileTools",
                 pkg_url_type::Symbol = :html)
    fk = GitHub.create_fork(repo; auth)
    if pkg_url_type === :html
        pkg_url_with_auth = fk.html_url.uri
    elseif pkg_url_type === :ssh
        pkg_url_with_auth = fk.ssh_url.uri
    else
        throw(ArgumentError("`pkg_url_type = $(pkg_url_type)` not supported"))
    end
    sleep(5)
    with_temp_dir() do tmp_dir
        git() do git
            cd(tmp_dir) do
                run(`$(git) clone $(pkg_url_with_auth) REPO`)
                cd("REPO")
                run(`$(git) checkout -B $(pr_branch_name)`)
                if convert2pct(joinpath(tmp_dir, "REPO"))
                    run(`$(git) add -A`)
                    run(`$(git) commit -m $(commit_message)`)
                    # try
                        run(`$(git) push --force origin $(pr_branch_name)`)
                    # catch
                    #     # try again?
                    #     run(`$(git) push --force origin $(pr_branch_name)`)
                    # end
                    sleep(5)
                    params = Dict{String, String}()
                    params["title"] = pr_title
                    params["head"] = "timholy:" * pr_branch_name
                    params["base"] = repo.default_branch
                    params["body"] = pr_body
                    GitHub.create_pull_request(repo; params, auth)
                    @info "Pull request submitted for $(repo.name)"
                end
            end
        end
    end
    return nothing
end

regs = Pkg.Registry.reachable_registries()
reg = only(filter(r -> r.name == "General", regs))
regpath = splitext(reg.path)[1]
toml = Pkg.TOML.parsefile(joinpath(regpath, "Registry.toml"))
pkgurls = String[]
for (uuid, data) in toml["packages"]
    pkgpath = data["path"]
    depfile = joinpath(regpath, pkgpath, "Deps.toml")
    if isfile(depfile)
        deps = read(depfile, String)
        if occursin("SnoopPrecompile", deps)
            pkgfile = joinpath(regpath, pkgpath, "Package.toml")
            pkginfo = Pkg.TOML.parsefile(pkgfile)
            url = splitext(pkginfo["repo"])[1]
            push!(pkgurls, url)
        end
    end
end
sort!(pkgurls; by=name->splitpath(name)[end])
unique!(pkgurls)

# A chance to fix errors/edit the list. This was needed because the
# script didn't initially run to completion and I had to remove the ones already tackled
error("edit `pkgurls` to narrow the list of packages, then run the block below")

while !isempty(pkgurls)
    url = pkgurls[end]
    println(url)
    repo = GitHub.repo(joinpath(splitpath(url)[3:end]...); auth)
    migrate(repo; auth, pkg_url_type=:ssh)
    pop!(pkgurls)   # worked, delete from queue
    println("\n\n")
end

convertpc.jl is the script I posted in the OP, and commitmsg.md was the message many of you received with the pull requests. auth is a GitHub authentication token that you have to set up externally.

12 Likes