// 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.

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var hookFile = filepath.FromSlash(".git/hooks/commit-msg")

const usage = `Usage: %s [command]

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

Available comands:

	create <name>

		Create a local feature branch with the provided name
		and commit the staged changes to it.

	commit

		Amend feature branch HEAD with the staged changes.

	diff

		View differences between remote branch HEAD and
		the feature branch HEAD.
		(The differences introduced by this change.)

	upload

		Upload HEAD commit to the code review server.

	sync

		Fetch changes from the remote repository and merge them to the
		current branch, rebasing the HEAD commit (if any) on top of
		them.

	pending 

		Show local feature branches and their head commits.

`

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		os.Exit(2)
	}
	flag.Parse()

	goToRepoRoot()
	installHook()

	switch flag.Arg(0) {
	case "create", "cr":
		name := flag.Arg(1)
		if name == "" {
			flag.Usage()
		}
		create(name)
	case "commit", "co":
		commit()
	case "diff", "d":
		diff()
	case "upload", "u":
		upload()
	case "sync", "s":
		sync()
	case "pending", "p":
		pending()
	default:
		flag.Usage()
	}
}

func create(name string) {
	if !hasStagedChanges() {
		dief("No staged changes. Did you forget to \"git add\" your files?\n")
	}
	if !isOnMaster() {
		dief("You must run create from the master branch. " +
			"(\"git checkout master\".)")
	}
	fmt.Printf("Creating and checking out branch: %v\n", name)
	run("git", "checkout", "-b", name)
	fmt.Printf("Committing staged changes to branch.\n")
	run("git", "commit")
}

func commit() {
	if !hasStagedChanges() {
		dief(`No staged changes. Did you forget to "git add" your files?\n`)
	}
	if isOnMaster() {
		dief("Can't commit to master branch.\n")
	}
	fmt.Printf("Amending head commit with staged changes.\n")
	run("git", "commit", "--amend", "-C", "HEAD")
}

func diff() {
	run("git", "diff", "HEAD^", "HEAD")
}

func upload() {
	if isOnMaster() {
		dief("Can't upload from master branch.\n")
	}
	fmt.Printf("Pushing commit to Gerrit code review server.\n")
	run("git", "push", "origin", "HEAD:refs/for/master")
}

func sync() {
	fmt.Printf("Fetching changes from remote repo.\n")
	run("git", "fetch")
	if isOnMaster() {
		run("git", "pull", "--ff-only")
		return
	}
	fmt.Printf("Rebasing head commit atop origin/master.\n")
	run("git", "rebase", "origin/master")
}

func pending() {
	dief("not implemented\n")
}

func hasStagedChanges() bool {
	status, err := exec.Command("git", "status", "-s").CombinedOutput()
	if err != nil {
		dief("%s\nchecking for staged changes: %v\n", status, err)
	}
	for _, s := range strings.Split(string(status), "\n") {
		if strings.HasPrefix(s, "A  ") ||
			strings.HasPrefix(s, "M  ") ||
			strings.HasPrefix(s, "D  ") {
			return true
		}
	}
	return false
}

func isOnMaster() bool {
	branch, err := exec.Command("git", "branch").CombinedOutput()
	if err != nil {
		dief("%s\nchecking current branch: %v\n", branch, err)
	}
	for _, s := range strings.Split(string(branch), "\n") {
		if strings.HasPrefix(s, "* ") {
			return s == "* master"
		}
	}
	return false
}

func goToRepoRoot() {
	prevDir, err := os.Getwd()
	if err != nil {
		dief("could not get current directory: %v\n", err)
	}
	for {
		if _, err := os.Stat(".git"); err == nil {
			return
		}
		if err := os.Chdir(".."); err != nil {
			dief("could not chdir: %v\n", err)
		}
		currentDir, err := os.Getwd()
		if err != nil {
			dief("could not get current directory: %v\n", err)
		}
		if currentDir == prevDir {
			dief("Git root not found. Run from within the Git tree please.\n")
		}
		prevDir = currentDir
	}
}

func installHook() {
	_, err := os.Stat(hookFile)
	if err == nil {
		return
	}
	if !os.IsNotExist(err) {
		dief("checking for hook file: %v\n", err)
	}
	fmt.Printf("Presubmit hook to add Change-Id to commit messages is missing.\n"+
		"Now automatically creating it at %v.\n\n", hookFile)
	hookContent := []byte(commitMsgHook)
	if err := ioutil.WriteFile(hookFile, hookContent, 0700); err != nil {
		dief("writing hook file: %v\n", err)
	}
}

func dief(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format, args...)
	os.Exit(1)
}

func run(command string, args ...string) {
	cmd := exec.Command(command, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		dief("%v\n", err)
	}
}
