github.com/jgrancell/metasync@v0.0.0-20220105143315-c43793d9d9c1/app/repository.go (about) 1 package app 2 3 import ( 4 "fmt" 5 "io/fs" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 git "github.com/go-git/go-git/v5" 11 plumbing "github.com/go-git/go-git/v5/plumbing" 12 13 "github.com/jgrancell/metasync/utils" 14 ) 15 16 type Repository struct { 17 CandidateFiles []*SyncCandidate 18 FilesystemPath string 19 RawRepository *git.Repository 20 Ref string 21 RefType string 22 RequiresAuthentication bool 23 ShowDiffs bool 24 TemplatesDirectory string 25 Url string 26 } 27 28 func (r *Repository) Clone(tempdir string, verbose bool) error { 29 repo, err := git.PlainClone(tempdir, false, &git.CloneOptions{ 30 URL: r.Url, 31 }) 32 r.RawRepository = repo 33 r.FilesystemPath = tempdir 34 return utils.ReturnError("failed to clone source repository", err) 35 } 36 37 func (r *Repository) Checkout() error { 38 w, err := r.RawRepository.Worktree() 39 if err != nil { 40 return utils.ReturnError("unable to open source repository worktree", err) 41 } 42 43 var opts *git.CheckoutOptions 44 if r.RefType == "branch" { 45 opts = &git.CheckoutOptions{ 46 Branch: plumbing.ReferenceName("refs/remotes/origin/" + r.Ref), 47 } 48 } else { 49 opts = &git.CheckoutOptions{ 50 Hash: plumbing.NewHash(r.Ref), 51 } 52 } 53 err = w.Checkout(opts) 54 return utils.ReturnError("unable to checkout target ref", err) 55 } 56 57 func (r *Repository) FindSyncCandidates() error { 58 sourceFiles, err := r.ListFiles() 59 if err != nil { 60 return utils.ReturnError("unable to list files from source repository", err) 61 } 62 63 cwd, err := os.Getwd() 64 if err != nil { 65 return utils.ReturnError("unable to determine the current working directory", err) 66 } 67 68 for _, source := range sourceFiles { 69 70 c := &SyncCandidate{ 71 Name: source.Name(), 72 SourceFile: filepath.Join(r.FilesystemPath, r.TemplatesDirectory, source.Name()), 73 TargetFile: filepath.Join(cwd, source.Name()), 74 } 75 76 ok, err := c.RequiresSync() 77 if err != nil { 78 fmt.Println("Sync candidate", c.Name, "could not be read properly. Skipping.") 79 } 80 if ok { 81 r.CandidateFiles = append(r.CandidateFiles, c) 82 } 83 } 84 85 r.PrintCandidates() 86 return nil 87 } 88 89 func (r *Repository) ExecuteCandidateSync() error { 90 for _, c := range r.CandidateFiles { 91 err := c.Sync() 92 if err != nil { 93 return err 94 } 95 } 96 return nil 97 } 98 99 func (r *Repository) ListFiles() ([]fs.FileInfo, error) { 100 files, err := ioutil.ReadDir(r.FilesystemPath + "/" + r.TemplatesDirectory) 101 if err != nil { 102 return nil, err 103 } 104 return files, nil 105 } 106 107 func (r *Repository) PrintCandidates() { 108 if len(r.CandidateFiles) == 0 { 109 fmt.Println("All files are in sync.") 110 return 111 } 112 113 if !r.ShowDiffs { 114 fmt.Println("Out of sync files:") 115 } 116 117 for _, c := range r.CandidateFiles { 118 if r.ShowDiffs { 119 fmt.Println() 120 fmt.Println(c.Name + ":") 121 if len(c.Diff) > 0 { 122 fmt.Println(c.Diff) 123 } else { 124 fmt.Println("File does not exist in target.") 125 } 126 fmt.Println("") 127 fmt.Println("----------------------------------------") 128 } else { 129 fmt.Println(" -", c.Name) 130 } 131 } 132 }