Repository: goplus/gop
Pull request #501 (2020-07-26 10:04:43)

qexp: fix export mod pkg with version
gop export github.com/qiniu/x/log
gop export github.com/qiniu/x@v1.11.5/log


Patch:
diff --git a/cmd/internal/export/gopkg/export.go b/cmd/internal/export/gopkg/export.go
index f6dda364..8228af7f 100644
--- a/cmd/internal/export/gopkg/export.go
+++ b/cmd/internal/export/gopkg/export.go
@@ -64,6 +64,18 @@ func exportConst(e *Exporter, o *types.Const) (err error) {
 	return e.ExportConst(o)
 }
 
+func cleanPkgVer(pkgPath string) string {
+	i := strings.Index(pkgPath, "@")
+	if i == -1 {
+		return pkgPath
+	}
+	j := strings.Index(pkgPath[i:], "/")
+	if j == -1 {
+		return pkgPath[:i]
+	}
+	return pkgPath[:i] + pkgPath[i:][j:]
+}
+
 func findLastVerPkg(pkgDirBase string, name string) (verName string) {
 	verName = name
 	fis, err := ioutil.ReadDir(pkgDirBase)
@@ -110,6 +122,33 @@ func getPkgKind(pkgPath string) int {
 	return pkgStandard
 }
 
+// LookupMod looup pkgPath srcDir from GOMOD root
+// github.com/qiniu/x/log
+// github.com/qiniu/x@v1.11.5/log
+func LookupMod(pkgPath string) (srcDir string, err error) {
+	parts := strings.Split(pkgPath, "/")
+	n := len(parts)
+	if n < 3 {
+		return "", ErrInvalidPkgPath
+	}
+	srcDir = filepath.Join(getModRoot(), parts[0], parts[1])
+	noVer := strings.Index(parts[2], "@") == -1
+	if noVer {
+		parts[2] = findLastVerPkg(srcDir, parts[2])
+	}
+	srcDir = filepath.Join(srcDir, parts[2])
+	if n > 3 {
+		srcDir += "/" + strings.Join(parts[3:], "/")
+	}
+	return srcDir, nil
+}
+
+// ImportSource import a Go package from pkgPath and srcDir
+func ImportSource(pkgPath string, srcDir string) (*types.Package, error) {
+	imp := importer.ForCompiler(token.NewFileSet(), "source", nil)
+	return imp.(types.ImporterFrom).ImportFrom(pkgPath, srcDir, 0)
+}
+
 // Import imports a Go package.
 func Import(pkgPath string) (*types.Package, error) {
 	var imp types.Importer
@@ -125,6 +164,8 @@ func Import(pkgPath string) (*types.Package, error) {
 		noVer := strings.Index(parts[2], "@") == -1
 		if noVer {
 			parts[2] = findLastVerPkg(srcDir, parts[2])
+		} else {
+			pkgPath = cleanPkgVer(pkgPath)
 		}
 		srcDir = filepath.Join(srcDir, parts[2])
 		if n > 3 {
@@ -153,7 +194,11 @@ var (
 
 func getModRoot() string {
 	gOnce.Do(func() {
-		gModRoot = os.Getenv("GOPATH") + "/pkg/mod"
+		gModRoot = os.Getenv("GOMODCACHE")
+		if gModRoot == "" {
+			paths := strings.Split(os.Getenv("GOPATH"), string(filepath.ListSeparator))
+			gModRoot = paths[0] + "/pkg/mod"
+		}
 	})
 	return gModRoot
 }


Test patch:
diff --git a/cmd/internal/export/gopkg/exporter_test.go b/cmd/internal/export/gopkg/exporter_test.go
index f3d5bd8d..7f23caa5 100644
--- a/cmd/internal/export/gopkg/exporter_test.go
+++ b/cmd/internal/export/gopkg/exporter_test.go
@@ -8,6 +8,7 @@ import (
 	"go/types"
 	"io/ioutil"
 	"os/exec"
+	"path/filepath"
 	"strings"
 	"testing"
 
@@ -179,6 +180,61 @@ func TestImport(t *testing.T) {
 	}
 }
 
+func TestLooupMod(t *testing.T) {
+	dir, err := LookupMod("github.com/qiniu/x/log")
+	if err != nil {
+		t.Fatal("LookupMod failed:", err)
+	}
+	i := strings.Index(dir, "github.com")
+	dir1, err := LookupMod(filepath.ToSlash(dir[i:]))
+	if err != nil {
+		t.Fatal("LookupMod failed:", err)
+	}
+	if dir != dir1 {
+		t.Fatal("LookupMod failed:", dir, dir1)
+	}
+}
+
+func TestExportVersion(t *testing.T) {
+	pkgPath := "github.com/qiniu/x/log"
+	dir, err := LookupMod(pkgPath)
+	if err != nil {
+		t.Fatal("LookupMod failed:", err)
+	}
+	pkgPath = filepath.ToSlash(dir[len(getModRoot())+1:])
+	err = Export(pkgPath, ioutil.Discard)
+	if err != nil {
+		t.Fatal("TestExport failed:", err)
+	}
+}
+
+func TestCleanVersion(t *testing.T) {
+	pkg := cleanPkgVer("github.com/qiniu/x@v1.11.5/log")
+	if pkg != "github.com/qiniu/x/log" {
+		t.Fatal("cleanPkgVer failed:", pkg)
+	}
+	pkg = cleanPkgVer("github.com/qiniu/x@v1.11.5")
+	if pkg != "github.com/qiniu/x" {
+		t.Fatal("cleanPkgVer failed:", pkg)
+	}
+}
+
+func TestImportSource(t *testing.T) {
+	pkgPath := "github.com/qiniu/x/log"
+	dir, err := LookupMod(pkgPath)
+	if err != nil {
+		t.Fatal("LookupMod failed:", err)
+	}
+	pkg, err := ImportSource(pkgPath, dir)
+	if err != nil {
+		t.Fatal("ImportSource failed:", err)
+	}
+	err = ExportPackage(pkg, ioutil.Discard)
+	if err != nil {
+		t.Fatal("ExportPackage failed:", err)
+	}
+}
+
 func TestBadImport(t *testing.T) {
 	_, err := Import("go/badtypes")
 	if err == nil {