// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// TODO(adg): recognize non-master remote branches
// TODO(adg): accept -a flag on 'commit' (like git commit -a)
// TODO(adg): check style of commit message
// TOOD(adg): print gerrit votes on 'pending'
// TODO(adg): add gofmt commit hook
// TODO(adg): print changed files on review sync
// TODO(adg): translate email addresses without @ by looking up somewhere

// Command git-review provides a simple command-line user interface for
// working with git repositories and the Gerrit code review system.
// See "git-review help" for details.
package main // import "golang.org/x/review/git-review"

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

var (
	flags   = flag.NewFlagSet("", flag.ExitOnError)
	verbose = flags.Bool("v", false, "verbose output")
	noRun   = flags.Bool("n", false, "print but do not run commands")
)

const globalFlags = "[-n] [-v]"

const usage = `Usage: %s <command> ` + globalFlags + `
Type "%s help" for more information.
`

func init() {
	flags.Usage = func() {
		fmt.Fprintf(os.Stderr, usage, os.Args[0], os.Args[0])
	}
}

const help = `Usage: %s <command> ` + globalFlags + `

The review command is a wrapper for the git command that provides a simple
interface to the "single-commit feature branch" development model.

Available commands:

	change [name]
		Create a change commit, or amend an existing change commit,
		with the staged changes. If a branch name is provided, check
		out that branch (creating it if it does not exist).
		(Does not amend the existing commit when switching branches.)

	pending [-r]
		Show local branches and their head commits.
		If -r is specified, show additional information from Gerrit.

	mail [-f] [-r reviewer,...] [-cc mail,...]
		Upload change commit to the code review server and send mail
		requesting a code review.
		If -f is specified, upload even if there are staged changes.

	mail -diff
		Show the changes but do not send mail or upload.

	sync
		Fetch changes from the remote repository and merge them into
		the current branch, rebasing the change commit on top of them.

	revert files...
		Revert the specified files to their state before the change
		commit. (Be careful! This will discard your changes!)

	gofmt
		TBD

`

func main() {
	installHook()

	if len(os.Args) < 2 {
		flags.Usage()
		os.Exit(2)
	}
	command, args := os.Args[1], os.Args[2:]

	switch command {
	case "help":
		fmt.Fprintf(os.Stdout, help, os.Args[0])
	case "change", "c":
		change(args)
	case "pending", "p":
		pending(args)
	case "mail", "m":
		mail(args)
	case "sync", "s":
		doSync(args)
	case "revert":
		dief("revert not implemented")
	case "gofmt":
		dief("gofmt not implemented")
	default:
		flags.Usage()
	}
}

func expectZeroArgs(args []string, command string) {
	flags.Parse(args)
	if len(flags.Args()) > 0 {
		fmt.Fprintf(os.Stderr, "Usage: %s %s %s\n", os.Args[0], command, globalFlags)
		os.Exit(2)
	}
}

func run(command string, args ...string) {
	if err := runErr(command, args...); err != nil {
		if !*verbose {
			// If we're not in verbose mode, print the command
			// before dying to give context to the failure.
			fmt.Fprintln(os.Stderr, commandString(command, args))
		}
		dief("%v", err)
	}
}

func runErr(command string, args ...string) error {
	if *verbose || *noRun {
		fmt.Fprintln(os.Stderr, commandString(command, args))
	}
	if *noRun {
		return nil
	}
	cmd := exec.Command(command, args...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

// getOutput runs the specified command and returns its combined standard
// output and standard error outputs.
// NOTE: It should only be used to run commands that return information,
// **not** commands that make any actual changes.
func getOutput(command string, args ...string) string {
	if *verbose {
		fmt.Fprintln(os.Stderr, commandString(command, args))
	}
	b, err := exec.Command(command, args...).CombinedOutput()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n%s\n", commandString(command, args), b)
		dief("%v", err)
	}
	return string(bytes.TrimSpace(b))
}

// getLines is like getOutput but it returns non-empty output lines.
// NOTE: It should only be used to run commands that return information,
// **not** commands that make any actual changes.
func getLines(command string, args ...string) []string {
	var s []string
	for _, l := range strings.Split(getOutput(command, args...), "\n") {
		s = append(s, strings.TrimSpace(l))
	}
	return s
}

func commandString(command string, args []string) string {
	return strings.Join(append([]string{command}, args...), " ")
}

func dief(format string, args ...interface{}) {
	printf(format, args...)
	os.Exit(1)
}

func verbosef(format string, args ...interface{}) {
	if *verbose {
		printf(format, args...)
	}
}

func printf(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, "review: "+format+"\n", args...)
}
