github.com/jchengjr77/canaveral@v1.0.1-0.20200715160102-ea9245d1a2fb/git/git.go (about)

     1  package git
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"os/exec"
    10  	"strings"
    11  
    12  	"github.com/jchengjr77/canaveral/lib"
    13  )
    14  
    15  // InitRepo initializes a git repo in the current directory
    16  // * tested
    17  func InitRepo(wsPath, project string) (finalErr error) {
    18  	// defer a recover function that returns the thrown error
    19  	defer func() {
    20  		if r := recover(); r != nil {
    21  			finalErr = r.(error)
    22  		}
    23  	}()
    24  	if project != "" {
    25  		// Get workspace path
    26  		ws, err := ioutil.ReadFile(wsPath)
    27  		lib.Check(err)
    28  		err = os.Chdir(string(ws) + "/")
    29  		lib.Check(err)
    30  		if !lib.DirExists(project) {
    31  			fmt.Println("No project found: ", project)
    32  			return
    33  		}
    34  		err = os.Chdir(string(ws) + "/" + project)
    35  		lib.Check(err)
    36  	}
    37  	initRepo := exec.Command("git", "init")
    38  	initRepo.Stdout = os.Stdout
    39  	initRepo.Stdin = os.Stdin
    40  	initRepo.Stderr = os.Stderr
    41  	err := initRepo.Run()
    42  	if err != nil {
    43  		fmt.Println(err.Error())
    44  	}
    45  	return nil
    46  }
    47  
    48  // Status prints current git status in a git directory
    49  // * tested
    50  func Status(wsPath, project string) (finalErr error) {
    51  	// defer a recover function that returns the thrown error
    52  	defer func() {
    53  		if r := recover(); r != nil {
    54  			finalErr = r.(error)
    55  		}
    56  	}()
    57  	if project != "" {
    58  		// Get workspace path
    59  		ws, err := ioutil.ReadFile(wsPath)
    60  		lib.Check(err)
    61  		err = os.Chdir(string(ws) + "/")
    62  		lib.Check(err)
    63  		if !lib.DirExists(project) {
    64  			fmt.Println("No project found: ", project)
    65  			return
    66  		}
    67  		err = os.Chdir(string(ws) + "/" + project)
    68  		lib.Check(err)
    69  	}
    70  	gitStatus := exec.Command("git", "status")
    71  	gitStatus.Stdout = os.Stdout
    72  	gitStatus.Stdin = os.Stdin
    73  	gitStatus.Stderr = os.Stderr
    74  	err := gitStatus.Run()
    75  	if err != nil {
    76  		fmt.Println(err.Error())
    77  	}
    78  	return nil
    79  }
    80  
    81  // Add performs a git add on the specified files
    82  // * tested
    83  func Add(files []string, wsPath string, project string) (finalErr error) {
    84  	// defer a recover function that returns the thrown error
    85  	defer func() {
    86  		if r := recover(); r != nil {
    87  			finalErr = r.(error)
    88  		}
    89  	}()
    90  	if project != "" {
    91  		// Get workspace path
    92  		ws, err := ioutil.ReadFile(wsPath)
    93  		lib.Check(err)
    94  		err = os.Chdir(string(ws) + "/")
    95  		lib.Check(err)
    96  		if !lib.DirExists(project) {
    97  			fmt.Println("No project found: ", project)
    98  			return
    99  		}
   100  		err = os.Chdir(string(ws) + "/" + project)
   101  		lib.Check(err)
   102  	}
   103  	gitAdd := exec.Command("git", "add")
   104  	gitAdd.Stdout = os.Stdout
   105  	gitAdd.Stdin = os.Stdin
   106  	gitAdd.Stderr = os.Stderr
   107  	gitAdd.Args = append(gitAdd.Args, files...)
   108  	err := gitAdd.Run()
   109  	if err != nil {
   110  		fmt.Println(err.Error())
   111  	}
   112  	return nil
   113  }
   114  
   115  func getStaged() (res []string, finalErr error) {
   116  	// defer a recover function that returns the thrown error
   117  	defer func() {
   118  		if r := recover(); r != nil {
   119  			finalErr = r.(error)
   120  		}
   121  	}()
   122  	out, err := exec.Command("git", "diff", "--name-only", "--staged").Output()
   123  	lib.Check(err)
   124  	staged := strings.Split(string(out), "\n")
   125  	var ret []string
   126  	for i := range staged {
   127  		curr := strings.TrimSpace(staged[i])
   128  		if curr != "" {
   129  			ret = append(ret, curr)
   130  		}
   131  	}
   132  	res = ret
   133  	finalErr = nil
   134  	return
   135  }
   136  
   137  func confirmCommit(stdin io.Reader) bool {
   138  	fmt.Printf("Would you still like to commit? ('y' or 'n')> ")
   139  	reader := bufio.NewReader(stdin)
   140  	response, err := reader.ReadByte()
   141  	lib.Check(err)
   142  	return (response == 'y')
   143  }
   144  
   145  // Commit performs a git commit on added files
   146  // * tested
   147  // ! reminders untested
   148  func Commit(
   149  	commitMessage string, wsPath string, project string) (finalErr error) {
   150  	// defer a recover function that returns the thrown error
   151  	defer func() {
   152  		if r := recover(); r != nil {
   153  			finalErr = r.(error)
   154  		}
   155  	}()
   156  	if project != "" {
   157  		// Get workspace path
   158  		ws, err := ioutil.ReadFile(wsPath)
   159  		lib.Check(err)
   160  		err = os.Chdir(string(ws) + "/")
   161  		lib.Check(err)
   162  		if !lib.DirExists(project) {
   163  			fmt.Println("No project found: ", project)
   164  			return
   165  		}
   166  		err = os.Chdir(string(ws) + "/" + project)
   167  		lib.Check(err)
   168  	}
   169  	reminders, err := loadReminders()
   170  	lib.Check(err)
   171  	stagedFiles, err := getStaged()
   172  	lib.Check(err)
   173  	sawRems := false
   174  	confirm := true
   175  	for _, file := range stagedFiles {
   176  		res, err := checkReminders(file, false, reminders)
   177  		lib.Check(err)
   178  		sawRems = sawRems || res
   179  	}
   180  	if sawRems {
   181  		confirm = confirmCommit(os.Stdin)
   182  	}
   183  	if !confirm {
   184  		return
   185  	}
   186  	gitCommit := exec.Command("git", "commit")
   187  	gitCommit.Stdout = os.Stdout
   188  	gitCommit.Stdin = os.Stdin
   189  	gitCommit.Stderr = os.Stderr
   190  	if commitMessage != "" {
   191  		gitCommit.Args = append(gitCommit.Args, "-m", "\""+commitMessage+"\"")
   192  	}
   193  	err = gitCommit.Run()
   194  	if err != nil {
   195  		fmt.Println(err.Error())
   196  	}
   197  	lib.Check(err)
   198  	return nil
   199  }
   200  
   201  // Checks if searchFor is a line in file
   202  // ? untested, low priority
   203  func inFile(file io.Reader, searchFor string) bool {
   204  	s := bufio.NewScanner(file)
   205  	if err := s.Err(); err != nil {
   206  		fmt.Println(err)
   207  	}
   208  	for s.Scan() {
   209  		if s.Text() == searchFor {
   210  			return true
   211  		}
   212  	}
   213  	return false
   214  }
   215  
   216  // Ignore adds files to the .gitignore file in the current directory
   217  // * tested
   218  func Ignore(files []string, wsPath, project string) (finalErr error) {
   219  	// defer a recover function that returns the thrown error
   220  	defer func() {
   221  		if r := recover(); r != nil {
   222  			finalErr = r.(error)
   223  		}
   224  	}()
   225  	if project != "" {
   226  		// Get workspace path
   227  		ws, err := ioutil.ReadFile(wsPath)
   228  		lib.Check(err)
   229  		err = os.Chdir(string(ws) + "/")
   230  		lib.Check(err)
   231  		if !lib.DirExists(project) {
   232  			fmt.Println("No project found: ", project)
   233  			return
   234  		}
   235  		err = os.Chdir(string(ws) + "/" + project)
   236  		lib.Check(err)
   237  	}
   238  	var startsEmpty = false
   239  	gitignore, err := os.OpenFile(".gitignore", os.O_APPEND|os.O_WRONLY, 0644)
   240  	ignoreReader, err := os.OpenFile(".gitignore", os.O_RDONLY, 0644)
   241  	lib.Check(err)
   242  	stat, err := gitignore.Stat()
   243  	if stat.Size() == 0 {
   244  		startsEmpty = true
   245  	}
   246  	defer gitignore.Close()
   247  	for idx, file := range files {
   248  		ignoreReader.Seek(0, io.SeekStart)
   249  		if inFile(ignoreReader, file) {
   250  			fmt.Println("Skipping", file, "because it is already being ignored.")
   251  			continue
   252  		}
   253  		if idx == 0 && !startsEmpty {
   254  			gitignore.Write([]byte{'\n'})
   255  		} else if idx > 0 {
   256  			gitignore.Write([]byte{'\n'})
   257  		}
   258  		_, err = gitignore.WriteString(file)
   259  	}
   260  	lib.Check(err)
   261  	return nil
   262  }