poc ready

This commit is contained in:
Chen Asraf
2022-05-18 15:22:39 +03:00
parent 026243dbb9
commit fda50debe1
6 changed files with 250 additions and 69 deletions

View File

@@ -1,16 +0,0 @@
package main
import (
"os"
"path/filepath"
)
func getGitignores(sourceDir string) ([]string, error) {
return filepath.Glob(filepath.Join(sourceDir, "*.gitignore"))
}
func readFile(path string) string {
res, err := os.ReadFile(path)
handleErr(err)
return string(res)
}

107
gi_gen.go
View File

@@ -1,72 +1,83 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"strings"
// "github.com/tcnksm/go-input"
)
// UNUSED allows unused variables to be included in Go programs
func UNUSED(x ...interface{}) {}
"github.com/AlecAivazis/survey/v2"
"golang.org/x/exp/maps"
)
// create line cache map for skipping previously checked glob lines
var lineCache = make(map[string]bool)
func main() {
var callerSkip = 0 // might need to be 1 in release mode?
_, filename, _, _ := runtime.Caller(callerSkip)
binDir := filepath.Dir(filename)
sourceDir := filepath.Join(binDir, ".github.gitignore")
wd, _ := os.Getwd()
allFiles, err := prepareGitignores()
log.Println(binDir)
if !fileExists(sourceDir) {
log.Println("Getting gitignore files...")
runCmd("git", "clone", "--depth=1", repoUrl, sourceDir)
}
if getNeedsUpdate() {
log.Println("Updating gitignore files...")
runCmd("git", "pull", "origin", "master")
}
allFiles, err := getGitignores(sourceDir)
handleErr(err)
keep := []string{}
files := make(map[string]string)
fileNames := []string{}
log.Println("Found:")
for _, v := range allFiles {
log.Println("Parsing file: " + v)
contents := readFile(v)
lines := strings.Split(contents, "\n")
for _, line := range lines {
trimmed := strings.TrimSpace(line)
_, exists := lineCache[trimmed]
if exists {
continue
}
lineCache[trimmed] = true
if len(trimmed) == 0 || strings.ToLower(string(trimmed[0])) == "#" {
lineCache[trimmed] = false
continue
}
log.Println("Parsing line: " + line)
if globExists(filepath.Join(wd, line)) {
keep = append(keep, line)
}
for _, filename := range allFiles {
contents := readFile(filename)
basename := filepath.Base(filename)
langName := basename[:strings.Index(basename, ".")]
if findFileMatches(contents) {
sep := "#========================================================================\n"
header := fmt.Sprintf(sep+"# %s\n"+sep+"\n", basename)
files[langName] = header + contents
fileNames = append(fileNames, langName)
}
}
log.Println("Done")
log.Println("Done.")
log.Println("Final output:")
for _, v := range keep {
log.Println(v)
selected := []string{}
keys := maps.Keys(files)
if len(keys) > 1 {
prompt := &survey.MultiSelect{
Message: "Found matches in your project for the following gitignore files.\nPlease select which you want to write to .gitignore:",
Options: fileNames,
}
var inp []string
survey.AskOne(prompt, &inp)
for _, sel := range inp {
selected = append(selected, files[sel])
}
} else {
selected = keys
}
wd, _ := os.Getwd()
out := filepath.Join(wd, ".gitignore")
if fileExists(out) {
prompt2 := &survey.Select{
Message: ".gitignore file found in this directory. Please pick an option:",
Options: []string{"Overwrite", "Append", "Skip"},
}
var inp2 string
survey.AskOne(prompt2, &inp2)
switch inp2 {
case "Overwrite":
log.Printf("Writing to %s", out)
writeFile(out, strings.Join(selected, "\n"), true)
break
case "Append":
log.Printf("Appending to %s", out)
writeFile(out, strings.Join(selected, "\n"), false)
break
}
} else {
log.Printf("Writing to %s", out)
writeFile(out, strings.Join(selected, "\n"), true)
}
}

16
go.mod
View File

@@ -5,7 +5,17 @@ go 1.18
require github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8
require (
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
golang.org/x/text v0.3.6 // indirect
)
require (
github.com/AlecAivazis/survey/v2 v2.3.4
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 // indirect
golang.org/x/exp v0.0.0-20220516143420-24438e51023a
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect
)

31
go.sum
View File

@@ -1,9 +1,40 @@
github.com/AlecAivazis/survey/v2 v2.3.4 h1:pchTU9rsLUSvWEl2Aq9Pv3k0IE2fkqtGxazskAMd9Ng=
github.com/AlecAivazis/survey/v2 v2.3.4/go.mod h1:hrV6Y/kQCLhIZXGcriDCUBtB3wnN7156gMXJ3+b23xM=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8 h1:RB0v+/pc8oMzPsN97aZYEwNuJ6ouRJ2uhjxemJ9zvrY=
github.com/tcnksm/go-input v0.0.0-20180404061846-548a7d7a8ee8/go.mod h1:IlWNj9v/13q7xFbaK4mbyzMNwrZLaWSHx/aibKIZuIg=
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20220516143420-24438e51023a h1:tiLLxEjKNE6Hrah/Dp/cyHvsyjDLcMFSocOHO5XDmOM=
golang.org/x/exp v0.0.0-20220516143420-24438e51023a/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

102
ignore_files.go Normal file
View File

@@ -0,0 +1,102 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"strings"
)
func prepareGitignores() ([]string, error) {
var callerSkip = 0 // might need to be 1 in release mode?
_, filename, _, _ := runtime.Caller(callerSkip)
binDir := filepath.Dir(filename)
gitignoresDir := filepath.Join(binDir, ".github.gitignore")
if !fileExists(gitignoresDir) {
log.Println("Getting gitignore files...")
runCmd("git", "clone", "--depth=1", repoUrl, gitignoresDir)
}
if getNeedsUpdate() {
log.Println("Updating gitignore files...")
runCmd("git", "pull", "origin", "master")
}
return getGitignores(gitignoresDir)
}
func getGitignores(sourceDir string) ([]string, error) {
return filepath.Glob(filepath.Join(sourceDir, "*.gitignore"))
}
var ignoreLines = []string{
"/*",
".",
".vscode",
".vscode/*",
".idea",
".idea/*",
}
func findFileMatches(patterns string) bool {
lines := strings.Split(patterns, "\n")
wd, _ := os.Getwd()
for _, line := range lines {
// ignore empty lines / comments
line = strings.TrimSpace(line)
if len(line) == 0 || strings.ToLower(line)[0] == '#' {
continue
}
idx := strings.Index(line, "#")
// ignore comments at end of line
if idx > -1 && (idx == 0 || line[idx-1] != '\\') {
line = strings.TrimSpace(line[0:idx])
}
if len(line) == 0 || contains(ignoreLines, line) {
continue
}
if globExists(filepath.Join(wd, line)) {
return true
}
}
return false
}
func removeUnusedPatterns(filename string, keep []string) []string {
wd, _ := os.Getwd()
contents := readFile(filename)
lines := strings.Split(contents, "\n")
keepCopy := []string{}
copy(keep, keepCopy)
found := false
for _, line := range lines {
trimmed := strings.TrimSpace(line)
_, exists := lineCache[trimmed]
if exists {
continue
}
lineCache[trimmed] = true
if len(trimmed) == 0 || strings.ToLower(string(trimmed[0])) == "#" {
lineCache[trimmed] = false
continue
}
if globExists(filepath.Join(wd, line)) {
found = true
keepCopy = append(keepCopy, line)
}
}
if found {
keepCopy = insert(keepCopy, 0, fmt.Sprintf("\n# %s", filepath.Base(filename)))
}
return keep
}

View File

@@ -1,23 +1,26 @@
package main
import (
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
)
// UNUSED allows unused variables to be included in Go programs
func UNUSED(x ...interface{}) {}
var repoUrl = "https://github.com/github/gitignore"
func fileExists(path string) bool {
_, err := os.Stat(path)
exists := os.IsExist(err)
exists := !os.IsNotExist(err)
return exists
}
func globExists(path string) bool {
res, err := filepath.Glob(path)
// log.Println("globExists? " + path)
handleErr(err)
return res != nil
}
@@ -44,9 +47,49 @@ func runCmd(cmd string, args ...string) (string, error) {
return string(res), err
}
func readFile(path string) string {
res, err := os.ReadFile(path)
handleErr(err)
return string(res)
}
func writeFile(path string, data string, overwrite bool) bool {
var err error
if overwrite {
// os.Create(path)
err = os.WriteFile(path, []byte(data), fs.ModeAppend)
} else {
f, _ := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
defer f.Close()
_, err = f.WriteString("\n" + data)
}
handleErr(err)
return true
}
func handleErr(err error) {
if err != nil {
log.Fatal(err)
os.Exit(1)
}
}
func insert[T any](a []T, i int, item T) []T {
return append(a[:i], append([]T{item}, a[i:]...)...)
}
func contains[T comparable](list []T, item T) bool {
for _, v := range list {
if v == item {
return true
}
}
return false
}
func ternary[T any](cond bool, whenTrue T, whenFalse T) T {
if cond {
return whenTrue
}
return whenFalse
}