Merge pull request #7 from go-enry/win-support

Code generator Win support
This commit is contained in:
Alexander 2020-03-29 23:31:10 +02:00 committed by GitHub
commit fa1c6f39b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 69 deletions

View File

@ -13,10 +13,16 @@ jobs:
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- name: Set git on win to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Test - name: Test
run: go test ./... run: go test ./...
env:
ENRY_DEBUG: 1
test-oniguruma: test-oniguruma:
strategy: strategy:
matrix: matrix:

View File

@ -7,9 +7,11 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"math" "math"
"os"
"path/filepath" "path/filepath"
"sort" "sort"
"strconv" "strconv"
"strings"
"text/template" "text/template"
"github.com/go-enry/go-enry/v2/internal/tokenizer" "github.com/go-enry/go-enry/v2/internal/tokenizer"
@ -31,6 +33,21 @@ func Frequencies(fileToParse, samplesDir, outPath, tmplPath, tmplName, commit st
return err return err
} }
if _, ok := os.LookupEnv("ENRY_DEBUG"); ok {
log.Printf("Total samples: %d\n", freqs.LanguageTotal)
log.Printf("Total tokens: %d\n", freqs.TokensTotal)
keys := make([]string, 0, len(freqs.Languages))
for k := range freqs.Languages {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Printf(" %s: %d\n", k, freqs.Languages[k])
}
}
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
if err := executeFrequenciesTemplate(buf, freqs, tmplPath, tmplName, commit); err != nil { if err := executeFrequenciesTemplate(buf, freqs, tmplPath, tmplName, commit); err != nil {
return err return err
@ -91,49 +108,46 @@ func getFrequencies(samplesDir string) (*samplesFrequencies, error) {
}, nil }, nil
} }
// readSamples collects ./samples/ filenames from the Linguist codebase, skiping symlinks.
func readSamples(samplesLangDir string) ([]string, error) { func readSamples(samplesLangDir string) ([]string, error) {
const samplesLangFilesDir = "filenames" const specialSubDir = "filenames"
sampleFiles, err := ioutil.ReadDir(samplesLangDir)
if err != nil {
return nil, err
}
var samples []string var samples []string
for _, sampleFile := range sampleFiles {
filename := filepath.Join(samplesLangDir, sampleFile.Name())
if sampleFile.Mode().IsRegular() {
samples = append(samples, filename)
continue
}
if sampleFile.IsDir() && sampleFile.Name() == samplesLangFilesDir { err := filepath.Walk(samplesLangDir, func(path string, info os.FileInfo, err error) error {
subSamples, err := readSubSamples(filename) if err != nil {
if err != nil { fmt.Printf("failure accessing a path %q: %v\n", path, err)
return nil, err return err
}
if info.IsDir() {
switch info.Name() {
case filepath.Base(samplesLangDir):
return nil
case specialSubDir:
return nil
default:
return filepath.SkipDir
} }
samples = append(samples, subSamples...)
} }
// skip git file symlinks on win and *nix
if isKnownSymlinkInLinguist(path) || !info.Mode().IsRegular() {
return nil
}
samples = append(samples, path)
return nil
})
} return samples, err
return samples, nil
} }
func readSubSamples(path string) ([]string, error) { // isKnownSymlinkInLinguist checks if the file name is on the list of known symlinks.
subSamples := []string{} // On Windows, there is no symlink support in Git [1] and those become regular text files,
entries, err := ioutil.ReadDir(path) // so we have to skip these files manually, maintaing a list here :/
if err != nil { // 1. https://github.com/git-for-windows/git/wiki/Symbolic-Links
return nil, err //
} // $ find -L .linguist/samples -xtype l
func isKnownSymlinkInLinguist(path string) bool {
for _, entry := range entries { return strings.HasSuffix(path, filepath.Join("Ant Build System", "filenames", "build.xml")) ||
if entry.Mode().IsRegular() { strings.HasSuffix(path, filepath.Join("Markdown", "symlink.md"))
subSamples = append(subSamples, filepath.Join(path, entry.Name()))
}
}
return subSamples, nil
} }
func getTokens(samples []string) ([]string, error) { func getTokens(samples []string) ([]string, error) {

View File

@ -9,7 +9,10 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/go-enry/go-enry/v2/internal/tokenizer"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
) )
@ -302,9 +305,25 @@ func (s *GeneratorTestSuite) TestGenerationFiles() {
expected := normalizeSpaces(string(gold)) expected := normalizeSpaces(string(gold))
actual := normalizeSpaces(string(out)) actual := normalizeSpaces(string(out))
assert.Equal(s.T(), expected, actual, "Test %s", test.name) assert.Equal(s.T(), expected, actual, "Test %s", test.name)
if expected != actual {
s.T().Logf("%s generated is different from %q", test.name, test.wantOut)
s.T().Logf("Expected %q", expected[:400])
s.T().Logf("Actual %q", actual[:400])
}
} }
} }
func (s *GeneratorTestSuite) TestTokenizerOnATS() {
const suspiciousSample = "samples/ATS/csv_parse.hats"
sFile := filepath.Join(s.tmpLinguist, suspiciousSample)
content, err := ioutil.ReadFile(sFile)
require.NoError(s.T(), err)
tokens := tokenizer.Tokenize(content)
assert.Equal(s.T(), 381, len(tokens), "Number of tokens using LF as line endings")
}
// normalizeSpaces returns a copy of str with whitespaces normalized. // normalizeSpaces returns a copy of str with whitespaces normalized.
// We use this to compare generated source as gofmt format may change. // We use this to compare generated source as gofmt format may change.
// E.g for changes between Go 1.10 and 1.11 see // E.g for changes between Go 1.10 and 1.11 see

View File

@ -3,81 +3,84 @@ package main
import ( import (
"io/ioutil" "io/ioutil"
"log" "log"
"path/filepath"
"github.com/go-enry/go-enry/v2/internal/code-generator/generator" "github.com/go-enry/go-enry/v2/internal/code-generator/generator"
) )
const ( var (
// languages info file // directories
languagesYAML = ".linguist/lib/linguist/languages.yml" samplesDir = filepath.Join(".linguist", "samples")
libDir = filepath.Join(".linguist", "lib", "linguist")
assetsDir = filepath.Join("internal", "code-generator", "assets")
// linguist's samples directory // languages info file
samplesDir = ".linguist/samples" languagesYAML = filepath.Join(libDir, "languages.yml")
// extension.go generation // extension.go generation
extensionsFile = "data/extension.go" extensionsFile = filepath.Join("data", "extension.go")
extensionsTmplPath = "internal/code-generator/assets/extension.go.tmpl" extensionsTmplPath = filepath.Join(assetsDir, "extension.go.tmpl")
extensionsTmpl = "extension.go.tmpl" extensionsTmpl = "extension.go.tmpl"
// content.go generation // content.go generation
heuristicsYAML = ".linguist/lib/linguist/heuristics.yml" heuristicsYAML = filepath.Join(libDir, "heuristics.yml")
contentFile = "data/content.go" contentFile = filepath.Join("data", "content.go")
contentTmplPath = "internal/code-generator/assets/content.go.tmpl" contentTmplPath = filepath.Join(assetsDir, "content.go.tmpl")
contentTmpl = "content.go.tmpl" contentTmpl = "content.go.tmpl"
// vendor.go generation // vendor.go generation
vendorYAML = ".linguist/lib/linguist/vendor.yml" vendorYAML = filepath.Join(libDir, "vendor.yml")
vendorFile = "data/vendor.go" vendorFile = filepath.Join("data", "vendor.go")
vendorTmplPath = "internal/code-generator/assets/vendor.go.tmpl" vendorTmplPath = filepath.Join(assetsDir, "vendor.go.tmpl")
vendorTmpl = "vendor.go.tmpl" vendorTmpl = "vendor.go.tmpl"
// documentation.go generation // documentation.go generation
documentationYAML = ".linguist/lib/linguist/documentation.yml" documentationYAML = filepath.Join(libDir, "documentation.yml")
documentationFile = "data/documentation.go" documentationFile = filepath.Join("data", "documentation.go")
documentationTmplPath = "internal/code-generator/assets/documentation.go.tmpl" documentationTmplPath = filepath.Join(assetsDir, "documentation.go.tmpl")
documentationTmpl = "documentation.go.tmpl" documentationTmpl = "documentation.go.tmpl"
// type.go generation // type.go generation
typeFile = "data/type.go" typeFile = filepath.Join("data", "type.go")
typeTmplPath = "internal/code-generator/assets/type.go.tmpl" typeTmplPath = filepath.Join(assetsDir, "type.go.tmpl")
typeTmpl = "type.go.tmpl" typeTmpl = "type.go.tmpl"
// interpreter.go generation // interpreter.go generation
interpretersFile = "data/interpreter.go" interpretersFile = filepath.Join("data", "interpreter.go")
interpretersTmplPath = "internal/code-generator/assets/interpreter.go.tmpl" interpretersTmplPath = filepath.Join(assetsDir, "interpreter.go.tmpl")
interpretersTmpl = "interpreter.go.tmpl" interpretersTmpl = "interpreter.go.tmpl"
// filename.go generation // filename.go generation
filenamesFile = "data/filename.go" filenamesFile = filepath.Join("data", "filename.go")
filenamesTmplPath = "internal/code-generator/assets/filename.go.tmpl" filenamesTmplPath = filepath.Join(assetsDir, "filename.go.tmpl")
filenamesTmpl = "filename.go.tmpl" filenamesTmpl = "filename.go.tmpl"
// alias.go generation // alias.go generation
aliasesFile = "data/alias.go" aliasesFile = filepath.Join("data", "alias.go")
aliasesTmplPath = "internal/code-generator/assets/alias.go.tmpl" aliasesTmplPath = filepath.Join(assetsDir, "alias.go.tmpl")
aliasesTmpl = "alias.go.tmpl" aliasesTmpl = "alias.go.tmpl"
// frequencies.go generation // frequencies.go generation
frequenciesFile = "data/frequencies.go" frequenciesFile = filepath.Join("data", "frequencies.go")
frequenciesTmplPath = "internal/code-generator/assets/frequencies.go.tmpl" frequenciesTmplPath = filepath.Join(assetsDir, "frequencies.go.tmpl")
frequenciesTmpl = "frequencies.go.tmpl" frequenciesTmpl = "frequencies.go.tmpl"
// commit.go generation // commit.go generation
commitFile = "data/commit.go" commitFile = filepath.Join("data", "commit.go")
commitTmplPath = "internal/code-generator/assets/commit.go.tmpl" commitTmplPath = filepath.Join(assetsDir, "commit.go.tmpl")
commitTmpl = "commit.go.tmpl" commitTmpl = "commit.go.tmpl"
// mimeType.go generation // mimeType.go generation
mimeTypeFile = "data/mimeType.go" mimeTypeFile = filepath.Join("data", "mimeType.go")
mimeTypeTmplPath = "internal/code-generator/assets/mimeType.go.tmpl" mimeTypeTmplPath = filepath.Join(assetsDir, "mimeType.go.tmpl")
mimeTypeTmpl = "mimeType.go.tmpl" mimeTypeTmpl = "mimeType.go.tmpl"
// colors.go generation // colors.go generation
colorsFile = "data/colors.go" colorsFile = filepath.Join("data", "colors.go")
colorsTmplPath = "internal/code-generator/assets/colors.go.tmpl" colorsTmplPath = filepath.Join(assetsDir, "colors.go.tmpl")
colorsTmpl = "colors.go.tmpl" colorsTmpl = "colors.go.tmpl"
commitPath = ".linguist/.git/HEAD" commitPath = filepath.Join(".linguist", ".git", "HEAD")
) )
type generatorFiles struct { type generatorFiles struct {
@ -125,7 +128,7 @@ func getCommit(path string) (string, error) {
} }
if string(commit) == "ref: refs/heads/master\n" { if string(commit) == "ref: refs/heads/master\n" {
path = ".linguist/.git/" + string(commit[5:len(commit)-1]) path = filepath.Join(".linguist", ".git", string(commit[5:len(commit)-1]))
commit, err = ioutil.ReadFile(path) commit, err = ioutil.ReadFile(path)
if err != nil { if err != nil {
return "", err return "", err