func ReviewPatch(input []byte, maintainers map[string][]string) (map[string][]string, error) {
	var (
		reviewers = make(map[string][]string)
		index     = buildFileIndex(maintainers)
	)
	set, err := patch.Parse(input)
	if err != nil {
		return nil, err
	}
	mapReviewers := func(rm map[string]bool) []string {
		var (
			i   int
			out = make([]string, len(rm))
		)
		for k := range rm {
			out[i] = k
			i++
		}
		return out
	}
	for _, f := range set.File {
		for _, originalTarget := range []string{f.Dst, f.Src} {
			if originalTarget == "" {
				continue
			}
			target := path.Clean(originalTarget)
			if _, exists := reviewers[target]; exists {
				continue
			}
			var fileMaintainers map[string]bool
			fileMaintainers = index[target]
			for len(fileMaintainers) == 0 {
				target = path.Dir(target)
				fileMaintainers = index[target]
			}
			reviewers[originalTarget] = mapReviewers(fileMaintainers)
		}
	}
	return reviewers, nil
}
ReviewPatch reads a git-formatted patch from `src`, and for each file affected by the patch
it assign its Maintainers based on the current repository tree directories
The list of Maintainers are generated when the MaintainerManager object is instantiated.

The result is a map where the keys are the paths of files affected by the patch,
and the values are the maintainers assigned to review that partiular file.

There is no duplicate checks: the same maintainer may be present in multiple entries
of the map, or even multiple times in the same entry if the MAINTAINERS file has
duplicate lines.
package gordon
import (
	"bufio"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"github.com/fkautz/codereview/patch"
)
func GetFileExtensionsForPR(src []byte, ext string) ([]string, error) {
	extensions := []string{}
	set, err := patch.Parse(src)
	if err != nil {
		return nil, err
	}
	for _, fileset := range set.File {
		if strings.HasSuffix(fileset.Dst, ext) || strings.HasPrefix(fileset.Src, ext) {
			extensions = append(extensions, ext)
		}
	}
	return extensions, nil
}
func GetDirsForPR(src []byte, dir string) ([]string, error) {
	dirs := []string{}
	set, err := patch.Parse(src)
	if err != nil {
		return nil, err
	}
	for _, fileset := range set.File {
		if strings.HasPrefix(fileset.Dst, dir) || strings.HasPrefix(fileset.Src, dir) {
			dirs = append(dirs, dir)
		}
	}
	return dirs, nil
}
func GetReviewersForPR(patch []byte, withUsername bool) (map[string][]string, error) {
	toplevel, err := GetTopLevelGitRepo()
	if err != nil {
		return nil, err
	}
	maintainers, err := GetMaintainersFromRepo(toplevel, withUsername)
	if err != nil {
		return nil, err
	}
	return ReviewPatch(patch, maintainers)
}