Skip to content

Commit

Permalink
cmd/cue: allow cue mod tidy in non-module root
Browse files Browse the repository at this point in the history
The module-root-finding code somewhat duplicates similar
code in both `internal/mod/modpkgload` and `cue/load` but
the former isn't suitable because it's defined in terms of `io/fs.FS`
and reusing the latter would require adding new public API.

Also avoid writing the module file when there's no change.

Signed-off-by: Roger Peppe <[email protected]>
Change-Id: I2fb76abedc43f6be41e8eb16762d5e400acfa77d
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1173826
Reviewed-by: Daniel Martí <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
Unity-Result: CUE porcuepine <[email protected]>
  • Loading branch information
rogpeppe committed Dec 19, 2023
1 parent c4c064d commit f260855
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
39 changes: 35 additions & 4 deletions cmd/cue/cmd/modtidy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package cmd

import (
"bytes"
"context"
"fmt"
"os"
Expand Down Expand Up @@ -53,12 +54,11 @@ func runModTidy(cmd *Command, args []string) error {
return fmt.Errorf("no registry configured to upload to")
}
ctx := context.Background()
// TODO don't assume we're running in the module's root directory.
wd, err := os.Getwd()
modRoot, err := findModuleRoot()
if err != nil {
return err
}
mf, err := modload.Load(ctx, os.DirFS(wd), ".", reg)
mf, err := modload.Load(ctx, os.DirFS(modRoot), ".", reg)
if err != nil {
return err
}
Expand All @@ -67,12 +67,43 @@ func runModTidy(cmd *Command, args []string) error {
if err != nil {
return fmt.Errorf("internal error: invalid module.cue file generated: %v", err)
}
if err := os.WriteFile(filepath.Join("cue.mod", "module.cue"), data, 0o666); err != nil {
modPath := filepath.Join(modRoot, "cue.mod", "module.cue")
oldData, err := os.ReadFile(modPath)
if err != nil {
// Shouldn't happen because modload.Load returns an error
// if it can't load the module file.
return err
}
if bytes.Equal(data, oldData) {
return nil
}
if err := os.WriteFile(modPath, data, 0o666); err != nil {
return err
}
return nil
}

func findModuleRoot() (string, error) {
// TODO this logic is duplicated in multiple places. We should
// consider deduplicating it.
dir, err := os.Getwd()
if err != nil {
return "", err
}
for {
if _, err := os.Stat(filepath.Join(dir, "cue.mod")); err == nil {
return dir, nil
} else if !os.IsNotExist(err) {
return "", err
}
dir1 := filepath.Dir(dir)
if dir1 == dir {
return "", fmt.Errorf("module root not found")
}
dir = dir1
}
}

func modCacheDir() (string, error) {
if dir := os.Getenv("CUE_MODCACHE"); dir != "" {
return dir, nil
Expand Down
17 changes: 17 additions & 0 deletions cmd/cue/cmd/testdata/script/modtidy_non_root.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Check that cue mod tidy works OK even when not
# run in the module's root directory.

cd x/y
exec cue mod tidy
cd $WORK
cmp cue.mod/module.cue want-module

-- want-module --
module: "main.org@v0"
-- cue.mod/module.cue --
module: "main.org@v0"
-- x/y/z.cue --
package y
-- _registry/example.com_v0.0.1/cue.mod/module.cue --
// This file is just here to ensure that CUE_REGISTRY etc is set.
module: "example.com@v0"

0 comments on commit f260855

Please sign in to comment.