1package launchpad
2
3import (
4 "errors"
5 "fmt"
6 "net/http"
7 "regexp"
8
9 "github.com/git-bug/git-bug/bridge/core"
10 "github.com/git-bug/git-bug/cache"
11 "github.com/git-bug/git-bug/commands/input"
12)
13
14var ErrBadProjectURL = errors.New("bad Launchpad project URL")
15
16func (Launchpad) ValidParams() map[string]interface{} {
17 return map[string]interface{}{
18 "URL": nil,
19 "Project": nil,
20 }
21}
22
23func (l *Launchpad) Configure(repo *cache.RepoCache, params core.BridgeParams, interactive bool) (core.Configuration, error) {
24 var err error
25 var project string
26
27 switch {
28 case params.Project != "":
29 project = params.Project
30 case params.URL != "":
31 // get project name from url
32 project, err = splitURL(params.URL)
33 default:
34 if !interactive {
35 return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the project name with the --project option.")
36 }
37 // get project name from terminal prompt
38 project, err = input.Prompt("Launchpad project name", "project name", input.Required)
39 }
40
41 if err != nil {
42 return nil, err
43 }
44
45 // verify project
46 ok, err := validateProject(project)
47 if err != nil {
48 return nil, err
49 }
50 if !ok {
51 return nil, fmt.Errorf("project doesn't exist")
52 }
53
54 conf := make(core.Configuration)
55 conf[core.ConfigKeyTarget] = target
56 conf[confKeyProject] = project
57
58 err = l.ValidateConfig(conf)
59 if err != nil {
60 return nil, err
61 }
62
63 return conf, nil
64}
65
66func (*Launchpad) ValidateConfig(conf core.Configuration) error {
67 if v, ok := conf[core.ConfigKeyTarget]; !ok {
68 return fmt.Errorf("missing %s key", core.ConfigKeyTarget)
69 } else if v != target {
70 return fmt.Errorf("unexpected target name: %v", v)
71 }
72 if _, ok := conf[confKeyProject]; !ok {
73 return fmt.Errorf("missing %s key", confKeyProject)
74 }
75
76 return nil
77}
78
79func validateProject(project string) (bool, error) {
80 url := fmt.Sprintf("%s/%s", apiRoot, project)
81
82 client := &http.Client{
83 Timeout: defaultTimeout,
84 }
85
86 resp, err := client.Get(url)
87 if err != nil {
88 return false, err
89 }
90
91 _ = resp.Body.Close()
92
93 return resp.StatusCode == http.StatusOK, nil
94}
95
96// extract project name from url
97func splitURL(url string) (string, error) {
98 re := regexp.MustCompile(`launchpad\.net[\/:]([^\/]*[a-z]+)`)
99
100 res := re.FindStringSubmatch(url)
101 if res == nil {
102 return "", ErrBadProjectURL
103 }
104
105 return res[1], nil
106}