cmd/go/functions_framework/converter/get_package/main.go (62 lines of code) (raw):
// Copyright 2021 Google LLC
//
// 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.
// Script to extract Go package from a given source directory.
package main
import (
"encoding/json"
"flag"
"fmt"
"go/parser"
"go/token"
"log"
"strings"
)
var (
dir = flag.String("dir", "", "Directory containing *.go files from which to extract a package name.")
)
// parsedPackage represents a parsed package.
type parsedPackage struct {
Name string `json:"name"`
Imports map[string]struct{} `json:"imports"`
}
// extract extracts the name of the package in the specified directory.
// Expects that the specified directory contains one and only one Go package.
func extract(source string) (*parsedPackage, error) {
fset := token.NewFileSet() // positions are relative to fset
// Parse all .go files in dir but stop after processing the package.
pkgs, err := parser.ParseDir(fset, source, nil, parser.ImportsOnly)
if err != nil {
return nil, fmt.Errorf("failed to parse source in %s: %v", source, err)
}
// Check if all files belong to the same package
packageName := ""
for k := range pkgs {
if packageName == "" {
packageName = k
continue
}
if k != packageName {
return nil, fmt.Errorf("multiple packages in user code directory: %s != %s", packageName, k)
}
}
if packageName == "" {
return nil, fmt.Errorf("unable to find Go package in %s", source)
}
packageImports := map[string]struct{}{}
for _, fi := range pkgs[packageName].Files {
for _, im := range fi.Imports {
packageImports[strings.Trim(im.Path.Value, `"`)] = struct{}{}
}
}
return &parsedPackage{
Name: packageName,
Imports: packageImports,
}, nil
}
func main() {
flag.Parse()
if *dir == "" {
log.Fatalf("No directory specified.")
}
pkg, err := extract(*dir)
if err != nil {
log.Fatalf("Unable to extract package name and imports: %v.", err)
}
b, err := json.Marshal(pkg)
if err != nil {
log.Fatalf("Unable to marshal extracted package name and imports: %v.", err)
}
fmt.Print(string(b))
}