зеркало из https://github.com/golang/dep.git
rename 'hoard' to 'dep' (this time for sure)
This commit is contained in:
Родитель
2deaca6ae2
Коммит
f91353d8ed
|
@ -1,6 +1,6 @@
|
|||
# nest project generated files to ignore
|
||||
# dep project generated files to ignore
|
||||
# if you want to ignore files created by your editor/tools,
|
||||
# please consider a global .gitignore https://help.github.com/articles/ignoring-files
|
||||
# please do not open a pull request to add something created by your editor or tools
|
||||
nest
|
||||
testnest
|
||||
dep
|
||||
testdep
|
||||
|
|
14
README.md
14
README.md
|
@ -1,8 +1,8 @@
|
|||
# Nest
|
||||
# Dep
|
||||
|
||||
Linux & OSX: [![Build Status](https://travis-ci.com/golang/nest.svg?token=PbNwH1E9VppQaM7yAzpw&branch=master)](https://travis-ci.com/golang/nest) | Windows: [![Build Status](https://ci.appveyor.com/api/projects/status/jbfsybf98lfrxccy?svg=true)](https://ci.appveyor.com/project/jessfraz/hoard)
|
||||
Linux & OSX: [![Build Status](https://travis-ci.com/golang/dep.svg?token=PbNwH1E9VppQaM7yAzpw&branch=master)](https://travis-ci.com/golang/dep) | Windows: [![Build Status](https://ci.appveyor.com/api/projects/status/jbfsybf98lfrxccy?svg=true)](https://ci.appveyor.com/project/jessfraz/hoard)
|
||||
|
||||
Nest is a prototype dependency management tool.
|
||||
Dep is a prototype dependency management tool.
|
||||
|
||||
## Current status
|
||||
|
||||
|
@ -25,20 +25,20 @@ Please see below for feedback and contribution guidelines.
|
|||
Get the tool via
|
||||
|
||||
```sh
|
||||
$ go get github.com/golang/nest
|
||||
$ go get github.com/golang/dep
|
||||
```
|
||||
|
||||
Typical usage on a new repo might be
|
||||
|
||||
```sh
|
||||
$ nest init
|
||||
$ nest ensure -update
|
||||
$ dep init
|
||||
$ dep ensure -update
|
||||
```
|
||||
|
||||
To update a dependency to a new version, you might run
|
||||
|
||||
```sh
|
||||
$ nest ensure github.com/pkg/errors@^0.8.0
|
||||
$ dep ensure github.com/pkg/errors@^0.8.0
|
||||
```
|
||||
|
||||
See the help text for much more detailed usage instructions.
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
func TestDeriveManifestAndLock(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "nest")
|
||||
dir, err := ioutil.TempDir("", "dep")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func TestDeriveManifestAndLock(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeriveManifestAndLockDoesNotExist(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "nest")
|
||||
dir, err := ioutil.TempDir("", "dep")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
version: "{build}"
|
||||
|
||||
# Source Config
|
||||
clone_folder: c:\gopath\src\github.com\golang\nest
|
||||
clone_folder: c:\gopath\src\github.com\golang\dep
|
||||
|
||||
# Build host
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ func newContext() (*ctx, error) {
|
|||
}
|
||||
|
||||
func (c *ctx) sourceManager() (*gps.SourceMgr, error) {
|
||||
return gps.NewSourceManager(analyzer{}, filepath.Join(c.GOPATH, "pkg", "nest"))
|
||||
return gps.NewSourceManager(analyzer{}, filepath.Join(c.GOPATH, "pkg", "dep"))
|
||||
}
|
||||
|
||||
// loadProject searches for a project root from the provided path, then loads
|
||||
|
@ -73,7 +73,7 @@ func (c *ctx) loadProject(path string) (*project, error) {
|
|||
mf, err := os.Open(mp)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// TODO: list possible solutions? (nest init, cd $project)
|
||||
// TODO: list possible solutions? (dep init, cd $project)
|
||||
return nil, fmt.Errorf("no %v found in project root %v", manifestName, p.absroot)
|
||||
}
|
||||
// Unable to read the manifest file
|
||||
|
|
|
@ -34,7 +34,7 @@ func TestSplitAbsoluteProjectRoot(t *testing.T) {
|
|||
|
||||
tg.tempDir("src")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
nestCtx := &ctx{GOPATH: tg.path(".")}
|
||||
depCtx := &ctx{GOPATH: tg.path(".")}
|
||||
|
||||
importPaths := []string{
|
||||
"github.com/pkg/errors",
|
||||
|
@ -42,8 +42,8 @@ func TestSplitAbsoluteProjectRoot(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, ip := range importPaths {
|
||||
fullpath := filepath.Join(nestCtx.GOPATH, "src", ip)
|
||||
pr, err := nestCtx.splitAbsoluteProjectRoot(fullpath)
|
||||
fullpath := filepath.Join(depCtx.GOPATH, "src", ip)
|
||||
pr, err := depCtx.splitAbsoluteProjectRoot(fullpath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func TestSplitAbsoluteProjectRoot(t *testing.T) {
|
|||
}
|
||||
|
||||
// test where it should return error
|
||||
pr, err := nestCtx.splitAbsoluteProjectRoot("tra/la/la/la")
|
||||
pr, err := depCtx.splitAbsoluteProjectRoot("tra/la/la/la")
|
||||
if err == nil {
|
||||
t.Fatalf("should have gotten error but did not for tra/la/la/la: %s", pr)
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func TestAbsoluteProjectRoot(t *testing.T) {
|
|||
|
||||
tg.tempDir("src")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
nestCtx := &ctx{GOPATH: tg.path(".")}
|
||||
depCtx := &ctx{GOPATH: tg.path(".")}
|
||||
|
||||
importPaths := map[string]bool{
|
||||
"github.com/pkg/errors": true,
|
||||
|
@ -79,7 +79,7 @@ func TestAbsoluteProjectRoot(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, ok := range importPaths {
|
||||
pr, err := nestCtx.absoluteProjectRoot(i)
|
||||
pr, err := depCtx.absoluteProjectRoot(i)
|
||||
if ok {
|
||||
tg.must(err)
|
||||
expected := tg.path(filepath.Join("src", i))
|
||||
|
@ -96,7 +96,7 @@ func TestAbsoluteProjectRoot(t *testing.T) {
|
|||
|
||||
// test that a file fails
|
||||
tg.tempFile("src/thing/thing.go", "hello world")
|
||||
_, err := nestCtx.absoluteProjectRoot("thing/thing.go")
|
||||
_, err := depCtx.absoluteProjectRoot("thing/thing.go")
|
||||
if err == nil {
|
||||
t.Fatal("error should not be nil for a file found")
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ func TestVersionInWorkspace(t *testing.T) {
|
|||
|
||||
tg.tempDir("src")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
nestCtx := &ctx{GOPATH: tg.path(".")}
|
||||
depCtx := &ctx{GOPATH: tg.path(".")}
|
||||
|
||||
importPaths := map[string]struct {
|
||||
rev gps.Version
|
||||
|
@ -138,7 +138,7 @@ func TestVersionInWorkspace(t *testing.T) {
|
|||
tg.runGit(repoDir, "checkout", info.rev.String())
|
||||
}
|
||||
|
||||
v, err := nestCtx.versionInWorkspace(gps.ProjectRoot(ip))
|
||||
v, err := depCtx.versionInWorkspace(gps.ProjectRoot(ip))
|
||||
tg.must(err)
|
||||
|
||||
if v != info.rev {
|
||||
|
|
22
ensure.go
22
ensure.go
|
@ -35,41 +35,41 @@ Package spec:
|
|||
|
||||
Examples:
|
||||
|
||||
nest ensure Populate vendor from existing manifest and lock
|
||||
nest ensure github.com/pkg/foo@^1.0.1 Update a specific dependency to a specific version
|
||||
dep ensure Populate vendor from existing manifest and lock
|
||||
dep ensure github.com/pkg/foo@^1.0.1 Update a specific dependency to a specific version
|
||||
|
||||
For more detailed usage examples, see nest ensure -examples.
|
||||
For more detailed usage examples, see dep ensure -examples.
|
||||
`
|
||||
const ensureExamples = `
|
||||
nest ensure
|
||||
dep ensure
|
||||
|
||||
Solve the project's dependency graph, and place all dependencies in the
|
||||
vendor folder. If a dependency is in the lock file, use the version
|
||||
specified there. Otherwise, use the most recent version that can satisfy the
|
||||
constraints in the manifest file.
|
||||
|
||||
nest ensure -update
|
||||
dep ensure -update
|
||||
|
||||
Update all dependencies to the latest versions allowed by the manifest, ignoring
|
||||
any versions specified in the lock file. Update the lock file with any
|
||||
changes.
|
||||
|
||||
nest ensure github.com/pkg/foo@^1.0.1
|
||||
dep ensure github.com/pkg/foo@^1.0.1
|
||||
|
||||
Constrain pkg/foo to the latest release matching >= 1.0.1, < 2.0.0, and
|
||||
place that release in the vendor folder. If a constraint was previously set
|
||||
in the manifest, this resets it. This form of constraint strikes a good
|
||||
balance of safety and flexibility, and should be preferred for libraries.
|
||||
|
||||
nest ensure github.com/pkg/foo@~1.0.1
|
||||
dep ensure github.com/pkg/foo@~1.0.1
|
||||
|
||||
Same as above, but choose any release matching 1.0.x, preferring latest.
|
||||
|
||||
nest ensure github.com/pkg/foo:git.internal.com/alt/foo
|
||||
dep ensure github.com/pkg/foo:git.internal.com/alt/foo
|
||||
|
||||
Fetch the dependency from a different location.
|
||||
|
||||
nest ensure -override github.com/pkg/foo@^1.0.1
|
||||
dep ensure -override github.com/pkg/foo@^1.0.1
|
||||
|
||||
Forcefully and transitively override any constraint for this dependency.
|
||||
Overrides are powerful, but harmful in the long term. They should be used
|
||||
|
@ -105,12 +105,12 @@ func (cmd *ensureCommand) Run(args []string) error {
|
|||
return errors.New("Cannot pass -update and itemized project list (for now)")
|
||||
}
|
||||
|
||||
p, err := nestContext.loadProject("")
|
||||
p, err := depContext.loadProject("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sm, err := nestContext.sourceManager()
|
||||
sm, err := depContext.sourceManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ func TestDeduceConstraint(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCopyFolder(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "nest")
|
||||
dir, err := ioutil.TempDir("", "dep")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ func TestCopyFolder(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCopyFile(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "nest")
|
||||
dir, err := ioutil.TempDir("", "dep")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// The TestMain function creates a nest command for testing purposes and
|
||||
// The TestMain function creates a dep command for testing purposes and
|
||||
// deletes it after the tests have been run.
|
||||
// Most of this is taken from https://github.com/golang/go/blob/master/src/cmd/go/go_test.go and reused here.
|
||||
func TestMain(m *testing.M) {
|
||||
args := []string{"build", "-o", "testnest" + exeSuffix}
|
||||
args := []string{"build", "-o", "testdep" + exeSuffix}
|
||||
out, err := exec.Command("go", args...).CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "building testnest failed: %v\n%s", err, out)
|
||||
fmt.Fprintf(os.Stderr, "building testdep failed: %v\n%s", err, out)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
|
@ -49,11 +49,11 @@ func TestMain(m *testing.M) {
|
|||
// those systems. Set CCACHE_DIR to cope. Issue 17668.
|
||||
os.Setenv("CCACHE_DIR", filepath.Join(home, ".ccache"))
|
||||
}
|
||||
os.Setenv("HOME", "/test-nest-home-does-not-exist")
|
||||
os.Setenv("HOME", "/test-dep-home-does-not-exist")
|
||||
|
||||
r := m.Run()
|
||||
|
||||
os.Remove("testnest" + exeSuffix)
|
||||
os.Remove("testdep" + exeSuffix)
|
||||
|
||||
os.Exit(r)
|
||||
}
|
||||
|
@ -168,12 +168,12 @@ func (tg *testgoData) doRun(args []string) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
tg.t.Logf("running testnest %v", args)
|
||||
tg.t.Logf("running testdep %v", args)
|
||||
var prog string
|
||||
if tg.wd == "" {
|
||||
prog = "./testnest" + exeSuffix
|
||||
prog = "./testdep" + exeSuffix
|
||||
} else {
|
||||
prog = filepath.Join(tg.wd, "testnest"+exeSuffix)
|
||||
prog = filepath.Join(tg.wd, "testdep"+exeSuffix)
|
||||
}
|
||||
args = append(args[:1], append([]string{"-v"}, args[1:]...)...)
|
||||
cmd := exec.Command(prog, args...)
|
||||
|
@ -508,7 +508,7 @@ func (tg *testgoData) readLock() string {
|
|||
}
|
||||
|
||||
func (tg *testgoData) getCommit(repo string) string {
|
||||
repoPath := tg.path("pkg/nest/sources/https---" + strings.Replace(repo, "/", "-", -1))
|
||||
repoPath := tg.path("pkg/dep/sources/https---" + strings.Replace(repo, "/", "-", -1))
|
||||
cmd := exec.Command("git", "rev-parse", "HEAD")
|
||||
cmd.Dir = repoPath
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
|
12
init.go
12
init.go
|
@ -28,7 +28,7 @@ but it will be solved-for, and will appear in the lock.
|
|||
|
||||
Note: init may use the network to solve the dependency graph.
|
||||
|
||||
Note: init does NOT vendor dependencies at the moment. See nest ensure.
|
||||
Note: init does NOT vendor dependencies at the moment. See dep ensure.
|
||||
`
|
||||
|
||||
func (cmd *initCommand) Name() string { return "init" }
|
||||
|
@ -76,7 +76,7 @@ func (cmd *initCommand) Run(args []string) error {
|
|||
return fmt.Errorf("Invalid state: manifest %q does not exist, but lock %q does.", mf, lf)
|
||||
}
|
||||
|
||||
cpr, err := nestContext.splitAbsoluteProjectRoot(root)
|
||||
cpr, err := depContext.splitAbsoluteProjectRoot(root)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "determineProjectRoot")
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ func (cmd *initCommand) Run(args []string) error {
|
|||
return errors.Wrap(err, "gps.ListPackages")
|
||||
}
|
||||
vlogf("Found %d dependencies.", len(pkgT.Packages))
|
||||
sm, err := nestContext.sourceManager()
|
||||
sm, err := depContext.sourceManager()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getSourceManager")
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ func getProjectData(pkgT gps.PackageTree, cpr string, sm *gps.SourceMgr) (projec
|
|||
vlogf("Package %q has import %q, analyzing...", v.P.ImportPath, ip)
|
||||
|
||||
dependencies[pr] = []string{ip}
|
||||
v, err := nestContext.versionInWorkspace(pr)
|
||||
v, err := depContext.versionInWorkspace(pr)
|
||||
if err != nil {
|
||||
notondisk[pr] = true
|
||||
vlogf("Could not determine version for %q, omitting from generated manifest", pr)
|
||||
|
@ -357,7 +357,7 @@ func getProjectData(pkgT gps.PackageTree, cpr string, sm *gps.SourceMgr) (projec
|
|||
// It's fine if the root does not exist - it indicates that this
|
||||
// project is not present in the workspace, and so we need to
|
||||
// solve to deal with this dep.
|
||||
r := filepath.Join(nestContext.GOPATH, "src", string(pr))
|
||||
r := filepath.Join(depContext.GOPATH, "src", string(pr))
|
||||
_, err := os.Lstat(r)
|
||||
if os.IsNotExist(err) {
|
||||
colors[pkg] = black
|
||||
|
@ -396,7 +396,7 @@ func getProjectData(pkgT gps.PackageTree, cpr string, sm *gps.SourceMgr) (projec
|
|||
// whether we're first seeing it here, in the transitive
|
||||
// exploration, or if it arose in the direct dep parts
|
||||
if _, in := ondisk[pr]; !in {
|
||||
v, err := nestContext.versionInWorkspace(pr)
|
||||
v, err := depContext.versionInWorkspace(pr)
|
||||
if err != nil {
|
||||
colors[pkg] = black
|
||||
notondisk[pr] = true
|
||||
|
|
6
lock.go
6
lock.go
|
@ -134,14 +134,14 @@ func (l *lock) MarshalJSON() ([]byte, error) {
|
|||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// lockFromInterface converts an arbitrary gps.Lock to nest's representation of a
|
||||
// lock. If the input is already nest's *lock, the input is returned directly.
|
||||
// lockFromInterface converts an arbitrary gps.Lock to dep's representation of a
|
||||
// lock. If the input is already dep's *lock, the input is returned directly.
|
||||
//
|
||||
// Data is defensively copied wherever necessary to ensure the resulting *lock
|
||||
// shares no memory with the original lock.
|
||||
//
|
||||
// As gps.Solution is a superset of gps.Lock, this can also be used to convert
|
||||
// solutions to nest's lock format.
|
||||
// solutions to dep's lock format.
|
||||
func lockFromInterface(in gps.Lock) *lock {
|
||||
if in == nil {
|
||||
return nil
|
||||
|
|
14
main.go
14
main.go
|
@ -23,8 +23,8 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
nestContext *ctx
|
||||
verbose = flag.Bool("v", false, "enable verbose logging")
|
||||
depContext *ctx
|
||||
verbose = flag.Bool("v", false, "enable verbose logging")
|
||||
)
|
||||
|
||||
type command interface {
|
||||
|
@ -37,14 +37,14 @@ type command interface {
|
|||
}
|
||||
|
||||
func main() {
|
||||
// Set up the nest context.
|
||||
// Set up the dep context.
|
||||
// TODO(pb): can this be deglobalized, pretty please?
|
||||
hc, err := newContext()
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
nestContext = hc
|
||||
depContext = hc
|
||||
|
||||
// Build the list of available commands.
|
||||
commands := []command{
|
||||
|
@ -55,7 +55,7 @@ func main() {
|
|||
}
|
||||
|
||||
usage := func() {
|
||||
fmt.Fprintln(os.Stderr, "Usage: nest <command>")
|
||||
fmt.Fprintln(os.Stderr, "Usage: dep <command>")
|
||||
fmt.Fprintln(os.Stderr)
|
||||
fmt.Fprintln(os.Stderr, "Commands:")
|
||||
fmt.Fprintln(os.Stderr)
|
||||
|
@ -125,7 +125,7 @@ func resetUsage(fs *flag.FlagSet, name, args, longHelp string) {
|
|||
})
|
||||
flagWriter.Flush()
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: nest %s %s\n", name, args)
|
||||
fmt.Fprintf(os.Stderr, "Usage: dep %s %s\n", name, args)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
fmt.Fprintln(os.Stderr, strings.TrimSpace(longHelp))
|
||||
fmt.Fprintln(os.Stderr)
|
||||
|
@ -201,7 +201,7 @@ func (p *project) makeParams() gps.SolveParameters {
|
|||
|
||||
func logf(format string, args ...interface{}) {
|
||||
// TODO: something else?
|
||||
fmt.Fprintf(os.Stderr, "nest: "+format+"\n", args...)
|
||||
fmt.Fprintf(os.Stderr, "dep: "+format+"\n", args...)
|
||||
}
|
||||
|
||||
func vlogf(format string, args ...interface{}) {
|
||||
|
|
|
@ -42,19 +42,19 @@ type removeCommand struct {
|
|||
}
|
||||
|
||||
func (cmd *removeCommand) Run(args []string) error {
|
||||
p, err := nestContext.loadProject("")
|
||||
p, err := depContext.loadProject("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sm, err := nestContext.sourceManager()
|
||||
sm, err := depContext.sourceManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sm.UseDefaultSignalHandling()
|
||||
defer sm.Release()
|
||||
|
||||
cpr, err := nestContext.splitAbsoluteProjectRoot(p.absroot)
|
||||
cpr, err := depContext.splitAbsoluteProjectRoot(p.absroot)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "determineProjectRoot")
|
||||
}
|
||||
|
|
|
@ -64,12 +64,12 @@ type statusCommand struct {
|
|||
}
|
||||
|
||||
func (cmd *statusCommand) Run(args []string) error {
|
||||
p, err := nestContext.loadProject("")
|
||||
p, err := depContext.loadProject("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sm, err := nestContext.sourceManager()
|
||||
sm, err := depContext.sourceManager()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ type safeWriter struct {
|
|||
// tree, to a temp dir, then moves them into place if and only if all the write
|
||||
// operations succeeded. It also does its best to roll back if any moves fail.
|
||||
//
|
||||
// This mostly guarantees that nest cannot exit with a partial write that would
|
||||
// This mostly guarantees that dep cannot exit with a partial write that would
|
||||
// leave an undefined state on disk.
|
||||
//
|
||||
// - If a sw.m is provided, it will be written to the standard manifest file
|
||||
|
@ -101,7 +101,7 @@ func (sw safeWriter) writeAllSafe(forceVendor bool) error {
|
|||
lpath := filepath.Join(sw.root, lockName)
|
||||
vpath := filepath.Join(sw.root, "vendor")
|
||||
|
||||
td, err := ioutil.TempDir(os.TempDir(), "nest")
|
||||
td, err := ioutil.TempDir(os.TempDir(), "dep")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error while creating temp dir for writing manifest/lock/vendor")
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче