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
33 conf := make(core.Configuration)
34 var err error
35 var project string
36
37 switch {
38 case params.Project != "":
39 project = params.Project
40 case params.URL != "":
41 // get project name from url
42 project, err = splitURL(params.URL)
43 default:
44 // get project name from terminal prompt
45 project, err = promptProjectName()
46 }
47
48 if err != nil {
49 return nil, err
50 }
51
52 // verify project
53 ok, err := validateProject(project)
54 if err != nil {
55 return nil, err
56 }
57 if !ok {
58 return nil, fmt.Errorf("project doesn't exist")
59 }
60
61 conf[core.ConfigKeyTarget] = target
62 conf[keyProject] = project
63
64 err = l.ValidateConfig(conf)
65 if err != nil {
66 return nil, err
67 }
68
69 return conf, nil
70}
71
72func (*Launchpad) ValidateConfig(conf core.Configuration) error {
73 if v, ok := conf[core.ConfigKeyTarget]; !ok {
74 return fmt.Errorf("missing %s key", core.ConfigKeyTarget)
75 } else if v != target {
76 return fmt.Errorf("unexpected target name: %v", v)
77 }
78
79 if _, ok := conf[keyProject]; !ok {
80 return fmt.Errorf("missing %s key", keyProject)
81 }
82
83 return nil
84}
85
86func promptProjectName() (string, error) {
87 for {
88 fmt.Print("Launchpad project name: ")
89
90 line, err := bufio.NewReader(os.Stdin).ReadString('\n')
91 if err != nil {
92 return "", err
93 }
94
95 line = strings.TrimRight(line, "\n")
96
97 if line == "" {
98 fmt.Println("Project name is empty")
99 continue
100 }
101
102 return line, nil
103 }
104}
105
106func validateProject(project string) (bool, error) {
107 url := fmt.Sprintf("%s/%s", apiRoot, project)
108
109 client := &http.Client{
110 Timeout: defaultTimeout,
111 }
112
113 resp, err := client.Get(url)
114 if err != nil {
115 return false, err
116 }
117
118 return resp.StatusCode == http.StatusOK, nil
119}
120
121// extract project name from url
122func splitURL(url string) (string, error) {
123 re, err := regexp.Compile(`launchpad\.net[\/:]([^\/]*[a-z]+)`)
124 if err != nil {
125 panic("regexp compile:" + err.Error())
126 }
127
128 res := re.FindStringSubmatch(url)
129 if res == nil {
130 return "", ErrBadProjectURL
131 }
132
133 return res[1], nil
134}