Skip to content

Commit

Permalink
moving development related functions to PkgDev package
Browse files Browse the repository at this point in the history
  • Loading branch information
wildart committed Sep 30, 2015
1 parent 28e854b commit 5011d31
Show file tree
Hide file tree
Showing 4 changed files with 3 additions and 846 deletions.
28 changes: 0 additions & 28 deletions base/docs/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11648,13 +11648,6 @@ Initialize `Pkg.dir()` as a package directory. This will be done automatically w
"""
Pkg.init()

doc"""
publish()
For each new package version tagged in `METADATA` not already published, make sure that the tagged package commits have been pushed to the repo at the registered URL for the package and if they all have, open a pull request to `METADATA`.
"""
Pkg.publish()

doc"""
pin(pkg)
Expand Down Expand Up @@ -11690,13 +11683,6 @@ Returns the version numbers available for package `pkg`.
"""
Pkg.available(pkg)

doc"""
register(pkg, [url])
Register `pkg` at the git URL `url`, defaulting to the configured origin URL of the git repo `Pkg.dir(pkg)`.
"""
Pkg.register(pkg, url=?)

doc"""
rm(pkg)
Expand Down Expand Up @@ -11762,13 +11748,6 @@ Add a requirement entry for `pkg` to `Pkg.dir("REQUIRE")` and call `Pkg.resolve(
"""
Pkg.add(pkg, vers...)

doc"""
tag(pkg, [ver, [commit]])
Tag `commit` as version `ver` of package `pkg` and create a version entry in `METADATA`. If not provided, `commit` defaults to the current commit of the `pkg` repo. If `ver` is one of the symbols `:patch`, `:minor`, `:major` the next patch, minor or major version is used. If `ver` is not provided, it defaults to `:patch`.
"""
Pkg.tag(pkg)

doc"""
test()
Expand All @@ -11783,13 +11762,6 @@ Run the tests for each package in `pkgs` ensuring that each package's test depen
"""
Pkg.test(pkgs...)

doc"""
generate(pkg,license)
Generate a new package named `pkg` with one of these license keys: `"MIT"`, `"BSD"` or `"ASL"`. If you want to make a package with a different license, you can edit it afterwards. Generate creates a git repo at `Pkg.dir(pkg)` for the package and inside it `LICENSE.md`, `README.md`, `REQUIRE`, the julia entrypoint `$pkg/src/$pkg.jl`, and Travis and AppVeyor CI configuration files `.travis.yml` and `appveyor.yml`.
"""
Pkg.generate(pkg,license)

doc"""
dir() -> AbstractString
Expand Down
26 changes: 3 additions & 23 deletions base/pkg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

module Pkg

export Git, Dir, GitHub, Types, Reqs, Cache, Read, Query, Resolve, Write, Generate, Entry, Git
export Git, Dir, GitHub, Types, Reqs, Cache, Read, Query, Resolve, Write, Entry, Git
export dir, init, rm, add, available, installed, status, clone, checkout,
update, resolve, register, tag, publish, generate, test,
build, free, pin, PkgError
update, resolve, test, build, free, pin, PkgError

const DEFAULT_META = "https://github.com/JuliaLang/METADATA.jl"
const META_BRANCH = "metadata-v2"
Expand All @@ -14,7 +13,7 @@ type PkgError <: Exception
msg::AbstractString
end

for file in split("dir github types reqs cache read query resolve write generate entry git")
for file in split("dir github types reqs cache read query resolve write entry git")
include("pkg/$file.jl")
end
const cd = Dir.cd
Expand Down Expand Up @@ -49,28 +48,9 @@ pin(pkg::AbstractString, ver::VersionNumber) = cd(Entry.pin,pkg,ver)
update() = cd(Entry.update,Dir.getmetabranch())
resolve() = cd(Entry.resolve)

register(pkg::AbstractString) = cd(Entry.register,pkg)
register(pkg::AbstractString, url::AbstractString) = cd(Entry.register,pkg,url)

tag(pkg::AbstractString, sym::Symbol=:patch) = cd(Entry.tag,pkg,sym)
tag(pkg::AbstractString, sym::Symbol, commit::AbstractString) = cd(Entry.tag,pkg,sym,false,commit)

tag(pkg::AbstractString, ver::VersionNumber; force::Bool=false) = cd(Entry.tag,pkg,ver,force)
tag(pkg::AbstractString, ver::VersionNumber, commit::AbstractString; force::Bool=false) =
cd(Entry.tag,pkg,ver,force,commit)

submit(pkg::AbstractString) = cd(Entry.submit,pkg)
submit(pkg::AbstractString, commit::AbstractString) = cd(Entry.submit,pkg,commit)

publish() = cd(Entry.publish,Dir.getmetabranch())

build() = cd(Entry.build)
build(pkgs::AbstractString...) = cd(Entry.build,[pkgs...])

generate(pkg::AbstractString, license::AbstractString; force::Bool=false, authors::Union{AbstractString,Array} = [], config::Dict=Dict()) =
cd(Generate.package,pkg,license,force=force,authors=authors,config=config)


test(;coverage::Bool=false) = cd(Entry.test; coverage=coverage)
test(pkgs::AbstractString...; coverage::Bool=false) = cd(Entry.test,AbstractString[pkgs...]; coverage=coverage)

Expand Down
259 changes: 0 additions & 259 deletions base/pkg/entry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -371,96 +371,6 @@ function update(branch::AbstractString)
updatehook(sort!(collect(keys(installed()))))
end

function pull_request(dir::AbstractString, commit::AbstractString="", url::AbstractString="")
with(GitRepo, dir) do repo
if isempty(commit)
commit = string(LibGit2.head_oid(repo))
else
!LibGit2.iscommit(commit, repo) && throw(PkgError("Cannot find pull commit: $commit"))
end
if isempty(url)
url = LibGit2.getconfig(repo, "remote.origin.url", "")
end

m = match(LibGit2.GITHUB_REGEX, url)
m === nothing && throw(PkgError("not a GitHub repo URL, can't make a pull request: $url"))
owner, owner_repo = m.captures[2:3]
user = GitHub.user()
info("Forking $owner/$owner_repo to $user")
response = GitHub.fork(owner,owner_repo)
fork = response["ssh_url"]
branch = "pull-request/$(commit[1:8])"
info("Pushing changes as branch $branch")
refspecs = ["HEAD:refs/heads/$branch"] # workaround for $commit:refs/heads/$branch
LibGit2.push(repo, remoteurl=fork, refspecs=refspecs)
pr_url = "$(response["html_url"])/compare/$branch"
info("To create a pull-request, open:\n\n $pr_url\n")
end
end

function submit(pkg::AbstractString, commit::AbstractString="")
urlpath = joinpath("METADATA",pkg,"url")
url = ispath(urlpath) ? readchomp(urlpath) : ""
pull_request(pkg, commit, url)
end

function publish(branch::AbstractString)
tags = Dict{ByteString,Vector{ASCIIString}}()

with(GitRepo, "METADATA") do repo
LibGit2.branch(repo) == branch ||
throw(PkgError("METADATA must be on $branch to publish changes"))
LibGit2.fetch(repo)

ahead_remote, ahead_local = LibGit2.revcount(repo, "origin/$branch", branch)
ahead_remote > 0 && throw(PkgError("METADATA is behind origin/$branch – run `Pkg.update()` before publishing"))
ahead_local == 0 && throw(PkgError("There are no METADATA changes to publish"))

# get changed files
for path in LibGit2.diff_files(repo, "origin/$branch", LibGit2.Consts.HEAD_FILE)
m = match(r"^(.+?)/versions/([^/]+)/sha1$", path)
m !== nothing && ismatch(Base.VERSION_REGEX, m.captures[2]) || continue
pkg, ver = m.captures; ver = convert(VersionNumber,ver)
sha1 = readchomp(joinpath("METADATA",path))
old = LibGit2.cat(repo, LibGit2.GitBlob, "origin/$branch:$path")
old !== nothing && old != sha1 && throw(PkgError("$pkg v$ver SHA1 changed in METADATA – refusing to publish"))
with(GitRepo, pkg) do pkg_repo
tag_name = "v$ver"
tag_commit = LibGit2.revparseid(pkg_repo, "$(tag_name)^{commit}")
LibGit2.iszero(tag_commit) || string(tag_commit) == sha1 || return false
haskey(tags,pkg) || (tags[pkg] = ASCIIString[])
push!(tags[pkg], tag_name)
return true
end || throw(PkgError("$pkg v$ver is incorrectly tagged – $sha1 expected"))
end
isempty(tags) && info("No new package versions to publish")
info("Validating METADATA")
check_metadata(Set(keys(tags)))
end

for pkg in sort!(collect(keys(tags)))
with(GitRepo, pkg) do pkg_repo
forced = ASCIIString[]
unforced = ASCIIString[]
for tag in tags[pkg]
ver = convert(VersionNumber,tag)
push!(isrewritable(ver) ? forced : unforced, tag)
end
if !isempty(forced)
info("Pushing $pkg temporary tags: ", join(forced,", "))
LibGit2.push(pkg_repo, remote="origin", force=true,
refspecs=["refs/tags/$tag:refs/tags/$tag" for tag in forced])
end
if !isempty(unforced)
info("Pushing $pkg permanent tags: ", join(unforced,", "))
LibGit2.push(pkg_repo, remote="origin",
refspecs=["refs/tags/$tag:refs/tags/$tag" for tag in unforced])
end
end
end
info("Submitting METADATA changes")
pull_request("METADATA")
end

function resolve(
reqs :: Dict = Reqs.parse("REQUIRE"),
Expand Down Expand Up @@ -547,175 +457,6 @@ function resolve(
build(map(x->x[1], filter(x -> x[2][2] !== nothing, changes)))
end

function write_tag_metadata(repo::GitRepo, pkg::AbstractString, ver::VersionNumber, commit::AbstractString, force::Bool=false)
content = with(GitRepo,pkg) do pkg_repo
LibGit2.cat(pkg_repo, LibGit2.GitBlob, "$commit:REQUIRE")
end
reqs = content !== nothing ? Reqs.read(split(content, '\n', keep=false)) : Reqs.Line[]
cd("METADATA") do
d = joinpath(pkg,"versions",string(ver))
mkpath(d)
sha1file = joinpath(d,"sha1")
if !force && ispath(sha1file)
current = readchomp(sha1file)
current == commit ||
throw(PkgError("$pkg v$ver is already registered as $current, bailing"))
end
open(io->println(io,commit), sha1file, "w")
LibGit2.add!(repo, sha1file)
reqsfile = joinpath(d,"requires")
if isempty(reqs)
ispath(reqsfile) && LibGit2.remove!(repo, reqsfile)
else
Reqs.write(reqsfile,reqs)
LibGit2.add!(repo, reqsfile)
end
end
return nothing
end

function register(pkg::AbstractString, url::AbstractString)
ispath(pkg,".git") || throw(PkgError("$pkg is not a git repo"))
isfile("METADATA",pkg,"url") && throw(PkgError("$pkg already registered"))
LibGit2.transact(GitRepo("METADATA")) do repo
# Get versions from package repo
versions = with(GitRepo, pkg) do pkg_repo
tags = filter(t->startswith(t,"v"), LibGit2.tag_list(pkg_repo))
filter!(tag->ismatch(Base.VERSION_REGEX,tag), tags)
[
convert(VersionNumber,tag) => string(LibGit2.revparseid(pkg_repo, "$tag^{commit}"))
for tag in tags
]
end
# Register package url in METADATA
cd("METADATA") do
info("Registering $pkg at $url")
mkdir(pkg)
path = joinpath(pkg,"url")
open(io->println(io,url), path, "w")
LibGit2.add!(repo, path)
end
# Register package version in METADATA
vers = sort!(collect(keys(versions)))
for ver in vers
info("Tagging $pkg v$ver")
write_tag_metadata(repo, pkg,ver,versions[ver])
end
# Commit changes in METADATA
if LibGit2.isdirty(repo)
info("Committing METADATA for $pkg")
msg = "Register $pkg"
if !isempty(versions)
msg *= ": $(join(map(v->"v$v", vers),", "))"
end
LibGit2.commit(repo, msg)
else
info("No METADATA changes to commit")
end
end
return
end

function register(pkg::AbstractString)
url = ""
try
url = LibGit2.getconfig(pkg, "remote.origin.url", "")
catch err
throw(PkgError("$pkg: $err"))
end
!isempty(url) || throw(PkgError("$pkg: no URL configured"))
register(pkg, GitHub.normalize_url(url))
end

function isrewritable(v::VersionNumber)
thispatch(v)==v"0" ||
length(v.prerelease)==1 && isempty(v.prerelease[1]) ||
length(v.build)==1 && isempty(v.build[1])
end

nextbump(v::VersionNumber) = isrewritable(v) ? v : nextpatch(v)

function tag(pkg::AbstractString, ver::Union{Symbol,VersionNumber}, force::Bool=false, commitish::AbstractString="HEAD")
ispath(pkg,".git") || throw(PkgError("$pkg is not a git repo"))
with(GitRepo,"METADATA") do repo
LibGit2.isdirty(repo, pkg) && throw(PkgError("METADATA/$pkg is dirty – commit or stash changes to tag"))
end
with(GitRepo,pkg) do repo
LibGit2.isdirty(repo) && throw(PkgError("$pkg is dirty – commit or stash changes to tag"))
commit = string(LibGit2.revparseid(repo, commitish))
registered = isfile("METADATA",pkg,"url")

if !force
if registered
avail = Read.available(pkg)
existing = VersionNumber[keys(Read.available(pkg))...]
ancestors = filter(v->LibGit2.is_ancestor_of(avail[v].sha1, commit, repo), existing)
else
tags = filter(t->startswith(t,"v"), Pkg.LibGit2.tag_list(repo))
filter!(tag->ismatch(Base.VERSION_REGEX,tag), tags)
existing = VersionNumber[tags...]
filter!(tags) do tag
sha1 = string(LibGit2.revparseid(repo, "$tag^{commit}"))
LibGit2.is_ancestor_of(sha1, commit, repo)
end
ancestors = VersionNumber[tags...]
end
sort!(existing)
if isa(ver,Symbol)
prv = isempty(existing) ? v"0" :
isempty(ancestors) ? maximum(existing) : maximum(ancestors)
ver = (ver == :bump ) ? nextbump(prv) :
(ver == :patch) ? nextpatch(prv) :
(ver == :minor) ? nextminor(prv) :
(ver == :major) ? nextmajor(prv) :
throw(PkgError("invalid version selector: $ver"))
end
isrewritable(ver) && filter!(v->v!=ver,existing)
check_new_version(existing,ver)
end
# TODO: check that SHA1 isn't the same as another version
info("Tagging $pkg v$ver")
LibGit2.tag_create(repo, "v$ver", commit,
msg=(!isrewritable(ver) ? "$pkg v$ver [$(commit[1:10])]" : ""),
force=(force || isrewritable(ver)) )
registered || return
try
LibGit2.transact(GitRepo("METADATA")) do repo
write_tag_metadata(repo, pkg, ver, commit, force)
if LibGit2.isdirty(repo)
info("Committing METADATA for $pkg")
LibGit2.commit(repo, "Tag $pkg v$ver")
else
info("No METADATA changes to commit")
end
end
catch
LibGit2.tag_delete(repo, "v$ver")
rethrow()
end
end
return
end

function check_metadata(pkgs::Set{ByteString} = Set{ByteString}())
avail = Read.available()
deps, conflicts = Query.dependencies(avail)

for (dp,dv) in deps, (v,a) in dv, p in keys(a.requires)
haskey(deps, p) || throw(PkgError("package $dp v$v requires a non-registered package: $p"))
end

problematic = Resolve.sanity_check(deps, pkgs)
if !isempty(problematic)
msg = "packages with unsatisfiable requirements found:\n"
for (p, vn, rp) in problematic
msg *= " $p v$vn – no valid versions exist for package $rp\n"
end
throw(PkgError(msg))
end
return
end

function warnbanner(msg...; label="[ WARNING ]", prefix="")
cols = Base.tty_size()[2]
warn(prefix="", Base.cpad(label,cols,"="))
Expand Down
Loading

0 comments on commit 5011d31

Please sign in to comment.