gitee.com/h79/goutils@v1.22.10/build/config.go (about)

     1  package build
     2  
     3  import (
     4  	"regexp"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // Build contains the build configuration section.
    10  type Build struct {
    11  	ID          string                          `yaml:"id,omitempty" json:"id,omitempty"`
    12  	Goos        []string                        `yaml:"goos,omitempty" json:"goos,omitempty"`
    13  	GoArch      []string                        `yaml:"goarch,omitempty" json:"goarch,omitempty"`
    14  	GoArm       []string                        `yaml:"goarm,omitempty" json:"goarm,omitempty"`
    15  	GoMips      []string                        `yaml:"gomips,omitempty" json:"gomips,omitempty"`
    16  	GoAmd64     []string                        `yaml:"goamd64,omitempty" json:"goamd64,omitempty"`
    17  	Executor    map[string]string               `yaml:"executor" json:"executor"` //生成的执行文件名,不同的操作系统对应不同的执行文件,"drawin":"projectName-mac",“linux":"projectName-linux","windows":"projectName-win.exe"
    18  	ModulePath  string                          `yaml:"module_path" json:"module_path"`
    19  	ProductId   string                          `yaml:"product_id" json:"product_id"`
    20  	ProjectName string                          `yaml:"project_name" json:"project_name"`
    21  	Target      string                          `yaml:"target,omitempty" json:"target,omitempty"` //生成目标目录
    22  	Dir         string                          `yaml:"dir,omitempty" json:"dir,omitempty"`
    23  	Main        string                          `yaml:"main,omitempty" json:"main,omitempty"`
    24  	GoBinary    string                          `yaml:"go_binary,omitempty" json:"go_binary,omitempty"`
    25  	Command     string                          `yaml:"command,omitempty" json:"command,omitempty"`
    26  	Package     Package                         `yaml:"package" json:"package"`
    27  	Details     `yaml:",inline" json:",inline"` // nolint: tagliatelle
    28  }
    29  
    30  type Details struct {
    31  	Buildmode string      `yaml:"buildmode,omitempty" json:"buildmode,omitempty"`
    32  	Ldflags   StringArray `yaml:"ldflags,omitempty" json:"ldflags,omitempty"`
    33  	Tags      FlagArray   `yaml:"tags,omitempty" json:"tags,omitempty"`
    34  	Flags     FlagArray   `yaml:"flags,omitempty" json:"flags,omitempty"`
    35  	AsmFlags  StringArray `yaml:"asm_flags,omitempty" json:"asm_flags,omitempty"`
    36  	GcFlags   StringArray `yaml:"gc_flags,omitempty" json:"gc_flags,omitempty"`
    37  	Env       []string    `yaml:"env,omitempty" json:"env,omitempty"`
    38  }
    39  
    40  type PackCheck func(path, name string, isDir bool) bool
    41  type PackCompleted func(out *PackOut, pf *PackFile, completed bool)
    42  
    43  type PackOut struct {
    44  	Version     string      `json:"version"`
    45  	Path        string      `json:"path"` // ./build
    46  	PackagePath string      `json:"packagePath"`
    47  	PublishPath string      `json:"publishPath"`
    48  	Name        string      `json:"name"` // file name
    49  	Ext         string      `json:"ext"`  // file ext
    50  	Target      string      `json:"target"`
    51  	Url         string      `json:"url"`
    52  	Hash        string      `json:"hash"` // updates.json 文件名(包括路径)
    53  	Data        interface{} `json:"-"`    //自定义
    54  }
    55  
    56  const (
    57  	OutHashFile       = 0x00001 // 输出updates.json(hash文件)
    58  	HashNeedProject   = 0x00002 // hash文件需要用程序名
    59  	HashNeedVersion   = 0x00004 // hash文件需要带版本号
    60  	HashNeedModel     = 0x00008 // hash输出带model
    61  	HashNeedOs        = 0x00010 // hash输出带os
    62  	TargetNeedVersion = 0x00020
    63  	TargetNeedModel   = 0x00040
    64  	TargetNeedOs      = 0x00080
    65  	TargetNeedDate    = 0x00100
    66  	NeedArchiveHash   = 0x02000 // hashFile需要添加到压缩文件中
    67  	OnlyPackOut       = 0x04000
    68  	NotArchive        = 0x08000 //不需要压缩
    69  	ArchiveVersion    = 0x10000 //压缩目录带版本
    70  	ArchiveProject    = 0x20000 //压缩目录带产品名(ProjectName)
    71  	NotCheckTpl       = 0x40000 //不需要检测模板 *.tpl
    72  	NotCheckPackFile  = 0x80000 //不对 exclude, include 检测
    73  )
    74  
    75  var flagMap = map[string]int{
    76  	"OutHashFile":       OutHashFile,
    77  	"HashNeedProject":   HashNeedProject, // hash文件需要用程序名
    78  	"HashNeedVersion":   HashNeedVersion, // hash文件需要带版本号
    79  	"HashNeedModel":     HashNeedModel,   // hash输出带model
    80  	"HashNeedOs":        HashNeedOs,      // hash输出带os
    81  	"TargetNeedVersion": TargetNeedVersion,
    82  	"TargetNeedModel":   TargetNeedModel,
    83  	"TargetNeedOs":      TargetNeedOs,
    84  	"TargetNeedDate":    TargetNeedDate,
    85  	"NeedArchiveHash":   NeedArchiveHash, // hashFile需要添加到压缩文件中
    86  	"OnlyPackOut":       OnlyPackOut,
    87  	"NotArchive":        NotArchive,     //不需要压缩
    88  	"ArchiveVersion":    ArchiveVersion, //压缩目录带版本
    89  	"ArchiveProject":    ArchiveProject, //压缩目录带产品名(ProjectName)
    90  	"NotCheckTpl":       NotCheckTpl,    //不需要检测模板 *.tpl
    91  	"NotCheckPackFile":  NotCheckPackFile,
    92  }
    93  
    94  func AddFlag(f string, bit int) {
    95  	flagMap[f] = bit
    96  }
    97  
    98  func GetFlag(f string) int {
    99  	ret, ok := flagMap[f]
   100  	if ok {
   101  		return ret
   102  	}
   103  	return 0
   104  }
   105  
   106  type Package struct {
   107  	ProductCode   string   `yaml:"productCode" json:"productCode"` //产品编号
   108  	Model         string   `yaml:"model" json:"model"`             //prod, test, dev
   109  	Os            string   `yaml:"os" json:"os"`                   //操作系统 windows,linux,darwin
   110  	Format        string   `yaml:"format" json:"format"`           //zip, tar.gz, tgz, tar, cab(windows), setup
   111  	Dist          string   `yaml:"dist" json:"dist"`               //输出目录
   112  	PackagePath   string   `yaml:"packagePath" json:"packagePath"` // 包目录 dist/package_path, 默认 dist/packages
   113  	PublishPath   string   `yaml:"publishPath" json:"publishPath"` // 发布目录 dist/publish_path 默认 dist/publishes
   114  	Target        string   `yaml:"target" json:"target"`           //输出文件名,可以为空
   115  	Hash          string   `yaml:"hash" json:"hash"`               //输出pack 总的包描述文件,如: updates.json
   116  	BaseUrl       string   `yaml:"baseUrl" json:"baseUrl"`         //文件存储基本地址(oss,如阿里云)
   117  	MgrHost       string   `yaml:"mgrHost" json:"mgrHost"`         //版本管理后台host,需要把打包的信息保存到后台进行管理,比如: http://xxx.com:port
   118  	Flag          string   `yaml:"flag" json:"flag"`               //标识 @see OutHashFile
   119  	Exclude       []string `yaml:"exclude" json:"exclude"`         //打包不包括的选项
   120  	Include       []string `yaml:"include" json:"include"`         //打包包括的选项
   121  	flag          Bit
   122  	excludeR      []Regex
   123  	includeR      []Regex
   124  	excludeCheck  PackCheck
   125  	includeCheck  PackCheck
   126  	packCompleted PackCompleted
   127  }
   128  
   129  type Bit int32
   130  
   131  func ToBit(b string) Bit {
   132  	var ret int
   133  	bits := strings.Split(b, "|")
   134  	for i := range bits {
   135  		bit, err := strconv.Atoi(bits[i])
   136  		if err != nil {
   137  			bit = GetFlag(bits[i])
   138  		}
   139  		ret |= bit
   140  	}
   141  	return Bit(ret)
   142  }
   143  
   144  func (a Bit) Bit(bit int32) bool {
   145  	return int32(a)&bit == bit
   146  }
   147  
   148  type Regex struct {
   149  	Path bool
   150  	Exp  *regexp.Regexp
   151  }
   152  
   153  func (p *Package) Parse() {
   154  	p.flag = ToBit(p.Flag)
   155  }
   156  
   157  func (p *Package) IsFlag(o int32) bool {
   158  	return p.flag.Bit(o)
   159  }
   160  
   161  func (p *Package) WithExcludeCheck(check PackCheck) {
   162  	p.excludeCheck = check
   163  }
   164  
   165  func (p *Package) WithIncludeCheck(check PackCheck) {
   166  	p.includeCheck = check
   167  }
   168  
   169  func (p *Package) WithCompleted(check PackCompleted) {
   170  	p.packCompleted = check
   171  }
   172  
   173  func (p *Package) buildCheck() {
   174  	if len(p.Exclude) > 0 && len(p.excludeR) == 0 {
   175  		p.excludeR = make([]Regex, len(p.Exclude))
   176  	}
   177  	if len(p.Include) > 0 && len(p.includeR) == 0 {
   178  		p.includeR = make([]Regex, len(p.Include))
   179  	}
   180  }
   181  
   182  const (
   183  	RegexPrefix = "regex|"
   184  	PathPrefix  = "path|"
   185  )
   186  
   187  func (p *Package) IncludeCheck(path, name string, isDir bool) bool {
   188  	p.buildCheck()
   189  	if p.includeCheck != nil {
   190  		if p.includeCheck(path, name, isDir) {
   191  			return true
   192  		}
   193  	}
   194  	for i := range p.Include {
   195  		if strings.EqualFold(p.Include[i], name) {
   196  			return true
   197  		}
   198  		if p.includeR[i].Exp == nil {
   199  			if strings.HasPrefix(p.Include[i], RegexPrefix) {
   200  				p.includeR[i].Exp, _ = regexp.Compile(strings.TrimPrefix(p.Include[i], RegexPrefix))
   201  			} else if strings.HasPrefix(p.Include[i], PathPrefix) {
   202  				p.includeR[i].Exp, _ = regexp.Compile(strings.TrimPrefix(p.Include[i], PathPrefix))
   203  				p.includeR[i].Path = true
   204  			}
   205  			if p.includeR[i].Exp == nil {
   206  				continue
   207  			}
   208  		}
   209  		if p.includeR[i].Path && isDir {
   210  			if path != "" && p.includeR[i].Exp.MatchString(path) {
   211  				return true
   212  			}
   213  		} else if p.includeR[i].Exp.MatchString(name) {
   214  			return true
   215  		}
   216  	}
   217  	return false
   218  }
   219  
   220  func (p *Package) ExcludeCheck(path, name string, isDir bool) bool {
   221  	p.buildCheck()
   222  	if p.excludeCheck != nil {
   223  		if p.excludeCheck(path, name, isDir) {
   224  			return true
   225  		}
   226  	}
   227  	for i := range p.Exclude {
   228  		if strings.EqualFold(p.Exclude[i], name) {
   229  			return true
   230  		}
   231  		if p.excludeR[i].Exp == nil {
   232  			if strings.HasPrefix(p.Exclude[i], RegexPrefix) {
   233  				p.excludeR[i].Exp, _ = regexp.Compile(strings.TrimPrefix(p.Exclude[i], RegexPrefix))
   234  			} else if strings.HasPrefix(p.Exclude[i], PathPrefix) {
   235  				p.excludeR[i].Exp, _ = regexp.Compile(strings.TrimPrefix(p.Exclude[i], PathPrefix))
   236  				p.excludeR[i].Path = true
   237  			}
   238  			if p.excludeR[i].Exp == nil {
   239  				continue
   240  			}
   241  		}
   242  		if p.excludeR[i].Path {
   243  			if isDir && path != "" && p.excludeR[i].Exp.MatchString(path) {
   244  				return true
   245  			}
   246  		} else if p.excludeR[i].Exp.MatchString(name) {
   247  			return true
   248  		}
   249  	}
   250  	return false
   251  }
   252  
   253  func (p *Package) Ignore(path, name string, isDir bool) bool {
   254  	if p.IsFlag(NotCheckPackFile) {
   255  		return false
   256  	}
   257  	ss := strings.ToLower(name)
   258  	if p.CheckOs(ss) {
   259  		return true
   260  	}
   261  	if p.IncludeCheck(path, ss, isDir) {
   262  		return false
   263  	}
   264  	if p.ExcludeCheck(path, ss, isDir) {
   265  		return true
   266  	}
   267  	return false
   268  }
   269  
   270  func (p *Package) CheckOs(name string) bool {
   271  	if p.Model != "" {
   272  		if strings.HasPrefix(name, "dev") && p.Model != "dev" {
   273  			return true
   274  		}
   275  		if strings.HasPrefix(name, "prod") && p.Model != "prod" {
   276  			return true
   277  		}
   278  		if strings.HasPrefix(name, "test") && p.Model != "test" {
   279  			return true
   280  		}
   281  	}
   282  	if p.Os != "" {
   283  		if p.Os == "windows" {
   284  			if strings.HasSuffix(name, ".sh") ||
   285  				strings.HasSuffix(name, "-mac") ||
   286  				strings.HasSuffix(name, "-linux") ||
   287  				strings.HasSuffix(name, ".so") {
   288  				return true
   289  			}
   290  		} else {
   291  			if p.Os == "darwin" {
   292  				if strings.HasSuffix(name, "-linux") {
   293  					return true
   294  				}
   295  			} else if p.Os == "linux" {
   296  				if strings.HasSuffix(name, "-mac") {
   297  					return true
   298  				}
   299  			}
   300  			if strings.HasSuffix(name, ".bat") ||
   301  				strings.HasSuffix(name, ".exe") ||
   302  				strings.HasSuffix(name, ".dll") {
   303  				return true
   304  			}
   305  		}
   306  	}
   307  	return strings.HasSuffix(name, ".lib") ||
   308  		strings.HasSuffix(name, ".go") ||
   309  		strings.HasSuffix(name, ".c") ||
   310  		strings.HasSuffix(name, ".h")
   311  }
   312  
   313  type PackFile struct {
   314  	Name string `json:"name"`
   315  	MD5  string `json:"md5"`
   316  	Size int64  `json:"size"`
   317  	Url  string `json:"url,omitempty"`
   318  }
   319  
   320  type HashFile struct {
   321  	Os          string     `json:"os"`
   322  	Version     string     `json:"version"`
   323  	Model       string     `json:"model"`
   324  	ProductId   string     `json:"product_id"`
   325  	ProductCode string     `json:"product_code"`
   326  	ProjectName string     `json:"project_name"`
   327  	Packs       []PackFile `json:"files"`
   328  }
   329  
   330  // StringArray is a wrapper for an array of strings.
   331  type StringArray []string
   332  
   333  type FlagArray []string