mirror of https://github.com/k3s-io/k3s
Remove third_party/forked/godep
parent
b3527f41f0
commit
7f246d461b
|
@ -404,34 +404,6 @@ kube::util::ensure_clean_working_dir() {
|
|||
done 1>&2
|
||||
}
|
||||
|
||||
# Ensure that the given godep version is installed and in the path. Almost
|
||||
# nobody should use any version but the default.
|
||||
#
|
||||
# Sets:
|
||||
# KUBE_GODEP: The path to the godep binary
|
||||
#
|
||||
kube::util::ensure_godep_version() {
|
||||
local godep_target_version=${1:-"v80-k8s-r1"} # this version is known to work
|
||||
|
||||
# If KUBE_GODEP is already set, and it's the right version, then use it.
|
||||
if [[ -n "${KUBE_GODEP:-}" && "$(${KUBE_GODEP:?} version 2>/dev/null)" == *"godep ${godep_target_version}"* ]]; then
|
||||
kube::log::status "Using ${KUBE_GODEP}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Otherwise, install forked godep
|
||||
kube::log::status "Installing godep version ${godep_target_version}"
|
||||
GOBIN="${KUBE_OUTPUT_BINPATH}" go install k8s.io/kubernetes/third_party/forked/godep
|
||||
export KUBE_GODEP="${KUBE_OUTPUT_BINPATH}/godep"
|
||||
kube::log::status "Installed ${KUBE_GODEP}"
|
||||
|
||||
# Verify that the installed godep from fork is what we expect
|
||||
if [[ "$(${KUBE_GODEP:?} version 2>/dev/null)" != *"godep ${godep_target_version}"* ]]; then
|
||||
kube::log::error "Expected godep ${godep_target_version} from ${KUBE_GODEP}, got $(${KUBE_GODEP:?} version)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensure that none of the staging repos is checked out in the GOPATH because this
|
||||
# easily confused godep.
|
||||
kube::util::ensure_no_staging_repos_in_gopath() {
|
||||
|
|
|
@ -22,7 +22,6 @@ filegroup(
|
|||
"//third_party/forked/etcd221/wal:all-srcs",
|
||||
"//third_party/forked/etcd237/pkg/fileutil:all-srcs",
|
||||
"//third_party/forked/etcd237/wal:all-srcs",
|
||||
"//third_party/forked/godep:all-srcs",
|
||||
"//third_party/forked/golang/expansion:all-srcs",
|
||||
"//third_party/forked/golang/reflect:all-srcs",
|
||||
"//third_party/forked/golang/template:all-srcs",
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/godep
|
|
@ -1,34 +0,0 @@
|
|||
language: go
|
||||
sudo: false
|
||||
go: 1.6
|
||||
script:
|
||||
# Godep's unit tests run git, and git complains
|
||||
# if we don't set these config parameters.
|
||||
# We put dummy values here because they don't matter.
|
||||
- git config --global user.email "you@example.com"
|
||||
- git config --global user.name "Your Name"
|
||||
- test -z "$(go fmt)"
|
||||
- go vet
|
||||
- go test -v
|
||||
- go test -v -race
|
||||
- test -z "$(goimports -l .)"
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/goimports
|
||||
before_deploy:
|
||||
- export OS_TARGETS="linux darwin windows"
|
||||
- export ARCH_TARGETS="386 amd64"
|
||||
- go get github.com/mitchellh/gox
|
||||
- gox -os "$OS_TARGETS" -arch="$ARCH_TARGETS"
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: Q1JP8LziaXMTxFmNXiyC1YhS9e4M4WnI6UDjRTMf6mm1LZeJyUFOCCtXnifL7RyCIR1hpjp6s8M1aWE+NpuweF96IZI3Uk4ASx5C8FePC4qvhsCdtJ2sLD2GTIrp9b0MS9/+ao20AIbpVDSaLaF9IjqXpMxMyM0P8P5coRTkwItlGxmQbVJW3YuiYcPa8UojwM4EyafO2CIoUKapW8lwb9KcimBJV8PfF/XZjPVhMkn2ABhh5Hqbn2zBJtvPYMMzi0CnY50JQF5LwN3vGTMpTsRP+lOLCNbOWfkl+2hgG7VpKrtx+cX62knOodpF457sIJ31KUzmeLUVBejTGb1zuVeTojuyi8Huo8YBIBCcN+p3Dqd+n2ZK45mIrheGiEJIkf/vI4MI6A01Nu/o+xU0IPsVfAL/xU5j5nntEGfFWVoclPrl9qcfqf74xdRcARzcCJVmdc8iw49DBDHJfnPa3zxzVz//00+Rz6mZXmhk+Npk/HLLNW59vmJIjP+8XOtPor7dST9HrS1a9AcnmIjNuw9yfbwK5769SDVxCKgqNwXW/Dy5F39aIH5AL4I4y9hCEeeT8ctvSJHGOyiB9MWU5jnt5tluPtz5opG51tFXnIYP/XaWpTfO+eJ6x55pbwT+n3LfRS5l1POM+jGAFF1MFWwc14RY7qynEIEzm4Wb/UE=
|
||||
file:
|
||||
- godep_darwin_amd64
|
||||
- godep_linux_amd64
|
||||
- godep_windows_386.exe
|
||||
- godep_windows_amd64.exe
|
||||
on:
|
||||
tags: true
|
||||
repo: tools/godep
|
|
@ -1,57 +0,0 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"dep.go",
|
||||
"diff.go",
|
||||
"doc.go",
|
||||
"errors.go",
|
||||
"get.go",
|
||||
"go.go",
|
||||
"godepfile.go",
|
||||
"license.go",
|
||||
"list.go",
|
||||
"main.go",
|
||||
"msg.go",
|
||||
"path.go",
|
||||
"pkg.go",
|
||||
"restore.go",
|
||||
"rewrite.go",
|
||||
"save.go",
|
||||
"update.go",
|
||||
"util.go",
|
||||
"vcs.go",
|
||||
"version.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/third_party/forked/godep",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//vendor/github.com/kr/fs:go_default_library",
|
||||
"//vendor/github.com/kr/pretty:go_default_library",
|
||||
"//vendor/github.com/pmezard/go-difflib/difflib:go_default_library",
|
||||
"//vendor/golang.org/x/tools/go/vcs:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "godep",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -1,412 +0,0 @@
|
|||
#v80 (2018/01/26)
|
||||
|
||||
* Address lin/vet feedback.
|
||||
|
||||
#v79 (2017/02/01)
|
||||
|
||||
* Fixes #531: fullPackageInDir didn't capture the error from fillPackage()
|
||||
|
||||
#v78 (2017/01/19)
|
||||
|
||||
* Don't use build.ImportDir when discovering packages for the package spec. Fixes #529
|
||||
|
||||
#v77 (2017/01/13)
|
||||
|
||||
* Don't include quotes around hg revisions
|
||||
|
||||
#v76 (2017/01/10)
|
||||
|
||||
* Default to vendor being on unless older go versions.
|
||||
|
||||
#v75 (2016/11/02)
|
||||
|
||||
* Add "AUTHORS" and "CONTRIBUTORS" to legal files list: https://github.com/tools/godep/pull/522
|
||||
|
||||
#v74 (2016/06/01)
|
||||
|
||||
* Enable vendor/ on go1.7
|
||||
* No longer use a godep workspace, use vendor/ (yay!)
|
||||
* Notify that support for Godep workspaces will be removed once go1.8 ships
|
||||
|
||||
#v73 (2016/05/31)
|
||||
|
||||
* Fix permission changes on Windows via @alexbrand. Closes #481.
|
||||
|
||||
#v72 (2016/05/27)
|
||||
|
||||
* Improve handling of git remote show origin. Should help in cases where remote HEAD is ambiguous.
|
||||
* Add ISSUE_TEMPLATE
|
||||
|
||||
#v71 (2016/05/24)
|
||||
|
||||
* Preserve permissions on copied files.
|
||||
|
||||
#v70 (2016/05/20)
|
||||
|
||||
* Fix the May changelog dates
|
||||
* No need to call build.Import, we already have the root of the dependency. Fixes an additional comment on #365
|
||||
|
||||
#v69 (2016/05/16)
|
||||
|
||||
* Make sure `devel-<short sha>` enabled `vendor/` unless there is a classic Godep _workspace already.
|
||||
|
||||
#v68 (2016/05/16)
|
||||
|
||||
* `devel-<short sha>` is always considered newer than any released go version
|
||||
|
||||
#v67 (2016/05/13)
|
||||
|
||||
* Attempt to handle missing deps a little better.
|
||||
|
||||
#v66 (2016/05/10)
|
||||
|
||||
* Use `git remote show origin` to find the default branch when restoring a git based package repository that is in detached head state
|
||||
|
||||
#v65 (2016/05/09)
|
||||
|
||||
* Rewrite update so that it considers new transitive dependencies, both in the same repo and outside of it.
|
||||
|
||||
#v64 (2016/05/09)
|
||||
|
||||
* godep update golang.org/x/tools/go/vcs
|
||||
|
||||
#v63 (2016/05/03)
|
||||
|
||||
* Support recording devel-<short sha> so development versions of Go can be matched
|
||||
|
||||
#v62 (2016/04/07)
|
||||
|
||||
* Note new go1.6+ behavior of not checking out master in README / restore help text.
|
||||
|
||||
#v61 (2016/04/06)
|
||||
|
||||
* Obey go version build tags based on recorded major go version. Fixes #448.
|
||||
|
||||
#v60 (2016/03/18)
|
||||
|
||||
* Make the $GOPATH check a warning.
|
||||
|
||||
#v59 (2016/03/18)
|
||||
|
||||
* Enforce requirement to be inside of a go src directory. A lot of time is usually spent
|
||||
tracking down bug reports where people are doign stuff from outside of their $GOPATH. This
|
||||
should help with that, at least until there it time to properly test godep use outside of a
|
||||
$GOPATH and fix the issues.
|
||||
|
||||
#v58 (2016/03/15)
|
||||
|
||||
* Add GodepVersion to Godeps.json file so that as godep changes / adds features / fixes bugs we can know which version of godep most recently wrote out the file.
|
||||
|
||||
#v57 (2016/03/07)
|
||||
|
||||
* Don't use `git rev-parse --show-toplevel` to determine git repo roots as it resolves symlinks: https://github.com/tools/godep/pull/418
|
||||
|
||||
# v56 (2016/02/26)
|
||||
|
||||
* replace path comparisons with case insensitive pathEqual()
|
||||
* add versionString() to debug output
|
||||
* Send log output to Stderr
|
||||
|
||||
# v55 2016/02/22
|
||||
|
||||
* re-saved deps to clean out extra stuff (see v54; godep restore; godep save -r=false; rm -rf Godeps; godep save -r). We're still using a workspace with rewrites so users of older go version can still go get this tool.
|
||||
* Replace simple == with strings.EqualFold in listFiles to avoid problems with case insensitive filesystems ("Code" != "code" when doing a byte by byte comparison)
|
||||
|
||||
# v54 2016/02/22
|
||||
|
||||
* Update some docs around vendor/
|
||||
* More precise recording of dependencies. Removed recursive copying of sub directories of a package (precise vendoring). This should allow using `./...` with the go tool for compilation of project using `vendor/`. See https://github.com/tools/godep/pull/415
|
||||
|
||||
# v53 2016/02/11
|
||||
|
||||
* Disable VendorExperiment if a godep workspace already exists.
|
||||
|
||||
# v52 2016/01/27
|
||||
|
||||
* Trim 'rc' out of go version strings when determining major version.
|
||||
|
||||
# v51 2016/01/21
|
||||
|
||||
* Trim 'beta' out of go version strings when determining major version.
|
||||
|
||||
# v50 2016/01/19
|
||||
|
||||
* More verbose output on save -v.
|
||||
|
||||
# v49 2016/01/13
|
||||
|
||||
* Add UK spelling license/licence to the pile + fix up a bunch of typos
|
||||
* Clarify tag handling in docs
|
||||
|
||||
# v48 2016/01/13
|
||||
|
||||
* Abort restore if there is no $GOPATH set.
|
||||
|
||||
# v47 2016/01/12
|
||||
|
||||
* Dev versions of go should honor the current meaning of GO15VENDOREXPERIMENT
|
||||
|
||||
# v46 2016/01/03
|
||||
|
||||
* Record "devel" when the release is a devel release of go (compiled from git).
|
||||
|
||||
# v45 2015/12/28
|
||||
|
||||
* Upcase windows drive letters before comparing. Fixes #383.
|
||||
|
||||
# v44 2015/12/23
|
||||
|
||||
* Clean package roots when attempting to find a vendor directory so we don't loop forever.
|
||||
* Fixes 382
|
||||
|
||||
# v43 2015/12/22
|
||||
|
||||
* Better error messages when parsing Godeps.json: Fixes #372
|
||||
|
||||
# v42 2015/12/22
|
||||
|
||||
* Fix a bunch of GO15VENDOREXPERIMENT issues
|
||||
* Find package directories better. Previously we used build.FindOnly which didn't work the way I expected it to (any dir would work w/o error).
|
||||
* Set the VendorExperiment bool based on go version as 1.6 defaults to on.
|
||||
* A bunch of extra debugging for use while sanity checking myself.
|
||||
* vendor flag for test structs.
|
||||
* Some tests for vendor/ stuff:
|
||||
* Basic Test
|
||||
* Transitive
|
||||
* Transitive, across GOPATHs + collapse vendor/ directories.
|
||||
* Should Fix #358
|
||||
|
||||
# v41 2015/12/17
|
||||
|
||||
* Don't rewrite packages outside of the project. This would happen if you specified
|
||||
an external package for vendoring when you ran `goodep save -r ./... github.com/some/other/package`
|
||||
|
||||
# v40 2015/12/17
|
||||
|
||||
* When downloading a dependency, create the base directory if needed.
|
||||
|
||||
# v39 2015/12/16
|
||||
|
||||
* Record only the major go version (ex. go1.5) instead of the complete string.
|
||||
|
||||
# v38 2015/12/16
|
||||
|
||||
* Replace `go get`, further fix up restore error handling/reporting.
|
||||
* Fixes #186
|
||||
* Don't bother restoring/downloading if already done.
|
||||
|
||||
# v37 2015/12/15
|
||||
|
||||
* Change up how download/restore works a little
|
||||
* Try to load the package after downloading/restoring. Previously
|
||||
that was done too early in the process.
|
||||
* make previous verbose output debug output
|
||||
* report a typed error instead of a string from listPackage so it can
|
||||
be asserted to provide a nicer error.
|
||||
* Catch go get errors that say there are no go files found. See code
|
||||
comment as to why.
|
||||
* do *all* downloading during download phase.
|
||||
|
||||
# v36 2015/12/14
|
||||
|
||||
* Fixes #358: Using wrong variable. Will add test after release.
|
||||
|
||||
# v35 2015/12/11
|
||||
|
||||
* Fixes #356: Major performance regressions in v34
|
||||
* Enable cpu profiling via flag on save.
|
||||
* Cache packages by dir
|
||||
* Don't do a full import pass on deps for packages in the GOROOT
|
||||
* create a bit less garbage at times
|
||||
* Generalize -v & -d flags
|
||||
|
||||
# v34 2015/12/08
|
||||
|
||||
* We now use build.Context to help locate packages only and do our own parsing (via go/ast).
|
||||
* Fixes reported issues caused by v33 (Removal of `go list`):
|
||||
* #345: Bug in godep restore
|
||||
* #346: Fix loading a dot package
|
||||
* #348: Godep save issue when importing lib/pq
|
||||
* #350: undefined: build.MultiplePackageError
|
||||
* #351: stow away helper files
|
||||
* #353: cannot find package "appengine"
|
||||
* Don't process imports of `.go` files tagged with the `appengine` build tag.
|
||||
|
||||
# v33 2015/12/07
|
||||
|
||||
* Replace the use of `go list`. This is a large change although all existing tests pass.
|
||||
* Don't process the imports of `.go` files with the `ignore` build tag.
|
||||
|
||||
# v32 2015/12/02
|
||||
|
||||
* Eval Symlinks in Contains() check.
|
||||
|
||||
# v31 2015/12/02
|
||||
|
||||
* In restore, mention which package had the problem -- @shurcool
|
||||
|
||||
# v30 2015/11/25
|
||||
|
||||
* Add `-t` flag to the `godep get` command.
|
||||
|
||||
# v29 2015/11/17
|
||||
|
||||
* Temp work around to fix issue with LICENSE files.
|
||||
|
||||
# v28 2015/11/09
|
||||
|
||||
* Make `version` an actual command.
|
||||
|
||||
# v27 2015/11/06
|
||||
|
||||
* run command once during restore -v
|
||||
|
||||
# v26 2015/11/05
|
||||
|
||||
* Better fix for the issue fixed in v25: All update paths are now path.Clean()'d
|
||||
|
||||
# v25 2015/11/05
|
||||
|
||||
* `godep update package/` == `godep update package`. Fixes #313
|
||||
|
||||
# v24 2015/11/05
|
||||
|
||||
* Honor -t during update. Fixes #312
|
||||
|
||||
# v23 2015/11/05
|
||||
|
||||
* Do not use --debug to find full revision name for mercurial repositories
|
||||
|
||||
# v22 2015/11/14
|
||||
|
||||
* s/GOVENDOREXPERIMENT/GO15VENDOREXPERIMENT :-(
|
||||
|
||||
# v21 2015/11/13
|
||||
|
||||
* Fix #310: Case insensitive fs issue
|
||||
|
||||
# v20 2015/11/13
|
||||
|
||||
* Attempt to include license files when vendoring. (@client9)
|
||||
|
||||
# v19 2015/11/3
|
||||
|
||||
* Fix conflict error message. Revisions were swapped. Also better selection of package that needs update.
|
||||
|
||||
# v18 2015/10/16
|
||||
|
||||
* Improve error message when trying to save a conflicting revision.
|
||||
|
||||
# v17 2015/10/15
|
||||
|
||||
* Fix for v16 bug. All vcs list commands now produce paths relative to the root of the vcs.
|
||||
|
||||
# v16 2015/10/15
|
||||
|
||||
* Determine repo root using vcs commands and use that instead of dep.dir
|
||||
|
||||
# v15 2015/10/14
|
||||
|
||||
* Update .travis.yml file to do releases to github
|
||||
|
||||
# v14 2015/10/08
|
||||
|
||||
* Don't print out a workspace path when GO15VENDOREXPERIMENT is active. The vendor/ directory is not a valid workspace, so can't be added to your $GOPATH.
|
||||
|
||||
# v13 2015/10/07
|
||||
|
||||
* Do restores in 2 separate steps, first download all deps and then check out the recorded revisions.
|
||||
* Update Changelog date format
|
||||
|
||||
# v12 2015/09/22
|
||||
|
||||
* Extract errors into separate file.
|
||||
|
||||
# v11 2015/08/22
|
||||
|
||||
* Amend code to pass golint.
|
||||
|
||||
# v10 2015/09/21
|
||||
|
||||
* Analyse vendored package test dependencies.
|
||||
* Update documentation.
|
||||
|
||||
# v9 2015/09/17
|
||||
|
||||
* Don't save test dependencies by default.
|
||||
|
||||
# v8 2015/09/17
|
||||
|
||||
* Reorganize code.
|
||||
|
||||
# v7 2015/09/09
|
||||
|
||||
* Add verbose flag.
|
||||
* Skip untracked files.
|
||||
* Add VCS list command.
|
||||
|
||||
# v6 2015/09/04
|
||||
|
||||
* Revert ignoring testdata directories and instead ignore it while
|
||||
processing Go files and copy the whole directory unmodified.
|
||||
|
||||
# v5 2015/09/04
|
||||
|
||||
* Fix vcs selection in restore command to work as go get does
|
||||
|
||||
# v4 2015/09/03
|
||||
|
||||
* Remove the deprecated copy option.
|
||||
|
||||
# v3 2015/08/26
|
||||
|
||||
* Ignore testdata directories
|
||||
|
||||
# v2 2015/08/11
|
||||
|
||||
* Include command line packages in the set to copy
|
||||
|
||||
This is a simplification to how we define the behavior
|
||||
of the save command. Now it has two distinct package
|
||||
parameters, the "root set" and the "destination", and
|
||||
they have clearer roles. The packages listed on the
|
||||
command line form the root set; they and all their
|
||||
dependencies will be copied into the Godeps directory.
|
||||
Additionally, the destination (always ".") will form the
|
||||
initial list of "seen" import paths to exclude from
|
||||
copying.
|
||||
|
||||
In the common case, the root set is equal to the
|
||||
destination, so the effective behavior doesn't change.
|
||||
This is primarily just a simpler definition. However, if
|
||||
the user specifies a package on the command line that
|
||||
lives outside of . then that package will be copied.
|
||||
|
||||
As a side effect, there's a simplification to the way we
|
||||
add packages to the initial "seen" set. Formerly, to
|
||||
avoid copying dependencies unnecessarily, we would try
|
||||
to find the root of the VCS repo for each package in the
|
||||
root set, and mark the import path of the entire repo as
|
||||
seen. This meant for a repo at path C, if destination
|
||||
C/S imports C/T, we would not copy C/T into C/S/Godeps.
|
||||
Now we don't treat the repo root specially, and as
|
||||
mentioned above, the destination alone is considered
|
||||
seen.
|
||||
|
||||
This also means we don't require listed packages to be
|
||||
in VCS unless they're outside of the destination.
|
||||
|
||||
# v1 2015/07/20
|
||||
|
||||
* godep version command
|
||||
|
||||
Output the version as well as some godep runtime information that is
|
||||
useful for debugging user's issues.
|
||||
|
||||
The version const would be bumped each time a PR is merged into master
|
||||
to ensure that we'll be able to tell which version someone got when they
|
||||
did a `go get github.com/tools/godep`.
|
||||
|
||||
# Older changes
|
||||
|
||||
Many and more, see `git log -p`
|
|
@ -1,22 +0,0 @@
|
|||
## Why do I need to check in `vendor/`?
|
||||
|
||||
godep's primary concern is to allow you to repeatably build your project. Your
|
||||
dependencies are part of that project. Without them it won't build. Not
|
||||
committing `vendor/` adds additional external dependencies that are outside of
|
||||
your control. In Go, fetching packages is tied to multiple external systems
|
||||
(DNS, web servers, etc). Over time other developers or code hosting sites may
|
||||
discontinue service, delete code, force push, or take any number of other
|
||||
actions that may make a package unreachable. Therefore it's the opinion of the
|
||||
godep authors that `vendor/` should always be checked in.
|
||||
|
||||
## Should I use `godep restore`?
|
||||
|
||||
Probably not, unless you **need** to. Situations where you would **need** to are:
|
||||
|
||||
1. Using older Godep Workspaces (`Godeps/_workspace`) and not using `godep go
|
||||
<cmd>`.
|
||||
1. Resetting the state of $GOPATH to what is in your `Godeps.json` file in order
|
||||
to cleanly re-vendor everything w/o upgrading/changing any deps. This is
|
||||
useful when [migrating](https://github.com/tools/godep#migrating-to-vendor)
|
||||
from workspaces to `vendor` or when a bug is fixed in `godep` that cleans up
|
||||
a previous vendoring error.
|
|
@ -1,28 +0,0 @@
|
|||
Copyright © 2013 Keith Rarick.
|
||||
Portions Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
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.
|
|
@ -1,209 +0,0 @@
|
|||
# Godep - Archived
|
||||
|
||||
Please use [dep](https://github.com/golang/dep) or another tool instead.
|
||||
|
||||
The rest of this readme is preserved for those that may still need its contents.
|
||||
|
||||
[![Build Status](https://travis-ci.org/tools/godep.svg)](https://travis-ci.org/tools/godep)
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/tools/godep?status.svg)](https://godoc.org/github.com/tools/godep)
|
||||
|
||||
godep helps build packages reproducibly by fixing their dependencies.
|
||||
|
||||
This tool assumes you are working in a standard Go workspace, as described [here](http://golang.org/doc/code.html). We
|
||||
expect godep to build on Go 1.4* or newer, but you can use it on any project that works with Go 1 or newer.
|
||||
|
||||
Please check the [FAQ](FAQ.md) if you have a question.
|
||||
|
||||
## Golang Dep
|
||||
|
||||
The Go community now has the [dep](https://github.com/golang/dep) project to
|
||||
manage dependencies. Please consider trying to migrate from Godep to dep. If there
|
||||
is an issue preventing you from migrating please file an issue with dep so the
|
||||
problem can be corrected. Godep will continue to be supported for some time but
|
||||
is considered to be in a state of support rather than active feature development.
|
||||
|
||||
## Install
|
||||
|
||||
```console
|
||||
go get github.com/tools/godep
|
||||
```
|
||||
|
||||
## How to use godep with a new project
|
||||
|
||||
Assuming you've got everything working already, so you can build your project
|
||||
with `go install` and test it with `go test`, it's one command to start using:
|
||||
|
||||
```console
|
||||
godep save
|
||||
```
|
||||
|
||||
This will save a list of dependencies to the file `Godeps/Godeps.json` and copy
|
||||
their source code into `vendor/` (or `Godeps/_workspace/` when using older
|
||||
versions of Go). Godep does **not copy**:
|
||||
|
||||
- files from source repositories that are not tracked in version control.
|
||||
- `*_test.go` files.
|
||||
- `testdata` directories.
|
||||
- files outside of the go packages.
|
||||
|
||||
Godep does not process the imports of `.go` files with either the `ignore`
|
||||
or `appengine` build tags.
|
||||
|
||||
Test files and testdata directories can be saved by adding `-t`.
|
||||
|
||||
Read over the contents of `vendor/` and make sure it looks reasonable. Then
|
||||
commit the `Godeps/` and `vendor/` directories to version control.
|
||||
|
||||
## The deprecated `-r` flag
|
||||
|
||||
For older versions of Go, the `-r` flag tells save to automatically rewrite
|
||||
package import paths. This allows your code to refer directly to the copied
|
||||
dependencies in `Godeps/_workspace`. So, a package C that depends on package
|
||||
D will actually import `C/Godeps/_workspace/src/D`. This makes C's repo
|
||||
self-contained and causes `go get` to build C with the right version of all
|
||||
dependencies.
|
||||
|
||||
If you don't use `-r`, when using older version of Go, then in order to use the
|
||||
fixed dependencies and get reproducible builds, you must make sure that **every
|
||||
time** you run a Go-related command, you wrap it in one of these two ways:
|
||||
|
||||
- If the command you are running is just `go`, run it as `godep go ...`, e.g.
|
||||
`godep go install -v ./...`
|
||||
- When using a different command, set your `$GOPATH` using `godep path` as
|
||||
described below.
|
||||
|
||||
`-r` isn't necessary with go1.6+ and isn't allowed.
|
||||
|
||||
## Additional Operations
|
||||
|
||||
### Restore
|
||||
|
||||
The `godep restore` installs the
|
||||
package versions specified in `Godeps/Godeps.json` to your `$GOPATH`. This
|
||||
modifies the state of packages in your `$GOPATH`. NOTE: `godep restore` leaves
|
||||
git repositories in a detached state. `go1.6`+ no longer checks out the master
|
||||
branch when doing a `go get`, see [here](https://github.com/golang/go/commit/42206598671a44111c8f726ad33dc7b265bdf669).
|
||||
|
||||
> If you run `godep restore` in your main `$GOPATH` `go get -u` will fail on packages that are behind master.
|
||||
|
||||
Please see the [FAQ](https://github.com/tools/godep/blob/master/FAQ.md#should-i-use-godep-restore) section about restore.
|
||||
|
||||
### Edit-test Cycle
|
||||
|
||||
1. Edit code
|
||||
1. Run `godep go test`
|
||||
1. (repeat)
|
||||
|
||||
### Add a Dependency
|
||||
|
||||
To add a new package foo/bar, do this:
|
||||
|
||||
1. Run `go get foo/bar`
|
||||
1. Edit your code to import foo/bar.
|
||||
1. Run `godep save` (or `godep save ./...`).
|
||||
|
||||
### Update a Dependency
|
||||
|
||||
To update a package from your `$GOPATH`, do this:
|
||||
|
||||
1. Run `go get -u foo/bar`
|
||||
1. Run `godep update foo/bar`.
|
||||
|
||||
You can use the `...` wildcard, for example `godep update foo/...`. Before comitting the change, you'll probably want to
|
||||
inspect the changes to Godeps, for example with `git diff`, and make sure it looks reasonable.
|
||||
|
||||
## Multiple Packages
|
||||
|
||||
If your repository has more than one package, you're probably accustomed to
|
||||
running commands like `go test ./...`, `go install ./...`, and `go fmt ./...`.
|
||||
Similarly, you should run `godep save ./...` to capture the dependencies of all
|
||||
packages in your application.
|
||||
|
||||
## File Format
|
||||
|
||||
Godeps is a json file with the following structure:
|
||||
|
||||
```go
|
||||
type Godeps struct {
|
||||
ImportPath string
|
||||
GoVersion string // Abridged output of 'go version'.
|
||||
GodepVersion string // Abridged output of 'godep version'
|
||||
Packages []string // Arguments to godep save, if any.
|
||||
Deps []struct {
|
||||
ImportPath string
|
||||
Comment string // Description of commit, if present.
|
||||
Rev string // VCS-specific commit ID.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example Godeps:
|
||||
|
||||
```json
|
||||
{
|
||||
"ImportPath": "github.com/kr/hk",
|
||||
"GoVersion": "go1.6",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go-netrc/netrc",
|
||||
"Rev": "28676070ab99"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/binarydist",
|
||||
"Rev": "3380ade90f8b0dfa3e363fd7d7e941fa857d0d13"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Migrating to vendor/
|
||||
|
||||
Godep supports the Go 1.5+ vendor/
|
||||
[experiment](https://github.com/golang/go/commit/183cc0cd41f06f83cb7a2490a499e3f9101befff)
|
||||
utilizing the same environment variable that the go tooling itself supports
|
||||
(`GO15VENDOREXPERIMENT`).
|
||||
|
||||
godep mostly works the same way as the `go` command line tool. If you have go
|
||||
1.5.X and set `GO15VENDOREXPERIMENT=1` or have go1.6.X (or devel) `vendor/`
|
||||
is enabled. **Unless** you already have a `Godeps/_workspace`. This is a safety
|
||||
feature and godep warns you about this.
|
||||
|
||||
When `vendor/` is enabled godep will write the vendored code into the top level
|
||||
`./vendor/` directory. A `./Godeps/Godeps.json` file is created to track
|
||||
the dependencies and revisions. `vendor/` is not compatible with rewrites.
|
||||
|
||||
There is currently no automated migration between the old Godeps workspace and
|
||||
the vendor directory, but the following steps should work:
|
||||
|
||||
```term
|
||||
# just to be safe
|
||||
$ unset GO15VENDOREXPERIMENT
|
||||
|
||||
# restore currently vendored deps to the $GOPATH
|
||||
$ godep restore
|
||||
|
||||
# The next line is only needed to automatically undo rewritten imports that were
|
||||
# created with godep save -r.
|
||||
$ godep save -r=false <pkg spec>
|
||||
|
||||
# Remove the old Godeps folder
|
||||
$ rm -rf Godeps
|
||||
|
||||
# If on go1.5.X to enable `vendor/`
|
||||
$ export GO15VENDOREXPERIMENT=1
|
||||
|
||||
# re-analyze deps and save to `vendor/`.
|
||||
$ godep save <pkg spec>
|
||||
|
||||
# Add the changes to your VCS
|
||||
$ git add -A . ; git commit -am "Godep workspace -> vendor/"
|
||||
|
||||
# You should see your Godeps/_workspace/src files "moved" to vendor/.
|
||||
```
|
||||
|
||||
## Releasing
|
||||
|
||||
1. Increment the version in `version.go`.
|
||||
1. Tag the commit with the same version number.
|
||||
1. Update `Changelog.md`.
|
|
@ -1,128 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A Dependency is a specific revision of a package.
|
||||
type Dependency struct {
|
||||
ImportPath string
|
||||
Comment string `json:",omitempty"` // Description of commit, if present.
|
||||
Rev string // VCS-specific commit ID.
|
||||
|
||||
// used by command save & update
|
||||
ws string // workspace
|
||||
root string // import path to repo root
|
||||
dir string // full path to package
|
||||
|
||||
// used by command update
|
||||
matched bool // selected for update by command line
|
||||
pkg *Package
|
||||
missing bool // packages is missing
|
||||
|
||||
// used by command go
|
||||
vcs *VCS
|
||||
}
|
||||
|
||||
func eqDeps(a, b []Dependency) bool {
|
||||
ok := true
|
||||
for _, da := range a {
|
||||
for _, db := range b {
|
||||
if da.ImportPath == db.ImportPath && da.Rev != db.Rev {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// containsPathPrefix returns whether any string in a
|
||||
// is s or a directory containing s.
|
||||
// For example, pattern ["a"] matches "a" and "a/b"
|
||||
// (but not "ab").
|
||||
func containsPathPrefix(pats []string, s string) bool {
|
||||
for _, pat := range pats {
|
||||
if pat == s || strings.HasPrefix(s, pat+"/") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func uniq(a []string) []string {
|
||||
var s string
|
||||
var i int
|
||||
if !sort.StringsAreSorted(a) {
|
||||
sort.Strings(a)
|
||||
}
|
||||
for _, t := range a {
|
||||
if t != s {
|
||||
a[i] = t
|
||||
i++
|
||||
s = t
|
||||
}
|
||||
}
|
||||
return a[:i]
|
||||
}
|
||||
|
||||
// trimGoVersion and return the major version
|
||||
func trimGoVersion(version string) (string, error) {
|
||||
if version == "devel" {
|
||||
return "devel", nil
|
||||
}
|
||||
if strings.HasPrefix(version, "devel+") || strings.HasPrefix(version, "devel-") {
|
||||
return strings.Replace(version, "devel+", "devel-", 1), nil
|
||||
}
|
||||
p := strings.Split(version, ".")
|
||||
if len(p) < 2 {
|
||||
return "", fmt.Errorf("Error determining major go version from: %q", version)
|
||||
}
|
||||
var split string
|
||||
switch {
|
||||
case strings.Contains(p[1], "beta"):
|
||||
split = "beta"
|
||||
case strings.Contains(p[1], "rc"):
|
||||
split = "rc"
|
||||
}
|
||||
if split != "" {
|
||||
p[1] = strings.Split(p[1], split)[0]
|
||||
}
|
||||
return p[0] + "." + p[1], nil
|
||||
}
|
||||
|
||||
var goVersionTestOutput = ""
|
||||
|
||||
func getGoVersion() (string, error) {
|
||||
// For testing purposes only
|
||||
if goVersionTestOutput != "" {
|
||||
return goVersionTestOutput, nil
|
||||
}
|
||||
|
||||
// Godep might have been compiled with a different
|
||||
// version, so we can't just use runtime.Version here.
|
||||
cmd := exec.Command("go", "version")
|
||||
cmd.Stderr = os.Stderr
|
||||
out, err := cmd.Output()
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
// goVersion returns the major version string of the Go compiler
|
||||
// currently installed, e.g. "go1.5".
|
||||
func goVersion() (string, error) {
|
||||
out, err := getGoVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
gv := strings.Split(out, " ")
|
||||
if len(gv) < 4 {
|
||||
return "", fmt.Errorf("Error splitting output of `go version`: Expected 4 or more elements, but there are < 4: %q", out)
|
||||
}
|
||||
if gv[2] == "devel" {
|
||||
return trimGoVersion(gv[2] + gv[3])
|
||||
}
|
||||
return trimGoVersion(gv[2])
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
)
|
||||
|
||||
var cmdDiff = &Command{
|
||||
Name: "diff",
|
||||
Short: "shows the diff between current and previously saved set of dependencies",
|
||||
Long: `
|
||||
Shows the difference, in a unified diff format, between the
|
||||
current set of dependencies and those generated on a
|
||||
previous 'go save' execution.
|
||||
`,
|
||||
Run: runDiff,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
func runDiff(cmd *Command, args []string) {
|
||||
gold, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
pkgs := []string{"."}
|
||||
dot, err := LoadPackages(pkgs...)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
gnew := &Godeps{
|
||||
ImportPath: dot[0].ImportPath,
|
||||
GoVersion: gold.GoVersion,
|
||||
}
|
||||
|
||||
err = gnew.fill(dot, dot[0].ImportPath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
diff, err := diffStr(&gold, gnew)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
fmt.Println(diff)
|
||||
}
|
||||
|
||||
// diffStr returns a unified diff string of two Godeps.
|
||||
func diffStr(a, b *Godeps) (string, error) {
|
||||
var ab, bb bytes.Buffer
|
||||
|
||||
_, err := a.writeTo(&ab)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
_, err = b.writeTo(&bb)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
diff := difflib.UnifiedDiff{
|
||||
A: difflib.SplitLines(ab.String()),
|
||||
B: difflib.SplitLines(bb.String()),
|
||||
FromFile: b.file(),
|
||||
ToFile: "$GOPATH",
|
||||
Context: 10,
|
||||
}
|
||||
return difflib.GetUnifiedDiffString(diff)
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
|
||||
Command godep helps build packages reproducibly by fixing
|
||||
their dependencies.
|
||||
|
||||
Example Usage
|
||||
|
||||
Save currently-used dependencies to file Godeps:
|
||||
|
||||
$ godep save
|
||||
|
||||
Build project using saved dependencies:
|
||||
|
||||
$ godep go install
|
||||
|
||||
or
|
||||
|
||||
$ GOPATH=`godep path`:$GOPATH
|
||||
$ go install
|
||||
|
||||
*/
|
||||
package main
|
|
@ -1,18 +0,0 @@
|
|||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
errorLoadingDeps = errors.New("error loading dependencies")
|
||||
errorLoadingPackages = errors.New("error loading packages")
|
||||
errorCopyingSourceCode = errors.New("error copying source code")
|
||||
errorNoPackagesUpdatable = errors.New("no packages can be updated")
|
||||
)
|
||||
|
||||
type errPackageNotFound struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (e errPackageNotFound) Error() string {
|
||||
return "Package (" + e.path + ") not found"
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var cmdGet = &Command{
|
||||
Name: "get",
|
||||
Args: "[-t] [packages]",
|
||||
Short: "download and install packages with specified dependencies",
|
||||
Long: `
|
||||
Get downloads to GOPATH the packages named by the import paths, and installs
|
||||
them with the dependencies specified in their Godeps files.
|
||||
|
||||
If any of the packages do not have Godeps files, those are installed
|
||||
as if by go get.
|
||||
|
||||
If -t is given, dependencies of test files are also downloaded and installed.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
`,
|
||||
Run: runGet,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
var getT bool
|
||||
|
||||
func init() {
|
||||
cmdGet.Flag.BoolVar(&getT, "t", false, "get test dependencies")
|
||||
}
|
||||
|
||||
func runGet(cmd *Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
|
||||
cmdArgs := []interface{}{"get", "-d"}
|
||||
if verbose {
|
||||
cmdArgs = append(cmdArgs, "-v")
|
||||
}
|
||||
|
||||
if getT {
|
||||
cmdArgs = append(cmdArgs, "-t")
|
||||
}
|
||||
|
||||
err := command("go", append(cmdArgs, args)...).Run()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// group import paths by Godeps location
|
||||
groups := make(map[string][]string)
|
||||
ps, err := LoadPackages(args...)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
for _, pkg := range ps {
|
||||
if pkg.Error.Err != "" {
|
||||
log.Fatalln(pkg.Error.Err)
|
||||
}
|
||||
dir, _ := findInParents(pkg.Dir, "Godeps")
|
||||
groups[dir] = append(groups[dir], pkg.ImportPath)
|
||||
}
|
||||
for dir, packages := range groups {
|
||||
var c *exec.Cmd
|
||||
if dir == "" {
|
||||
c = command("go", "install", packages)
|
||||
} else {
|
||||
c = command("godep", "go", "install", packages)
|
||||
c.Dir = dir
|
||||
}
|
||||
if err := c.Run(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// command is like exec.Command, but the returned
|
||||
// Cmd inherits stderr from the current process, and
|
||||
// elements of args may be either string or []string.
|
||||
func command(name string, args ...interface{}) *exec.Cmd {
|
||||
var a []string
|
||||
for _, arg := range args {
|
||||
switch v := arg.(type) {
|
||||
case string:
|
||||
a = append(a, v)
|
||||
case []string:
|
||||
a = append(a, v...)
|
||||
}
|
||||
}
|
||||
c := exec.Command(name, a...)
|
||||
c.Stderr = os.Stderr
|
||||
return c
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdGo = &Command{
|
||||
Name: "go",
|
||||
Args: "command [arguments]",
|
||||
Short: "run the go tool with saved dependencies",
|
||||
Long: `
|
||||
Go runs the go tool with a modified GOPATH giving access to
|
||||
dependencies saved in Godeps.
|
||||
|
||||
Any go tool command can run this way, but "godep go get"
|
||||
is unnecessary and has been disabled. Instead, use
|
||||
"godep go install".
|
||||
`,
|
||||
Run: runGo,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
// Find the godep GOPATH for this file tree and run the go tool.
|
||||
func runGo(cmd *Command, args []string) {
|
||||
gopath := prepareGopath()
|
||||
if s := os.Getenv("GOPATH"); s != "" {
|
||||
gopath += string(os.PathListSeparator) + os.Getenv("GOPATH")
|
||||
}
|
||||
if len(args) > 0 && args[0] == "get" {
|
||||
log.Printf("invalid subcommand: %q", "go get")
|
||||
fmt.Fprintln(os.Stderr, "Use 'godep go install' instead.")
|
||||
fmt.Fprintln(os.Stderr, "Run 'godep help go' for usage.")
|
||||
os.Exit(2)
|
||||
}
|
||||
c := exec.Command("go", args...)
|
||||
c.Env = append(envNoGopath(), "GOPATH="+gopath)
|
||||
c.Stdin = os.Stdin
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
err := c.Run()
|
||||
if err != nil {
|
||||
log.Fatalln("go", err)
|
||||
}
|
||||
}
|
||||
|
||||
// prepareGopath reads dependency information from the filesystem
|
||||
// entry name, fetches any necessary code, and returns a gopath
|
||||
// causing the specified dependencies to be used.
|
||||
func prepareGopath() (gopath string) {
|
||||
dir, isDir := findGodeps()
|
||||
if dir == "" {
|
||||
log.Fatalln("No Godeps found (or in any parent directory)")
|
||||
}
|
||||
if !isDir {
|
||||
log.Fatalln(strings.TrimSpace(needSource))
|
||||
}
|
||||
return filepath.Join(dir, "Godeps", "_workspace")
|
||||
}
|
||||
|
||||
// findGodeps looks for a directory entry "Godeps" in the
|
||||
// current directory or any parent, and returns the containing
|
||||
// directory and whether the entry itself is a directory.
|
||||
// If Godeps can't be found, findGodeps returns "".
|
||||
// For any other error, it exits the program.
|
||||
func findGodeps() (dir string, isDir bool) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return findInParents(wd, "Godeps")
|
||||
}
|
||||
|
||||
// isRoot returns true iff a path is a root.
|
||||
// On Unix: "/".
|
||||
// On Windows: "C:\", "D:\", ...
|
||||
func isRoot(p string) bool {
|
||||
p = filepath.Clean(p)
|
||||
volume := filepath.VolumeName(p)
|
||||
|
||||
p = strings.TrimPrefix(p, volume)
|
||||
p = filepath.ToSlash(p)
|
||||
|
||||
return p == "/"
|
||||
}
|
||||
|
||||
// findInParents returns the path to the directory containing name
|
||||
// in dir or any ancestor, and whether name itself is a directory.
|
||||
// If name cannot be found, findInParents returns the empty string.
|
||||
func findInParents(dir, name string) (container string, isDir bool) {
|
||||
for {
|
||||
fi, err := os.Stat(filepath.Join(dir, name))
|
||||
if os.IsNotExist(err) && isRoot(dir) {
|
||||
return "", false
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
dir = filepath.Dir(dir)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return dir, fi.IsDir()
|
||||
}
|
||||
}
|
||||
|
||||
func envNoGopath() (a []string) {
|
||||
for _, s := range os.Environ() {
|
||||
if !strings.HasPrefix(s, "GOPATH=") {
|
||||
a = append(a, s)
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
const needSource = `
|
||||
outdated Godeps missing source code
|
||||
|
||||
This dependency list was created with an old version of godep.
|
||||
|
||||
To work around this, you have two options:
|
||||
1. Run 'godep restore', and try again.
|
||||
2. Ask the maintainer to switch to a newer version of godep,
|
||||
then try again with the updated package.
|
||||
`
|
|
@ -1,218 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
godepsFile = filepath.Join("Godeps", "Godeps.json")
|
||||
oldGodepsFile = filepath.Join("Godeps")
|
||||
)
|
||||
|
||||
// Godeps describes what a package needs to be rebuilt reproducibly.
|
||||
// It's the same information stored in file Godeps.
|
||||
type Godeps struct {
|
||||
ImportPath string
|
||||
GoVersion string
|
||||
GodepVersion string
|
||||
Packages []string `json:",omitempty"` // Arguments to save, if any.
|
||||
Deps []Dependency
|
||||
isOldFile bool
|
||||
}
|
||||
|
||||
func loadGodepsFile(path string) (Godeps, error) {
|
||||
var g Godeps
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return g, err
|
||||
}
|
||||
defer f.Close()
|
||||
err = json.NewDecoder(f).Decode(&g)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Unable to parse %s: %s", path, err.Error())
|
||||
}
|
||||
return g, err
|
||||
}
|
||||
|
||||
func loadDefaultGodepsFile() (Godeps, error) {
|
||||
var g Godeps
|
||||
var err error
|
||||
g, err = loadGodepsFile(godepsFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
var err1 error
|
||||
g, err1 = loadGodepsFile(oldGodepsFile)
|
||||
if err1 != nil {
|
||||
if os.IsNotExist(err1) {
|
||||
return g, err
|
||||
}
|
||||
return g, err1
|
||||
}
|
||||
g.isOldFile = true
|
||||
return g, nil
|
||||
}
|
||||
}
|
||||
return g, err
|
||||
}
|
||||
|
||||
// pkgs is the list of packages to read dependencies for
|
||||
func (g *Godeps) fill(pkgs []*Package, destImportPath string) error {
|
||||
debugln("fill", destImportPath)
|
||||
ppln(pkgs)
|
||||
var err1 error
|
||||
var path, testImports []string
|
||||
dipp := []string{destImportPath}
|
||||
for _, p := range pkgs {
|
||||
if p.Standard {
|
||||
log.Println("ignoring stdlib package:", p.ImportPath)
|
||||
continue
|
||||
}
|
||||
if p.Error.Err != "" {
|
||||
log.Println(p.Error.Err)
|
||||
err1 = errorLoadingPackages
|
||||
continue
|
||||
}
|
||||
path = append(path, p.ImportPath)
|
||||
path = append(path, p.Deps...)
|
||||
testImports = append(testImports, p.TestImports...)
|
||||
testImports = append(testImports, p.XTestImports...)
|
||||
}
|
||||
ps, err := LoadPackages(testImports...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range ps {
|
||||
if p.Standard {
|
||||
continue
|
||||
}
|
||||
if p.Error.Err != "" {
|
||||
log.Println(p.Error.Err)
|
||||
err1 = errorLoadingPackages
|
||||
continue
|
||||
}
|
||||
path = append(path, p.ImportPath)
|
||||
path = append(path, p.Deps...)
|
||||
}
|
||||
debugln("path", path)
|
||||
for i, p := range path {
|
||||
path[i] = unqualify(p)
|
||||
}
|
||||
path = uniq(path)
|
||||
debugln("uniq, unqualify'd path", path)
|
||||
ps, err = LoadPackages(path...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pkg := range ps {
|
||||
if pkg.Error.Err != "" {
|
||||
log.Println(pkg.Error.Err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
if pkg.Standard || containsPathPrefix(dipp, pkg.ImportPath) {
|
||||
debugln("standard or dest skipping", pkg.ImportPath)
|
||||
continue
|
||||
}
|
||||
vcs, reporoot, err := VCSFromDir(pkg.Dir, filepath.Join(pkg.Root, "src"))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
id, err := vcs.identify(pkg.Dir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
if vcs.isDirty(pkg.Dir, id) {
|
||||
log.Println("dirty working tree (please commit changes):", pkg.Dir)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
comment := vcs.describe(pkg.Dir, id)
|
||||
g.Deps = append(g.Deps, Dependency{
|
||||
ImportPath: pkg.ImportPath,
|
||||
Rev: id,
|
||||
Comment: comment,
|
||||
dir: pkg.Dir,
|
||||
ws: pkg.Root,
|
||||
root: filepath.ToSlash(reporoot),
|
||||
vcs: vcs,
|
||||
})
|
||||
}
|
||||
return err1
|
||||
}
|
||||
|
||||
func (g *Godeps) copy() *Godeps {
|
||||
h := *g
|
||||
h.Deps = make([]Dependency, len(g.Deps))
|
||||
copy(h.Deps, g.Deps)
|
||||
return &h
|
||||
}
|
||||
|
||||
func (g *Godeps) file() string {
|
||||
if g.isOldFile {
|
||||
return oldGodepsFile
|
||||
}
|
||||
return godepsFile
|
||||
}
|
||||
|
||||
func (g *Godeps) save() (int64, error) {
|
||||
f, err := os.Create(g.file())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
return g.writeTo(f)
|
||||
}
|
||||
|
||||
func (g *Godeps) writeTo(w io.Writer) (int64, error) {
|
||||
g.GodepVersion = fmt.Sprintf("v%s", version) // godep always writes its current version.
|
||||
b, err := json.MarshalIndent(g, "", "\t")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err := w.Write(append(b, '\n'))
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
func (g *Godeps) addOrUpdateDeps(deps []Dependency) {
|
||||
var missing []Dependency
|
||||
for _, d := range deps {
|
||||
var found bool
|
||||
for i := range g.Deps {
|
||||
if g.Deps[i].ImportPath == d.ImportPath {
|
||||
g.Deps[i] = d
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
missing = append(missing, d)
|
||||
}
|
||||
}
|
||||
g.Deps = append(g.Deps, missing...)
|
||||
}
|
||||
|
||||
func (g *Godeps) removeDeps(deps []Dependency) {
|
||||
var f []Dependency
|
||||
for i := range g.Deps {
|
||||
var found bool
|
||||
for _, d := range deps {
|
||||
if g.Deps[i].ImportPath == d.ImportPath {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
f = append(f, g.Deps[i])
|
||||
}
|
||||
}
|
||||
g.Deps = f
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LicenseFilePrefix is a list of filename prefixes that indicate it
|
||||
// might contain a software license
|
||||
var LicenseFilePrefix = []string{
|
||||
"licence", // UK spelling
|
||||
"license", // US spelling
|
||||
"copying",
|
||||
"unlicense",
|
||||
"copyright",
|
||||
"copyleft",
|
||||
"authors",
|
||||
"contributors",
|
||||
}
|
||||
|
||||
// LegalFileSubstring are substrings that indicate the file is likely
|
||||
// to contain some type of legal declaration. "legal" is often used
|
||||
// that it might moved to LicenseFilePrefix
|
||||
var LegalFileSubstring = []string{
|
||||
"legal",
|
||||
"notice",
|
||||
"disclaimer",
|
||||
"patent",
|
||||
"third-party",
|
||||
"thirdparty",
|
||||
}
|
||||
|
||||
// IsLicenseFile returns true if the filename might be contain a
|
||||
// software license
|
||||
func IsLicenseFile(filename string) bool {
|
||||
lowerfile := strings.ToLower(filename)
|
||||
for _, prefix := range LicenseFilePrefix {
|
||||
if strings.HasPrefix(lowerfile, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsLegalFile returns true if the file is likely to contain some type
|
||||
// of of legal declaration or licensing information
|
||||
func IsLegalFile(filename string) bool {
|
||||
lowerfile := strings.ToLower(filename)
|
||||
for _, prefix := range LicenseFilePrefix {
|
||||
if strings.HasPrefix(lowerfile, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, substring := range LegalFileSubstring {
|
||||
if strings.Contains(lowerfile, substring) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -1,601 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
pathpkg "path"
|
||||
)
|
||||
|
||||
var (
|
||||
gorootSrc = filepath.Join(build.Default.GOROOT, "src")
|
||||
ignoreTags = []string{"appengine", "ignore"} //TODO: appengine is a special case for now: https://github.com/tools/godep/issues/353
|
||||
versionMatch = regexp.MustCompile(`\Ago\d+\.\d+\z`)
|
||||
versionNegativeMatch = regexp.MustCompile(`\A\!go\d+\.\d+\z`)
|
||||
)
|
||||
|
||||
type errorMissingDep struct {
|
||||
i, dir string // import, dir
|
||||
}
|
||||
|
||||
func (e errorMissingDep) Error() string {
|
||||
return "Unable to find dependent package " + e.i + " in context of " + e.dir
|
||||
}
|
||||
|
||||
// packageContext is used to track an import and which package imported it.
|
||||
type packageContext struct {
|
||||
pkg *build.Package // package that imports the import
|
||||
imp string // import
|
||||
}
|
||||
|
||||
// depScanner tracks the processed and to be processed packageContexts
|
||||
type depScanner struct {
|
||||
processed []packageContext
|
||||
todo []packageContext
|
||||
}
|
||||
|
||||
// Next package and import to process
|
||||
func (ds *depScanner) Next() (*build.Package, string) {
|
||||
c := ds.todo[0]
|
||||
ds.processed = append(ds.processed, c)
|
||||
ds.todo = ds.todo[1:]
|
||||
return c.pkg, c.imp
|
||||
}
|
||||
|
||||
// Continue looping?
|
||||
func (ds *depScanner) Continue() bool {
|
||||
return len(ds.todo) > 0
|
||||
}
|
||||
|
||||
// Add a package and imports to the depScanner. Skips already processed/pending package/import combos
|
||||
func (ds *depScanner) Add(pkg *build.Package, imports ...string) {
|
||||
NextImport:
|
||||
for _, i := range imports {
|
||||
if i == "C" {
|
||||
i = "runtime/cgo"
|
||||
}
|
||||
for _, epc := range ds.processed {
|
||||
if pkg.Dir == epc.pkg.Dir && i == epc.imp {
|
||||
debugln("ctxts epc.pkg.Dir == pkg.Dir && i == epc.imp, skipping", epc.pkg.Dir, i)
|
||||
continue NextImport
|
||||
}
|
||||
}
|
||||
for _, epc := range ds.todo {
|
||||
if pkg.Dir == epc.pkg.Dir && i == epc.imp {
|
||||
debugln("ctxts epc.pkg.Dir == pkg.Dir && i == epc.imp, skipping", epc.pkg.Dir, i)
|
||||
continue NextImport
|
||||
}
|
||||
}
|
||||
pc := packageContext{pkg, i}
|
||||
debugln("Adding pc:", pc.pkg.Dir, pc.imp)
|
||||
ds.todo = append(ds.todo, pc)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
pkgCache = make(map[string]*build.Package) // dir => *build.Package
|
||||
)
|
||||
|
||||
// returns the package in dir either from a cache or by importing it and then caching it
|
||||
func fullPackageInDir(dir string) (*build.Package, error) {
|
||||
var err error
|
||||
pkg, ok := pkgCache[dir]
|
||||
if !ok {
|
||||
pkg, _ = build.ImportDir(dir, build.FindOnly)
|
||||
if pkg.Goroot {
|
||||
pkg, err = build.ImportDir(pkg.Dir, 0)
|
||||
} else {
|
||||
err = fillPackage(pkg)
|
||||
}
|
||||
if err == nil {
|
||||
pkgCache[dir] = pkg
|
||||
}
|
||||
}
|
||||
return pkg, err
|
||||
}
|
||||
|
||||
// listPackage specified by path
|
||||
func listPackage(path string) (*Package, error) {
|
||||
debugln("listPackage", path)
|
||||
var lp *build.Package
|
||||
dir, err := findDirForPath(path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lp, err = fullPackageInDir(dir)
|
||||
p := &Package{
|
||||
Dir: lp.Dir,
|
||||
Root: lp.Root,
|
||||
ImportPath: lp.ImportPath,
|
||||
XTestImports: lp.XTestImports,
|
||||
TestImports: lp.TestImports,
|
||||
GoFiles: lp.GoFiles,
|
||||
CgoFiles: lp.CgoFiles,
|
||||
TestGoFiles: lp.TestGoFiles,
|
||||
XTestGoFiles: lp.XTestGoFiles,
|
||||
IgnoredGoFiles: lp.IgnoredGoFiles,
|
||||
}
|
||||
p.Standard = lp.Goroot && lp.ImportPath != "" && !strings.Contains(lp.ImportPath, ".")
|
||||
if err != nil || p.Standard {
|
||||
return p, err
|
||||
}
|
||||
debugln("Looking For Package:", path, "in", dir)
|
||||
ppln(lp)
|
||||
|
||||
ds := depScanner{}
|
||||
ds.Add(lp, lp.Imports...)
|
||||
for ds.Continue() {
|
||||
ip, i := ds.Next()
|
||||
|
||||
debugf("Processing import %s for %s\n", i, ip.Dir)
|
||||
pdir, err := findDirForPath(i, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dp, err := fullPackageInDir(pdir)
|
||||
if err != nil { // This really should happen in this context though
|
||||
ppln(err)
|
||||
return nil, errorMissingDep{i: i, dir: ip.Dir}
|
||||
}
|
||||
ppln(dp)
|
||||
if !dp.Goroot {
|
||||
// Don't bother adding packages in GOROOT to the dependency scanner, they don't import things from outside of it.
|
||||
ds.Add(dp, dp.Imports...)
|
||||
}
|
||||
debugln("lp:")
|
||||
ppln(lp)
|
||||
debugln("ip:")
|
||||
ppln(ip)
|
||||
if lp == ip {
|
||||
debugln("lp == ip")
|
||||
p.Imports = append(p.Imports, dp.ImportPath)
|
||||
}
|
||||
p.Deps = append(p.Deps, dp.ImportPath)
|
||||
p.Dependencies = addDependency(p.Dependencies, dp)
|
||||
}
|
||||
p.Imports = uniq(p.Imports)
|
||||
p.Deps = uniq(p.Deps)
|
||||
debugln("Done Looking For Package:", path, "in", dir)
|
||||
ppln(p)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func addDependency(deps []build.Package, d *build.Package) []build.Package {
|
||||
for i := range deps {
|
||||
if deps[i].Dir == d.Dir {
|
||||
return deps
|
||||
}
|
||||
}
|
||||
return append(deps, *d)
|
||||
}
|
||||
|
||||
// finds the directory for the given import path in the context of the provided build.Package (if provided)
|
||||
func findDirForPath(path string, ip *build.Package) (string, error) {
|
||||
debugln("findDirForPath", path, ip)
|
||||
var search []string
|
||||
|
||||
if build.IsLocalImport(path) {
|
||||
dir := path
|
||||
if !filepath.IsAbs(dir) {
|
||||
if abs, err := filepath.Abs(dir); err == nil {
|
||||
// interpret relative to current directory
|
||||
dir = abs
|
||||
}
|
||||
}
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
// We need to check to see if the import exists in vendor/ folders up the hierarchy of the importing package
|
||||
if VendorExperiment && ip != nil {
|
||||
debugln("resolving vendor posibilities:", ip.Dir, ip.Root)
|
||||
cr := cleanPath(ip.Root)
|
||||
|
||||
for base := cleanPath(ip.Dir); !pathEqual(base, cr); base = cleanPath(filepath.Dir(base)) {
|
||||
s := filepath.Join(base, "vendor", path)
|
||||
debugln("Adding search dir:", s)
|
||||
search = append(search, s)
|
||||
}
|
||||
}
|
||||
|
||||
for _, base := range build.Default.SrcDirs() {
|
||||
search = append(search, filepath.Join(base, path))
|
||||
}
|
||||
|
||||
for _, dir := range search {
|
||||
debugln("searching", dir)
|
||||
fi, err := stat(dir)
|
||||
if err == nil && fi.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errPackageNotFound{path}
|
||||
}
|
||||
|
||||
type statEntry struct {
|
||||
fi os.FileInfo
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
statCache = make(map[string]statEntry)
|
||||
)
|
||||
|
||||
func clearStatCache() {
|
||||
statCache = make(map[string]statEntry)
|
||||
}
|
||||
|
||||
func stat(p string) (os.FileInfo, error) {
|
||||
if e, ok := statCache[p]; ok {
|
||||
return e.fi, e.err
|
||||
}
|
||||
fi, err := os.Stat(p)
|
||||
statCache[p] = statEntry{fi, err}
|
||||
return fi, err
|
||||
}
|
||||
|
||||
// fillPackage full of info. Assumes p.Dir is set at a minimum
|
||||
func fillPackage(p *build.Package) error {
|
||||
if p.Goroot {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.SrcRoot == "" {
|
||||
for _, base := range build.Default.SrcDirs() {
|
||||
if strings.HasPrefix(p.Dir, base) {
|
||||
p.SrcRoot = base
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.SrcRoot == "" {
|
||||
return errors.New("Unable to find SrcRoot for package " + p.ImportPath)
|
||||
}
|
||||
|
||||
if p.Root == "" {
|
||||
p.Root = filepath.Dir(p.SrcRoot)
|
||||
}
|
||||
|
||||
var buildMatch = "+build "
|
||||
var buildFieldSplit = func(r rune) bool {
|
||||
return unicode.IsSpace(r) || r == ','
|
||||
}
|
||||
|
||||
debugln("Filling package:", p.ImportPath, "from", p.Dir)
|
||||
gofiles, err := filepath.Glob(filepath.Join(p.Dir, "*.go"))
|
||||
if err != nil {
|
||||
debugln("Error globbing", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(gofiles) == 0 {
|
||||
return &build.NoGoError{Dir: p.Dir}
|
||||
}
|
||||
|
||||
var testImports []string
|
||||
var imports []string
|
||||
NextFile:
|
||||
for _, file := range gofiles {
|
||||
debugln(file)
|
||||
pf, err := parser.ParseFile(token.NewFileSet(), file, nil, parser.ImportsOnly|parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
testFile := strings.HasSuffix(file, "_test.go")
|
||||
fname := filepath.Base(file)
|
||||
for _, c := range pf.Comments {
|
||||
ct := c.Text()
|
||||
if i := strings.Index(ct, buildMatch); i != -1 {
|
||||
for _, t := range strings.FieldsFunc(ct[i+len(buildMatch):], buildFieldSplit) {
|
||||
for _, tag := range ignoreTags {
|
||||
if t == tag {
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, fname)
|
||||
continue NextFile
|
||||
}
|
||||
}
|
||||
|
||||
if versionMatch.MatchString(t) && !isSameOrNewer(t, majorGoVersion) {
|
||||
debugln("Adding", fname, "to ignored list because of version tag", t)
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, fname)
|
||||
continue NextFile
|
||||
}
|
||||
if versionNegativeMatch.MatchString(t) && isSameOrNewer(t[1:], majorGoVersion) {
|
||||
debugln("Adding", fname, "to ignored list because of version tag", t)
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, fname)
|
||||
continue NextFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if testFile {
|
||||
p.TestGoFiles = append(p.TestGoFiles, fname)
|
||||
} else {
|
||||
p.GoFiles = append(p.GoFiles, fname)
|
||||
}
|
||||
for _, is := range pf.Imports {
|
||||
name, err := strconv.Unquote(is.Path.Value)
|
||||
if err != nil {
|
||||
return err // can't happen?
|
||||
}
|
||||
if testFile {
|
||||
testImports = append(testImports, name)
|
||||
} else {
|
||||
imports = append(imports, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
imports = uniq(imports)
|
||||
testImports = uniq(testImports)
|
||||
p.Imports = imports
|
||||
p.TestImports = testImports
|
||||
return nil
|
||||
}
|
||||
|
||||
// All of the following functions were vendored from go proper. Locations are noted in comments, but may change in future Go versions.
|
||||
|
||||
// importPaths returns the import paths to use for the given command line.
|
||||
// $GOROOT/src/cmd/main.go:366
|
||||
func importPaths(args []string) []string {
|
||||
debugf("importPathsNoDotExpansion(%q) == ", args)
|
||||
args = importPathsNoDotExpansion(args)
|
||||
debugf("%q\n", args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
debugf("build.IsLocalImport(%q) == true\n", a)
|
||||
pkgs := allPackagesInFS(a)
|
||||
debugf("allPackagesInFS(%q) == %q\n", a, pkgs)
|
||||
out = append(out, pkgs...)
|
||||
} else {
|
||||
debugf("build.IsLocalImport(%q) == false\n", a)
|
||||
pkgs := allPackages(a)
|
||||
debugf("allPackages(%q) == %q\n", a, pkgs)
|
||||
out = append(out, allPackages(a)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// importPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
// $GOROOT/src/cmd/main.go:332
|
||||
func importPathsNoDotExpansion(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
if filepath.Separator == '\\' {
|
||||
a = strings.Replace(a, `\`, `/`, -1)
|
||||
}
|
||||
|
||||
// Put argument in canonical form, but preserve leading ./.
|
||||
if strings.HasPrefix(a, "./") {
|
||||
a = "./" + pathpkg.Clean(a)
|
||||
if a == "./." {
|
||||
a = "."
|
||||
}
|
||||
} else {
|
||||
a = pathpkg.Clean(a)
|
||||
}
|
||||
if a == "all" || a == "std" || a == "cmd" {
|
||||
out = append(out, allPackages(a)...)
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// allPackagesInFS is like allPackages but is passed a pattern
|
||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||
// at the given directory. There are ... in the pattern too.
|
||||
// $GOROOT/src/cmd/main.go:620
|
||||
func allPackagesInFS(pattern string) []string {
|
||||
pkgs := matchPackagesInFS(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// allPackages returns all the packages that can be found
|
||||
// under the $GOPATH directories and $GOROOT matching pattern.
|
||||
// The pattern is either "all" (all packages), "std" (standard packages),
|
||||
// "cmd" (standard commands), or a path including "...".
|
||||
// $GOROOT/src/cmd/main.go:542
|
||||
func allPackages(pattern string) []string {
|
||||
pkgs := matchPackages(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// $GOROOT/src/cmd/main.go:554
|
||||
// This has been changed to not use build.ImportDir
|
||||
func matchPackages(pattern string) []string {
|
||||
match := func(string) bool { return true }
|
||||
treeCanMatch := func(string) bool { return true }
|
||||
if pattern != "all" && pattern != "std" && pattern != "cmd" {
|
||||
match = matchPattern(pattern)
|
||||
treeCanMatch = treeCanMatchPattern(pattern)
|
||||
}
|
||||
|
||||
have := map[string]bool{
|
||||
"builtin": true, // ignore pseudo-package that exists only for documentation
|
||||
}
|
||||
if !build.Default.CgoEnabled {
|
||||
have["runtime/cgo"] = true // ignore during walk
|
||||
}
|
||||
var pkgs []string
|
||||
|
||||
for _, src := range build.Default.SrcDirs() {
|
||||
if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
|
||||
continue
|
||||
}
|
||||
src = filepath.Clean(src) + string(filepath.Separator)
|
||||
root := src
|
||||
if pattern == "cmd" {
|
||||
root += "cmd" + string(filepath.Separator)
|
||||
}
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() || path == src {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees.
|
||||
_, elem := filepath.Split(path)
|
||||
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(path[len(src):])
|
||||
if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
|
||||
// The name "std" is only the standard library.
|
||||
// If the name has a dot, assume it's a domain name for go get,
|
||||
// and if the name is cmd, it's the root of the command tree.
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if !treeCanMatch(name) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if have[name] {
|
||||
return nil
|
||||
}
|
||||
have[name] = true
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ap, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if _, err = fullPackageInDir(ap); err != nil {
|
||||
debugf("matchPackage(%q) ap=%q Error: %q\n", ap, pattern, err)
|
||||
if _, noGo := err.(*build.NoGoError); noGo {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// treeCanMatchPattern(pattern)(name) reports whether
|
||||
// name or children of name can possibly match pattern.
|
||||
// Pattern is the same limited glob accepted by matchPattern.
|
||||
// $GOROOT/src/cmd/main.go:527
|
||||
func treeCanMatchPattern(pattern string) func(name string) bool {
|
||||
wildCard := false
|
||||
if i := strings.Index(pattern, "..."); i >= 0 {
|
||||
wildCard = true
|
||||
pattern = pattern[:i]
|
||||
}
|
||||
return func(name string) bool {
|
||||
return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
|
||||
wildCard && strings.HasPrefix(name, pattern)
|
||||
}
|
||||
}
|
||||
|
||||
// hasPathPrefix reports whether the path s begins with the
|
||||
// elements in prefix.
|
||||
// $GOROOT/src/cmd/main.go:489
|
||||
func hasPathPrefix(s, prefix string) bool {
|
||||
switch {
|
||||
default:
|
||||
return false
|
||||
case len(s) == len(prefix):
|
||||
return s == prefix
|
||||
case len(s) > len(prefix):
|
||||
if prefix != "" && prefix[len(prefix)-1] == '/' {
|
||||
return strings.HasPrefix(s, prefix)
|
||||
}
|
||||
return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
|
||||
}
|
||||
}
|
||||
|
||||
// $GOROOT/src/cmd/go/main.go:631
|
||||
// This has been changed to not use build.ImportDir
|
||||
func matchPackagesInFS(pattern string) []string {
|
||||
// Find directory to begin the scan.
|
||||
// Could be smarter but this one optimization
|
||||
// is enough for now, since ... is usually at the
|
||||
// end of a path.
|
||||
i := strings.Index(pattern, "...")
|
||||
dir, _ := pathpkg.Split(pattern[:i])
|
||||
|
||||
// pattern begins with ./ or ../.
|
||||
// path.Clean will discard the ./ but not the ../.
|
||||
// We need to preserve the ./ for pattern matching
|
||||
// and in the returned import paths.
|
||||
prefix := ""
|
||||
if strings.HasPrefix(pattern, "./") {
|
||||
prefix = "./"
|
||||
}
|
||||
match := matchPattern(pattern)
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if path == dir {
|
||||
// filepath.Walk starts at dir and recurses. For the recursive case,
|
||||
// the path is the result of filepath.Join, which calls filepath.Clean.
|
||||
// The initial case is not Cleaned, though, so we do this explicitly.
|
||||
//
|
||||
// This converts a path like "./io/" to "io". Without this step, running
|
||||
// "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
|
||||
// package, because prepending the prefix "./" to the unclean path would
|
||||
// result in "././io", and match("././io") returns false.
|
||||
path = filepath.Clean(path)
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
|
||||
_, elem := filepath.Split(path)
|
||||
dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
|
||||
if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := prefix + filepath.ToSlash(path)
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
ap, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if _, err = fullPackageInDir(ap); err != nil {
|
||||
debugf("matchPackageInFS(%q) ap=%q Error: %q\n", ap, pattern, err)
|
||||
if _, noGo := err.(*build.NoGoError); !noGo {
|
||||
log.Print(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
return pkgs
|
||||
}
|
|
@ -1,255 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
cpuprofile string
|
||||
verbose bool // Verbose flag for commands that support it
|
||||
debug bool // Debug flag for commands that support it
|
||||
majorGoVersion string
|
||||
VendorExperiment bool
|
||||
sep string
|
||||
)
|
||||
|
||||
// Command is an implementation of a godep command
|
||||
// like godep save or godep go.
|
||||
type Command struct {
|
||||
// Run runs the command.
|
||||
// The args are the arguments after the command name.
|
||||
Run func(cmd *Command, args []string)
|
||||
|
||||
// Name of the command
|
||||
Name string
|
||||
|
||||
// Args the command would expect
|
||||
Args string
|
||||
|
||||
// Short is the short description shown in the 'godep help' output.
|
||||
Short string
|
||||
|
||||
// Long is the long message shown in the
|
||||
// 'godep help <this-command>' output.
|
||||
Long string
|
||||
|
||||
// Flag is a set of flags specific to this command.
|
||||
Flag flag.FlagSet
|
||||
|
||||
// OnlyInGOPATH limits this command to being run only while inside of a GOPATH
|
||||
OnlyInGOPATH bool
|
||||
}
|
||||
|
||||
// UsageExit prints usage information and exits.
|
||||
func (c *Command) UsageExit() {
|
||||
fmt.Fprintf(os.Stderr, "Args: godep %s [-v] [-d] %s\n\n", c.Name, c.Args)
|
||||
fmt.Fprintf(os.Stderr, "Run 'godep help %s' for help.\n", c.Name)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Commands lists the available commands and help topics.
|
||||
// The order here is the order in which they are printed
|
||||
// by 'godep help'.
|
||||
var commands = []*Command{
|
||||
cmdSave,
|
||||
cmdGo,
|
||||
cmdGet,
|
||||
cmdPath,
|
||||
cmdRestore,
|
||||
cmdUpdate,
|
||||
cmdDiff,
|
||||
cmdVersion,
|
||||
}
|
||||
|
||||
// VendorExperiment is the Go 1.5 vendor directory experiment flag, see
|
||||
// https://github.com/golang/go/commit/183cc0cd41f06f83cb7a2490a499e3f9101befff
|
||||
// Honor the env var unless the project already has an old school godep workspace
|
||||
func determineVendor(v string) bool {
|
||||
go15ve := os.Getenv("GO15VENDOREXPERIMENT")
|
||||
var ev bool
|
||||
switch v {
|
||||
case "go1", "go1.1", "go1.2", "go1.3", "go1.4":
|
||||
ev = false
|
||||
case "go1.5":
|
||||
ev = go15ve == "1"
|
||||
case "go1.6":
|
||||
ev = go15ve != "0"
|
||||
default: //go1.7+, devel*
|
||||
ev = true
|
||||
}
|
||||
|
||||
ws := filepath.Join("Godeps", "_workspace")
|
||||
s, err := os.Stat(ws)
|
||||
if err == nil && s.IsDir() {
|
||||
log.Printf("WARNING: Godep workspaces (./Godeps/_workspace) are deprecated and support for them will be removed when go1.8 is released.")
|
||||
if ev {
|
||||
log.Printf("WARNING: Go version (%s) & $GO15VENDOREXPERIMENT=%s wants to enable the vendor experiment, but disabling because a Godep workspace (%s) exists\n", v, go15ve, ws)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return ev
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("godep: ")
|
||||
log.SetOutput(os.Stderr)
|
||||
|
||||
flag.Usage = usageExit
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
usageExit()
|
||||
}
|
||||
|
||||
if args[0] == "help" {
|
||||
help(args[1:])
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
majorGoVersion, err = goVersion()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name == args[0] {
|
||||
if cmd.OnlyInGOPATH {
|
||||
checkInGOPATH()
|
||||
}
|
||||
|
||||
VendorExperiment = determineVendor(majorGoVersion)
|
||||
// sep is the signature set of path elements that
|
||||
// precede the original path of an imported package.
|
||||
sep = defaultSep(VendorExperiment)
|
||||
|
||||
cmd.Flag.BoolVar(&verbose, "v", false, "enable verbose output")
|
||||
cmd.Flag.BoolVar(&debug, "d", false, "enable debug output")
|
||||
cmd.Flag.StringVar(&cpuprofile, "cpuprofile", "", "Write cpu profile to this file")
|
||||
cmd.Flag.Usage = func() { cmd.UsageExit() }
|
||||
cmd.Flag.Parse(args[1:])
|
||||
|
||||
debugln("versionString()", versionString())
|
||||
debugln("majorGoVersion", majorGoVersion)
|
||||
debugln("VendorExperiment", VendorExperiment)
|
||||
debugln("sep", sep)
|
||||
|
||||
if cpuprofile != "" {
|
||||
f, err := os.Create(cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
cmd.Run(cmd, cmd.Flag.Args())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "godep: unknown command %q\n", args[0])
|
||||
fmt.Fprintf(os.Stderr, "Run 'godep help' for usage.\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func subPath(sub, path string) bool {
|
||||
ls := strings.ToLower(sub)
|
||||
lp := strings.ToLower(path)
|
||||
if ls == lp {
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(ls, lp)
|
||||
}
|
||||
|
||||
func checkInGOPATH() {
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal("Unable to determine current working directory", err)
|
||||
}
|
||||
dirs := build.Default.SrcDirs()
|
||||
for _, p := range dirs {
|
||||
if ok := subPath(pwd, p); ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("[WARNING]: godep should only be used inside a valid go package directory and")
|
||||
log.Println("[WARNING]: may not function correctly. You are probably outside of your $GOPATH.")
|
||||
log.Printf("[WARNING]:\tCurrent Directory: %s\n", pwd)
|
||||
log.Printf("[WARNING]:\t$GOPATH: %s\n", os.Getenv("GOPATH"))
|
||||
}
|
||||
|
||||
var usageTemplate = `
|
||||
Godep is a tool for managing Go package dependencies.
|
||||
|
||||
Usage:
|
||||
|
||||
godep command [arguments]
|
||||
|
||||
The commands are:
|
||||
{{range .}}
|
||||
{{.Name | printf "%-8s"}} {{.Short}}{{end}}
|
||||
|
||||
Use "godep help [command]" for more information about a command.
|
||||
`
|
||||
|
||||
var helpTemplate = `
|
||||
Args: godep {{.Name}} [-v] [-d] {{.Args}}
|
||||
|
||||
{{.Long | trim}}
|
||||
|
||||
If -v is given, verbose output is enabled.
|
||||
|
||||
If -d is given, debug output is enabled (you probably don't want this, see -v).
|
||||
|
||||
`
|
||||
|
||||
func help(args []string) {
|
||||
if len(args) == 0 {
|
||||
printUsage(os.Stdout)
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "usage: godep help command\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Too many arguments given.\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name == args[0] {
|
||||
tmpl(os.Stdout, helpTemplate, cmd)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func usageExit() {
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func printUsage(w io.Writer) {
|
||||
tmpl(w, usageTemplate, commands)
|
||||
}
|
||||
|
||||
// tmpl executes the given template text on data, writing the result to w.
|
||||
func tmpl(w io.Writer, text string, data interface{}) {
|
||||
t := template.New("top")
|
||||
t.Funcs(template.FuncMap{
|
||||
"trim": strings.TrimSpace,
|
||||
})
|
||||
template.Must(t.Parse(strings.TrimSpace(text) + "\n\n"))
|
||||
if err := t.Execute(w, data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func debugln(a ...interface{}) (int, error) {
|
||||
if debug {
|
||||
return fmt.Println(a...)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func verboseln(a ...interface{}) {
|
||||
if verbose {
|
||||
log.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
func debugf(format string, a ...interface{}) (int, error) {
|
||||
if debug {
|
||||
return fmt.Printf(format, a...)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func ppln(a ...interface{}) (int, error) {
|
||||
if debug {
|
||||
return pretty.Println(a...)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var cmdPath = &Command{
|
||||
Name: "path",
|
||||
Short: "print GOPATH for dependency code",
|
||||
Long: `
|
||||
Command path prints a path for use in env var GOPATH
|
||||
that makes available the specified version of each dependency.
|
||||
|
||||
The printed path does not include any GOPATH value from
|
||||
the environment.
|
||||
|
||||
For more about how GOPATH works, see 'go help gopath'.
|
||||
`,
|
||||
Run: runPath,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
// Print the gopath that points to
|
||||
// the included dependency code.
|
||||
func runPath(cmd *Command, args []string) {
|
||||
if len(args) != 0 {
|
||||
cmd.UsageExit()
|
||||
}
|
||||
if VendorExperiment {
|
||||
fmt.Fprintln(os.Stderr, "Error: GO15VENDOREXPERIMENT is enabled and the vendor/ directory is not a valid Go workspace.")
|
||||
os.Exit(1)
|
||||
}
|
||||
gopath := prepareGopath()
|
||||
fmt.Println(gopath)
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Package represents a Go package.
|
||||
type Package struct {
|
||||
Dir string
|
||||
Root string
|
||||
ImportPath string
|
||||
Deps []string
|
||||
Standard bool
|
||||
Processed bool
|
||||
|
||||
GoFiles []string
|
||||
CgoFiles []string
|
||||
IgnoredGoFiles []string
|
||||
|
||||
TestGoFiles []string
|
||||
TestImports []string
|
||||
XTestGoFiles []string
|
||||
XTestImports []string
|
||||
|
||||
Error struct {
|
||||
Err string
|
||||
}
|
||||
|
||||
// --- New stuff for now
|
||||
Imports []string
|
||||
Dependencies []build.Package
|
||||
}
|
||||
|
||||
// LoadPackages loads the named packages
|
||||
// Unlike the go tool, an empty argument list is treated as an empty list; "."
|
||||
// must be given explicitly if desired.
|
||||
// IgnoredGoFiles will be processed and their dependencies resolved recursively
|
||||
func LoadPackages(names ...string) (a []*Package, err error) {
|
||||
debugln("LoadPackages", names)
|
||||
if len(names) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pkgs := strings.Split(ignorePackages, ",")
|
||||
sort.Strings(pkgs)
|
||||
for _, i := range importPaths(names) {
|
||||
p, err := listPackage(i)
|
||||
if err != nil {
|
||||
if len(pkgs) > 0 {
|
||||
idx := sort.SearchStrings(pkgs, i)
|
||||
if idx < len(pkgs) && pkgs[idx] == i {
|
||||
fmt.Fprintf(os.Stderr, "warning: ignoring package %q \n", i)
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
a = append(a, p)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (p *Package) allGoFiles() []string {
|
||||
var a []string
|
||||
a = append(a, p.GoFiles...)
|
||||
a = append(a, p.CgoFiles...)
|
||||
a = append(a, p.TestGoFiles...)
|
||||
a = append(a, p.XTestGoFiles...)
|
||||
a = append(a, p.IgnoredGoFiles...)
|
||||
return a
|
||||
}
|
||||
|
||||
// matchPattern(pattern)(name) reports whether
|
||||
// name matches pattern. Pattern is a limited glob
|
||||
// pattern in which '...' means 'any string' and there
|
||||
// is no other special syntax.
|
||||
// Taken from $GOROOT/src/cmd/go/main.go.
|
||||
func matchPattern(pattern string) func(name string) bool {
|
||||
re := regexp.QuoteMeta(pattern)
|
||||
re = strings.Replace(re, `\.\.\.`, `.*`, -1)
|
||||
// Special case: foo/... matches foo too.
|
||||
if strings.HasSuffix(re, `/.*`) {
|
||||
re = re[:len(re)-len(`/.*`)] + `(/.*)?`
|
||||
}
|
||||
reg := regexp.MustCompile(`^` + re + `$`)
|
||||
return func(name string) bool {
|
||||
return reg.MatchString(name)
|
||||
}
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go/build"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/tools/go/vcs"
|
||||
)
|
||||
|
||||
var cmdRestore = &Command{
|
||||
Name: "restore",
|
||||
Short: "check out listed dependency versions in GOPATH",
|
||||
Long: `
|
||||
Restore checks out the Godeps-specified version of each package in GOPATH.
|
||||
|
||||
NOTE: restore leaves git repositories in a detached state. go1.6+ no longer
|
||||
checks out the master branch when doing a "go get", see:
|
||||
https://github.com/golang/go/commit/42206598671a44111c8f726ad33dc7b265bdf669.
|
||||
|
||||
`,
|
||||
Run: runRestore,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
// Three phases:
|
||||
// 1. Download all deps
|
||||
// 2. Restore all deps (checkout the recorded rev)
|
||||
// 3. Attempt to load all deps as a simple consistency check
|
||||
func runRestore(cmd *Command, args []string) {
|
||||
if len(build.Default.GOPATH) == 0 {
|
||||
log.Println("Error restore requires GOPATH but it is empty.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var hadError bool
|
||||
checkErr := func(s string) {
|
||||
if hadError {
|
||||
log.Println(s)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
g, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
for i, dep := range g.Deps {
|
||||
verboseln("Downloading dependency (if needed):", dep.ImportPath)
|
||||
err := download(&dep)
|
||||
if err != nil {
|
||||
log.Printf("error downloading dep (%s): %s\n", dep.ImportPath, err)
|
||||
hadError = true
|
||||
}
|
||||
g.Deps[i] = dep
|
||||
}
|
||||
checkErr("Error downloading some deps. Aborting restore and check.")
|
||||
for _, dep := range g.Deps {
|
||||
verboseln("Restoring dependency (if needed):", dep.ImportPath)
|
||||
err := restore(dep)
|
||||
if err != nil {
|
||||
log.Printf("error restoring dep (%s): %s\n", dep.ImportPath, err)
|
||||
hadError = true
|
||||
}
|
||||
}
|
||||
checkErr("Error restoring some deps. Aborting check.")
|
||||
for _, dep := range g.Deps {
|
||||
verboseln("Checking dependency:", dep.ImportPath)
|
||||
_, err := LoadPackages(dep.ImportPath)
|
||||
if err != nil {
|
||||
log.Printf("Dep (%s) restored, but was unable to load it with error:\n\t%s\n", dep.ImportPath, err)
|
||||
if me, ok := err.(errorMissingDep); ok {
|
||||
log.Println("\tThis may be because the dependencies were saved with an older version of godep (< v33).")
|
||||
log.Printf("\tTry `go get %s`. Then `godep save` to update deps.\n", me.i)
|
||||
}
|
||||
hadError = true
|
||||
}
|
||||
}
|
||||
checkErr("Error checking some deps.")
|
||||
}
|
||||
|
||||
var downloaded = make(map[string]bool)
|
||||
|
||||
// download the given dependency.
|
||||
// 2 Passes: 1) go get -d <pkg>, 2) git pull (if necessary)
|
||||
func download(dep *Dependency) error {
|
||||
|
||||
rr, err := vcs.RepoRootForImportPath(dep.ImportPath, debug)
|
||||
if err != nil {
|
||||
debugln("Error determining repo root for", dep.ImportPath)
|
||||
return err
|
||||
}
|
||||
ppln("rr", rr)
|
||||
|
||||
dep.vcs = cmd[rr.VCS]
|
||||
|
||||
// try to find an existing directory in the GOPATHs
|
||||
for _, gp := range filepath.SplitList(build.Default.GOPATH) {
|
||||
t := filepath.Join(gp, "src", rr.Root)
|
||||
fi, err := os.Stat(t)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if fi.IsDir() {
|
||||
dep.root = t
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none found, just pick the first GOPATH entry (AFAICT that's what go get does)
|
||||
if dep.root == "" {
|
||||
dep.root = filepath.Join(filepath.SplitList(build.Default.GOPATH)[0], "src", rr.Root)
|
||||
}
|
||||
ppln("dep", dep)
|
||||
|
||||
if downloaded[rr.Repo] {
|
||||
verboseln("Skipping already downloaded repo", rr.Repo)
|
||||
return nil
|
||||
}
|
||||
|
||||
fi, err := os.Stat(dep.root)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(filepath.Dir(dep.root), os.ModePerm); err != nil {
|
||||
debugln("Error creating base dir of", dep.root)
|
||||
return err
|
||||
}
|
||||
err := rr.VCS.CreateAtRev(dep.root, rr.Repo, dep.Rev)
|
||||
debugln("CreatedAtRev", dep.root, rr.Repo, dep.Rev)
|
||||
if err != nil {
|
||||
debugln("CreateAtRev error", err)
|
||||
return err
|
||||
}
|
||||
downloaded[rr.Repo] = true
|
||||
return nil
|
||||
}
|
||||
debugln("Error checking repo root for", dep.ImportPath, "at", dep.root, ":", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
return errors.New("repo root src dir exists, but isn't a directory for " + dep.ImportPath + " at " + dep.root)
|
||||
}
|
||||
|
||||
if !dep.vcs.exists(dep.root, dep.Rev) {
|
||||
debugln("Updating existing", dep.root)
|
||||
if dep.vcs == vcsGit {
|
||||
detached, err := gitDetached(dep.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if detached {
|
||||
db, err := gitDefaultBranch(dep.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gitCheckout(dep.root, db); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dep.vcs.vcs.Download(dep.root)
|
||||
downloaded[rr.Repo] = true
|
||||
}
|
||||
|
||||
debugln("Nothing to download")
|
||||
return nil
|
||||
}
|
||||
|
||||
var restored = make(map[string]string) // dep.root -> dep.Rev
|
||||
|
||||
// restore checks out the given revision.
|
||||
func restore(dep Dependency) error {
|
||||
rev, ok := restored[dep.root]
|
||||
debugln(rev)
|
||||
debugln(ok)
|
||||
debugln(dep.root)
|
||||
if ok {
|
||||
if rev != dep.Rev {
|
||||
return errors.New("Wanted to restore rev " + dep.Rev + ", already restored rev " + rev + " for another package in the repo")
|
||||
}
|
||||
verboseln("Skipping already restored repo")
|
||||
return nil
|
||||
}
|
||||
|
||||
debugln("Restoring:", dep.ImportPath, dep.Rev)
|
||||
err := dep.vcs.RevSync(dep.root, dep.Rev)
|
||||
if err == nil {
|
||||
restored[dep.root] = dep.Rev
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
|
||||
"github.com/kr/fs"
|
||||
)
|
||||
|
||||
// rewrite visits the go files in pkgs, plus all go files
|
||||
// in the directory tree Godeps, rewriting import statements
|
||||
// according to the rules for func qualify.
|
||||
func rewrite(pkgs []*Package, qual string, paths []string) error {
|
||||
for _, path := range pkgFiles(pkgs) {
|
||||
debugln("rewrite", path)
|
||||
err := rewriteTree(path, qual, paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return rewriteTree("Godeps", qual, paths)
|
||||
}
|
||||
|
||||
// pkgFiles returns the full filesystem path to all go files in pkgs.
|
||||
func pkgFiles(pkgs []*Package) []string {
|
||||
var a []string
|
||||
for _, pkg := range pkgs {
|
||||
for _, s := range pkg.allGoFiles() {
|
||||
a = append(a, filepath.Join(pkg.Dir, s))
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// rewriteTree recursively visits the go files in path, rewriting
|
||||
// import statements according to the rules for func qualify.
|
||||
// This function ignores the 'testdata' directory.
|
||||
func rewriteTree(path, qual string, paths []string) error {
|
||||
w := fs.Walk(path)
|
||||
for w.Step() {
|
||||
if w.Err() != nil {
|
||||
log.Println("rewrite:", w.Err())
|
||||
continue
|
||||
}
|
||||
s := w.Stat()
|
||||
if s.IsDir() && s.Name() == "testdata" {
|
||||
w.SkipDir()
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(w.Path(), ".go") {
|
||||
err := rewriteGoFile(w.Path(), qual, paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rewriteGoFile rewrites import statements in the named file
|
||||
// according to the rules for func qualify.
|
||||
func rewriteGoFile(name, qual string, paths []string) error {
|
||||
debugln("rewriteGoFile", name, ",", qual, ",", paths)
|
||||
printerConfig := &printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var changed bool
|
||||
for _, s := range f.Imports {
|
||||
name, err := strconv.Unquote(s.Path.Value)
|
||||
if err != nil {
|
||||
return err // can't happen
|
||||
}
|
||||
q := qualify(unqualify(name), qual, paths)
|
||||
if q != name {
|
||||
s.Path.Value = strconv.Quote(q)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
var buffer bytes.Buffer
|
||||
if err = printerConfig.Fprint(&buffer, fset, f); err != nil {
|
||||
return err
|
||||
}
|
||||
fset = token.NewFileSet()
|
||||
f, err = parser.ParseFile(fset, name, &buffer, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ast.SortImports(fset, f)
|
||||
tpath := name + ".temp"
|
||||
t, err := os.Create(tpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = printerConfig.Fprint(t, fset, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = t.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// This is required before the rename on windows.
|
||||
if err = os.Remove(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tpath, name)
|
||||
}
|
||||
|
||||
func defaultSep(experiment bool) string {
|
||||
if experiment {
|
||||
return "/vendor/"
|
||||
}
|
||||
return "/Godeps/_workspace/src/"
|
||||
}
|
||||
|
||||
func relativeVendorTarget(experiment bool) string {
|
||||
full := defaultSep(experiment)
|
||||
if full[0] == '/' {
|
||||
full = full[1:]
|
||||
}
|
||||
return filepath.FromSlash(full)
|
||||
}
|
||||
|
||||
// unqualify returns the part of importPath after the last
|
||||
// occurrence of the signature path elements
|
||||
// (Godeps/_workspace/src) that always precede imported
|
||||
// packages in rewritten import paths.
|
||||
//
|
||||
// For example,
|
||||
// unqualify(C) = C
|
||||
// unqualify(D/Godeps/_workspace/src/C) = C
|
||||
func unqualify(importPath string) string {
|
||||
if i := strings.LastIndex(importPath, sep); i != -1 {
|
||||
importPath = importPath[i+len(sep):]
|
||||
}
|
||||
return importPath
|
||||
}
|
||||
|
||||
// qualify qualifies importPath with its corresponding import
|
||||
// path in the Godeps src copy of package pkg. If importPath
|
||||
// is a directory lexically contained in a path in paths,
|
||||
// it will be qualified with package pkg; otherwise, it will
|
||||
// be returned unchanged.
|
||||
//
|
||||
// For example, given paths {D, T} and pkg C,
|
||||
// importPath returns
|
||||
// C C
|
||||
// fmt fmt
|
||||
// D C/Godeps/_workspace/src/D
|
||||
// D/P C/Godeps/_workspace/src/D/P
|
||||
// T C/Godeps/_workspace/src/T
|
||||
func qualify(importPath, pkg string, paths []string) string {
|
||||
if containsPathPrefix(paths, importPath) {
|
||||
return pkg + sep + importPath
|
||||
}
|
||||
return importPath
|
||||
}
|
|
@ -1,613 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/kr/fs"
|
||||
)
|
||||
|
||||
var cmdSave = &Command{
|
||||
Name: "save",
|
||||
Args: "[-r] [-t] [packages]",
|
||||
Short: "list and copy dependencies into Godeps",
|
||||
Long: `
|
||||
|
||||
Save writes a list of the named packages and their dependencies along
|
||||
with the exact source control revision of each package, and copies
|
||||
their source code into a subdirectory. Packages inside "." are excluded
|
||||
from the list to be copied.
|
||||
|
||||
The list is written to Godeps/Godeps.json, and source code for all
|
||||
dependencies is copied into either Godeps/_workspace or, if the vendor
|
||||
experiment is turned on, vendor/.
|
||||
|
||||
The dependency list is a JSON document with the following structure:
|
||||
|
||||
type Godeps struct {
|
||||
ImportPath string
|
||||
GoVersion string // Abridged output of 'go version'.
|
||||
Packages []string // Arguments to godep save, if any.
|
||||
Deps []struct {
|
||||
ImportPath string
|
||||
Comment string // Tag or description of commit.
|
||||
Rev string // VCS-specific commit ID.
|
||||
}
|
||||
}
|
||||
|
||||
Any packages already present in the list will be left unchanged.
|
||||
To update a dependency to a newer revision, use 'godep update'.
|
||||
|
||||
If -r is given, import statements will be rewritten to refer directly
|
||||
to the copied source code. This is not compatible with the vendor
|
||||
experiment. Note that this will not rewrite the statements in the
|
||||
files outside the project.
|
||||
|
||||
If -t is given, test files (*_test.go files + testdata directories) are
|
||||
also saved.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
`,
|
||||
Run: runSave,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
var (
|
||||
saveR, saveT bool
|
||||
ignorePackages string
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdSave.Flag.BoolVar(&saveR, "r", false, "rewrite import paths")
|
||||
cmdSave.Flag.BoolVar(&saveT, "t", false, "save test files")
|
||||
cmdSave.Flag.StringVar(&ignorePackages, "i", "", "list of packages to ignore separated by commas")
|
||||
}
|
||||
|
||||
func runSave(cmd *Command, args []string) {
|
||||
if VendorExperiment && saveR {
|
||||
log.Println("flag -r is incompatible with the vendoring experiment")
|
||||
cmd.UsageExit()
|
||||
}
|
||||
err := save(args)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
func dotPackage() (*build.Package, error) {
|
||||
dir, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return build.ImportDir(dir, build.FindOnly)
|
||||
}
|
||||
|
||||
func projectPackages(dDir string, a []*Package) []*Package {
|
||||
var projPkgs []*Package
|
||||
dotDir := fmt.Sprintf("%s%c", dDir, filepath.Separator)
|
||||
for _, p := range a {
|
||||
pkgDir := fmt.Sprintf("%s%c", p.Dir, filepath.Separator)
|
||||
if strings.HasPrefix(pkgDir, dotDir) {
|
||||
projPkgs = append(projPkgs, p)
|
||||
}
|
||||
}
|
||||
return projPkgs
|
||||
}
|
||||
|
||||
func save(pkgs []string) error {
|
||||
var err error
|
||||
dp, err := dotPackage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
debugln("dotPackageImportPath:", dp.ImportPath)
|
||||
debugln("dotPackageDir:", dp.Dir)
|
||||
|
||||
cv, err := goVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
verboseln("Go Version:", cv)
|
||||
|
||||
gold, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
verboseln("No old Godeps.json found.")
|
||||
gold.GoVersion = cv
|
||||
}
|
||||
|
||||
printVersionWarnings(gold.GoVersion)
|
||||
if len(gold.GoVersion) == 0 {
|
||||
gold.GoVersion = majorGoVersion
|
||||
} else {
|
||||
majorGoVersion, err = trimGoVersion(gold.GoVersion)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to determine go major version from value specified in %s: %s\n", gold.file(), gold.GoVersion)
|
||||
}
|
||||
}
|
||||
|
||||
gnew := &Godeps{
|
||||
ImportPath: dp.ImportPath,
|
||||
GoVersion: gold.GoVersion,
|
||||
}
|
||||
|
||||
switch len(pkgs) {
|
||||
case 0:
|
||||
pkgs = []string{"."}
|
||||
default:
|
||||
gnew.Packages = pkgs
|
||||
}
|
||||
|
||||
verboseln("Finding dependencies for", pkgs)
|
||||
a, err := LoadPackages(pkgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, p := range a {
|
||||
verboseln("Found package:", p.ImportPath)
|
||||
verboseln("\tDeps:", strings.Join(p.Deps, " "))
|
||||
}
|
||||
ppln(a)
|
||||
|
||||
projA := projectPackages(dp.Dir, a)
|
||||
debugln("Filtered projectPackages")
|
||||
ppln(projA)
|
||||
|
||||
verboseln("Computing new Godeps.json file")
|
||||
err = gnew.fill(a, dp.ImportPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
debugln("New Godeps Filled")
|
||||
ppln(gnew)
|
||||
|
||||
if gnew.Deps == nil {
|
||||
gnew.Deps = make([]Dependency, 0) // produce json [], not null
|
||||
}
|
||||
gdisk := gnew.copy()
|
||||
err = carryVersions(&gold, gnew)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if gold.isOldFile {
|
||||
// If we are migrating from an old format file,
|
||||
// we require that the listed version of every
|
||||
// dependency must be installed in GOPATH, so it's
|
||||
// available to copy.
|
||||
if !eqDeps(gnew.Deps, gdisk.Deps) {
|
||||
return errors.New(strings.TrimSpace(needRestore))
|
||||
}
|
||||
gold = Godeps{}
|
||||
}
|
||||
os.Remove("Godeps") // remove regular file if present; ignore error
|
||||
readme := filepath.Join("Godeps", "Readme")
|
||||
err = writeFile(readme, strings.TrimSpace(Readme)+"\n")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = gnew.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
verboseln("Computing diff between old and new deps")
|
||||
// We use a name starting with "_" so the go tool
|
||||
// ignores this directory when traversing packages
|
||||
// starting at the project's root. For example,
|
||||
// godep go list ./...
|
||||
srcdir := filepath.FromSlash(strings.Trim(sep, "/"))
|
||||
rem := subDeps(gold.Deps, gnew.Deps)
|
||||
ppln(rem)
|
||||
add := subDeps(gnew.Deps, gold.Deps)
|
||||
ppln(add)
|
||||
if len(rem) > 0 {
|
||||
verboseln("Deps to remove:")
|
||||
for _, r := range rem {
|
||||
verboseln("\t", r.ImportPath)
|
||||
}
|
||||
verboseln("Removing unused dependencies")
|
||||
err = removeSrc(srcdir, rem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(add) > 0 {
|
||||
verboseln("Deps to add:")
|
||||
for _, a := range add {
|
||||
verboseln("\t", a.ImportPath)
|
||||
}
|
||||
verboseln("Adding new dependencies")
|
||||
err = copySrc(srcdir, add)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !VendorExperiment {
|
||||
f, _ := filepath.Split(srcdir)
|
||||
writeVCSIgnore(f)
|
||||
}
|
||||
var rewritePaths []string
|
||||
if saveR {
|
||||
for _, dep := range gnew.Deps {
|
||||
rewritePaths = append(rewritePaths, dep.ImportPath)
|
||||
}
|
||||
}
|
||||
verboseln("Rewriting paths (if necessary)")
|
||||
ppln(rewritePaths)
|
||||
return rewrite(projA, dp.ImportPath, rewritePaths)
|
||||
}
|
||||
|
||||
func printVersionWarnings(ov string) {
|
||||
var warning bool
|
||||
cv, err := goVersion()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Trim the old version because we may have saved it w/o trimming it
|
||||
// cv is already trimmed by goVersion()
|
||||
tov, err := trimGoVersion(ov)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tov != ov {
|
||||
log.Printf("WARNING: Recorded go version (%s) with minor version string found.\n", ov)
|
||||
warning = true
|
||||
}
|
||||
if cv != tov {
|
||||
log.Printf("WARNING: Recorded major go version (%s) and in-use major go version (%s) differ.\n", tov, cv)
|
||||
warning = true
|
||||
}
|
||||
if warning {
|
||||
log.Println("To record current major go version run `godep update -goversion`.")
|
||||
}
|
||||
}
|
||||
|
||||
type revError struct {
|
||||
ImportPath string
|
||||
WantRev string
|
||||
HavePath string
|
||||
HaveRev string
|
||||
}
|
||||
|
||||
func (v *revError) Error() string {
|
||||
return fmt.Sprintf("cannot save %s at revision %s: already have %s at revision %s.\n"+
|
||||
"Run `godep update %s' first.", v.ImportPath, v.WantRev, v.HavePath, v.HaveRev, v.HavePath)
|
||||
}
|
||||
|
||||
// carryVersions copies Rev and Comment from a to b for
|
||||
// each dependency with an identical ImportPath. For any
|
||||
// dependency in b that appears to be from the same repo
|
||||
// as one in a (for example, a parent or child directory),
|
||||
// the Rev must already match - otherwise it is an error.
|
||||
func carryVersions(a, b *Godeps) error {
|
||||
for i := range b.Deps {
|
||||
err := carryVersion(a, &b.Deps[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func carryVersion(a *Godeps, db *Dependency) error {
|
||||
// First see if this exact package is already in the list.
|
||||
for _, da := range a.Deps {
|
||||
if db.ImportPath == da.ImportPath {
|
||||
db.Rev = da.Rev
|
||||
db.Comment = da.Comment
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// No exact match, check for child or sibling package.
|
||||
// We can't handle mismatched versions for packages in
|
||||
// the same repo, so report that as an error.
|
||||
for _, da := range a.Deps {
|
||||
if strings.HasPrefix(db.ImportPath, da.ImportPath+"/") ||
|
||||
strings.HasPrefix(da.ImportPath, db.root+"/") {
|
||||
if da.Rev != db.Rev {
|
||||
return &revError{
|
||||
ImportPath: db.ImportPath,
|
||||
WantRev: db.Rev,
|
||||
HavePath: da.ImportPath,
|
||||
HaveRev: da.Rev,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No related package in the list, must be a new repo.
|
||||
return nil
|
||||
}
|
||||
|
||||
// subDeps returns a - b, using ImportPath for equality.
|
||||
func subDeps(a, b []Dependency) (diff []Dependency) {
|
||||
Diff:
|
||||
for _, da := range a {
|
||||
for _, db := range b {
|
||||
if da.ImportPath == db.ImportPath {
|
||||
continue Diff
|
||||
}
|
||||
}
|
||||
diff = append(diff, da)
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
func removeSrc(srcdir string, deps []Dependency) error {
|
||||
for _, dep := range deps {
|
||||
path := filepath.FromSlash(dep.ImportPath)
|
||||
err := os.RemoveAll(filepath.Join(srcdir, path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copySrc(dir string, deps []Dependency) error {
|
||||
// mapping to see if we visited a parent directory already
|
||||
visited := make(map[string]bool)
|
||||
ok := true
|
||||
for _, dep := range deps {
|
||||
debugln("copySrc for", dep.ImportPath)
|
||||
srcdir := filepath.Join(dep.ws, "src")
|
||||
rel, err := filepath.Rel(srcdir, dep.dir)
|
||||
debugln("srcdir", srcdir)
|
||||
debugln("rel", rel)
|
||||
debugln("err", err)
|
||||
if err != nil { // this should never happen
|
||||
return err
|
||||
}
|
||||
dstpkgroot := filepath.Join(dir, rel)
|
||||
err = os.RemoveAll(dstpkgroot)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ok = false
|
||||
}
|
||||
|
||||
// copy actual dependency
|
||||
vf := dep.vcs.listFiles(dep.dir)
|
||||
debugln("vf", vf)
|
||||
w := fs.Walk(dep.dir)
|
||||
for w.Step() {
|
||||
err = copyPkgFile(vf, dir, srcdir, w)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
// Look for legal files in root
|
||||
// some packages are imports as a sub-package but license info
|
||||
// is at root: exampleorg/common has license file in exampleorg
|
||||
//
|
||||
if dep.ImportPath == dep.root {
|
||||
// we are already at root
|
||||
continue
|
||||
}
|
||||
|
||||
// prevent copying twice This could happen if we have
|
||||
// two subpackages listed someorg/common and
|
||||
// someorg/anotherpack which has their license in
|
||||
// the parent dir of someorg
|
||||
rootdir := filepath.Join(srcdir, filepath.FromSlash(dep.root))
|
||||
if visited[rootdir] {
|
||||
continue
|
||||
}
|
||||
visited[rootdir] = true
|
||||
vf = dep.vcs.listFiles(rootdir)
|
||||
w = fs.Walk(rootdir)
|
||||
for w.Step() {
|
||||
fname := filepath.Base(w.Path())
|
||||
if IsLegalFile(fname) && !strings.Contains(w.Path(), sep) {
|
||||
err = copyPkgFile(vf, dir, srcdir, w)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return errorCopyingSourceCode
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyPkgFile(vf vcsFiles, dstroot, srcroot string, w *fs.Walker) error {
|
||||
if w.Err() != nil {
|
||||
return w.Err()
|
||||
}
|
||||
name := w.Stat().Name()
|
||||
if w.Stat().IsDir() {
|
||||
if name[0] == '.' || name[0] == '_' || (!saveT && name == "testdata") {
|
||||
// Skip directories starting with '.' or '_' or
|
||||
// 'testdata' (last is only skipped if saveT is false)
|
||||
w.SkipDir()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
rel, err := filepath.Rel(srcroot, w.Path())
|
||||
if err != nil { // this should never happen
|
||||
return err
|
||||
}
|
||||
if !saveT && strings.HasSuffix(name, "_test.go") {
|
||||
if verbose {
|
||||
log.Printf("save: skipping test file: %s", w.Path())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !vf.Contains(w.Path()) {
|
||||
if verbose {
|
||||
log.Printf("save: skipping untracked file: %s", w.Path())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return copyFile(filepath.Join(dstroot, rel), w.Path())
|
||||
}
|
||||
|
||||
// copyFile copies a regular file from src to dst.
|
||||
// dst is opened with os.Create.
|
||||
// If the file name ends with .go,
|
||||
// copyFile strips canonical import path annotations.
|
||||
// These are comments of the form:
|
||||
// package foo // import "bar/foo"
|
||||
// package foo /* import "bar/foo" */
|
||||
func copyFile(dst, src string) error {
|
||||
err := os.MkdirAll(filepath.Dir(dst), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
linkDst, err := os.Readlink(src)
|
||||
if err == nil {
|
||||
return os.Symlink(linkDst, dst)
|
||||
}
|
||||
|
||||
si, err := stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
w, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Chmod(dst, si.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.HasSuffix(dst, ".go") {
|
||||
debugln("Copy Without Import Comment", w, r)
|
||||
err = copyWithoutImportComment(w, r)
|
||||
} else {
|
||||
debugln("Copy (plain)", w, r)
|
||||
_, err = io.Copy(w, r)
|
||||
}
|
||||
err1 := w.Close()
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func copyWithoutImportComment(w io.Writer, r io.Reader) error {
|
||||
b := bufio.NewReader(r)
|
||||
for {
|
||||
l, err := b.ReadBytes('\n')
|
||||
eof := err == io.EOF
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we have data then write it out...
|
||||
if len(l) > 0 {
|
||||
// Strip off \n if it exists because stripImportComment
|
||||
_, err := w.Write(append(stripImportComment(bytes.TrimRight(l, "\n")), '\n'))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if eof {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
importAnnotation = `import\s+(?:"[^"]*"|` + "`[^`]*`" + `)`
|
||||
importComment = `(?://\s*` + importAnnotation + `\s*$|/\*\s*` + importAnnotation + `\s*\*/)`
|
||||
)
|
||||
|
||||
var (
|
||||
importCommentRE = regexp.MustCompile(`^\s*(package\s+\w+)\s+` + importComment + `(.*)`)
|
||||
pkgPrefix = []byte("package ")
|
||||
)
|
||||
|
||||
// stripImportComment returns line with its import comment removed.
|
||||
// If s is not a package statement containing an import comment,
|
||||
// it is returned unaltered.
|
||||
// FIXME: expects lines w/o a \n at the end
|
||||
// See also http://golang.org/s/go14customimport.
|
||||
func stripImportComment(line []byte) []byte {
|
||||
if !bytes.HasPrefix(line, pkgPrefix) {
|
||||
// Fast path; this will skip all but one line in the file.
|
||||
// This assumes there is no whitespace before the keyword.
|
||||
return line
|
||||
}
|
||||
if m := importCommentRE.FindSubmatch(line); m != nil {
|
||||
return append(m[1], m[2]...)
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
// Func writeVCSIgnore writes "ignore" files inside dir for known VCSs,
|
||||
// so that dir/pkg and dir/bin don't accidentally get committed.
|
||||
// It logs any errors it encounters.
|
||||
func writeVCSIgnore(dir string) {
|
||||
// Currently git is the only VCS for which we know how to do this.
|
||||
// Mercurial and Bazaar have similar mechanisms, but they apparently
|
||||
// require writing files outside of dir.
|
||||
const ignore = "/pkg\n/bin\n"
|
||||
name := filepath.Join(dir, ".gitignore")
|
||||
err := writeFile(name, ignore)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// writeFile is like ioutil.WriteFile but it creates
|
||||
// intermediate directories with os.MkdirAll.
|
||||
func writeFile(name, body string) error {
|
||||
err := os.MkdirAll(filepath.Dir(name), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(name, []byte(body), 0666)
|
||||
}
|
||||
|
||||
const (
|
||||
// Readme contains the README text.
|
||||
Readme = `
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
`
|
||||
needRestore = `
|
||||
mismatched versions while migrating
|
||||
|
||||
It looks like you are switching from the old Godeps format
|
||||
(from flag -copy=false). The old format is just a file; it
|
||||
doesn't contain source code. For this migration, godep needs
|
||||
the appropriate version of each dependency to be installed in
|
||||
GOPATH, so that the source code is available to copy.
|
||||
|
||||
To fix this, run 'godep restore'.
|
||||
`
|
||||
)
|
|
@ -1,292 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdUpdate = &Command{
|
||||
Name: "update",
|
||||
Args: "[-goversion] [packages]",
|
||||
Short: "update selected packages or the go version",
|
||||
Long: `
|
||||
Update changes the named dependency packages to use the
|
||||
revision of each currently installed in GOPATH. New code will
|
||||
be copied into the Godeps workspace or vendor folder and the
|
||||
new revision will be written to the manifest.
|
||||
|
||||
If -goversion is specified, update the recorded go version.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
`,
|
||||
Run: runUpdate,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
var (
|
||||
updateGoVer bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdUpdate.Flag.BoolVar(&saveT, "t", false, "save test files during update")
|
||||
cmdUpdate.Flag.BoolVar(&updateGoVer, "goversion", false, "update the recorded go version")
|
||||
}
|
||||
|
||||
func runUpdate(cmd *Command, args []string) {
|
||||
if updateGoVer {
|
||||
err := updateGoVersion()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
if len(args) > 0 {
|
||||
err := update(args)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateGoVersion() error {
|
||||
gold, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cv, err := goVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gv := gold.GoVersion
|
||||
gold.GoVersion = cv
|
||||
_, err = gold.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if gv != cv {
|
||||
log.Println("Updated major go version to", cv)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func update(args []string) error {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
g, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, arg := range args {
|
||||
arg := path.Clean(arg)
|
||||
any := markMatches(arg, g.Deps)
|
||||
if !any {
|
||||
log.Println("not in manifest:", arg)
|
||||
}
|
||||
}
|
||||
deps, rdeps, err := LoadVCSAndUpdate(g.Deps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(deps) == 0 {
|
||||
return errorNoPackagesUpdatable
|
||||
}
|
||||
g.addOrUpdateDeps(deps)
|
||||
g.removeDeps(rdeps)
|
||||
if _, err = g.save(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcdir := relativeVendorTarget(VendorExperiment)
|
||||
if err := removeSrc(filepath.FromSlash(strings.Trim(sep, "/")), rdeps); err != nil {
|
||||
return err
|
||||
}
|
||||
copySrc(srcdir, deps)
|
||||
|
||||
ok, err := needRewrite(g.Packages)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rewritePaths []string
|
||||
if ok {
|
||||
for _, dep := range g.Deps {
|
||||
rewritePaths = append(rewritePaths, dep.ImportPath)
|
||||
}
|
||||
}
|
||||
return rewrite(nil, g.ImportPath, rewritePaths)
|
||||
}
|
||||
|
||||
func needRewrite(importPaths []string) (bool, error) {
|
||||
if len(importPaths) == 0 {
|
||||
importPaths = []string{"."}
|
||||
}
|
||||
a, err := LoadPackages(importPaths...)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, p := range a {
|
||||
for _, name := range p.allGoFiles() {
|
||||
path := filepath.Join(p.Dir, name)
|
||||
hasSep, err := hasRewrittenImportStatement(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if hasSep {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func hasRewrittenImportStatement(path string) (bool, error) {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, path, nil, 0)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, s := range f.Imports {
|
||||
name, _ := strconv.Unquote(s.Path.Value)
|
||||
if strings.Contains(name, sep) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// markMatches marks each entry in deps with an import path that
|
||||
// matches pat. It returns whether any matches occurred.
|
||||
func markMatches(pat string, deps []Dependency) (matched bool) {
|
||||
f := matchPattern(pat)
|
||||
for i, dep := range deps {
|
||||
if f(dep.ImportPath) {
|
||||
deps[i].matched = true
|
||||
matched = true
|
||||
}
|
||||
}
|
||||
return matched
|
||||
}
|
||||
|
||||
func fillDeps(deps []Dependency) ([]Dependency, error) {
|
||||
for i := range deps {
|
||||
if deps[i].pkg != nil {
|
||||
continue
|
||||
}
|
||||
ps, err := LoadPackages(deps[i].ImportPath)
|
||||
if err != nil {
|
||||
if _, ok := err.(errPackageNotFound); ok {
|
||||
deps[i].missing = true
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if len(ps) > 1 {
|
||||
panic("More than one package found for " + deps[i].ImportPath)
|
||||
}
|
||||
p := ps[0]
|
||||
deps[i].pkg = p
|
||||
deps[i].dir = p.Dir
|
||||
deps[i].ws = p.Root
|
||||
|
||||
vcs, reporoot, err := VCSFromDir(p.Dir, filepath.Join(p.Root, "src"))
|
||||
if err != nil {
|
||||
return nil, errorLoadingDeps
|
||||
}
|
||||
deps[i].root = filepath.ToSlash(reporoot)
|
||||
deps[i].vcs = vcs
|
||||
}
|
||||
|
||||
return deps, nil
|
||||
}
|
||||
|
||||
// LoadVCSAndUpdate loads and updates a set of dependencies.
|
||||
func LoadVCSAndUpdate(deps []Dependency) ([]Dependency, []Dependency, error) {
|
||||
var err1 error
|
||||
|
||||
deps, err := fillDeps(deps)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repoMask := make(map[string]bool)
|
||||
for i := range deps {
|
||||
if !deps[i].matched {
|
||||
repoMask[deps[i].root] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we need any new packages because of new transitive imports
|
||||
for _, dep := range deps {
|
||||
if !dep.matched || dep.missing {
|
||||
continue
|
||||
}
|
||||
for _, dp := range dep.pkg.Dependencies {
|
||||
if dp.Goroot {
|
||||
continue
|
||||
}
|
||||
var have bool
|
||||
for _, d := range deps {
|
||||
if d.ImportPath == dp.ImportPath {
|
||||
have = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !have {
|
||||
deps = append(deps, Dependency{ImportPath: dp.ImportPath, matched: true})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deps, err = fillDeps(deps)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var toUpdate, toRemove []Dependency
|
||||
for _, d := range deps {
|
||||
if !d.matched || repoMask[d.root] {
|
||||
continue
|
||||
}
|
||||
if d.missing {
|
||||
toRemove = append(toRemove, d)
|
||||
continue
|
||||
}
|
||||
toUpdate = append(toUpdate, d)
|
||||
}
|
||||
|
||||
debugln("toUpdate")
|
||||
ppln(toUpdate)
|
||||
|
||||
var toCopy []Dependency
|
||||
for _, d := range toUpdate {
|
||||
id, err := d.vcs.identify(d.dir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
if d.vcs.isDirty(d.dir, id) {
|
||||
log.Println("dirty working tree (please commit changes):", d.dir)
|
||||
}
|
||||
d.Rev = id
|
||||
d.Comment = d.vcs.describe(d.dir, id)
|
||||
toCopy = append(toCopy, d)
|
||||
}
|
||||
debugln("toCopy")
|
||||
ppln(toCopy)
|
||||
|
||||
if err1 != nil {
|
||||
return nil, nil, err1
|
||||
}
|
||||
return toCopy, toRemove, nil
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// driveLetterToUpper converts Windows path's drive letters to uppercase. This
|
||||
// is needed when comparing 2 paths with different drive letter case.
|
||||
func driveLetterToUpper(path string) string {
|
||||
if runtime.GOOS != "windows" || path == "" {
|
||||
return path
|
||||
}
|
||||
|
||||
p := path
|
||||
|
||||
// If path's drive letter is lowercase, change it to uppercase.
|
||||
if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
|
||||
p = string(p[0]+'A'-'a') + p[1:]
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// clean the path and ensure that a drive letter is upper case (if it exists).
|
||||
func cleanPath(path string) string {
|
||||
return driveLetterToUpper(filepath.Clean(path))
|
||||
}
|
||||
|
||||
// deal with case insensitive filesystems and other weirdness
|
||||
func pathEqual(a, b string) bool {
|
||||
a = cleanPath(a)
|
||||
b = cleanPath(b)
|
||||
return strings.EqualFold(a, b)
|
||||
}
|
|
@ -1,293 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/vcs"
|
||||
)
|
||||
|
||||
// VCS represents a version control system.
|
||||
type VCS struct {
|
||||
vcs *vcs.Cmd
|
||||
|
||||
IdentifyCmd string
|
||||
DescribeCmd string
|
||||
DiffCmd string
|
||||
ListCmd string
|
||||
RootCmd string
|
||||
|
||||
// run in sandbox repos
|
||||
ExistsCmd string
|
||||
}
|
||||
|
||||
var vcsBzr = &VCS{
|
||||
vcs: vcs.ByCmd("bzr"),
|
||||
|
||||
IdentifyCmd: "version-info --custom --template {revision_id}",
|
||||
DescribeCmd: "revno", // TODO(kr): find tag names if possible
|
||||
DiffCmd: "diff -r {rev}",
|
||||
ListCmd: "ls --from-root -R",
|
||||
RootCmd: "root",
|
||||
}
|
||||
|
||||
var vcsGit = &VCS{
|
||||
vcs: vcs.ByCmd("git"),
|
||||
|
||||
IdentifyCmd: "rev-parse HEAD",
|
||||
DescribeCmd: "describe --tags --abbrev=14",
|
||||
DiffCmd: "diff {rev}",
|
||||
ListCmd: "ls-files --full-name",
|
||||
RootCmd: "rev-parse --show-cdup",
|
||||
|
||||
ExistsCmd: "cat-file -e {rev}",
|
||||
}
|
||||
|
||||
var vcsHg = &VCS{
|
||||
vcs: vcs.ByCmd("hg"),
|
||||
|
||||
IdentifyCmd: "parents --template {node}",
|
||||
DescribeCmd: "log -r . --template {latesttag}-{latesttagdistance}",
|
||||
DiffCmd: "diff -r {rev}",
|
||||
ListCmd: "status --all --no-status",
|
||||
RootCmd: "root",
|
||||
|
||||
ExistsCmd: "cat -r {rev} .",
|
||||
}
|
||||
|
||||
var cmd = map[*vcs.Cmd]*VCS{
|
||||
vcsBzr.vcs: vcsBzr,
|
||||
vcsGit.vcs: vcsGit,
|
||||
vcsHg.vcs: vcsHg,
|
||||
}
|
||||
|
||||
// VCSFromDir returns a VCS value from a directory.
|
||||
func VCSFromDir(dir, srcRoot string) (*VCS, string, error) {
|
||||
vcscmd, reporoot, err := vcs.FromDir(dir, srcRoot)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("error while inspecting %q: %v", dir, err)
|
||||
}
|
||||
vcsext := cmd[vcscmd]
|
||||
if vcsext == nil {
|
||||
return nil, "", fmt.Errorf("%s is unsupported: %s", vcscmd.Name, dir)
|
||||
}
|
||||
return vcsext, reporoot, nil
|
||||
}
|
||||
|
||||
func (v *VCS) identify(dir string) (string, error) {
|
||||
out, err := v.runOutput(dir, v.IdentifyCmd)
|
||||
return string(bytes.TrimSpace(out)), err
|
||||
}
|
||||
|
||||
func absRoot(dir, out string) string {
|
||||
if filepath.IsAbs(out) {
|
||||
return filepath.Clean(out)
|
||||
}
|
||||
return filepath.Join(dir, out)
|
||||
}
|
||||
|
||||
func (v *VCS) root(dir string) (string, error) {
|
||||
out, err := v.runOutput(dir, v.RootCmd)
|
||||
return absRoot(dir, string(bytes.TrimSpace(out))), err
|
||||
}
|
||||
|
||||
func (v *VCS) describe(dir, rev string) string {
|
||||
out, err := v.runOutputVerboseOnly(dir, v.DescribeCmd, "rev", rev)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(bytes.TrimSpace(out))
|
||||
}
|
||||
|
||||
func (v *VCS) isDirty(dir, rev string) bool {
|
||||
out, err := v.runOutput(dir, v.DiffCmd, "rev", rev)
|
||||
return err != nil || len(out) != 0
|
||||
}
|
||||
|
||||
type vcsFiles map[string]bool
|
||||
|
||||
func (vf vcsFiles) Contains(path string) bool {
|
||||
// Fast path, we have the path
|
||||
if vf[path] {
|
||||
return true
|
||||
}
|
||||
|
||||
// Slow path for case insensitive filesystems
|
||||
// See #310
|
||||
for f := range vf {
|
||||
if pathEqual(f, path) {
|
||||
return true
|
||||
}
|
||||
// git's root command (maybe other vcs as well) resolve symlinks, so try that too
|
||||
// FIXME: rev-parse --show-cdup + extra logic will fix this for git but also need to validate the other vcs commands. This is maybe temporary.
|
||||
p, err := filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if pathEqual(f, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// No matches by either method
|
||||
return false
|
||||
}
|
||||
|
||||
// listFiles tracked by the VCS in the repo that contains dir, converted to absolute path.
|
||||
func (v *VCS) listFiles(dir string) vcsFiles {
|
||||
root, err := v.root(dir)
|
||||
debugln("vcs dir", dir)
|
||||
debugln("vcs root", root)
|
||||
ppln(v)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
out, err := v.runOutput(dir, v.ListCmd)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
files := make(vcsFiles)
|
||||
for _, file := range bytes.Split(out, []byte{'\n'}) {
|
||||
if len(file) > 0 {
|
||||
path, err := filepath.Abs(filepath.Join(root, string(file)))
|
||||
if err != nil {
|
||||
panic(err) // this should not happen
|
||||
}
|
||||
|
||||
if pathEqual(filepath.Dir(path), dir) {
|
||||
files[path] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
func (v *VCS) exists(dir, rev string) bool {
|
||||
err := v.runVerboseOnly(dir, v.ExistsCmd, "rev", rev)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// RevSync checks out the revision given by rev in dir.
|
||||
// The dir must exist and rev must be a valid revision.
|
||||
func (v *VCS) RevSync(dir, rev string) error {
|
||||
return v.run(dir, v.vcs.TagSyncCmd, "tag", rev)
|
||||
}
|
||||
|
||||
// run runs the command line cmd in the given directory.
|
||||
// keyval is a list of key, value pairs. run expands
|
||||
// instances of {key} in cmd into value, but only after
|
||||
// splitting cmd into individual arguments.
|
||||
// If an error occurs, run prints the command line and the
|
||||
// command's combined stdout+stderr to standard error.
|
||||
// Otherwise run discards the command's output.
|
||||
func (v *VCS) run(dir string, cmdline string, kv ...string) error {
|
||||
_, err := v.run1(dir, cmdline, kv, true)
|
||||
return err
|
||||
}
|
||||
|
||||
// runVerboseOnly is like run but only generates error output to standard error in verbose mode.
|
||||
func (v *VCS) runVerboseOnly(dir string, cmdline string, kv ...string) error {
|
||||
_, err := v.run1(dir, cmdline, kv, false)
|
||||
return err
|
||||
}
|
||||
|
||||
// runOutput is like run but returns the output of the command.
|
||||
func (v *VCS) runOutput(dir string, cmdline string, kv ...string) ([]byte, error) {
|
||||
return v.run1(dir, cmdline, kv, true)
|
||||
}
|
||||
|
||||
// runOutputVerboseOnly is like runOutput but only generates error output to standard error in verbose mode.
|
||||
func (v *VCS) runOutputVerboseOnly(dir string, cmdline string, kv ...string) ([]byte, error) {
|
||||
return v.run1(dir, cmdline, kv, false)
|
||||
}
|
||||
|
||||
// run1 is the generalized implementation of run and runOutput.
|
||||
func (v *VCS) run1(dir string, cmdline string, kv []string, verbose bool) ([]byte, error) {
|
||||
m := make(map[string]string)
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
m[kv[i]] = kv[i+1]
|
||||
}
|
||||
args := strings.Fields(cmdline)
|
||||
for i, arg := range args {
|
||||
args[i] = expand(m, arg)
|
||||
}
|
||||
|
||||
_, err := exec.LookPath(v.vcs.Cmd)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "godep: missing %s command.\n", v.vcs.Name)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := exec.Command(v.vcs.Cmd, args...)
|
||||
cmd.Dir = dir
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
err = cmd.Run()
|
||||
out := buf.Bytes()
|
||||
if err != nil {
|
||||
if verbose {
|
||||
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.vcs.Cmd, strings.Join(args, " "))
|
||||
os.Stderr.Write(out)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func expand(m map[string]string, s string) string {
|
||||
for k, v := range m {
|
||||
s = strings.Replace(s, "{"+k+"}", v, -1)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func gitDetached(r string) (bool, error) {
|
||||
o, err := vcsGit.runOutput(r, "status")
|
||||
if err != nil {
|
||||
return false, errors.New("unable to determine git status " + err.Error())
|
||||
}
|
||||
return bytes.Contains(o, []byte("HEAD detached at")), nil
|
||||
}
|
||||
|
||||
func gitDefaultBranch(r string) (string, error) {
|
||||
o, err := vcsGit.runOutput(r, "remote show origin")
|
||||
if err != nil {
|
||||
return "", errors.New("Running git remote show origin errored with: " + err.Error())
|
||||
}
|
||||
return gitDetermineDefaultBranch(r, string(o))
|
||||
}
|
||||
|
||||
func gitDetermineDefaultBranch(r, o string) (string, error) {
|
||||
e := "Unable to determine HEAD branch: "
|
||||
hb := "HEAD branch:"
|
||||
lbcfgp := "Local branch configured for 'git pull':"
|
||||
s := strings.Index(o, hb)
|
||||
if s < 0 {
|
||||
b := strings.Index(o, lbcfgp)
|
||||
if b < 0 {
|
||||
return "", errors.New(e + "Remote HEAD is ambiguous. Before godep can pull new commits you will need to:" + `
|
||||
cd ` + r + `
|
||||
git checkout <a HEAD branch>
|
||||
Here is what was reported:
|
||||
` + o)
|
||||
}
|
||||
s = b + len(lbcfgp)
|
||||
} else {
|
||||
s += len(hb)
|
||||
}
|
||||
f := strings.Fields(o[s:])
|
||||
if len(f) < 3 {
|
||||
return "", errors.New(e + "git output too short")
|
||||
}
|
||||
return f[0], nil
|
||||
}
|
||||
|
||||
func gitCheckout(r, b string) error {
|
||||
return vcsGit.run(r, "checkout "+b)
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const version = "80-k8s-r1"
|
||||
|
||||
var cmdVersion = &Command{
|
||||
Name: "version",
|
||||
Short: "show version info",
|
||||
Long: `
|
||||
|
||||
Displays the version of godep as well as the target OS, architecture and go runtime version.
|
||||
`,
|
||||
Run: runVersion,
|
||||
}
|
||||
|
||||
func versionString() string {
|
||||
return fmt.Sprintf("godep v%s (%s/%s/%s)", version, runtime.GOOS, runtime.GOARCH, runtime.Version())
|
||||
}
|
||||
|
||||
func runVersion(cmd *Command, args []string) {
|
||||
fmt.Printf("%s\n", versionString())
|
||||
}
|
||||
|
||||
func GoVersionFields(c rune) bool {
|
||||
return c == 'g' || c == 'o' || c == '.'
|
||||
}
|
||||
|
||||
// isSameOrNewer go version (goA.B)
|
||||
// go1.6 >= go1.6 == true
|
||||
// go1.5 >= go1.6 == false
|
||||
func isSameOrNewer(base, check string) bool {
|
||||
if base == check {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(check, "devel-") {
|
||||
return true
|
||||
}
|
||||
bp := strings.FieldsFunc(base, GoVersionFields)
|
||||
cp := strings.FieldsFunc(check, GoVersionFields)
|
||||
if len(bp) < 2 || len(cp) < 2 {
|
||||
log.Fatalf("Error comparing %s to %s\n", base, check)
|
||||
}
|
||||
if bp[0] == cp[0] { // We only have go version 1 right now
|
||||
bm, err := strconv.Atoi(bp[1])
|
||||
// These errors are unlikely and there is nothing nice to do here anyway
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cm, err := strconv.Atoi(cp[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cm >= bm
|
||||
}
|
||||
return false
|
||||
}
|
Loading…
Reference in New Issue