jsonnet-bundler/pkg/local.go

71 lines
1.7 KiB
Go
Raw Normal View History

// Copyright 2018 jsonnet-bundler authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pkg
import (
"context"
"os"
"path/filepath"
"github.com/fatih/color"
"github.com/pkg/errors"
2020-01-24 08:02:34 +01:00
"github.com/jsonnet-bundler/jsonnet-bundler/spec/v1/deps"
)
type LocalPackage struct {
2020-01-24 08:02:34 +01:00
Source *deps.Local
}
2020-01-24 08:02:34 +01:00
func NewLocalPackage(source *deps.Local) Interface {
return &LocalPackage{
Source: source,
}
}
func (p *LocalPackage) Install(ctx context.Context, name, dir, version string) (lockVersion string, err error) {
wd, err := os.Getwd()
if err != nil {
Correct path resolution to nested local dependencies The tool failed to properly resolve nested local dependencies to jsonnet bundles in different directory trees. This arises because the installation command resolves and installs nested jsonnet local dependencies relative to the root jsonnetfile, rather than track and evaluate the installation path relative to the nested library's jsonnetfile. Consider a repository with multiple local jsonnet bundles in various directory trees, organised as follows (lockfiles elided for brevity): /top/of/tree |- lib/module_A |- jsonnetfile.json |- lib/module_B |- jsonnetfile.json |- src/root_module |- jsonnetfile.json The modules depend on each other as follows: ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ │ │ │ │ │ │ src/root_module │──>│ lib/module_A │──>│ lib/module_B │ │ │ │ │ │ │ └───────────────────┘ └───────────────────┘ └───────────────────┘ where X ──> Y indicates bundle X depends on bundle Y, expressed by adding a dependency of type local in bundle X's jsonnetfile.json, whose path is the relative path from bundle X to bundle Y in the directory structure. For example, src/root_module will express a local dependency on path ../lib/module_A to depend on library module A. Invoking jb install in src/root_module will result in an error: jb: error: failed to install packages: downloading: symlink destination path does not exist: %w: stat /top/of/tree/src/module_B: no such file or directory This occurs because jsonnet-bundler improperly attempts to resolve the nested dependency on library module B relative to the root module path, i.e. src/root_module. The correct behaviour is to perform such resolution relative to the depending module's jsonnetfile.json, i.e. relative to lib/module_A.
2021-12-28 19:13:48 +00:00
return "", errors.Wrap(err, "failed to get current working directory")
}
oldname := filepath.Join(wd, p.Source.Directory)
newname := filepath.Join(dir, name)
linkname, err := filepath.Rel(dir, oldname)
if err != nil {
linkname = oldname
}
err = os.RemoveAll(newname)
if err != nil {
Correct path resolution to nested local dependencies The tool failed to properly resolve nested local dependencies to jsonnet bundles in different directory trees. This arises because the installation command resolves and installs nested jsonnet local dependencies relative to the root jsonnetfile, rather than track and evaluate the installation path relative to the nested library's jsonnetfile. Consider a repository with multiple local jsonnet bundles in various directory trees, organised as follows (lockfiles elided for brevity): /top/of/tree |- lib/module_A |- jsonnetfile.json |- lib/module_B |- jsonnetfile.json |- src/root_module |- jsonnetfile.json The modules depend on each other as follows: ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ │ │ │ │ │ │ src/root_module │──>│ lib/module_A │──>│ lib/module_B │ │ │ │ │ │ │ └───────────────────┘ └───────────────────┘ └───────────────────┘ where X ──> Y indicates bundle X depends on bundle Y, expressed by adding a dependency of type local in bundle X's jsonnetfile.json, whose path is the relative path from bundle X to bundle Y in the directory structure. For example, src/root_module will express a local dependency on path ../lib/module_A to depend on library module A. Invoking jb install in src/root_module will result in an error: jb: error: failed to install packages: downloading: symlink destination path does not exist: %w: stat /top/of/tree/src/module_B: no such file or directory This occurs because jsonnet-bundler improperly attempts to resolve the nested dependency on library module B relative to the root module path, i.e. src/root_module. The correct behaviour is to perform such resolution relative to the depending module's jsonnetfile.json, i.e. relative to lib/module_A.
2021-12-28 19:13:48 +00:00
return "", errors.Wrap(err, "failed to clean previous destination path")
}
_, err = os.Stat(oldname)
if os.IsNotExist(err) {
Correct path resolution to nested local dependencies The tool failed to properly resolve nested local dependencies to jsonnet bundles in different directory trees. This arises because the installation command resolves and installs nested jsonnet local dependencies relative to the root jsonnetfile, rather than track and evaluate the installation path relative to the nested library's jsonnetfile. Consider a repository with multiple local jsonnet bundles in various directory trees, organised as follows (lockfiles elided for brevity): /top/of/tree |- lib/module_A |- jsonnetfile.json |- lib/module_B |- jsonnetfile.json |- src/root_module |- jsonnetfile.json The modules depend on each other as follows: ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ │ │ │ │ │ │ src/root_module │──>│ lib/module_A │──>│ lib/module_B │ │ │ │ │ │ │ └───────────────────┘ └───────────────────┘ └───────────────────┘ where X ──> Y indicates bundle X depends on bundle Y, expressed by adding a dependency of type local in bundle X's jsonnetfile.json, whose path is the relative path from bundle X to bundle Y in the directory structure. For example, src/root_module will express a local dependency on path ../lib/module_A to depend on library module A. Invoking jb install in src/root_module will result in an error: jb: error: failed to install packages: downloading: symlink destination path does not exist: %w: stat /top/of/tree/src/module_B: no such file or directory This occurs because jsonnet-bundler improperly attempts to resolve the nested dependency on library module B relative to the root module path, i.e. src/root_module. The correct behaviour is to perform such resolution relative to the depending module's jsonnetfile.json, i.e. relative to lib/module_A.
2021-12-28 19:13:48 +00:00
return "", errors.Wrap(err, "symlink destination path does not exist")
}
err = os.Symlink(linkname, newname)
if err != nil {
Correct path resolution to nested local dependencies The tool failed to properly resolve nested local dependencies to jsonnet bundles in different directory trees. This arises because the installation command resolves and installs nested jsonnet local dependencies relative to the root jsonnetfile, rather than track and evaluate the installation path relative to the nested library's jsonnetfile. Consider a repository with multiple local jsonnet bundles in various directory trees, organised as follows (lockfiles elided for brevity): /top/of/tree |- lib/module_A |- jsonnetfile.json |- lib/module_B |- jsonnetfile.json |- src/root_module |- jsonnetfile.json The modules depend on each other as follows: ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ │ │ │ │ │ │ src/root_module │──>│ lib/module_A │──>│ lib/module_B │ │ │ │ │ │ │ └───────────────────┘ └───────────────────┘ └───────────────────┘ where X ──> Y indicates bundle X depends on bundle Y, expressed by adding a dependency of type local in bundle X's jsonnetfile.json, whose path is the relative path from bundle X to bundle Y in the directory structure. For example, src/root_module will express a local dependency on path ../lib/module_A to depend on library module A. Invoking jb install in src/root_module will result in an error: jb: error: failed to install packages: downloading: symlink destination path does not exist: %w: stat /top/of/tree/src/module_B: no such file or directory This occurs because jsonnet-bundler improperly attempts to resolve the nested dependency on library module B relative to the root module path, i.e. src/root_module. The correct behaviour is to perform such resolution relative to the depending module's jsonnetfile.json, i.e. relative to lib/module_A.
2021-12-28 19:13:48 +00:00
return "", errors.Wrap(err, "failed to create symlink for local dependency")
}
color.Magenta("LOCAL %s -> %s", name, oldname)
return "", nil
}