1package launchpad
2
3import (
4 "bufio"
5 "errors"
6 "fmt"
7 "net/http"
8 "os"
9 "regexp"
10 "strings"
11 "time"
12
13 "github.com/MichaelMure/git-bug/bridge/core"
14 "github.com/MichaelMure/git-bug/cache"
15)
16
17var ErrBadProjectURL = errors.New("bad Launchpad project URL")
18
19const (
20 target = "launchpad-preview"
21 keyProject = "project"
22 defaultTimeout = 60 * time.Second
23)
24
25func (l *Launchpad) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.Configuration, error) {
26 if params.TokenRaw != "" {
27 fmt.Println("warning: token params are ineffective for a Launchpad bridge")
28 }
29 if params.Owner != "" {
30 fmt.Println("warning: --owner is ineffective for a Launchpad bridge")
31 }
32 if params.BaseURL != "" {
33 fmt.Println("warning: --base-url is ineffective for a Launchpad bridge")
34 }
35
36 conf := make(core.Configuration)
37 var err error
38 var project string
39
40 switch {
41 case params.Project != "":
42 project = params.Project
43 case params.URL != "":
44 // get project name from url
45 project, err = splitURL(params.URL)
46 default:
47 // get project name from terminal prompt
48 project, err = promptProjectName()
49 }
50
51 if err != nil {
52 return nil, err
53 }
54
55 // verify project
56 ok, err := validateProject(project)
57 if err != nil {
58 return nil, err
59 }
60 if !ok {
61 return nil, fmt.Errorf("project doesn't exist")
62 }
63
64 conf[core.ConfigKeyTarget] = target
65 conf[keyProject] = project
66
67 err = l.ValidateConfig(conf)
68 if err != nil {
69 return nil, err
70 }
71
72 return conf, nil
73}
74
75func (*Launchpad) ValidateConfig(conf core.Configuration) error {
76 if v, ok := conf[core.ConfigKeyTarget]; !ok {
77 return fmt.Errorf("missing %s key", core.ConfigKeyTarget)
78 } else if v != target {
79 return fmt.Errorf("unexpected target name: %v", v)
80 }
81
82 if _, ok := conf[keyProject]; !ok {
83 return fmt.Errorf("missing %s key", keyProject)
84 }
85
86 return nil
87}
88
89func promptProjectName() (string, error) {
90 for {
91 fmt.Print("Launchpad project name: ")
92
93 line, err := bufio.NewReader(os.Stdin).ReadString('\n')
94 if err != nil {
95 return "", err
96 }
97
98 line = strings.TrimRight(line, "\n")
99
100 if line == "" {
101 fmt.Println("Project name is empty")
102 continue
103 }
104
105 return line, nil
106 }
107}
108
109func validateProject(project string) (bool, error) {
110 url := fmt.Sprintf("%s/%s", apiRoot, project)
111
112 client := &http.Client{
113 Timeout: defaultTimeout,
114 }
115
116 resp, err := client.Get(url)
117 if err != nil {
118 return false, err
119 }
120
121 return resp.StatusCode == http.StatusOK, nil
122}
123
124// extract project name from url
125func splitURL(url string) (string, error) {
126 re, err := regexp.Compile(`launchpad\.net[\/:]([^\/]*[a-z]+)`)
127 if err != nil {
128 panic("regexp compile:" + err.Error())
129 }
130
131 res := re.FindStringSubmatch(url)
132 if res == nil {
133 return "", ErrBadProjectURL
134 }
135
136 return res[1], nil
137}