github.com/octohelm/cuekit@v0.0.0-20240424021256-e7df8d743066/pkg/mod/modregistry/registry.go (about)

     1  package modregistry
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"github.com/octohelm/cuekit/pkg/mod/modfile"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"cuelang.org/go/mod/modconfig"
    12  
    13  	"github.com/octohelm/cuekit/pkg/mod/modmem"
    14  	"github.com/octohelm/cuekit/pkg/mod/module"
    15  )
    16  
    17  func NewRegistry(m *module.Module) (modconfig.Registry, error) {
    18  	userCacheDir, err := os.UserCacheDir()
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	if err := m.Load(true); err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	r := &resolver{
    28  		CacheDir: getEnv("CUE_CACHE_DIR", filepath.Join(userCacheDir, "cue")),
    29  		Root:     m,
    30  	}
    31  
    32  	std, err := modconfig.NewRegistry(&modconfig.Config{
    33  		Env: []string{
    34  			fmt.Sprintf("CUE_REGISTRY=%s", getEnv("CUE_REGISTRY", "ghcr.io")),
    35  			fmt.Sprintf("CUE_CACHE_DIR=%s", r.CacheDir),
    36  		},
    37  	})
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	if err := modmem.DefaultRegistry.Dump(r.CacheDir); err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	return &registry{
    47  		mem:   modmem.DefaultRegistry,
    48  		local: r,
    49  		std:   std,
    50  	}, nil
    51  }
    52  
    53  type registry struct {
    54  	mem   modmem.Registry
    55  	local *resolver
    56  	std   modconfig.Registry
    57  }
    58  
    59  func (r *registry) Fetch(ctx context.Context, mv module.Version) (loc module.SourceLoc, err error) {
    60  	defer func() {
    61  		if err == nil {
    62  			mod := &module.Module{
    63  				SourceLoc: loc,
    64  			}
    65  
    66  			if err := mod.Load(true); err == nil {
    67  				if version := mod.Overwrites.Version; version != "" {
    68  					r.local.Root.Overwrites.AddDep(mod.Module, &modfile.DepOverwrite{
    69  						Path:    mod.Overwrites.Path,
    70  						Version: version,
    71  					})
    72  				}
    73  			}
    74  
    75  			_ = r.local.Root.Save()
    76  		}
    77  	}()
    78  
    79  	if depOverwrite, ok := r.local.Root.GetDepOverwrite(mv.Path()); ok {
    80  		if depOverwrite.IsLocalReplacement() {
    81  			return r.local.ResolveLocal(ctx, depOverwrite.Path)
    82  		}
    83  
    84  		return r.local.Resolve(ctx, mv.Path(), depOverwrite.Version)
    85  	}
    86  
    87  	sl, err := r.std.Fetch(ctx, mv)
    88  	if err != nil {
    89  		if r.isNotExistsOfCueRegistry(err) {
    90  			resp, err := r.local.Fetch(ctx, mv)
    91  			return resp, err
    92  		}
    93  		return module.SourceLoc{}, err
    94  	}
    95  	return sl, nil
    96  }
    97  
    98  func (r *registry) isNotExistsOfCueRegistry(err error) bool {
    99  	if err != nil {
   100  		errMsg := err.Error()
   101  		return strings.Contains(errMsg, "HTTP response 403") || strings.Contains(errMsg, "HTTP response 400")
   102  	}
   103  	return false
   104  }
   105  
   106  func (r *registry) Requirements(ctx context.Context, mv module.Version) ([]module.Version, error) {
   107  	if m, ok := r.mem.Resolve(mv.Path()); ok {
   108  		m.SourceLoc = module.SourceLocOfOSDir(r.mem.CacheDir(r.local.CacheDir, m.Module, m.Overwrites.Version))
   109  		if err := m.Load(true); err != nil {
   110  			return nil, err
   111  		}
   112  		return m.DepVersions(), nil
   113  	}
   114  
   115  	if depOverwrite, ok := r.local.Root.GetDepOverwrite(mv.Path()); ok {
   116  		if depOverwrite.IsLocalReplacement() {
   117  			s, err := r.local.ResolveLocal(ctx, depOverwrite.Path)
   118  			if err != nil {
   119  				return nil, err
   120  			}
   121  			m := &module.Module{SourceLoc: s}
   122  			if err := m.Load(false); err != nil {
   123  				return nil, err
   124  			}
   125  			return m.DepVersions(), nil
   126  		}
   127  		s, err := r.local.Fetch(ctx, mv)
   128  		if err != nil {
   129  			return nil, err
   130  		}
   131  		m := &module.Module{
   132  			SourceLoc: s,
   133  		}
   134  		if err := m.Load(false); err != nil {
   135  			return nil, err
   136  		}
   137  		return m.DepVersions(), nil
   138  	}
   139  
   140  	return r.std.Requirements(ctx, mv)
   141  }
   142  
   143  func (r *registry) ModuleVersions(ctx context.Context, mpath string) ([]string, error) {
   144  	if m, ok := r.mem.Resolve(mpath); ok {
   145  		return []string{m.Overwrites.Version}, nil
   146  	}
   147  
   148  	if depOverwrite, ok := r.local.Root.GetDepOverwrite(mpath); ok {
   149  		if depOverwrite.IsLocalReplacement() {
   150  			return []string{"v0.0.0"}, nil
   151  		}
   152  	}
   153  
   154  	versions, _ := r.local.ModuleVersions(ctx, mpath)
   155  	if len(versions) > 0 {
   156  		return versions, nil
   157  	}
   158  
   159  	versions2, _ := r.std.ModuleVersions(ctx, mpath)
   160  	return versions2, nil
   161  }