Fetch the repository succeeded.
package template
import (
	"bytes"
	"compress/gzip"
	"context"
	"errors"
	"fmt"
	"gitee.com/anesec/chameleon/pkg/template/expr"
	"gitee.com/anesec/chameleon/pkg/template/language"
	"gitee.com/anesec/chameleon/pkg/utils"
	"go.etcd.io/bbolt"
	"path/filepath"
	"sort"
	"sync"
	"time"
)
type Kind uint8
const (
	KindUnknown Kind = iota
	KindApplication
	KindFramework
)
var (
	ErrNotMatch = errors.New("not match")
)
type EnumerateOptions struct {
	Templates []string
}
type Enumerator interface {
	Enumerate(ctx context.Context, source expr.Source, options *EnumerateOptions) error
}
func Compile(templates ...string) (Enumerator, error) {
	var (
		services  []*Template
		languages []*Template
		err       error
	)
	enum := &enumerator{}
	if services, languages, err = enum.compile(templates...); err != nil {
		return nil, err
	}
	enum.services = services
	enum.languages = languages
	return enum, nil
}
type enumerator struct {
	services  []*Template
	languages []*Template
	rwl sync.RWMutex
}
func (enum *enumerator) Enumerate(ctx context.Context, source expr.Source, options *EnumerateOptions) error {
	var (
		services  []*Template
		languages []*Template
		service   *Template
		err       error
	)
	if options == nil {
		options = &EnumerateOptions{}
	}
	if len(options.Templates) > 0 {
		if services, languages, err = enum.compile(options.Templates...); err != nil {
			return err
		}
	} else {
		services = enum.services
		languages = enum.languages
	}
	// enumerate AI service first
	sort.Sort(templates(services))
	var llmServiceFound bool
	source = language.New(source)
	for _, template := range services {
		if llmServiceFound && template.Category == "ai" {
			continue
		}
		if template.eval(ctx, source, KindApplication) {
			if template.Category == "ai" {
				// found AI llm service, continue to enumerate web/application... services
				llmServiceFound = true
				continue
			}
			service = template
			break
		}
	}
	if service == nil {
		if llmServiceFound {
			return nil
		}
		return ErrNotMatch
	}
	ports, _ := source.Provide("proc.ports").([]int)
	if (service.Category == "web" || len(ports) > 0) && len(languages) > 0 {
		lang, ok := source.Provide("distribute.language").(string)
		if !ok || lang == "" {
			return nil
		}
		for _, template := range languages {
			if template.Name != lang {
				continue
			}
			template.eval(ctx, source, KindFramework)
		}
	}
	return nil
}
func (enum *enumerator) compile(templates ...string) (services, languages []*Template, err error) {
	services = make([]*Template, 0, len(templates))
	languages = make([]*Template, 0, len(templates))
	buf := utils.Acquire(utils.BufferSize2K)
	defer utils.Recycle(buf)
	for _, template := range templates {
		switch filepath.Ext(template) {
		case ".yaml", ".yml":
			buf.Reset()
			if err = utils.BufferedRead(template, buf); err != nil {
				return
			}
			var tpl Template
			if err = tpl.compile(buf); err != nil {
				return
			}
			switch enum.detectTemplateKind(&tpl) {
			case KindApplication:
				services = append(services, &tpl)
			case KindFramework:
				languages = append(languages, &tpl)
			default:
			}
		case ".templates":
			var db *bbolt.DB
			if db, err = bbolt.Open(template, 0600, &bbolt.Options{ReadOnly: true, Timeout: 15 * time.Second}); err != nil {
				return
			}
			err = db.View(func(tx *bbolt.Tx) error {
				bkt := tx.Bucket([]byte("templates"))
				if bkt == nil {
					return fmt.Errorf("no templates bucket in file %s", template)
				}
				return bkt.ForEach(func(k, v []byte) error {
					var gzipReader *gzip.Reader
					if gzipReader, err = gzip.NewReader(bytes.NewReader(v)); err != nil {
						return err
					}
					defer gzipReader.Close()
					var tpl Template
					if err = tpl.compile(gzipReader); err != nil {
						return err
					}
					switch enum.detectTemplateKind(&tpl) {
					case KindApplication:
						services = append(services, &tpl)
					case KindFramework:
						languages = append(languages, &tpl)
					default:
					}
					return nil
				})
			})
			_ = db.Close()
			if err != nil {
				return
			}
		default:
			return nil, nil, fmt.Errorf("unknown template type: %s", filepath.Ext(template))
		}
	}
	return
}
func (enum *enumerator) detectTemplateKind(template *Template) Kind {
	switch template.Name {
	case language.Python, language.Java, language.Golang, language.NodeJS, language.Node, language.PHP:
		if template.Frameworks != nil {
			return KindFramework
		}
	}
	if template.Service != nil && template.Frameworks == nil {
		return KindApplication
	}
	return KindUnknown
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
 马建仓 AI 助手
马建仓 AI 助手