| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package gerrit |
| |
| import ( |
| "fmt" |
| "net/url" |
| "strconv" |
| "strings" |
| |
| "go.chromium.org/luci/common/api/gerrit" |
| ) |
| |
| const ( |
| fuchsiaReviewHost = "fuchsia-review.googlesource.com/" |
| turquoiseInternalReviewHost = "turquoise-internal-review.googlesource.com/" |
| ) |
| |
| var prefixes = []string{ |
| "https://", |
| "http://", |
| "go/", |
| } |
| |
| var shortLinkMap = map[string]string{ |
| "fxrev.dev/": fuchsiaReviewHost, |
| "fxr/": fuchsiaReviewHost, |
| "tqr/": turquoiseInternalReviewHost, |
| } |
| |
| // ResolveChangeUrl resolves common change URLs for fuchsia hosts, |
| // returning a canonical gerrit host and change ID. |
| // |
| // Note: only supports numeric change IDs, and does not support |
| // deprecated change IDs. |
| // See https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-id |
| // In practice however, deprecated change IDs are very unlikely to be |
| // used as inputs. |
| // |
| // Examples: |
| // |
| // fxr/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // tqr/<change_id> |
| // -> turquoise-internal-review.googlesource.com, <change_id> |
| // go/fxr/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // go/tqr/<change_id> |
| // -> turquoise-internal-review.googlesource.com, <change_id> |
| // http://go/fxr/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // fxrev.dev/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // https://fxrev.dev/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // http://go/tqr/<change_id> |
| // -> turquoise-internal-review.googlesource.com, <change_id> |
| // https://fuchsia-review.googlesource.com/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // https://fuchsia-review.googlesource.com/<change_id>/ |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // https://turquoise-internal-review.googlesource.com/<change_id> |
| // -> turquoise-internal-review.googlesource.com, <change_id> |
| // https://fuchsia-review.googlesource.com/c/<project>/+/<change_id> |
| // -> fuchsia-review.googlesource.com, <change_id> |
| // https://turquoise-internal-review.googlesource.com/c/<project>/+/<change_id> |
| // -> turquoise-internal-review.googlesource.com, <change_id> |
| // https://turquoise-internal-review.git.corp.google.com/c/<project>/+/<change_id> |
| // -> turquoise-internal-review.googlesource.com, <change_id> |
| func ResolveChangeUrl(changeUrl *url.URL) (host string, changeId int64, err error) { |
| host, changeId, err = "", 0, nil |
| change := changeUrl.String() |
| // Replace corp with googlesource. |
| change = strings.Replace(change, ".git.corp.google.com", ".googlesource.com", 1) |
| // Trim prefixes in order. |
| for _, prefix := range prefixes { |
| if strings.HasPrefix(change, prefix) { |
| change = strings.TrimPrefix(change, prefix) |
| } |
| } |
| // Map short-link to full host. |
| for k, v := range shortLinkMap { |
| if strings.HasPrefix(change, k) { |
| change = strings.Replace(change, k, v, 1) |
| break |
| } |
| } |
| // Trim trailing slash. |
| change = strings.TrimSuffix(change, "/") |
| // Split by slash and take the first and last elements, ignoring anything in-between. |
| // This should be the host and change ID. |
| sp := strings.Split(change, "/") |
| if len(sp) < 2 { |
| err = fmt.Errorf("%s is not a valid change URL", changeUrl) |
| return |
| } |
| host = sp[0] |
| err = gerrit.ValidateGerritURL("https://" + host) |
| if err != nil { |
| return |
| } |
| // Change ID can only be numeric. |
| num, err := strconv.Atoi(sp[len(sp)-1]) |
| if err != nil { |
| err = fmt.Errorf("%s is not a valid numeric changeID: %v", sp[len(sp)-1], err) |
| return |
| } |
| changeId = int64(num) |
| return |
| } |