-
Notifications
You must be signed in to change notification settings - Fork 0
/
dotfiles.go
118 lines (97 loc) · 2.13 KB
/
dotfiles.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package zcmd
import (
"context"
"os"
"path/filepath"
"github.com/go-git/go-git/v5"
log "github.com/sirupsen/logrus"
)
// DotFiler is client for dotfiles management
type DotFiler struct {
homeDir string
hostname string
config *DotFilesConfig
}
// NewDotFiler returns DotFiler with given home directory
func NewDotFiler(cfg *DotFilesConfig) (*DotFiler, error) {
_, err := os.Stat(cfg.Dir)
if err != nil && !os.IsNotExist(err) {
return nil, err
}
hostname, err := os.Hostname()
if err != nil {
return nil, err
}
return &DotFiler{
homeDir: os.Getenv("HOME"),
hostname: hostname,
config: cfg,
}, nil
}
// Init initializes dotfiles directory if not exist
func (d *DotFiler) Init(ctx context.Context, gitURL string) error {
_, err := os.Stat(d.config.Dir)
if err != nil && !os.IsNotExist(err) {
return err
}
_, err = git.PlainCloneContext(ctx, d.config.Dir, false, &git.CloneOptions{
URL: gitURL,
Progress: os.Stdout,
})
if err != nil {
return err
}
return d.MakeSymlinks()
}
// Pull updates dotfiles and make symlinks
func (d *DotFiler) Pull(ctx context.Context) error {
repo, err := git.PlainOpen(d.config.Dir)
if err != nil {
return err
}
log.WithFields(log.Fields{
"path": d.config.Dir,
}).Info("found git repository")
worktree, err := repo.Worktree()
if err != nil {
return err
}
err = worktree.PullContext(ctx, &git.PullOptions{
Progress: os.Stdout,
})
if err != nil && err != git.NoErrAlreadyUpToDate {
return err
}
return d.MakeSymlinks()
}
// MakeSymlinks makes symlinks to the home directory
func (d *DotFiler) MakeSymlinks() error {
for _, p := range d.config.Files {
src := filepath.Join(d.config.Dir, p)
dst := filepath.Join(d.homeDir, "."+p)
dstDir := filepath.Dir(dst)
err := os.MkdirAll(dstDir, 0o755)
if err != nil {
return err
}
_, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return err
}
if err == nil {
err := os.Remove(dst)
if err != nil {
return err
}
}
err = os.Symlink(src, dst)
if err != nil {
return err
}
log.WithFields(log.Fields{
"src": src,
"dst": dst,
}).Info("symlinked")
}
return nil
}