hello world! 🌸

This commit is contained in:
commit 4b582e6c48
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C
8 changed files with 225 additions and 0 deletions

31
.gitignore vendored Normal file

@ -0,0 +1,31 @@
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# env file
.env
.idea/material_theme_project_new.xml
build/**/*
.idea/workspace.xml
.idea/vcs.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,15 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GoErrorStringFormat" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="GoSwitchMissingCasesForIotaConsts" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
<inspection_tool class="GoUnhandledErrorResult" enabled="true" level="WEAK WARNING" enabled_by_default="true" editorAttributes="INFO_ATTRIBUTES" />
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

8
.idea/modules.xml Normal file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/gopack-internal.iml" filepath="$PROJECT_DIR$/.idea/gopack-internal.iml" />
</modules>
</component>
</project>

9
README.md Normal file

@ -0,0 +1,9 @@
# gopack
internal utility to create zip files from go module directories
## usage
```
gopack PACKAGE-NAME VERSION PATH [COMMA-SEPARATED-EXCLUSION-GLOBS]
```

8
go.mod Normal file

@ -0,0 +1,8 @@
module rockfic.com/gopack
go 1.23.0
require (
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
golang.org/x/mod v0.21.0 // indirect
)

4
go.sum Normal file

@ -0,0 +1,4 @@
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=

141
main.go Normal file

@ -0,0 +1,141 @@
package main
import (
"bytes"
"fmt"
"github.com/bmatcuk/doublestar/v4"
"golang.org/x/mod/module"
"golang.org/x/mod/zip"
"io"
"log"
"os"
"path"
"path/filepath"
"slices"
"strings"
)
type dirFile struct {
filePath, slashPath string
info os.FileInfo
}
func (f dirFile) Path() string { return f.slashPath }
func (f dirFile) Lstat() (os.FileInfo, error) { return f.info, nil }
func (f dirFile) Open() (io.ReadCloser, error) { return os.Open(f.filePath) }
func parseGitignore(wd string) []string {
f := make([]string, 0)
file, err := os.ReadFile(path.Join(wd, ".gitignore"))
if err == nil {
str := bytes.NewBuffer(file).String()
for _, rline := range strings.Split(str, "\n") {
line := strings.TrimSpace(rline)
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, "!") {
continue
}
if strings.HasPrefix(line, "*") {
f = append(f, line)
f = append(f, fmt.Sprintf("**/%s", line))
} else if strings.HasSuffix(line, "/") {
f = append(f, fmt.Sprintf("%s/**", line))
f = append(f, fmt.Sprintf("%s/**/*", line))
}
}
}
fmt.Println(f)
return f
}
func doWalk(wd string, exGlobs []string) []zip.File {
f := make([]zip.File, 0)
filepath.Walk(wd, func(p string, info os.FileInfo, err error) error {
slashed := filepath.ToSlash(p)
rel, _ := filepath.Rel(wd, slashed)
rel = filepath.ToSlash(rel)
if info.IsDir() {
if p == wd {
return nil
}
switch filepath.Base(p) {
case ".git", ".bzr", ".svn", ".hg":
return filepath.SkipDir
}
if goModInfo, err := os.Lstat(filepath.Join(p, "go.mod")); err == nil && !goModInfo.IsDir() {
return filepath.SkipDir
}
for _, pat := range exGlobs {
ok, _ := doublestar.Match(pat, rel)
if ok {
return filepath.SkipDir
}
}
return nil
}
if !info.Mode().IsRegular() {
return nil
}
ok, err := doublestar.Match(fmt.Sprintf("{%s}", strings.Join(exGlobs, ",")), rel)
if err != nil {
log.Fatal(err)
}
if !ok {
if !slices.Contains(maps(f, func(t zip.File) string {
return t.Path()
}), slashed) {
f = append(f, dirFile{
filePath: p,
info: info,
slashPath: rel,
})
}
}
return nil
})
return f
}
func maps[T any, R any](slice []T, fn func(t T) R) []R {
ret := make([]R, 0)
for _, e := range slice {
ret = append(ret, fn(e))
}
return ret
}
func main() {
args := os.Args[1:]
if len(args) < 3 {
log.Fatal("usage: PACKAGE-NAME VERSION PATH [EXCLUSION-GLOBS...]")
}
version := args[1]
if !strings.HasPrefix(version, "v") {
version = fmt.Sprintf("v%s", version)
}
var absPath string
absPath, _ = filepath.Abs(args[2])
excludeGlobs := make([]string, 0)
excludeGlobs = append(excludeGlobs, ".*/*", "build/**")
excludeGlobs = append(excludeGlobs, parseGitignore(absPath)...)
if len(args) >= 4 {
excludeGlobs = append(excludeGlobs, args[3:]...)
}
buildFile := fmt.Sprintf(filepath.Join(absPath, "build", "%s.zip"), version)
walked := doWalk(absPath, excludeGlobs)
_ = os.Remove(buildFile)
f, _ := os.Create(buildFile)
err := zip.Create(f, module.Version{
Version: version,
Path: args[0],
}, walked)
if err != nil {
log.Fatal(err)
}
}