From 4dd3364c6e4a3128f271ee12fad3591b20335a4b Mon Sep 17 00:00:00 2001 From: wildart Date: Wed, 30 Sep 2015 15:14:50 -0400 Subject: [PATCH 1/4] moving development related functions to `PkgDev` package --- base/docs/helpdb.jl | 28 --- base/pkg.jl | 26 +-- base/pkg/entry.jl | 259 --------------------- base/pkg/generate.jl | 536 ------------------------------------------- 4 files changed, 3 insertions(+), 846 deletions(-) delete mode 100644 base/pkg/generate.jl diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index aecf883f77206..5bd3b4126224d 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -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) @@ -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) @@ -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() @@ -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 diff --git a/base/pkg.jl b/base/pkg.jl index 5c49c5ff26860..73596f6779315 100644 --- a/base/pkg.jl +++ b/base/pkg.jl @@ -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" @@ -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 @@ -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) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 8e25da91524b1..c9dec1a77e572 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -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"), @@ -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"), 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,"=")) diff --git a/base/pkg/generate.jl b/base/pkg/generate.jl deleted file mode 100644 index b3b1aee469580..0000000000000 --- a/base/pkg/generate.jl +++ /dev/null @@ -1,536 +0,0 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license - -module Generate - -import ...LibGit2, ..Read, ...Pkg.PkgError -importall ...LibGit2 - -copyright_year() = string(Dates.year(Dates.today())) -copyright_name(repo::GitRepo) = LibGit2.getconfig(repo, "user.name", "") -github_user() = LibGit2.getconfig("github.user", "") - -function git_contributors(repo::GitRepo, n::Int=typemax(Int)) - contrib = Dict() - for sig in LibGit2.authors(repo) - if haskey(contrib, sig.email) - contrib[sig.email][1] += 1 - else - contrib[sig.email] = [1, sig.name] - end - end - - names = Dict() - for (commits,name) in values(contrib) - names[name] = get(names,name,0) + commits - end - names = sort!(collect(keys(names)),by=name->names[name],rev=true) - length(names) <= n ? names : [names[1:n]; "et al."] -end - -function package( - pkg::AbstractString, - license::AbstractString; - force::Bool = false, - authors::Union{AbstractString,Array} = "", - years::Union{Int,AbstractString} = copyright_year(), - user::AbstractString = github_user(), - config::Dict = Dict(), -) - isnew = !ispath(pkg) - try - repo = if isnew - url = isempty(user) ? "" : "https://github.com/$user/$pkg.jl.git" - Generate.init(pkg,url,config=config) - else - repo = GitRepo(pkg) - if LibGit2.isdirty(repo) - finalize(repo) - throw(PkgError("$pkg is dirty – commit or stash your changes")) - end - repo - end - - LibGit2.transact(repo) do repo - if isempty(authors) - authors = isnew ? copyright_name(repo) : git_contributors(repo,5) - end - - files = [Generate.license(pkg,license,years,authors,force=force), - Generate.readme(pkg,user,force=force), - Generate.entrypoint(pkg,force=force), - Generate.tests(pkg,force=force), - Generate.require(pkg,force=force), - Generate.travis(pkg,force=force), - Generate.appveyor(pkg,force=force), - Generate.gitignore(pkg,force=force) ] - - msg = """ - $pkg.jl $(isnew ? "generated" : "regenerated") files. - - license: $license - authors: $(join(vcat(authors),", ")) - years: $years - user: $user - - Julia Version $VERSION [$(Base.GIT_VERSION_INFO.commit_short)] - """ - LibGit2.add!(repo, files..., flags = LibGit2.Consts.INDEX_ADD_FORCE) - if isnew - info("Committing $pkg generated files") - LibGit2.commit(repo, msg) - elseif LibGit2.isdirty(repo) - LibGit2.remove!(repo, files...) - info("Regenerated files left unstaged, use `git add -p` to select") - open(io->print(io,msg), joinpath(LibGit2.gitdir(repo),"MERGE_MSG"), "w") - else - info("Regenerated files are unchanged") - end - end - catch - isnew && rm(pkg, recursive=true) - rethrow() - end - return -end - -function init(pkg::AbstractString, url::AbstractString=""; config::Dict=Dict()) - if !ispath(pkg) - info("Initializing $pkg repo: $(abspath(pkg))") - repo = LibGit2.init(pkg) - try - with(GitConfig, repo) do cfg - for (key,val) in config - LibGit2.set!(cfg, key, val) - end - end - LibGit2.commit(repo, "initial empty commit") - catch err - throw(PkgError("Unable to initialize $pkg package: $err")) - end - else - repo = GitRepo(pkg) - end - try - if !isempty(url) - info("Origin: $url") - with(LibGit2.GitRemote, repo, "origin", url) do rmt - LibGit2.save(rmt) - end - LibGit2.set_remote_url(repo, url) - end - end - return repo -end - -function genfile(f::Function, pkg::AbstractString, file::AbstractString, force::Bool=false) - path = joinpath(pkg,file) - if force || !ispath(path) - info("Generating $file") - mkpath(dirname(path)) - open(f, path, "w") - return file - end - return "" -end - -function license(pkg::AbstractString, - license::AbstractString, - years::Union{Int,AbstractString}, - authors::Union{AbstractString,Array}; - force::Bool=false) - file = genfile(pkg,"LICENSE.md",force) do io - if !haskey(LICENSES,license) - licenses = join(sort!(collect(keys(LICENSES)), by=lowercase), ", ") - throw(PkgError("$license is not a known license choice, choose one of: $licenses.")) - end - print(io, LICENSES[license](pkg, string(years), authors)) - end - !isempty(file) || info("License file exists, leaving unmodified; use `force=true` to overwrite") - file -end - -function readme(pkg::AbstractString, user::AbstractString=""; force::Bool=false) - genfile(pkg,"README.md",force) do io - println(io, "# $pkg") - isempty(user) && return - url = "https://travis-ci.org/$user/$pkg.jl" - println(io, "\n[![Build Status]($url.svg?branch=master)]($url)") - end -end - -function tests(pkg::AbstractString; force::Bool=false) - genfile(pkg,"test/runtests.jl",force) do io - print(io, """ - using $pkg - using Base.Test - - # write your own tests here - @test 1 == 1 - """) - end -end - -function versionfloor(ver::VersionNumber) - # return "major.minor" for the most recent release version relative to ver - # for prereleases with ver.minor == ver.patch == 0, return "major-" since we - # don't know what the most recent minor version is for the previous major - if isempty(ver.prerelease) || ver.patch > 0 - return string(ver.major, '.', ver.minor) - elseif ver.minor > 0 - return string(ver.major, '.', ver.minor - 1) - else - return string(ver.major, '-') - end -end - -function require(pkg::AbstractString; force::Bool=false) - genfile(pkg,"REQUIRE",force) do io - print(io, """ - julia $(versionfloor(VERSION)) - """) - end -end - -function travis(pkg::AbstractString; force::Bool=false) - genfile(pkg,".travis.yml",force) do io - print(io, """ - # Documentation: http://docs.travis-ci.com/user/languages/julia/ - language: julia - os: - - linux - - osx - julia: - - release - - nightly - notifications: - email: false - # uncomment the following lines to override the default test script - #script: - # - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - # - julia -e 'Pkg.clone(pwd()); Pkg.build("$pkg"); Pkg.test("$pkg"; coverage=true)' - """) - end -end - -function appveyor(pkg::AbstractString; force::Bool=false) - vf = versionfloor(VERSION) - if vf[end] == '-' # don't know what previous release was - vf = string(VERSION.major, '.', VERSION.minor) - rel32 = "# - JULIAVERSION: \"julialang/bin/winnt/x86/$vf/julia-$vf-latest-win32.exe\"" - rel64 = "# - JULIAVERSION: \"julialang/bin/winnt/x64/$vf/julia-$vf-latest-win64.exe\"" - else - rel32 = " - JULIAVERSION: \"julialang/bin/winnt/x86/$vf/julia-$vf-latest-win32.exe\"" - rel64 = " - JULIAVERSION: \"julialang/bin/winnt/x64/$vf/julia-$vf-latest-win64.exe\"" - end - genfile(pkg,"appveyor.yml",force) do io - print(io, """ - environment: - matrix: - $rel32 - $rel64 - - JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe" - - JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe" - - branches: - only: - - master - - /release-.*/ - - notifications: - - provider: Email - on_build_success: false - on_build_failure: false - on_build_status_changed: false - - install: - # Download most recent Julia Windows binary - - ps: (new-object net.webclient).DownloadFile( - \$("http://s3.amazonaws.com/"+\$env:JULIAVERSION), - "C:\\projects\\julia-binary.exe") - # Run installer silently, output to C:\\projects\\julia - - C:\\projects\\julia-binary.exe /S /D=C:\\projects\\julia - - build_script: - # Need to convert from shallow to complete for Pkg.clone to work - - IF EXIST .git\\shallow (git fetch --unshallow) - - C:\\projects\\julia\\bin\\julia -e "versioninfo(); - Pkg.clone(pwd(), \\"$pkg\\"); Pkg.build(\\"$pkg\\")" - - test_script: - - C:\\projects\\julia\\bin\\julia --check-bounds=yes -e "Pkg.test(\\"$pkg\\")" - """) - end -end - -function gitignore(pkg::AbstractString; force::Bool=false) - genfile(pkg,".gitignore",force) do io - print(io, """ - *.jl.cov - *.jl.*.cov - *.jl.mem - """) - end -end - -function entrypoint(pkg::AbstractString; force::Bool=false) - genfile(pkg,"src/$pkg.jl",force) do io - print(io, """ - module $pkg - - # package code goes here - - end # module - """) - end -end - -copyright(years::AbstractString, authors::AbstractString) = "> Copyright (c) $years: $authors." - -function copyright(years::AbstractString, authors::Array) - text = "> Copyright (c) $years:" - for author in authors - text *= "\n> * $author" - end - return text -end - -mit(pkg::AbstractString, years::AbstractString, authors::Union{AbstractString,Array}) = -""" -The $pkg.jl package is licensed under the MIT "Expat" License: - -$(copyright(years,authors)) -> -> Permission is hereby granted, free of charge, to any person obtaining -> a copy of this software and associated documentation files (the -> "Software"), to deal in the Software without restriction, including -> without limitation the rights to use, copy, modify, merge, publish, -> distribute, sublicense, and/or sell copies of the Software, and to -> permit persons to whom the Software is furnished to do so, subject to -> the following conditions: -> -> The above copyright notice and this permission notice shall be -> included in all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -""" - -bsd(pkg::AbstractString, years::AbstractString, authors::Union{AbstractString,Array}) = -""" -The $pkg.jl package is licensed under the Simplified "2-clause" BSD License: - -$(copyright(years,authors)) -> -> Redistribution and use in source and binary forms, with or without -> modification, are permitted provided that the following conditions are -> met: -> -> 1. Redistributions of source code must retain the above copyright -> notice, this list of conditions and the following disclaimer. -> 2. Redistributions in binary form must reproduce the above copyright -> notice, this list of conditions and the following disclaimer in the -> documentation and/or other materials provided with the distribution. -> -> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -> A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -> OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -> SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -> LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -> DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -> THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -""" - -asl(pkg::AbstractString, years::AbstractString, authors::Union{AbstractString,Array}) = -""" -The $pkg.jl package is licensed under version 2.0 of the Apache License: - -$(copyright(years,authors)) -> -> Apache License -> Version 2.0, January 2004 -> http://www.apache.org/licenses/ -> -> TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -> -> 1. Definitions. -> -> "License" shall mean the terms and conditions for use, reproduction, -> and distribution as defined by Sections 1 through 9 of this document. -> -> "Licensor" shall mean the copyright owner or entity authorized by -> the copyright owner that is granting the License. -> -> "Legal Entity" shall mean the union of the acting entity and all -> other entities that control, are controlled by, or are under common -> control with that entity. For the purposes of this definition, -> "control" means (i) the power, direct or indirect, to cause the -> direction or management of such entity, whether by contract or -> otherwise, or (ii) ownership of fifty percent (50%) or more of the -> outstanding shares, or (iii) beneficial ownership of such entity. -> -> "You" (or "Your") shall mean an individual or Legal Entity -> exercising permissions granted by this License. -> -> "Source" form shall mean the preferred form for making modifications, -> including but not limited to software source code, documentation -> source, and configuration files. -> -> "Object" form shall mean any form resulting from mechanical -> transformation or translation of a Source form, including but -> not limited to compiled object code, generated documentation, -> and conversions to other media types. -> -> "Work" shall mean the work of authorship, whether in Source or -> Object form, made available under the License, as indicated by a -> copyright notice that is included in or attached to the work -> (an example is provided in the Appendix below). -> -> "Derivative Works" shall mean any work, whether in Source or Object -> form, that is based on (or derived from) the Work and for which the -> editorial revisions, annotations, elaborations, or other modifications -> represent, as a whole, an original work of authorship. For the purposes -> of this License, Derivative Works shall not include works that remain -> separable from, or merely link (or bind by name) to the interfaces of, -> the Work and Derivative Works thereof. -> -> "Contribution" shall mean any work of authorship, including -> the original version of the Work and any modifications or additions -> to that Work or Derivative Works thereof, that is intentionally -> submitted to Licensor for inclusion in the Work by the copyright owner -> or by an individual or Legal Entity authorized to submit on behalf of -> the copyright owner. For the purposes of this definition, "submitted" -> means any form of electronic, verbal, or written communication sent -> to the Licensor or its representatives, including but not limited to -> communication on electronic mailing lists, source code control systems, -> and issue tracking systems that are managed by, or on behalf of, the -> Licensor for the purpose of discussing and improving the Work, but -> excluding communication that is conspicuously marked or otherwise -> designated in writing by the copyright owner as "Not a Contribution." -> -> "Contributor" shall mean Licensor and any individual or Legal Entity -> on behalf of whom a Contribution has been received by Licensor and -> subsequently incorporated within the Work. -> -> 2. Grant of Copyright License. Subject to the terms and conditions of -> this License, each Contributor hereby grants to You a perpetual, -> worldwide, non-exclusive, no-charge, royalty-free, irrevocable -> copyright license to reproduce, prepare Derivative Works of, -> publicly display, publicly perform, sublicense, and distribute the -> Work and such Derivative Works in Source or Object form. -> -> 3. Grant of Patent License. Subject to the terms and conditions of -> this License, each Contributor hereby grants to You a perpetual, -> worldwide, non-exclusive, no-charge, royalty-free, irrevocable -> (except as stated in this section) patent license to make, have made, -> use, offer to sell, sell, import, and otherwise transfer the Work, -> where such license applies only to those patent claims licensable -> by such Contributor that are necessarily infringed by their -> Contribution(s) alone or by combination of their Contribution(s) -> with the Work to which such Contribution(s) was submitted. If You -> institute patent litigation against any entity (including a -> cross-claim or counterclaim in a lawsuit) alleging that the Work -> or a Contribution incorporated within the Work constitutes direct -> or contributory patent infringement, then any patent licenses -> granted to You under this License for that Work shall terminate -> as of the date such litigation is filed. -> -> 4. Redistribution. You may reproduce and distribute copies of the -> Work or Derivative Works thereof in any medium, with or without -> modifications, and in Source or Object form, provided that You -> meet the following conditions: -> -> (a) You must give any other recipients of the Work or -> Derivative Works a copy of this License; and -> -> (b) You must cause any modified files to carry prominent notices -> stating that You changed the files; and -> -> (c) You must retain, in the Source form of any Derivative Works -> that You distribute, all copyright, patent, trademark, and -> attribution notices from the Source form of the Work, -> excluding those notices that do not pertain to any part of -> the Derivative Works; and -> -> (d) If the Work includes a "NOTICE" text file as part of its -> distribution, then any Derivative Works that You distribute must -> include a readable copy of the attribution notices contained -> within such NOTICE file, excluding those notices that do not -> pertain to any part of the Derivative Works, in at least one -> of the following places: within a NOTICE text file distributed -> as part of the Derivative Works; within the Source form or -> documentation, if provided along with the Derivative Works; or, -> within a display generated by the Derivative Works, if and -> wherever such third-party notices normally appear. The contents -> of the NOTICE file are for informational purposes only and -> do not modify the License. You may add Your own attribution -> notices within Derivative Works that You distribute, alongside -> or as an addendum to the NOTICE text from the Work, provided -> that such additional attribution notices cannot be construed -> as modifying the License. -> -> You may add Your own copyright statement to Your modifications and -> may provide additional or different license terms and conditions -> for use, reproduction, or distribution of Your modifications, or -> for any such Derivative Works as a whole, provided Your use, -> reproduction, and distribution of the Work otherwise complies with -> the conditions stated in this License. -> -> 5. Submission of Contributions. Unless You explicitly state otherwise, -> any Contribution intentionally submitted for inclusion in the Work -> by You to the Licensor shall be under the terms and conditions of -> this License, without any additional terms or conditions. -> Notwithstanding the above, nothing herein shall supersede or modify -> the terms of any separate license agreement you may have executed -> with Licensor regarding such Contributions. -> -> 6. Trademarks. This License does not grant permission to use the trade -> names, trademarks, service marks, or product names of the Licensor, -> except as required for reasonable and customary use in describing the -> origin of the Work and reproducing the content of the NOTICE file. -> -> 7. Disclaimer of Warranty. Unless required by applicable law or -> agreed to in writing, Licensor provides the Work (and each -> Contributor provides its Contributions) on an "AS IS" BASIS, -> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -> implied, including, without limitation, any warranties or conditions -> of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -> PARTICULAR PURPOSE. You are solely responsible for determining the -> appropriateness of using or redistributing the Work and assume any -> risks associated with Your exercise of permissions under this License. -> -> 8. Limitation of Liability. In no event and under no legal theory, -> whether in tort (including negligence), contract, or otherwise, -> unless required by applicable law (such as deliberate and grossly -> negligent acts) or agreed to in writing, shall any Contributor be -> liable to You for damages, including any direct, indirect, special, -> incidental, or consequential damages of any character arising as a -> result of this License or out of the use or inability to use the -> Work (including but not limited to damages for loss of goodwill, -> work stoppage, computer failure or malfunction, or any and all -> other commercial damages or losses), even if such Contributor -> has been advised of the possibility of such damages. -> -> 9. Accepting Warranty or Additional Liability. While redistributing -> the Work or Derivative Works thereof, You may choose to offer, -> and charge a fee for, acceptance of support, warranty, indemnity, -> or other liability obligations and/or rights consistent with this -> License. However, in accepting such obligations, You may act only -> on Your own behalf and on Your sole responsibility, not on behalf -> of any other Contributor, and only if You agree to indemnify, -> defend, and hold each Contributor harmless for any liability -> incurred by, or claims asserted against, such Contributor by reason -> of your accepting any such warranty or additional liability. -""" - -const LICENSES = Dict("MIT" => mit, "BSD" => bsd, "ASL" => asl) - -end # module From 698fa612f68bb22e2370b267d9b9b5a472cf1550 Mon Sep 17 00:00:00 2001 From: wildart Date: Wed, 30 Sep 2015 15:41:03 -0400 Subject: [PATCH 2/4] removed dev related tests --- test/pkg.jl | 121 ---------------------------------------------------- 1 file changed, 121 deletions(-) diff --git a/test/pkg.jl b/test/pkg.jl index f0c56efc82d41..c27cda05b7318 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -115,124 +115,3 @@ temp_pkg_dir() do Pkg.rm("Example") @test isempty(Pkg.installed()) end - -# testing a package with test dependencies causes them to be installed for the duration of the test -temp_pkg_dir() do - Pkg.generate("PackageWithTestDependencies", "MIT", config=Dict("user.name"=>"Julia Test", "user.email"=>"test@julialang.org")) - @test [keys(Pkg.installed())...] == ["PackageWithTestDependencies"] - @test readall(Pkg.dir("PackageWithTestDependencies","REQUIRE")) == "julia $(Pkg.Generate.versionfloor(VERSION))\n" - - isdir(Pkg.dir("PackageWithTestDependencies","test")) || mkdir(Pkg.dir("PackageWithTestDependencies","test")) - open(Pkg.dir("PackageWithTestDependencies","test","REQUIRE"),"w") do f - println(f,"Example") - end - - open(Pkg.dir("PackageWithTestDependencies","test","runtests.jl"),"w") do f - println(f,"using Base.Test") - println(f,"@test haskey(Pkg.installed(), \"Example\")") - end - - Pkg.resolve() - @test [keys(Pkg.installed())...] == ["PackageWithTestDependencies"] - - Pkg.test("PackageWithTestDependencies") - - @test [keys(Pkg.installed())...] == ["PackageWithTestDependencies"] - - # trying to pin an unregistered package errors - try - Pkg.pin("PackageWithTestDependencies", v"1.0.0") - error("unexpected") - catch err - @test isa(err, PkgError) - @test err.msg == "PackageWithTestDependencies cannot be pinned – not a registered package" - end -end - -# testing a package with no runtests.jl errors -temp_pkg_dir() do - Pkg.generate("PackageWithNoTests", "MIT", config=Dict("user.name"=>"Julia Test", "user.email"=>"test@julialang.org")) - - if isfile(Pkg.dir("PackageWithNoTests", "test", "runtests.jl")) - rm(Pkg.dir("PackageWithNoTests", "test", "runtests.jl")) - end - - try - Pkg.test("PackageWithNoTests") - error("unexpected") - catch err - @test err.msg == "PackageWithNoTests did not provide a test/runtests.jl file" - end -end - -# testing a package with failing tests errors -temp_pkg_dir() do - Pkg.generate("PackageWithFailingTests", "MIT", config=Dict("user.name"=>"Julia Test", "user.email"=>"test@julialang.org")) - - isdir(Pkg.dir("PackageWithFailingTests","test")) || mkdir(Pkg.dir("PackageWithFailingTests","test")) - open(Pkg.dir("PackageWithFailingTests", "test", "runtests.jl"),"w") do f - println(f,"using Base.Test") - println(f,"@test false") - end - - try - Pkg.test("PackageWithFailingTests") - error("unexpected") - catch err - @test err.msg == "PackageWithFailingTests had test errors" - end -end - -# Testing with code-coverage -temp_pkg_dir() do - Pkg.generate("PackageWithCodeCoverage", "MIT", config=Dict("user.name"=>"Julia Test", "user.email"=>"test@julialang.org")) - - src = """ -module PackageWithCodeCoverage - -export f1, f2, f3, untested - -f1(x) = 2x -f2(x) = f1(x) -function f3(x) - 3x -end -untested(x) = 7 - -end""" - linetested = [false, false, false, false, true, true, false, true, false, false] - open(Pkg.dir("PackageWithCodeCoverage", "src", "PackageWithCodeCoverage.jl"), "w") do f - println(f, src) - end - isdir(Pkg.dir("PackageWithCodeCoverage","test")) || mkdir(Pkg.dir("PackageWithCodeCoverage","test")) - open(Pkg.dir("PackageWithCodeCoverage", "test", "runtests.jl"),"w") do f - println(f,"using PackageWithCodeCoverage, Base.Test") - println(f,"@test f2(2) == 4") - println(f,"@test f3(5) == 15") - end - - Pkg.test("PackageWithCodeCoverage") - covdir = Pkg.dir("PackageWithCodeCoverage","src") - covfiles = filter!(x -> contains(x, "PackageWithCodeCoverage.jl") && contains(x,".cov"), readdir(covdir)) - @test isempty(covfiles) - Pkg.test("PackageWithCodeCoverage", coverage=true) - covfiles = filter!(x -> contains(x, "PackageWithCodeCoverage.jl") && contains(x,".cov"), readdir(covdir)) - @test !isempty(covfiles) - for file in covfiles - @test isfile(joinpath(covdir,file)) - covstr = readall(joinpath(covdir,file)) - srclines = split(src, '\n') - covlines = split(covstr, '\n') - for i = 1:length(linetested) - covline = (linetested[i] ? " 1 " : " - ")*srclines[i] - @test covlines[i] == covline - end - end -end - -# issue #13374 -temp_pkg_dir() do - Pkg.generate("Foo", "MIT", config=Dict("user.name"=>"Julia Test", "user.email"=>"test@julialang.org")) - Pkg.tag("Foo") - Pkg.tag("Foo") -end From fcfac39e7d29b34dd8cd71158d74c9de673009bb Mon Sep 17 00:00:00 2001 From: wildart Date: Mon, 5 Oct 2015 01:10:53 -0400 Subject: [PATCH 3/4] fix test helper to keep generated data --- test/pkg.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/pkg.jl b/test/pkg.jl index c27cda05b7318..24f344735d23f 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -2,7 +2,7 @@ import Base.Pkg.PkgError -function temp_pkg_dir(fn::Function) +function temp_pkg_dir(fn::Function, remove_tmp_dir::Bool=true) # Used in tests below to setup and teardown a sandboxed package directory const tmpdir = ENV["JULIA_PKGDIR"] = joinpath(tempdir(),randstring()) @test !isdir(Pkg.dir()) @@ -13,7 +13,7 @@ function temp_pkg_dir(fn::Function) fn() finally - rm(tmpdir, recursive=true) + remove_tmp_dir && rm(tmpdir, recursive=true) end end From c07de056afc6ae6b33837279b74005d01bfb5754 Mon Sep 17 00:00:00 2001 From: wildart Date: Wed, 7 Oct 2015 22:48:39 -0400 Subject: [PATCH 4/4] removed github module --- base/pkg.jl | 4 +- base/pkg/entry.jl | 2 +- base/pkg/github.jl | 144 --------------------------------------------- 3 files changed, 3 insertions(+), 147 deletions(-) delete mode 100644 base/pkg/github.jl diff --git a/base/pkg.jl b/base/pkg.jl index 73596f6779315..fb7d3fbde2a35 100644 --- a/base/pkg.jl +++ b/base/pkg.jl @@ -2,7 +2,7 @@ module Pkg -export Git, Dir, GitHub, Types, Reqs, Cache, Read, Query, Resolve, Write, Entry, Git +export Git, Dir, Types, Reqs, Cache, Read, Query, Resolve, Write, Entry, Git export dir, init, rm, add, available, installed, status, clone, checkout, update, resolve, test, build, free, pin, PkgError @@ -13,7 +13,7 @@ type PkgError <: Exception msg::AbstractString end -for file in split("dir github types reqs cache read query resolve write entry git") +for file in split("dir types reqs cache read query resolve write entry git") include("pkg/$file.jl") end const cd = Dir.cd diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index c9dec1a77e572..a487d732e3f91 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -3,7 +3,7 @@ module Entry import Base: thispatch, nextpatch, nextminor, nextmajor, check_new_version -import ..Reqs, ..Read, ..Query, ..Resolve, ..Cache, ..Write, ..GitHub, ..Dir +import ..Reqs, ..Read, ..Query, ..Resolve, ..Cache, ..Write, ..Dir import ...LibGit2 importall ...LibGit2 import ...Pkg.PkgError diff --git a/base/pkg/github.jl b/base/pkg/github.jl deleted file mode 100644 index 1eced0e9aa99c..0000000000000 --- a/base/pkg/github.jl +++ /dev/null @@ -1,144 +0,0 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license - -module GitHub - -import Main, ...LibGit2, ..Dir, ...Pkg.PkgError - -const AUTH_NOTE = "Julia Package Manager" -const AUTH_DATA = Dict{Any,Any}( - "scopes" => ["repo"], - "note" => AUTH_NOTE, - "note_url" => "http://docs.julialang.org/en/latest/manual/packages/", -) - -function user() - usr = LibGit2.getconfig("github.user", "") - if isempty(usr) #TODO: add `config` command to Git REPL and change below info - throw(PkgError(""" - no GitHub user name configured; please configure it with: - - git config --global github.user USERNAME - - where USERNAME is replaced with your GitHub user name. - """)) - end - return usr -end - -function json() - isdefined(:JSON) || try eval(Main, :(import JSON)) - catch err - warn(err) - throw(PkgError("using the GitHub API requires having the JSON package installed ")) - end - Main.JSON -end - -function curl(url::AbstractString, opts::Cmd=``) - success(`curl --version`) || throw(PkgError("using the GitHub API requires having `curl` installed")) - out, proc = open(`curl -i -s -S $opts $url`,"r") - head = readline(out) - status = parse(Int,split(head,r"\s+";limit=3)[2]) - header = Dict{AbstractString,AbstractString}() - for line in eachline(out) - if !ismatch(r"^\s*$",line) - (k,v) = split(line, r":\s*"; limit=2) - header[k] = v - continue - end - wait(proc); return status, header, readall(out) - end - throw(PkgError("strangely formatted HTTP response")) -end -curl(url::AbstractString, data::Void, opts::Cmd=``) = curl(url,opts) -curl(url::AbstractString, data, opts::Cmd=``) = - curl(url,`--data $(sprint(io->json().print(io,data))) $opts`) - -function delete_token() - tokfile = Dir.path(".github","token") - Base.rm(tokfile) - info("Could not authenticate with existing token. Deleting token and trying again.") -end - -readtoken(tokfile=Dir.path(".github","token")) = isfile(tokfile) ? strip(readchomp(tokfile)) : "" - -function token(user::AbstractString=user()) - tokfile = Dir.path(".github","token") - tok = readtoken(tokfile) - !isempty(tok) && return tok - - params = merge(AUTH_DATA, Dict("fingerprint" => randstring(40))) - status, header, content = curl("https://api.github.com/authorizations",params,`-u $user`) - tfa = false - - # Check for two-factor authentication - if status == 401 && get(header, "X-GitHub-OTP", "") |> x->startswith(x, "required") && isinteractive() - tfa = true - info("Two-factor authentication in use. Enter auth code. (You may have to re-enter your password.)") - print(STDERR, "Authentication code: ") - code = readline(STDIN) |> chomp - status, header, content = curl("https://api.github.com/authorizations",params,`-H "X-GitHub-OTP: $code" -u $user`) - end - - if status == 422 - error_code = json().parse(content)["errors"][1]["code"] - throw(PkgError("GitHub returned validation error (422): $error_code: $(json().parse(content)["message"])")) - else - (status != 401 && status != 403) || throw(PkgError("$status: $(json().parse(content)["message"])")) - tok = json().parse(content)["token"] - end - - mkpath(dirname(tokfile)) - open(io->println(io,tok),tokfile,"w") - return tok -end - -function req(resource::AbstractString, data, opts::Cmd=``) - url = "https://api.github.com/$resource" - status, header, content = curl(url,data,`-u $(token()):x-oauth-basic $opts`) - response = json().parse(content) - status, response -end - -GET(resource::AbstractString, data, opts::Cmd=``) = req(resource,data,opts) -HEAD(resource::AbstractString, data, opts::Cmd=``) = req(resource,data,`-I $opts`) -PUT(resource::AbstractString, data, opts::Cmd=``) = req(resource,data,`-X PUT $opts`) -POST(resource::AbstractString, data, opts::Cmd=``) = req(resource,data,`-X POST $opts`) -PATCH(resource::AbstractString, data, opts::Cmd=``) = req(resource,data,`-X PATCH $opts`) -DELETE(resource::AbstractString, data, opts::Cmd=``) = req(resource,data,`-X DELETE $opts`) - -for m in (:GET,:HEAD,:PUT,:POST,:PATCH,:DELETE) - @eval $m(resource::AbstractString, opts::Cmd=``) = $m(resource,nothing,opts) -end - -function pushable(owner::AbstractString, repo::AbstractString, user::AbstractString=user()) - status, response = HEAD("repos/$owner/$repo") - status == 404 && throw(PkgError("repo $owner/$repo does not exist")) - status, response = GET("repos/$owner/$repo/collaborators/$user") - status == 204 && return true - status == 404 && return false - throw(PkgError("unexpected API status code: $status – $(response["message"])")) -end - -function fork(owner::AbstractString, repo::AbstractString) - status, response = POST("repos/$owner/$repo/forks") - if status == 401 - delete_token() - status, response = POST("repos/$owner/$repo/forks") - end - status == 202 || throw(PkgError("forking $owner/$repo failed: $(response["message"])")) - return response -end - -function normalize_url(url::AbstractString) - m = match(LibGit2.GITHUB_REGEX,url) - m === nothing ? url : "https://github.com/$(m.captures[1]).git" -end - -function credentials() - username = try user() catch "" end - password = readtoken() - return Nullable(LibGit2.UserPasswordCredentials(username, password)) -end - -end # module