github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/linter/file/protoSet.go (about)

     1  package file
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  )
     8  
     9  // ProtoSet represents a set of .proto files.
    10  type ProtoSet struct {
    11  	protoFiles []ProtoFile
    12  }
    13  
    14  // NewProtoSet creates a new ProtoSet.
    15  func NewProtoSet(
    16  	targetPaths []string,
    17  ) (ProtoSet, error) {
    18  	fs, err := collectAllProtoFilesFromArgs(targetPaths)
    19  	if err != nil {
    20  		return ProtoSet{}, err
    21  	}
    22  	if len(fs) == 0 {
    23  		return ProtoSet{}, fmt.Errorf("not found protocol buffer files in %v", targetPaths)
    24  	}
    25  
    26  	return ProtoSet{
    27  		protoFiles: fs,
    28  	}, nil
    29  }
    30  
    31  // ProtoFiles returns proto files.
    32  func (s ProtoSet) ProtoFiles() []ProtoFile {
    33  	return s.protoFiles
    34  }
    35  
    36  func collectAllProtoFilesFromArgs(
    37  	targetPaths []string,
    38  ) ([]ProtoFile, error) {
    39  	cwd, err := os.Getwd()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	absCwd, err := absClean(cwd)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	// Eval a possible symlink for the cwd to calculate the correct relative paths in the next step.
    48  	if newPath, err := filepath.EvalSymlinks(absCwd); err == nil {
    49  		absCwd = newPath
    50  	}
    51  
    52  	var fs []ProtoFile
    53  	for _, path := range targetPaths {
    54  		absTarget, err := absClean(path)
    55  		if err != nil {
    56  			return nil, err
    57  		}
    58  
    59  		f, err := collectAllProtoFiles(absCwd, absTarget)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  		fs = append(fs, f...)
    64  	}
    65  	return fs, nil
    66  }
    67  
    68  func collectAllProtoFiles(
    69  	absWorkDirPath string,
    70  	absPath string,
    71  ) ([]ProtoFile, error) {
    72  	var fs []ProtoFile
    73  
    74  	err := filepath.Walk(
    75  		absPath,
    76  		func(path string, info os.FileInfo, err error) error {
    77  			if err != nil {
    78  				return err
    79  			}
    80  			if filepath.Ext(path) != ".proto" {
    81  				return nil
    82  			}
    83  
    84  			displayPath, err := filepath.Rel(absWorkDirPath, path)
    85  			if err != nil {
    86  				displayPath = path
    87  			}
    88  			displayPath = filepath.Clean(displayPath)
    89  			fs = append(fs, NewProtoFile(path, displayPath))
    90  			return nil
    91  		},
    92  	)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	return fs, nil
    97  }
    98  
    99  // absClean returns the cleaned absolute path of the given path.
   100  func absClean(path string) (string, error) {
   101  	if path == "" {
   102  		return path, nil
   103  	}
   104  	if !filepath.IsAbs(path) {
   105  		return filepath.Abs(path)
   106  	}
   107  	return filepath.Clean(path), nil
   108  }