1package core
2
3import (
4 "fmt"
5 "os/exec"
6 "strings"
7
8 "github.com/MichaelMure/git-bug/cache"
9 "github.com/MichaelMure/git-bug/repository"
10 "github.com/pkg/errors"
11)
12
13var ErrImportNorSupported = errors.New("import is not supported")
14var ErrExportNorSupported = errors.New("export is not supported")
15
16// Bridge is a wrapper around a BridgeImpl that will bind low-level
17// implementation with utility code to provide high-level functions.
18type Bridge struct {
19 impl BridgeImpl
20 conf Configuration
21}
22
23func NewBridge(impl BridgeImpl) *Bridge {
24 return &Bridge{
25 impl: impl,
26 }
27}
28
29func (b *Bridge) Configure(repo repository.RepoCommon) error {
30 conf, err := b.impl.Configure(repo)
31 if err != nil {
32 return err
33 }
34
35 return b.storeConfig(repo, conf)
36}
37
38func (b *Bridge) storeConfig(repo repository.RepoCommon, conf Configuration) error {
39 for key, val := range conf {
40 storeKey := fmt.Sprintf("git-bug.%s.%s", b.impl.Name(), key)
41
42 cmd := exec.Command("git", "config", "--replace-all", storeKey, val)
43 cmd.Dir = repo.GetPath()
44
45 out, err := cmd.CombinedOutput()
46 if err != nil {
47 return fmt.Errorf("error while storing bridge configuration: %s", out)
48 }
49 }
50
51 return nil
52}
53
54func (b Bridge) getConfig(repo repository.RepoCommon) (Configuration, error) {
55 var err error
56 if b.conf == nil {
57 b.conf, err = b.loadConfig(repo)
58 if err != nil {
59 return nil, err
60 }
61 }
62
63 return b.conf, nil
64}
65
66func (b Bridge) loadConfig(repo repository.RepoCommon) (Configuration, error) {
67 key := fmt.Sprintf("git-bug.%s", b.impl.Name())
68 cmd := exec.Command("git", "config", "--get-regexp", key)
69 cmd.Dir = repo.GetPath()
70
71 out, err := cmd.CombinedOutput()
72 if err != nil {
73 return nil, fmt.Errorf("error while reading bridge configuration: %s", out)
74 }
75
76 lines := strings.Split(string(out), "\n")
77
78 result := make(Configuration, len(lines))
79 for _, line := range lines {
80 if strings.TrimSpace(line) == "" {
81 continue
82 }
83
84 parts := strings.Fields(line)
85 if len(parts) != 2 {
86 return nil, fmt.Errorf("bad bridge configuration: %s", line)
87 }
88
89 result[parts[0]] = parts[1]
90 }
91
92 return result, nil
93}
94
95func (b Bridge) ImportAll(repo *cache.RepoCache) error {
96 importer := b.impl.Importer()
97 if importer == nil {
98 return ErrImportNorSupported
99 }
100
101 conf, err := b.getConfig(repo)
102 if err != nil {
103 return err
104 }
105
106 return b.impl.Importer().ImportAll(repo, conf)
107}
108
109func (b Bridge) Import(repo *cache.RepoCache, id string) error {
110 importer := b.impl.Importer()
111 if importer == nil {
112 return ErrImportNorSupported
113 }
114
115 conf, err := b.getConfig(repo)
116 if err != nil {
117 return err
118 }
119
120 return b.impl.Importer().Import(repo, conf, id)
121}
122
123func (b Bridge) ExportAll(repo *cache.RepoCache) error {
124 exporter := b.impl.Exporter()
125 if exporter == nil {
126 return ErrExportNorSupported
127 }
128
129 conf, err := b.getConfig(repo)
130 if err != nil {
131 return err
132 }
133
134 return b.impl.Exporter().ExportAll(repo, conf)
135}
136
137func (b Bridge) Export(repo *cache.RepoCache, id string) error {
138 exporter := b.impl.Exporter()
139 if exporter == nil {
140 return ErrExportNorSupported
141 }
142
143 conf, err := b.getConfig(repo)
144 if err != nil {
145 return err
146 }
147
148 return b.impl.Exporter().Export(repo, conf, id)
149}