diff --git a/internal/config/constants.go b/internal/config/constants.go index dc9e5b5..6ea9546 100644 --- a/internal/config/constants.go +++ b/internal/config/constants.go @@ -5,6 +5,7 @@ const ( APP_NAME = "devlocal" PROJECT_ROOT = ".devlocal" CONFIG_FILE_NAME = "config.yaml" + PATCHES_DIR = "patches" ) var ( diff --git a/internal/filesystem/initialization.go b/internal/filesystem/initialization.go index 77fc18d..1282e24 100644 --- a/internal/filesystem/initialization.go +++ b/internal/filesystem/initialization.go @@ -29,6 +29,13 @@ func createRootDirectory() error { return os.Mkdir(config.PROJECT_ROOT, 0755) } +func createPatchesDirectory() error { + return os.MkdirAll( + filepath.Join(config.PROJECT_ROOT, config.PATCHES_DIR), + 0755, + ) +} + func createConfigFile() error { err := os.WriteFile( filepath.Join(config.PROJECT_ROOT, config.CONFIG_FILE_NAME), @@ -64,11 +71,16 @@ func InitilizeDevLocalFilesystem() error { if err := createConfigFile(); err != nil { return err } - + // populate config file with basics if err := seedYamlConfigFile(); err != nil { return err } + // where my patches will go + if err := createPatchesDirectory(); err != nil { + return err + } + fmt.Println("[Completed] initializing devlocal setup for your repo") return nil } @@ -103,3 +115,14 @@ func ValidateDevLocalFilesystem() error { return nil } + +func ValidatePatchesSetup() error { + pdinfo, pderr := os.Stat(filepath.Join(config.PROJECT_ROOT, config.PATCHES_DIR)) + + if pderr != nil || !pdinfo.IsDir() { + return fmt.Errorf("%s directory has gone missing from inside your devlocal setup!!\n"+ + "\tIf you think something is wrong run `devlocal cleanup` and reinit.\n\t\t[Note] this will remove the configs in %s so best backitup", config.PATCHES_DIR, config.CONFIG_FILE_NAME) + } + + return nil +} diff --git a/internal/git/patches.go b/internal/git/patches.go new file mode 100644 index 0000000..1321b55 --- /dev/null +++ b/internal/git/patches.go @@ -0,0 +1,79 @@ +package git + +import "fmt" + +func checkPatchValidity(filePath string) error { + checkApplyArgs := append( + []string{ + "apply", + "--check", + }, + filePath, + ) + + return executeGitCommand(checkApplyArgs) +} + +func checkRevertPatchValidity(filePath string) error { + checkApplyArgs := append( + []string{ + "apply", + "--check", + "--reverse", + }, + filePath, + ) + + return executeGitCommand(checkApplyArgs) +} + +func patchFile(filePath string) error { + patchFileArgs := append( + []string{ + "apply", + }, + filePath, + ) + + return executeGitCommand(patchFileArgs) +} + +func unpatchFile(filePath string) error { + patchFileArgs := append( + []string{ + "apply", + "--reverse", + }, + filePath, + ) + + return executeGitCommand(patchFileArgs) +} + +func ApplyPatches(filesToPatch []string) error { + for _, filePath := range filesToPatch { + if err := checkPatchValidity(filePath); err != nil { + fmt.Printf("\t[Error] while trying to patch file %s : %s\n", filePath, err.Error()) + continue + } + if err := patchFile(filePath); err != nil { + fmt.Printf("\t[Error] while trying to patch file %s : %s\n", filePath, err.Error()) + } + } + + return nil +} + +func RevertPatches(filesToUnpatch []string) error { + for _, filePath := range filesToUnpatch { + if err := checkRevertPatchValidity(filePath); err != nil { + fmt.Printf("\t[Error] while trying to unpatch file %s : %s\n", filePath, err.Error()) + continue + } + if err := unpatchFile(filePath); err != nil { + fmt.Printf("\t[Error] while trying to unpatch file %s : %s\n", filePath, err.Error()) + } + } + + return nil +} diff --git a/internal/git/utils.go b/internal/git/utils.go new file mode 100644 index 0000000..6ca50c3 --- /dev/null +++ b/internal/git/utils.go @@ -0,0 +1,30 @@ +package git + +import ( + "fmt" + "os/exec" +) + +func executeGitCommand(args []string) error { + cmd := exec.Command("git", args...) + + out, err := cmd.CombinedOutput() + + if err != nil { + return fmt.Errorf("Failed to run git command: %s", out) + } + + return nil +} + +func isFileTracked(file string) bool { + trackCheckArgs := []string{ + "ls-files", + "--error-unmatch", + file, + } + + err := executeGitCommand(trackCheckArgs) + + return err == nil +} diff --git a/internal/git/worktrees.go b/internal/git/worktrees.go index 1fdd513..487512d 100644 --- a/internal/git/worktrees.go +++ b/internal/git/worktrees.go @@ -5,18 +5,6 @@ import ( "os/exec" ) -func executeGitCommand(args []string) error { - cmd := exec.Command("git", args...) - - out, err := cmd.CombinedOutput() - - if err != nil { - return fmt.Errorf("[Error] Failed to run Skip Worktree: %s", out) - } - - return nil -} - func SkipWorkTree(files []string) error { filesToSkip := sanitizeToTrackedFiles(files) @@ -49,18 +37,6 @@ func NoSkipWorkTree(files []string) error { return executeGitCommand(skipWorktreeArgs) } -func isFileTracked(file string) bool { - trackCheckArgs := []string{ - "ls-files", - "--error-unmatch", - file, - } - - err := executeGitCommand(trackCheckArgs) - - return err == nil -} - func sanitizeToTrackedFiles(files []string) []string { filesTracked := []string{} diff --git a/internal/service/apply/applicator.go b/internal/service/apply/applicator.go index b4697cb..219b546 100644 --- a/internal/service/apply/applicator.go +++ b/internal/service/apply/applicator.go @@ -8,6 +8,26 @@ import ( "github.com/RohitRavindra-dev/devlocal/internal/git" ) +func applyPatches(patchFiles []string) error { + + if err := filesystem.ValidatePatchesSetup(); err != nil { + return err + } + + fmt.Println("[Running] patch for files: ", strings.Join(patchFiles, ", ")) + if len(patchFiles) == 0 { + fmt.Println("[Warn] No patch files found in patches section of devlocal config, skipping") + return nil + } + + if err := git.ApplyPatches(patchFiles); err != nil { + return err + } + + fmt.Println("[Completed] applying patches") + return nil +} + func applyOverlook(overlookFiles []string) error { fmt.Println("[Running] git skip worktree for files: ", strings.Join(overlookFiles, ", ")) if len(overlookFiles) == 0 { @@ -32,12 +52,16 @@ func Run() error { return err } + // apply patches + if patchingErr := applyPatches(config.Patches); patchingErr != nil { + return patchingErr + } + // overlook files if overlookErr := applyOverlook(config.Overlook); overlookErr != nil { return overlookErr } - // TODO: apply patches - + fmt.Println("[Completed] applying devlocal changes") return nil } diff --git a/internal/service/revert/reverter.go b/internal/service/revert/reverter.go index 41bd2ee..525f65c 100644 --- a/internal/service/revert/reverter.go +++ b/internal/service/revert/reverter.go @@ -8,6 +8,26 @@ import ( "github.com/RohitRavindra-dev/devlocal/internal/git" ) +func revertPatches(patchedfiles []string) error { + if err := filesystem.ValidatePatchesSetup(); err != nil { + return err + } + + fmt.Println("[Running] revert patches for files: ", strings.Join(patchedfiles, ", ")) + + if len(patchedfiles) == 0 { + fmt.Println("[Warn] No patch files found in patches section of devlocal config, skipping") + return nil + } + + if err := git.RevertPatches(patchedfiles); err != nil { + return err + } + + fmt.Println("[Completed] reverting patches") + return nil +} + func revertOverlook(overlookedFiles []string) error { fmt.Println("[Running] revert git skip worktree for files: ", strings.Join(overlookedFiles, ", ")) @@ -34,12 +54,16 @@ func Run() error { return err } + //revert patches applied + if patchesRevertErr := revertPatches(config.Patches); patchesRevertErr != nil { + return patchesRevertErr + } + // revert overlooked files if overlookRevertErr := revertOverlook(config.Overlook); overlookRevertErr != nil { return overlookRevertErr } - //TODO: revert patches - + fmt.Println("[Completed] reverting devlocal changes") return nil } diff --git a/todos.md b/todos.md new file mode 100644 index 0000000..5a2e981 --- /dev/null +++ b/todos.md @@ -0,0 +1,8 @@ +# todos + +1. Apply: +- revert +- status +- conflicts +- overlook +- config \ No newline at end of file