// copyStash copies parent's stash directory to child's func copyStash(parent string, child string) error { repoDir, err := dirutils.OpenRepo() if err != nil { return err } metaDir := repoDir.Name() + "/" + dirutils.ObjectDir + "/" return exec.Command("cp", "-r", metaDir+parent, metaDir+child).Run() }
// CompareStatusToCommit maps file names to their status with respect // to a specific commit. func CompareStatusToCommit(commit *meta.Commit) (map[string]int, error) { // Open base directory repoDir, err := dirutils.OpenRepo() if err != nil { return nil, err } files := readFiles(repoDir, "") // Check if modified, unmodified, or new markStatus(commit, files) return files, nil }
// Init initializes the stash directory func Init(branch string, timestamp string) error { // Make unique directory .svc/BRANCH/COMMIT_TIME if needed repoBase, err := dirutils.OpenRepo() if err != nil { return err } repoDir = repoBase.Name() stashDir = repoDir + "/" + dirutils.ObjectDir + "/" + branch + "/" + timestamp err = os.MkdirAll(stashDir, dirutils.Permissions) if err != nil { return err } return nil }
// Write writes a repo to the metadata file func (repo *Repo) Write() error { dir, err := dirutils.OpenRepo() if err != nil { return err } defer dir.Close() filename := dir.Name() + "/" + dirutils.ObjectDir + "/" + metafileName file, err := os.Create(filename) if err != nil { return err } defer file.Close() err = WriteMetadata(file, repo) return err }
// cleanup removes the commits and stash directories after a revert func cleanup(branch *meta.Branch, n int) error { repoBase, err := dirutils.OpenRepo() if err != nil { return err } stashBase := repoBase.Name() + "/" + dirutils.ObjectDir + "/" + branch.Title + "/" m := len(branch.Commit) - n for _, commit := range branch.Commit[m:] { err = os.RemoveAll(stashBase + commit.Timestamp.String()) if err != nil { return err } } branch.Commit = branch.Commit[:m] return nil }
// Revert reverts the state of the working directory to that // of n commits ago. func Revert(n int) { repo, err := meta.Open() if err != nil { fmt.Println(err) return } branch, _ := repo.Find(repo.Current) if len(branch.Commit) < n { fmt.Printf("Only %d commits exist!\n", len(branch.Commit)) return } var commit *meta.Commit if len(branch.Commit) == n { commit = nil } else { commit = &branch.Commit[(len(branch.Commit)-1)-n] } files, err := status.CompareStatusToCommit(commit) if err != nil { fmt.Println(err) return } repoDir, err := dirutils.OpenRepo() if err != nil { fmt.Println(err) return } // Might have to restore some files if not at initial commit if commit != nil { err = stash.Init(branch.Title, commit.Timestamp.String()) if err != nil { fmt.Println(err) return } } for file, stat := range files { if stat == status.NEW { fileWithPath := repoDir.Name() + "/" + file err = os.Remove(fileWithPath) if err != nil { fmt.Println(err) fmt.Println("Repo may be corrupt.") return } err = dirutils.DeleteIfEmpty(fileWithPath[:strings.LastIndex(fileWithPath, "/")]) if err != nil { fmt.Println(err) fmt.Println("Repo may be corrupt.") return } } else if stat == status.REMOVED || stat == status.MODIFIED { err = stash.Restore(file) if err != nil { fmt.Println(err) fmt.Println("Repo may be corrupt.") return } } } err = cleanup(branch, n) if err != nil { fmt.Println(err) fmt.Println("Repo may be corrupt.") return } err = repo.Write() if err != nil { fmt.Println(err) fmt.Println("Repo may be corrupt.") return } if len(branch.Commit) == 0 { fmt.Println("Repo reset to intial state") } else { fmt.Println("Repo reset to commit:") fmt.Println("\x1b[32;1m" + branch.Commit[len(branch.Commit)-1].Title + "\x1b[0m") fmt.Printf("%v\n", branch.Commit[len(branch.Commit)-1].Timestamp) } }