Skip to content

Instantly share code, notes, and snippets.

@roscopecoltran
Forked from tyru/detect_dirty_worktree.go
Created November 16, 2018 00:18
Show Gist options
  • Save roscopecoltran/bf62b43b3f3998218d5d3f3e4446b214 to your computer and use it in GitHub Desktop.
Save roscopecoltran/bf62b43b3f3998218d5d3f3e4446b214 to your computer and use it in GitHub Desktop.
Try to detect worktree (currently not working)
package main
import (
"fmt"
"io/ioutil"
"os"
"os/user"
"path/filepath"
"strings"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/plumbing/format/gitignore"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("specify repository path.")
return
}
cfg, err := parseGitIgnore()
if err != nil {
fmt.Fprintln(os.Stderr, "Could not read ~/.gitconfig: "+err.Error())
return
}
excludesfile := getExcludesFile(cfg)
if excludesfile == "" {
fmt.Fprintln(os.Stderr, "Could not get core.excludesfile from ~/.gitconfig")
return
}
ps, err := parseExcludesFile(excludesfile)
if err != nil {
fmt.Fprintln(os.Stderr, "Could not parse core.excludesfile: "+excludesfile+": "+err.Error())
return
}
fmt.Println("dirty?:", isDirtyWorktree(os.Args[1], ps))
}
const globalGitConfig = "/home/tyru/.gitconfig"
func parseGitIgnore() (*config.Config, error) {
cfg := config.NewConfig()
b, err := ioutil.ReadFile(globalGitConfig)
if err != nil {
return nil, err
}
if err := cfg.Unmarshal(b); err != nil {
return nil, err
}
return cfg, err
}
func getExcludesFile(cfg *config.Config) string {
for _, sec := range cfg.Raw.Sections {
if sec.Name == "core" {
for _, opt := range sec.Options {
if opt.Key == "excludesfile" {
return opt.Value
}
}
}
}
return ""
}
func parseExcludesFile(excludesfile string) ([]gitignore.Pattern, error) {
excludesfile, err := expandTilde(excludesfile)
if err != nil {
return nil, err
}
data, err := ioutil.ReadFile(excludesfile)
if err != nil {
return nil, err
}
var ps []gitignore.Pattern
for _, s := range strings.Split(string(data), "\n") {
if !strings.HasPrefix(s, "#") && len(strings.TrimSpace(s)) > 0 {
ps = append(ps, gitignore.ParsePattern(s, nil))
}
}
return ps, nil
}
// "~/.gitignore" -> "/home/tyru/.gitignore"
func expandTilde(path string) (string, error) {
var paths []string
u, err := user.Current()
if err != nil {
return "", err
}
for _, p := range strings.Split(path, string(filepath.Separator)) {
if p == "~" {
paths = append(paths, u.HomeDir)
} else {
paths = append(paths, p)
}
}
return filepath.Join(paths...), nil
}
func isDirtyWorktree(fullpath string, ps []gitignore.Pattern) bool {
repos, err := git.PlainOpen(fullpath)
if err != nil {
return true
}
wt, err := repos.Worktree()
if err != nil {
return true
}
st, err := wt.Status()
if err != nil {
return true
}
// Instead of using IsClean(), check each file with ignored patterns
// return !st.IsClean()
paths := make([]string, 0, len(st))
for path := range st {
paths = append(paths, path)
}
fmt.Println("paths:", paths)
m := gitignore.NewMatcher(ps)
return !m.Match(paths, false)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment