all repos

mugit @ a3d1ce2

🐮 git server that your cow will love

mugit/internal/git/config.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
mirror: distinguish between sync and check time, 2 months ago
1
package git
2
3
import (
4
	"fmt"
5
	"os"
6
	"path/filepath"
7
	"strconv"
8
	"strings"
9
	"time"
10
11
	gitconfig "github.com/go-git/go-git/v5/config"
12
)
13
14
func (g *Repo) IsPrivate() (bool, error) {
15
	v, err := g.readOption("private")
16
	if err != nil {
17
		return false, err
18
	}
19
	return v == "true", nil
20
}
21
22
func (g *Repo) SetPrivate(isPrivate bool) error {
23
	return g.setOption("private", strconv.FormatBool(isPrivate))
24
}
25
26
const originRemote = "origin"
27
28
func (g *Repo) IsMirror() (bool, error) {
29
	r, err := g.r.Remote(originRemote)
30
	if err != nil {
31
		return false, fmt.Errorf("failed to get remote: %w", err)
32
	}
33
	return r.Config().Mirror, nil
34
}
35
36
func (g *Repo) SetMirrorRemote(url string) error {
37
	_, err := g.r.CreateRemote(&gitconfig.RemoteConfig{
38
		Name:   originRemote,
39
		URLs:   []string{url},
40
		Mirror: true,
41
		Fetch: []gitconfig.RefSpec{
42
			"+refs/*:refs/*",
43
		},
44
	})
45
	if err != nil {
46
		return fmt.Errorf("failed to create origin remote: %w", err)
47
	}
48
	return nil
49
}
50
51
func (g *Repo) RemoteURL() (string, error) {
52
	r, err := g.r.Remote(originRemote)
53
	if err != nil {
54
		return "", fmt.Errorf("failed to get remote: %w", err)
55
	}
56
	return r.Config().URLs[0], nil
57
}
58
59
const defaultDescription = "Unnamed repository; edit this file 'description' to name the repository"
60
61
func (g *Repo) Description() (string, error) {
62
	path := filepath.Join(g.path, "description")
63
	if _, err := os.Stat(path); err != nil {
64
		return "", nil
65
	}
66
67
	d, err := os.ReadFile(path)
68
	if err != nil {
69
		return "", fmt.Errorf("failed to read description file: %w", err)
70
	}
71
72
	desc := string(d)
73
	if strings.Contains(desc, defaultDescription) {
74
		return "", nil
75
	}
76
	return desc, nil
77
}
78
79
func (g *Repo) SetDescription(desc string) error {
80
	path := filepath.Join(g.path, "description")
81
	return os.WriteFile(path, []byte(desc), 0o600)
82
}
83
84
func (g *Repo) LastSync() (time.Time, error) {
85
	raw, err := g.readOption("last-sync")
86
	if err != nil {
87
		return time.Time{}, err
88
	}
89
90
	if raw == "" {
91
		return time.Time{}, fmt.Errorf("last-sync not set")
92
	}
93
94
	out, err := time.Parse(time.RFC3339, raw)
95
	if err != nil {
96
		return time.Time{}, fmt.Errorf("failed to parse time: %w", err)
97
	}
98
99
	return out, nil
100
}
101
102
func (g *Repo) SetLastSync(lastSync time.Time) error {
103
	return g.setOption("last-sync", lastSync.Format(time.RFC3339))
104
}
105
106
func (g *Repo) LastChecked() (time.Time, error) {
107
	raw, err := g.readOption("last-checked")
108
	if err != nil {
109
		return time.Time{}, err
110
	}
111
112
	if raw == "" {
113
		return time.Time{}, fmt.Errorf("last-checked not set")
114
	}
115
116
	out, err := time.Parse(time.RFC3339, raw)
117
	if err != nil {
118
		return time.Time{}, fmt.Errorf("failed to parse time: %w", err)
119
	}
120
121
	return out, nil
122
}
123
124
func (g *Repo) SetLastChecked(lastChecked time.Time) error {
125
	return g.setOption("last-checked", lastChecked.Format(time.RFC3339))
126
}
127
128
func (g *Repo) readOption(key string) (string, error) {
129
	c, err := g.r.Config()
130
	if err != nil {
131
		return "", fmt.Errorf("failed to read config: %w", err)
132
	}
133
	return c.Raw.Section("mugit").Options.Get(key), nil
134
}
135
136
func (g *Repo) setOption(key, value string) error {
137
	c, err := g.r.Config()
138
	if err != nil {
139
		return fmt.Errorf("failed to read config: %w", err)
140
	}
141
	c.Raw.Section("mugit").SetOption(key, value)
142
	return g.r.SetConfig(c)
143
}