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 }