filemanager/gitwrapper.go (113 lines of code) (raw):

package filemanager import ( "fmt" "net/http" "os" "os/exec" "strings" ) var gitBinaryPath string func gitPath() (string, error) { if gitBinaryPath == "" { resolvedPath, err := exec.LookPath("git") if err != nil { return "", err } gitBinaryPath = resolvedPath } return gitBinaryPath, nil } func (fm *FileManager) isGitRepository() *Error { fi, err := os.Stat(fm.Path) if os.IsNotExist(err) { return &Error{code: http.StatusNotFound, err: fmt.Errorf("the path does not exist")} } if err != nil { return &Error{code: http.StatusUnprocessableEntity, err: err} } if !fi.Mode().IsDir() { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("the path must be a directory")} } if err := fm.runGitRepositoryCheck(); err != nil { return err } return nil } func (fm *FileManager) runGitRepositoryCheck() *Error { cmd, customErr := fm.buildGitCommand("rev-parse", "--is-inside-work-tree") if customErr != nil { return customErr } if err := cmd.Run(); err != nil { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("the path is not a git repository")} } return nil } func (fm *FileManager) runGitFilesCheckout() *Error { cmd, customErr := fm.buildGitCommand("checkout", ".") if customErr != nil { return customErr } if err := cmd.Run(); err != nil { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("error checking out files")} } return nil } func (fm *FileManager) runGitApply(diff string, check bool) *Error { args := []string{"apply", "--cached"} if check { args = append(args, "--check") } cmd, customErr := fm.buildGitCommand(args...) if customErr != nil { return customErr } cmd.Stdin = strings.NewReader(diff) if err := cmd.Run(); err != nil { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("error applying the patch")} } return nil } func (fm *FileManager) runGitResetHard() *Error { args := []string{"reset", "--hard", "HEAD"} cmd, customErr := fm.buildGitCommand(args...) if customErr != nil { return customErr } if err := cmd.Run(); err != nil { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("error resetting the repository")} } return nil } func (fm *FileManager) runCleanRepository() *Error { cmd, customErr := fm.buildGitCommand("clean", "-ffdx") if customErr != nil { return customErr } if err := cmd.Run(); err != nil { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("error cleaning the repository")} } return nil } func (fm *FileManager) buildGitCommand(args ...string) (*exec.Cmd, *Error) { gitBinary, err := gitPath() if err != nil { return nil, &Error{code: http.StatusInternalServerError, err: err} } cmd := exec.Command(gitBinary, args...) cmd.Dir = fm.Path return cmd, nil } func (fm *FileManager) runGitDelete(paths []string) *Error { if len(paths) == 0 { return nil } // Force flag is to delete files that have been already modified and cached // Recursive flag is used to remove directories cmd, customErr := fm.buildGitCommand(append([]string{"rm", "--force", "-r"}, paths...)...) if customErr != nil { return customErr } if err := cmd.Run(); err != nil { return &Error{code: http.StatusUnprocessableEntity, err: fmt.Errorf("error deleting the files")} } return nil }