func GetWD() (string, error) {
	dir, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	return dir, err
}
GetWD Gets the current working directory
package file
import (
	"archive/zip"
	"bufio"
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	cfgreader "github.com/americanexpress/earlybird/pkg/config"
	"github.com/americanexpress/earlybird/pkg/scan"
	"github.com/americanexpress/earlybird/pkg/utils"
	"github.com/americanexpress/earlybird/pkg/wildcard"
)
var (
	ignoreFiles    = [...]string{".ge_ignore", ".gitignore"}  
	ignorePatterns []string
)
func MultipartToScanFiles(files []*multipart.FileHeader, cfg cfgreader.EarlybirdConfig) (fileList []scan.File, err error) {
	ignorePatterns = getIgnorePatterns(cfg.SearchDir, cfg.IgnoreFile, cfg.VerboseEnabled)
	for _, fheader := range files {
		myfile, err := fheader.Open()
		if err != nil {
			return fileList, err
		}
		fileNameBytes, err := base64.StdEncoding.DecodeString(fheader.Filename)
		var fileName string
		if err != nil {
			fileName = fheader.Filename  
		} else {
			fileName = string(fileNameBytes)  
		}
		fileNameWithPathPrefix := fileName
		pathSeparator := "/"
		if !strings.HasPrefix(fileName, pathSeparator) {
			fileNameWithPathPrefix = pathSeparator + fileNameWithPathPrefix
		}
		if isIgnoredFile(fileNameWithPathPrefix, cfg.SearchDir) {
			continue
		}
		curFile := scan.File{
			Name: fileNameWithPathPrefix,
			Path: "buffer",
		}
		var line scan.Line
		reader := bufio.NewReader(myfile)
		for {
			var buffer bytes.Buffer
			var l []byte
			var isPrefix bool
			for {
				l, isPrefix, err = reader.ReadLine()
				buffer.Write(l)
				if !isPrefix {
					break
				}
				if err != nil {
					break
				}
			}
			if err == io.EOF {
				break
			}
			lineText := buffer.String()
			line.LineNum = line.LineNum + 1
			line.LineValue = lineText
			line.FilePath = curFile.Path
			line.FileName = fileNameWithPathPrefix
			curFile.Lines = append(curFile.Lines, line)
		}
		if err != io.EOF {
			return fileList, err
		}
		myfile.Close()
		fileList = append(fileList, curFile)
	}
	return
}
func GetGitFiles(fileType string, cfg *cfgreader.EarlybirdConfig) (fileContext Context, err error) {
	ignorePatterns = getIgnorePatterns(cfg.SearchDir, cfg.IgnoreFile, cfg.VerboseEnabled)
	var (
		output       []byte
		compressList []scan.File
		fileList     []scan.File
	)
	if fileType == utils.Tracked {
		output, err = exec.Command("git", "ls-tree", "--full-tree", "-r", "--name-only", "HEAD").Output()
	} else if fileType == utils.Staged {
		output, err = exec.Command("git", "--no-pager", "diff", "--name-only", "--staged").Output()
	}
	if err != nil {
		log.Println(notTrackedDir)
		return fileContext, err
	}
	fileList = parseGitFiles(output, cfg.VerboseEnabled, cfg.MaxFileSize)
	compressList, fileList = separateCompressedAndUncompressed(fileList)
	compressList, fileContext.CompressPaths, err = GetCompressedFiles(compressList, cfg.SearchDir)  
	if err != nil {
		return fileContext, err
	}
	fileContext.Files = append(fileList, compressList...)
	fileContext.IgnorePatterns = ignorePatterns
	return fileContext, nil
}
func parseGitFiles(out []byte, verbose bool, maxFileSize int64) (fileList []scan.File) {
	var curFile scan.File
	gitFiles := string(out)
	if len(gitFiles) < 1 {
		log.Println(gitErr)
	} else {
		scanner := bufio.NewScanner(strings.NewReader(gitFiles))
		for scanner.Scan() {
			curFile.Path = scanner.Text()
			curFile.Name = filepath.Base(scanner.Text())
			if fileExists := Exists(curFile.Path); fileExists {
				pathIsDirectory, dirErr := isDirectory(curFile.Path)
				if dirErr != nil {
					log.Println(dirErr)
				}
				if !pathIsDirectory && getFileSizeOK(curFile.Path, maxFileSize) {
					if verbose {
						log.Println("Reading file ", curFile.Path)
					}
					fileList = append(fileList, curFile)
				}
			}
		}
	}
	return fileList
}
func GetFiles(searchDir, ignoreFile string, verbose bool, maxFileSize int64) (fileContext Context, err error) {
	ignorePatterns = getIgnorePatterns(searchDir, ignoreFile, verbose)
	fileList := make([]scan.File, 0)
	var curFile scan.File
	err = filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error {
		if err != nil {
			log.Println("Error reading directory: ", err)
		}
		if !isIgnoredFile(path, searchDir) {
			pathIsDirectory, isDirErr := isDirectory(path)
			if !pathIsDirectory {
				if isDirErr != nil && verbose {
					log.Println("Error checking if path is directory")
				}
				if getFileSizeOK(path, maxFileSize) {
					curFile.Name = f.Name()
					curFile.Path = path
					fileList = append(fileList, curFile)
					if verbose {
						log.Println("Reading file ", curFile.Path)
					}
				} else {
					fileContext.SkippedFiles = append(fileContext.SkippedFiles, path)
					if verbose {
						log.Println("Ignoring", path, ". Filesize is too large.")
					}
				}
			}
		} else {
			fileContext.SkippedFiles = append(fileContext.SkippedFiles, path)
			if verbose {
				log.Println("Ignoring", path, ". File blacklisted.")
			}
		}
		return err
	})
	if err != nil {
		return fileContext, err
	}
	var compressList []scan.File
	compressList, fileList = separateCompressedAndUncompressed(fileList)
	compressList, fileContext.CompressPaths, err = GetCompressedFiles(compressList, searchDir)  
	if err != nil {
		return fileContext, err
	}
	fileContext.Files = append(fileList, compressList...)
	fileContext.IgnorePatterns = ignorePatterns
	return fileContext, nil
}
func GetFileFromStream(cfg *cfgreader.EarlybirdConfig) []scan.File {
	scanner := bufio.NewScanner(os.Stdin)
	fileList := make([]scan.File, 0)
	curFile := scan.File{
		Name: "buffer",
		Path: "buffer",
	}
	var line scan.Line
	ignoreAnnotationInLine := false
	nextLineIgnored := false
	for scanner.Scan() {
		lineText := scanner.Text()
		if scan.IsIgnoreAnnotation(cfg, lineText) {
			lineText = ""
			ignoreAnnotationInLine = true
			nextLineIgnored = true
		}
		if nextLineIgnored {
			lineText = ""
		}
		line.LineNum = line.LineNum + 1
		line.LineValue = lineText
		line.FilePath = curFile.Path
		curFile.Lines = append(curFile.Lines, line)
		if nextLineIgnored && !ignoreAnnotationInLine {
			nextLineIgnored = false
		}
	}
	if err := scanner.Err(); err != nil {
		log.Fatal("Reading standard input:", err)
	}
	fileList = append(fileList, curFile)
	return fileList
}
func GetFileSize(path string) (size int64, err error) {
	stat, err := os.Stat(path)
	if err != nil {
		return 0, err
	}
	return stat.Size(), nil
}
func getFileSizeOK(path string, maxFileSize int64) bool {
	size, err := GetFileSize(path)
	return err == nil && (size < maxFileSize || hasCompressionExtension(path))
}
func hasCompressionExtension(path string) bool {
	switch filepath.Ext(path) {
	case "war", "jar", "zip", "ear":
		return true
	default:
		return false
	}
}
func getIgnorePatterns(filePath, ignoreFile string, verbose bool) (ignorePatterns []string) {
	ignorePatterns = append(ignorePatterns, "*.git/*")
	for _, ignoreFile := range ignoreFiles {
		path := path.Join(filePath, ignoreFile)
		if Exists(path) {
			file, err := os.Open(path)
			if err != nil {
				log.Fatal(err)
			}
			defer file.Close()
			scanner := bufio.NewScanner(file)
			var line, firstChar string
			for scanner.Scan() {
				line = scanner.Text()
				runes := []rune(line)
				firstChar = string(runes[0:1])
				if !(firstChar == "#") && strings.Trim(line, " ") != "" {
					ignorePatterns = append(ignorePatterns, line)
				}
			}
		}
	}
	if ignoreFile != "" {
		file, err := os.Open(ignoreFile)
		if err != nil {
			log.Println("Failed to open ignore file", err)
		} else {
			defer file.Close()
			scanner := bufio.NewScanner(file)
			var line, firstChar string
			for scanner.Scan() {
				line = scanner.Text()
				runes := []rune(line)
				firstChar = string(runes[0:1])
				if !(firstChar == "#") && strings.Trim(line, " ") != "" {
					ignorePatterns = append(ignorePatterns, line)
				}
			}
		}
	}
	if verbose {
		log.Println("Ignore pattern: ", strings.Join(ignorePatterns, ", "))
	}
	return ignorePatterns
}
func isIgnoredFile(fileName string, fileRoot string) bool {
	trimmedName := strings.Replace(fileName, fileRoot, "", 1)
	for _, pattern := range ignorePatterns {
		if wildcard.PatternMatch(trimmedName, pattern) {
			return true
		}
	}
	return false
}
func isDirectory(path string) (bool, error) {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false, err
	}
	return fileInfo.IsDir(), nil
}