github.com/derekparker/go-pear@v1.3.2/main.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"os/user"
    10  	"path"
    11  	"sort"
    12  	"strings"
    13  
    14  	"github.com/jessevdk/go-flags"
    15  	"github.com/libgit2/git2go"
    16  	"gopkg.in/v1/yaml"
    17  )
    18  
    19  const version = "1.3.2"
    20  
    21  type Config struct {
    22  	Email string
    23  	Devs  map[string]string
    24  }
    25  
    26  type options struct {
    27  	File    string `short:"f" long:"file" description:"Optional alternative git config file"`
    28  	Email   string `short:"e" long:"email" description:"Base author email"`
    29  	Global  bool   `short:"g" long:"global" description:"Modify global git settings"`
    30  	Unset   bool   `short:"u" long:"unset" description:"Unset local pear information"`
    31  	Version bool   `short:"v" long:"version" description:"Print version string"`
    32  }
    33  
    34  func pearrcpath() string {
    35  	return path.Join(os.Getenv("HOME"), ".pearrc")
    36  }
    37  
    38  func parseFlags() ([]string, *options, error) {
    39  	opts := &options{}
    40  	devs, err := flags.ParseArgs(opts, os.Args[1:])
    41  	if err != nil {
    42  		return nil, nil, err
    43  	}
    44  
    45  	return devs, opts, nil
    46  }
    47  
    48  func initGitConfig(opts *options) (*git.Config, error) {
    49  	wd, err := os.Getwd()
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	usr, err := user.Current()
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	repopath, err := git.Discover(wd, false, []string{usr.HomeDir})
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	repo, err := git.OpenRepository(repopath)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	gitconf, err := repo.Config()
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	if opts.File != "" {
    75  		err = gitconf.AddFile(opts.File, git.ConfigLevelApp, false)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  	}
    80  
    81  	if opts.Global {
    82  		glconfpath := path.Join(usr.HomeDir, ".gitconfig")
    83  
    84  		err = gitconf.AddFile(glconfpath, git.ConfigLevelGlobal, false)
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  	}
    89  
    90  	return gitconf, nil
    91  }
    92  
    93  func printStderrAndDie(err error) {
    94  	os.Stderr.WriteString(err.Error())
    95  	os.Exit(1)
    96  }
    97  
    98  func main() {
    99  	devs, opts, err := parseFlags()
   100  	if err != nil {
   101  		return
   102  	}
   103  
   104  	if opts.Version {
   105  		fmt.Printf("Pear version %s\n", version)
   106  		os.Exit(0)
   107  	}
   108  
   109  	gitconfig, err := initGitConfig(opts)
   110  	if err != nil {
   111  		printStderrAndDie(err)
   112  	}
   113  
   114  	defer gitconfig.Free()
   115  
   116  	if len(os.Args) == 1 {
   117  		fmt.Println(username(gitconfig))
   118  		os.Exit(0)
   119  	}
   120  
   121  	conf, err := readPearrc(pearrcpath())
   122  	if err != nil {
   123  		printStderrAndDie(err)
   124  	}
   125  
   126  	sanitizeDevNames(devs)
   127  
   128  	if opts.Unset {
   129  		removePair(gitconfig)
   130  		os.Exit(0)
   131  	}
   132  
   133  	var (
   134  		fullnames = checkPair(devs, conf)
   135  		email     = formatEmail(checkEmail(conf), devs)
   136  	)
   137  
   138  	setPair(email, fullnames, gitconfig)
   139  	savePearrc(conf, pearrcpath())
   140  }
   141  
   142  func username(gitconfig *git.Config) string {
   143  	name, err := gitconfig.LookupString("user.name")
   144  	if err != nil {
   145  		printStderrAndDie(err)
   146  	}
   147  
   148  	return name
   149  }
   150  
   151  func email(gitconfig *git.Config) string {
   152  	email, err := gitconfig.LookupString("user.email")
   153  	if err != nil {
   154  		printStderrAndDie(err)
   155  	}
   156  
   157  	return email
   158  }
   159  
   160  func setPair(email string, pairs []string, gitconfig *git.Config) {
   161  	pair := strings.Join(pairs, " and ")
   162  
   163  	err := gitconfig.SetString("user.name", pair)
   164  	if err != nil {
   165  		printStderrAndDie(err)
   166  	}
   167  
   168  	err = gitconfig.SetString("user.email", email)
   169  	if err != nil {
   170  		printStderrAndDie(err)
   171  	}
   172  }
   173  
   174  func removePair(gitconfig *git.Config) {
   175  	err := gitconfig.Delete("user.name")
   176  	if err != nil {
   177  		os.Stderr.WriteString(err.Error() + "\n")
   178  	}
   179  
   180  	err = gitconfig.Delete("user.email")
   181  	if err != nil {
   182  		os.Stderr.WriteString(err.Error())
   183  	}
   184  }
   185  
   186  func checkEmail(conf *Config) string {
   187  	if conf.Email == "" {
   188  		conf.Email = getEmail()
   189  	}
   190  
   191  	return conf.Email
   192  }
   193  
   194  func checkPair(pair []string, conf *Config) []string {
   195  	var fullnames []string
   196  	for _, dev := range pair {
   197  		if _, ok := conf.Devs[dev]; !ok {
   198  			conf.Devs[dev] = getName(dev)
   199  		}
   200  
   201  		fullnames = append(fullnames, conf.Devs[dev])
   202  	}
   203  
   204  	return fullnames
   205  }
   206  
   207  func getName(devName string) string {
   208  	prompt := fmt.Sprintf("Please enter a full name for %s:", devName)
   209  	return promptForInput(prompt)
   210  }
   211  
   212  func getEmail() string {
   213  	return promptForInput("Please provide base author email:")
   214  }
   215  
   216  func promptForInput(prompt string) string {
   217  	_, err := fmt.Println(prompt)
   218  	if err != nil {
   219  		log.Fatal(err)
   220  	}
   221  
   222  	return readInput()
   223  }
   224  
   225  func readInput() string {
   226  	buf := bufio.NewReader(os.Stdin)
   227  	inputString, err := buf.ReadString('\n')
   228  	if err != nil {
   229  		log.Fatal("Could not read from stdin: ", err)
   230  	}
   231  
   232  	return trimNewline(inputString)
   233  }
   234  
   235  func savePearrc(conf *Config, path string) error {
   236  	contents, err := yaml.Marshal(conf)
   237  	if err != nil {
   238  		return err
   239  	}
   240  
   241  	err = ioutil.WriteFile(path, contents, os.ModeExclusive)
   242  	if err != nil {
   243  		return err
   244  	}
   245  
   246  	return nil
   247  }
   248  
   249  func readPearrc(path string) (*Config, error) {
   250  	conf := &Config{
   251  		Devs: make(map[string]string),
   252  	}
   253  
   254  	file, err := os.Open(path)
   255  	if err != nil {
   256  		file, err = os.Create(path)
   257  		if err != nil {
   258  			return nil, err
   259  		}
   260  	}
   261  
   262  	defer file.Close()
   263  
   264  	contents, err := ioutil.ReadAll(file)
   265  	if err != nil {
   266  		return nil, err
   267  	}
   268  
   269  	err = yaml.Unmarshal(contents, conf)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  
   274  	return conf, nil
   275  }
   276  
   277  func formatEmail(email string, devs []string) string {
   278  	parts := strings.Split(email, "@")
   279  	devlist := strings.Join(devs, "+")
   280  	return fmt.Sprintf("%s+%s@%s", parts[0], devlist, parts[1])
   281  }
   282  
   283  func trimNewline(s string) string {
   284  	return strings.TrimSuffix(s, "\n")
   285  }
   286  
   287  func sanitizeDevNames(devs []string) {
   288  	for i, dev := range devs {
   289  		devs[i] = strings.ToLower(dev)
   290  	}
   291  
   292  	sort.Strings(devs)
   293  }