How to use Len method of vcs Package

Best Syzkaller code snippet using vcs.Len

vcs.go

Source:vcs.go Github

copy

Full Screen

1// Copyright 2012 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4package get5import (6 "encoding/json"7 "errors"8 "fmt"9 "internal/lazyregexp"10 "internal/singleflight"11 "log"12 urlpkg "net/url"13 "os"14 "os/exec"15 "path/filepath"16 "regexp"17 "strings"18 "sync"19 "cmd/go/internal/base"20 "cmd/go/internal/cfg"21 "cmd/go/internal/load"22 "cmd/go/internal/web"23)24// A vcsCmd describes how to use a version control system25// like Mercurial, Git, or Subversion.26type vcsCmd struct {27 name string28 cmd string // name of binary to invoke command29 createCmd []string // commands to download a fresh copy of a repository30 downloadCmd []string // commands to download updates into an existing repository31 tagCmd []tagCmd // commands to list tags32 tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd33 tagSyncCmd []string // commands to sync to specific tag34 tagSyncDefault []string // commands to sync to default tag35 scheme []string36 pingCmd string37 remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)38 resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)39}40var defaultSecureScheme = map[string]bool{41 "https": true,42 "git+ssh": true,43 "bzr+ssh": true,44 "svn+ssh": true,45 "ssh": true,46}47func (v *vcsCmd) isSecure(repo string) bool {48 u, err := urlpkg.Parse(repo)49 if err != nil {50 // If repo is not a URL, it's not secure.51 return false52 }53 return v.isSecureScheme(u.Scheme)54}55func (v *vcsCmd) isSecureScheme(scheme string) bool {56 switch v.cmd {57 case "git":58 // GIT_ALLOW_PROTOCOL is an environment variable defined by Git. It is a59 // colon-separated list of schemes that are allowed to be used with git60 // fetch/clone. Any scheme not mentioned will be considered insecure.61 if allow := os.Getenv("GIT_ALLOW_PROTOCOL"); allow != "" {62 for _, s := range strings.Split(allow, ":") {63 if s == scheme {64 return true65 }66 }67 return false68 }69 }70 return defaultSecureScheme[scheme]71}72// A tagCmd describes a command to list available tags73// that can be passed to tagSyncCmd.74type tagCmd struct {75 cmd string // command to list tags76 pattern string // regexp to extract tags from list77}78// vcsList lists the known version control systems79var vcsList = []*vcsCmd{80 vcsHg,81 vcsGit,82 vcsSvn,83 vcsBzr,84 vcsFossil,85}86// vcsByCmd returns the version control system for the given87// command name (hg, git, svn, bzr).88func vcsByCmd(cmd string) *vcsCmd {89 for _, vcs := range vcsList {90 if vcs.cmd == cmd {91 return vcs92 }93 }94 return nil95}96// vcsHg describes how to use Mercurial.97var vcsHg = &vcsCmd{98 name: "Mercurial",99 cmd: "hg",100 createCmd: []string{"clone -U -- {repo} {dir}"},101 downloadCmd: []string{"pull"},102 // We allow both tag and branch names as 'tags'103 // for selecting a version. This lets people have104 // a go.release.r60 branch and a go1 branch105 // and make changes in both, without constantly106 // editing .hgtags.107 tagCmd: []tagCmd{108 {"tags", `^(\S+)`},109 {"branches", `^(\S+)`},110 },111 tagSyncCmd: []string{"update -r {tag}"},112 tagSyncDefault: []string{"update default"},113 scheme: []string{"https", "http", "ssh"},114 pingCmd: "identify -- {scheme}://{repo}",115 remoteRepo: hgRemoteRepo,116}117func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) {118 out, err := vcsHg.runOutput(rootDir, "paths default")119 if err != nil {120 return "", err121 }122 return strings.TrimSpace(string(out)), nil123}124// vcsGit describes how to use Git.125var vcsGit = &vcsCmd{126 name: "Git",127 cmd: "git",128 createCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},129 downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},130 tagCmd: []tagCmd{131 // tags/xxx matches a git tag named xxx132 // origin/xxx matches a git branch named xxx on the default remote repository133 {"show-ref", `(?:tags|origin)/(\S+)$`},134 },135 tagLookupCmd: []tagCmd{136 {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},137 },138 tagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"},139 // both createCmd and downloadCmd update the working dir.140 // No need to do more here. We used to 'checkout master'141 // but that doesn't work if the default branch is not named master.142 // DO NOT add 'checkout master' here.143 // See golang.org/issue/9032.144 tagSyncDefault: []string{"submodule update --init --recursive"},145 scheme: []string{"git", "https", "http", "git+ssh", "ssh"},146 // Leave out the '--' separator in the ls-remote command: git 2.7.4 does not147 // support such a separator for that command, and this use should be safe148 // without it because the {scheme} value comes from the predefined list above.149 // See golang.org/issue/33836.150 pingCmd: "ls-remote {scheme}://{repo}",151 remoteRepo: gitRemoteRepo,152}153// scpSyntaxRe matches the SCP-like addresses used by Git to access154// repositories by SSH.155var scpSyntaxRe = lazyregexp.New(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)156func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {157 cmd := "config remote.origin.url"158 errParse := errors.New("unable to parse output of git " + cmd)159 errRemoteOriginNotFound := errors.New("remote origin not found")160 outb, err := vcsGit.run1(rootDir, cmd, nil, false)161 if err != nil {162 // if it doesn't output any message, it means the config argument is correct,163 // but the config value itself doesn't exist164 if outb != nil && len(outb) == 0 {165 return "", errRemoteOriginNotFound166 }167 return "", err168 }169 out := strings.TrimSpace(string(outb))170 var repoURL *urlpkg.URL171 if m := scpSyntaxRe.FindStringSubmatch(out); m != nil {172 // Match SCP-like syntax and convert it to a URL.173 // Eg, "git@github.com:user/repo" becomes174 // "ssh://git@github.com/user/repo".175 repoURL = &urlpkg.URL{176 Scheme: "ssh",177 User: urlpkg.User(m[1]),178 Host: m[2],179 Path: m[3],180 }181 } else {182 repoURL, err = urlpkg.Parse(out)183 if err != nil {184 return "", err185 }186 }187 // Iterate over insecure schemes too, because this function simply188 // reports the state of the repo. If we can't see insecure schemes then189 // we can't report the actual repo URL.190 for _, s := range vcsGit.scheme {191 if repoURL.Scheme == s {192 return repoURL.String(), nil193 }194 }195 return "", errParse196}197// vcsBzr describes how to use Bazaar.198var vcsBzr = &vcsCmd{199 name: "Bazaar",200 cmd: "bzr",201 createCmd: []string{"branch -- {repo} {dir}"},202 // Without --overwrite bzr will not pull tags that changed.203 // Replace by --overwrite-tags after http://pad.lv/681792 goes in.204 downloadCmd: []string{"pull --overwrite"},205 tagCmd: []tagCmd{{"tags", `^(\S+)`}},206 tagSyncCmd: []string{"update -r {tag}"},207 tagSyncDefault: []string{"update -r revno:-1"},208 scheme: []string{"https", "http", "bzr", "bzr+ssh"},209 pingCmd: "info -- {scheme}://{repo}",210 remoteRepo: bzrRemoteRepo,211 resolveRepo: bzrResolveRepo,212}213func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) {214 outb, err := vcsBzr.runOutput(rootDir, "config parent_location")215 if err != nil {216 return "", err217 }218 return strings.TrimSpace(string(outb)), nil219}220func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) {221 outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo)222 if err != nil {223 return "", err224 }225 out := string(outb)226 // Expect:227 // ...228 // (branch root|repository branch): <URL>229 // ...230 found := false231 for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} {232 i := strings.Index(out, prefix)233 if i >= 0 {234 out = out[i+len(prefix):]235 found = true236 break237 }238 }239 if !found {240 return "", fmt.Errorf("unable to parse output of bzr info")241 }242 i := strings.Index(out, "\n")243 if i < 0 {244 return "", fmt.Errorf("unable to parse output of bzr info")245 }246 out = out[:i]247 return strings.TrimSpace(out), nil248}249// vcsSvn describes how to use Subversion.250var vcsSvn = &vcsCmd{251 name: "Subversion",252 cmd: "svn",253 createCmd: []string{"checkout -- {repo} {dir}"},254 downloadCmd: []string{"update"},255 // There is no tag command in subversion.256 // The branch information is all in the path names.257 scheme: []string{"https", "http", "svn", "svn+ssh"},258 pingCmd: "info -- {scheme}://{repo}",259 remoteRepo: svnRemoteRepo,260}261func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) {262 outb, err := vcsSvn.runOutput(rootDir, "info")263 if err != nil {264 return "", err265 }266 out := string(outb)267 // Expect:268 //269 // ...270 // URL: <URL>271 // ...272 //273 // Note that we're not using the Repository Root line,274 // because svn allows checking out subtrees.275 // The URL will be the URL of the subtree (what we used with 'svn co')276 // while the Repository Root may be a much higher parent.277 i := strings.Index(out, "\nURL: ")278 if i < 0 {279 return "", fmt.Errorf("unable to parse output of svn info")280 }281 out = out[i+len("\nURL: "):]282 i = strings.Index(out, "\n")283 if i < 0 {284 return "", fmt.Errorf("unable to parse output of svn info")285 }286 out = out[:i]287 return strings.TrimSpace(out), nil288}289// fossilRepoName is the name go get associates with a fossil repository. In the290// real world the file can be named anything.291const fossilRepoName = ".fossil"292// vcsFossil describes how to use Fossil (fossil-scm.org)293var vcsFossil = &vcsCmd{294 name: "Fossil",295 cmd: "fossil",296 createCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"},297 downloadCmd: []string{"up"},298 tagCmd: []tagCmd{{"tag ls", `(.*)`}},299 tagSyncCmd: []string{"up tag:{tag}"},300 tagSyncDefault: []string{"up trunk"},301 scheme: []string{"https", "http"},302 remoteRepo: fossilRemoteRepo,303}304func fossilRemoteRepo(vcsFossil *vcsCmd, rootDir string) (remoteRepo string, err error) {305 out, err := vcsFossil.runOutput(rootDir, "remote-url")306 if err != nil {307 return "", err308 }309 return strings.TrimSpace(string(out)), nil310}311func (v *vcsCmd) String() string {312 return v.name313}314// run runs the command line cmd in the given directory.315// keyval is a list of key, value pairs. run expands316// instances of {key} in cmd into value, but only after317// splitting cmd into individual arguments.318// If an error occurs, run prints the command line and the319// command's combined stdout+stderr to standard error.320// Otherwise run discards the command's output.321func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error {322 _, err := v.run1(dir, cmd, keyval, true)323 return err324}325// runVerboseOnly is like run but only generates error output to standard error in verbose mode.326func (v *vcsCmd) runVerboseOnly(dir string, cmd string, keyval ...string) error {327 _, err := v.run1(dir, cmd, keyval, false)328 return err329}330// runOutput is like run but returns the output of the command.331func (v *vcsCmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {332 return v.run1(dir, cmd, keyval, true)333}334// run1 is the generalized implementation of run and runOutput.335func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) {336 m := make(map[string]string)337 for i := 0; i < len(keyval); i += 2 {338 m[keyval[i]] = keyval[i+1]339 }340 args := strings.Fields(cmdline)341 for i, arg := range args {342 args[i] = expand(m, arg)343 }344 if len(args) >= 2 && args[0] == "-go-internal-mkdir" {345 var err error346 if filepath.IsAbs(args[1]) {347 err = os.Mkdir(args[1], os.ModePerm)348 } else {349 err = os.Mkdir(filepath.Join(dir, args[1]), os.ModePerm)350 }351 if err != nil {352 return nil, err353 }354 args = args[2:]355 }356 if len(args) >= 2 && args[0] == "-go-internal-cd" {357 if filepath.IsAbs(args[1]) {358 dir = args[1]359 } else {360 dir = filepath.Join(dir, args[1])361 }362 args = args[2:]363 }364 _, err := exec.LookPath(v.cmd)365 if err != nil {366 fmt.Fprintf(os.Stderr,367 "go: missing %s command. See https://golang.org/s/gogetcmd\n",368 v.name)369 return nil, err370 }371 cmd := exec.Command(v.cmd, args...)372 cmd.Dir = dir373 cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)374 if cfg.BuildX {375 fmt.Fprintf(os.Stderr, "cd %s\n", dir)376 fmt.Fprintf(os.Stderr, "%s %s\n", v.cmd, strings.Join(args, " "))377 }378 out, err := cmd.Output()379 if err != nil {380 if verbose || cfg.BuildV {381 fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))382 if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {383 os.Stderr.Write(ee.Stderr)384 } else {385 fmt.Fprintf(os.Stderr, err.Error())386 }387 }388 }389 return out, err390}391// ping pings to determine scheme to use.392func (v *vcsCmd) ping(scheme, repo string) error {393 return v.runVerboseOnly(".", v.pingCmd, "scheme", scheme, "repo", repo)394}395// create creates a new copy of repo in dir.396// The parent of dir must exist; dir must not.397func (v *vcsCmd) create(dir, repo string) error {398 for _, cmd := range v.createCmd {399 if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {400 return err401 }402 }403 return nil404}405// download downloads any new changes for the repo in dir.406func (v *vcsCmd) download(dir string) error {407 for _, cmd := range v.downloadCmd {408 if err := v.run(dir, cmd); err != nil {409 return err410 }411 }412 return nil413}414// tags returns the list of available tags for the repo in dir.415func (v *vcsCmd) tags(dir string) ([]string, error) {416 var tags []string417 for _, tc := range v.tagCmd {418 out, err := v.runOutput(dir, tc.cmd)419 if err != nil {420 return nil, err421 }422 re := regexp.MustCompile(`(?m-s)` + tc.pattern)423 for _, m := range re.FindAllStringSubmatch(string(out), -1) {424 tags = append(tags, m[1])425 }426 }427 return tags, nil428}429// tagSync syncs the repo in dir to the named tag,430// which either is a tag returned by tags or is v.tagDefault.431func (v *vcsCmd) tagSync(dir, tag string) error {432 if v.tagSyncCmd == nil {433 return nil434 }435 if tag != "" {436 for _, tc := range v.tagLookupCmd {437 out, err := v.runOutput(dir, tc.cmd, "tag", tag)438 if err != nil {439 return err440 }441 re := regexp.MustCompile(`(?m-s)` + tc.pattern)442 m := re.FindStringSubmatch(string(out))443 if len(m) > 1 {444 tag = m[1]445 break446 }447 }448 }449 if tag == "" && v.tagSyncDefault != nil {450 for _, cmd := range v.tagSyncDefault {451 if err := v.run(dir, cmd); err != nil {452 return err453 }454 }455 return nil456 }457 for _, cmd := range v.tagSyncCmd {458 if err := v.run(dir, cmd, "tag", tag); err != nil {459 return err460 }461 }462 return nil463}464// A vcsPath describes how to convert an import path into a465// version control system and repository name.466type vcsPath struct {467 prefix string // prefix this description applies to468 regexp *lazyregexp.Regexp // compiled pattern for import path469 repo string // repository to use (expand with match of re)470 vcs string // version control system to use (expand with match of re)471 check func(match map[string]string) error // additional checks472 schemelessRepo bool // if true, the repo pattern lacks a scheme473}474// vcsFromDir inspects dir and its parents to determine the475// version control system and code repository to use.476// On return, root is the import path477// corresponding to the root of the repository.478func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {479 // Clean and double-check that dir is in (a subdirectory of) srcRoot.480 dir = filepath.Clean(dir)481 srcRoot = filepath.Clean(srcRoot)482 if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {483 return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)484 }485 var vcsRet *vcsCmd486 var rootRet string487 origDir := dir488 for len(dir) > len(srcRoot) {489 for _, vcs := range vcsList {490 if _, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil {491 root := filepath.ToSlash(dir[len(srcRoot)+1:])492 // Record first VCS we find, but keep looking,493 // to detect mistakes like one kind of VCS inside another.494 if vcsRet == nil {495 vcsRet = vcs496 rootRet = root497 continue498 }499 // Allow .git inside .git, which can arise due to submodules.500 if vcsRet == vcs && vcs.cmd == "git" {501 continue502 }503 // Otherwise, we have one VCS inside a different VCS.504 return nil, "", fmt.Errorf("directory %q uses %s, but parent %q uses %s",505 filepath.Join(srcRoot, rootRet), vcsRet.cmd, filepath.Join(srcRoot, root), vcs.cmd)506 }507 }508 // Move to parent.509 ndir := filepath.Dir(dir)510 if len(ndir) >= len(dir) {511 // Shouldn't happen, but just in case, stop.512 break513 }514 dir = ndir515 }516 if vcsRet != nil {517 return vcsRet, rootRet, nil518 }519 return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir)520}521// checkNestedVCS checks for an incorrectly-nested VCS-inside-VCS522// situation for dir, checking parents up until srcRoot.523func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error {524 if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {525 return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)526 }527 otherDir := dir528 for len(otherDir) > len(srcRoot) {529 for _, otherVCS := range vcsList {530 if _, err := os.Stat(filepath.Join(otherDir, "."+otherVCS.cmd)); err == nil {531 // Allow expected vcs in original dir.532 if otherDir == dir && otherVCS == vcs {533 continue534 }535 // Allow .git inside .git, which can arise due to submodules.536 if otherVCS == vcs && vcs.cmd == "git" {537 continue538 }539 // Otherwise, we have one VCS inside a different VCS.540 return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.cmd, otherDir, otherVCS.cmd)541 }542 }543 // Move to parent.544 newDir := filepath.Dir(otherDir)545 if len(newDir) >= len(otherDir) {546 // Shouldn't happen, but just in case, stop.547 break548 }549 otherDir = newDir550 }551 return nil552}553// RepoRoot describes the repository root for a tree of source code.554type RepoRoot struct {555 Repo string // repository URL, including scheme556 Root string // import path corresponding to root of repo557 IsCustom bool // defined by served <meta> tags (as opposed to hard-coded pattern)558 VCS string // vcs type ("mod", "git", ...)559 vcs *vcsCmd // internal: vcs command access560}561func httpPrefix(s string) string {562 for _, prefix := range [...]string{"http:", "https:"} {563 if strings.HasPrefix(s, prefix) {564 return prefix565 }566 }567 return ""568}569// ModuleMode specifies whether to prefer modules when looking up code sources.570type ModuleMode int571const (572 IgnoreMod ModuleMode = iota573 PreferMod574)575// RepoRootForImportPath analyzes importPath to determine the576// version control system, and code repository to use.577func RepoRootForImportPath(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) {578 rr, err := repoRootFromVCSPaths(importPath, security, vcsPaths)579 if err == errUnknownSite {580 rr, err = repoRootForImportDynamic(importPath, mod, security)581 if err != nil {582 err = load.ImportErrorf(importPath, "unrecognized import path %q: %v", importPath, err)583 }584 }585 if err != nil {586 rr1, err1 := repoRootFromVCSPaths(importPath, security, vcsPathsAfterDynamic)587 if err1 == nil {588 rr = rr1589 err = nil590 }591 }592 // Should have been taken care of above, but make sure.593 if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") {594 // Do not allow wildcards in the repo root.595 rr = nil596 err = load.ImportErrorf(importPath, "cannot expand ... in %q", importPath)597 }598 return rr, err599}600var errUnknownSite = errors.New("dynamic lookup required to find mapping")601// repoRootFromVCSPaths attempts to map importPath to a repoRoot602// using the mappings defined in vcsPaths.603func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) {604 // A common error is to use https://packagepath because that's what605 // hg and git require. Diagnose this helpfully.606 if prefix := httpPrefix(importPath); prefix != "" {607 // The importPath has been cleaned, so has only one slash. The pattern608 // ignores the slashes; the error message puts them back on the RHS at least.609 return nil, fmt.Errorf("%q not allowed in import path", prefix+"//")610 }611 for _, srv := range vcsPaths {612 if !strings.HasPrefix(importPath, srv.prefix) {613 continue614 }615 m := srv.regexp.FindStringSubmatch(importPath)616 if m == nil {617 if srv.prefix != "" {618 return nil, load.ImportErrorf(importPath, "invalid %s import path %q", srv.prefix, importPath)619 }620 continue621 }622 // Build map of named subexpression matches for expand.623 match := map[string]string{624 "prefix": srv.prefix,625 "import": importPath,626 }627 for i, name := range srv.regexp.SubexpNames() {628 if name != "" && match[name] == "" {629 match[name] = m[i]630 }631 }632 if srv.vcs != "" {633 match["vcs"] = expand(match, srv.vcs)634 }635 if srv.repo != "" {636 match["repo"] = expand(match, srv.repo)637 }638 if srv.check != nil {639 if err := srv.check(match); err != nil {640 return nil, err641 }642 }643 vcs := vcsByCmd(match["vcs"])644 if vcs == nil {645 return nil, fmt.Errorf("unknown version control system %q", match["vcs"])646 }647 var repoURL string648 if !srv.schemelessRepo {649 repoURL = match["repo"]650 } else {651 scheme := vcs.scheme[0] // default to first scheme652 repo := match["repo"]653 if vcs.pingCmd != "" {654 // If we know how to test schemes, scan to find one.655 for _, s := range vcs.scheme {656 if security == web.SecureOnly && !vcs.isSecureScheme(s) {657 continue658 }659 if vcs.ping(s, repo) == nil {660 scheme = s661 break662 }663 }664 }665 repoURL = scheme + "://" + repo666 }667 rr := &RepoRoot{668 Repo: repoURL,669 Root: match["root"],670 VCS: vcs.cmd,671 vcs: vcs,672 }673 return rr, nil674 }675 return nil, errUnknownSite676}677// urlForImportPath returns a partially-populated URL for the given Go import path.678//679// The URL leaves the Scheme field blank so that web.Get will try any scheme680// allowed by the selected security mode.681func urlForImportPath(importPath string) (*urlpkg.URL, error) {682 slash := strings.Index(importPath, "/")683 if slash < 0 {684 slash = len(importPath)685 }686 host, path := importPath[:slash], importPath[slash:]687 if !strings.Contains(host, ".") {688 return nil, errors.New("import path does not begin with hostname")689 }690 if len(path) == 0 {691 path = "/"692 }693 return &urlpkg.URL{Host: host, Path: path, RawQuery: "go-get=1"}, nil694}695// repoRootForImportDynamic finds a *RepoRoot for a custom domain that's not696// statically known by repoRootForImportPathStatic.697//698// This handles custom import paths like "name.tld/pkg/foo" or just "name.tld".699func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) {700 url, err := urlForImportPath(importPath)701 if err != nil {702 return nil, err703 }704 resp, err := web.Get(security, url)705 if err != nil {706 msg := "https fetch: %v"707 if security == web.Insecure {708 msg = "http/" + msg709 }710 return nil, fmt.Errorf(msg, err)711 }712 body := resp.Body713 defer body.Close()714 imports, err := parseMetaGoImports(body, mod)715 if len(imports) == 0 {716 if respErr := resp.Err(); respErr != nil {717 // If the server's status was not OK, prefer to report that instead of718 // an XML parse error.719 return nil, respErr720 }721 }722 if err != nil {723 return nil, fmt.Errorf("parsing %s: %v", importPath, err)724 }725 // Find the matched meta import.726 mmi, err := matchGoImport(imports, importPath)727 if err != nil {728 if _, ok := err.(ImportMismatchError); !ok {729 return nil, fmt.Errorf("parse %s: %v", url, err)730 }731 return nil, fmt.Errorf("parse %s: no go-import meta tags (%s)", resp.URL, err)732 }733 if cfg.BuildV {734 log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, url)735 }736 // If the import was "uni.edu/bob/project", which said the737 // prefix was "uni.edu" and the RepoRoot was "evilroot.com",738 // make sure we don't trust Bob and check out evilroot.com to739 // "uni.edu" yet (possibly overwriting/preempting another740 // non-evil student). Instead, first verify the root and see741 // if it matches Bob's claim.742 if mmi.Prefix != importPath {743 if cfg.BuildV {744 log.Printf("get %q: verifying non-authoritative meta tag", importPath)745 }746 var imports []metaImport747 url, imports, err = metaImportsForPrefix(mmi.Prefix, mod, security)748 if err != nil {749 return nil, err750 }751 metaImport2, err := matchGoImport(imports, importPath)752 if err != nil || mmi != metaImport2 {753 return nil, fmt.Errorf("%s and %s disagree about go-import for %s", resp.URL, url, mmi.Prefix)754 }755 }756 if err := validateRepoRoot(mmi.RepoRoot); err != nil {757 return nil, fmt.Errorf("%s: invalid repo root %q: %v", resp.URL, mmi.RepoRoot, err)758 }759 vcs := vcsByCmd(mmi.VCS)760 if vcs == nil && mmi.VCS != "mod" {761 return nil, fmt.Errorf("%s: unknown vcs %q", resp.URL, mmi.VCS)762 }763 rr := &RepoRoot{764 Repo: mmi.RepoRoot,765 Root: mmi.Prefix,766 IsCustom: true,767 VCS: mmi.VCS,768 vcs: vcs,769 }770 return rr, nil771}772// validateRepoRoot returns an error if repoRoot does not seem to be773// a valid URL with scheme.774func validateRepoRoot(repoRoot string) error {775 url, err := urlpkg.Parse(repoRoot)776 if err != nil {777 return err778 }779 if url.Scheme == "" {780 return errors.New("no scheme")781 }782 if url.Scheme == "file" {783 return errors.New("file scheme disallowed")784 }785 return nil786}787var fetchGroup singleflight.Group788var (789 fetchCacheMu sync.Mutex790 fetchCache = map[string]fetchResult{} // key is metaImportsForPrefix's importPrefix791)792// metaImportsForPrefix takes a package's root import path as declared in a <meta> tag793// and returns its HTML discovery URL and the parsed metaImport lines794// found on the page.795//796// The importPath is of the form "golang.org/x/tools".797// It is an error if no imports are found.798// url will still be valid if err != nil.799// The returned url will be of the form "https://golang.org/x/tools?go-get=1"800func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.SecurityMode) (*urlpkg.URL, []metaImport, error) {801 setCache := func(res fetchResult) (fetchResult, error) {802 fetchCacheMu.Lock()803 defer fetchCacheMu.Unlock()804 fetchCache[importPrefix] = res805 return res, nil806 }807 resi, _, _ := fetchGroup.Do(importPrefix, func() (resi interface{}, err error) {808 fetchCacheMu.Lock()809 if res, ok := fetchCache[importPrefix]; ok {810 fetchCacheMu.Unlock()811 return res, nil812 }813 fetchCacheMu.Unlock()814 url, err := urlForImportPath(importPrefix)815 if err != nil {816 return setCache(fetchResult{err: err})817 }818 resp, err := web.Get(security, url)819 if err != nil {820 return setCache(fetchResult{url: url, err: fmt.Errorf("fetching %s: %v", importPrefix, err)})821 }822 body := resp.Body823 defer body.Close()824 imports, err := parseMetaGoImports(body, mod)825 if len(imports) == 0 {826 if respErr := resp.Err(); respErr != nil {827 // If the server's status was not OK, prefer to report that instead of828 // an XML parse error.829 return setCache(fetchResult{url: url, err: respErr})830 }831 }832 if err != nil {833 return setCache(fetchResult{url: url, err: fmt.Errorf("parsing %s: %v", resp.URL, err)})834 }835 if len(imports) == 0 {836 err = fmt.Errorf("fetching %s: no go-import meta tag found in %s", importPrefix, resp.URL)837 }838 return setCache(fetchResult{url: url, imports: imports, err: err})839 })840 res := resi.(fetchResult)841 return res.url, res.imports, res.err842}843type fetchResult struct {844 url *urlpkg.URL845 imports []metaImport846 err error847}848// metaImport represents the parsed <meta name="go-import"849// content="prefix vcs reporoot" /> tags from HTML files.850type metaImport struct {851 Prefix, VCS, RepoRoot string852}853// pathPrefix reports whether sub is a prefix of s,854// only considering entire path components.855func pathPrefix(s, sub string) bool {856 // strings.HasPrefix is necessary but not sufficient.857 if !strings.HasPrefix(s, sub) {858 return false859 }860 // The remainder after the prefix must either be empty or start with a slash.861 rem := s[len(sub):]862 return rem == "" || rem[0] == '/'863}864// A ImportMismatchError is returned where metaImport/s are present865// but none match our import path.866type ImportMismatchError struct {867 importPath string868 mismatches []string // the meta imports that were discarded for not matching our importPath869}870func (m ImportMismatchError) Error() string {871 formattedStrings := make([]string, len(m.mismatches))872 for i, pre := range m.mismatches {873 formattedStrings[i] = fmt.Sprintf("meta tag %s did not match import path %s", pre, m.importPath)874 }875 return strings.Join(formattedStrings, ", ")876}877// matchGoImport returns the metaImport from imports matching importPath.878// An error is returned if there are multiple matches.879// An ImportMismatchError is returned if none match.880func matchGoImport(imports []metaImport, importPath string) (metaImport, error) {881 match := -1882 errImportMismatch := ImportMismatchError{importPath: importPath}883 for i, im := range imports {884 if !pathPrefix(importPath, im.Prefix) {885 errImportMismatch.mismatches = append(errImportMismatch.mismatches, im.Prefix)886 continue887 }888 if match >= 0 {889 if imports[match].VCS == "mod" && im.VCS != "mod" {890 // All the mod entries precede all the non-mod entries.891 // We have a mod entry and don't care about the rest,892 // matching or not.893 break894 }895 return metaImport{}, fmt.Errorf("multiple meta tags match import path %q", importPath)896 }897 match = i898 }899 if match == -1 {900 return metaImport{}, errImportMismatch901 }902 return imports[match], nil903}904// expand rewrites s to replace {k} with match[k] for each key k in match.905func expand(match map[string]string, s string) string {906 // We want to replace each match exactly once, and the result of expansion907 // must not depend on the iteration order through the map.908 // A strings.Replacer has exactly the properties we're looking for.909 oldNew := make([]string, 0, 2*len(match))910 for k, v := range match {911 oldNew = append(oldNew, "{"+k+"}", v)912 }913 return strings.NewReplacer(oldNew...).Replace(s)914}915// vcsPaths defines the meaning of import paths referring to916// commonly-used VCS hosting sites (github.com/user/dir)917// and import paths referring to a fully-qualified importPath918// containing a VCS type (foo.com/repo.git/dir)919var vcsPaths = []*vcsPath{920 // Github921 {922 prefix: "github.com/",923 regexp: lazyregexp.New(`^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`),924 vcs: "git",925 repo: "https://{root}",926 check: noVCSSuffix,927 },928 // Bitbucket929 {930 prefix: "bitbucket.org/",931 regexp: lazyregexp.New(`^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),932 repo: "https://{root}",933 check: bitbucketVCS,934 },935 // IBM DevOps Services (JazzHub)936 {937 prefix: "hub.jazz.net/git/",938 regexp: lazyregexp.New(`^(?P<root>hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),939 vcs: "git",940 repo: "https://{root}",941 check: noVCSSuffix,942 },943 // Git at Apache944 {945 prefix: "git.apache.org/",946 regexp: lazyregexp.New(`^(?P<root>git\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`),947 vcs: "git",948 repo: "https://{root}",949 },950 // Git at OpenStack951 {952 prefix: "git.openstack.org/",953 regexp: lazyregexp.New(`^(?P<root>git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`),954 vcs: "git",955 repo: "https://{root}",956 },957 // chiselapp.com for fossil958 {959 prefix: "chiselapp.com/",960 regexp: lazyregexp.New(`^(?P<root>chiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`),961 vcs: "fossil",962 repo: "https://{root}",963 },964 // General syntax for any server.965 // Must be last.966 {967 regexp: lazyregexp.New(`(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`),968 schemelessRepo: true,969 },970}971// vcsPathsAfterDynamic gives additional vcsPaths entries972// to try after the dynamic HTML check.973// This gives those sites a chance to introduce <meta> tags974// as part of a graceful transition away from the hard-coded logic.975var vcsPathsAfterDynamic = []*vcsPath{976 // Launchpad. See golang.org/issue/11436.977 {978 prefix: "launchpad.net/",979 regexp: lazyregexp.New(`^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),980 vcs: "bzr",981 repo: "https://{root}",982 check: launchpadVCS,983 },984}985// noVCSSuffix checks that the repository name does not986// end in .foo for any version control system foo.987// The usual culprit is ".git".988func noVCSSuffix(match map[string]string) error {989 repo := match["repo"]990 for _, vcs := range vcsList {991 if strings.HasSuffix(repo, "."+vcs.cmd) {992 return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])993 }994 }995 return nil996}997// bitbucketVCS determines the version control system for a998// Bitbucket repository, by using the Bitbucket API.999func bitbucketVCS(match map[string]string) error {1000 if err := noVCSSuffix(match); err != nil {1001 return err1002 }1003 var resp struct {1004 SCM string `json:"scm"`1005 }1006 url := &urlpkg.URL{1007 Scheme: "https",1008 Host: "api.bitbucket.org",1009 Path: expand(match, "/2.0/repositories/{bitname}"),1010 RawQuery: "fields=scm",1011 }1012 data, err := web.GetBytes(url)1013 if err != nil {1014 if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 {1015 // this may be a private repository. If so, attempt to determine which1016 // VCS it uses. See issue 5375.1017 root := match["root"]1018 for _, vcs := range []string{"git", "hg"} {1019 if vcsByCmd(vcs).ping("https", root) == nil {1020 resp.SCM = vcs1021 break1022 }1023 }1024 }1025 if resp.SCM == "" {1026 return err1027 }1028 } else {1029 if err := json.Unmarshal(data, &resp); err != nil {1030 return fmt.Errorf("decoding %s: %v", url, err)1031 }1032 }1033 if vcsByCmd(resp.SCM) != nil {1034 match["vcs"] = resp.SCM1035 if resp.SCM == "git" {1036 match["repo"] += ".git"1037 }1038 return nil1039 }1040 return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")1041}1042// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,1043// "foo" could be a series name registered in Launchpad with its own branch,1044// and it could also be the name of a directory within the main project1045// branch one level up.1046func launchpadVCS(match map[string]string) error {1047 if match["project"] == "" || match["series"] == "" {1048 return nil1049 }1050 url := &urlpkg.URL{1051 Scheme: "https",1052 Host: "code.launchpad.net",1053 Path: expand(match, "/{project}{series}/.bzr/branch-format"),1054 }1055 _, err := web.GetBytes(url)1056 if err != nil {1057 match["root"] = expand(match, "launchpad.net/{project}")1058 match["repo"] = expand(match, "https://{root}")1059 }1060 return nil1061}...

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2type vcs struct {3}4func (v vcs) Len() int {5 return len(v.name)6}7func main() {8 v := vcs{"git"}9 fmt.Println(v.Len())10}

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import "fmt"2func main() {3 v := vcs{1, 2, 3}4 fmt.Println(v.Len())5}6import "fmt"7func main() {8 v := vcs{1, 2, 3}9 fmt.Println(v.Len())10}11import "fmt"12func main() {13 v := vcs{1, 2, 3}14 fmt.Println(v.Len())15}16import "fmt"17func main() {18 v := vcs{1, 2, 3}19 fmt.Println(v.Len())20}21import "fmt"22func main() {23 v := vcs{1, 2, 3}24 fmt.Println(v.Len())25}26import "fmt"27func main() {28 v := vcs{1, 2, 3}29 fmt.Println(v.Len())30}31import "fmt"32func main() {33 v := vcs{1, 2, 3}34 fmt.Println(v.Len())35}36import "fmt"37func main() {38 v := vcs{1, 2, 3}39 fmt.Println(v.Len())40}41import "fmt"42func main() {43 v := vcs{1, 2, 3}44 fmt.Println(v.Len())45}46import "fmt"47func main() {48 v := vcs{1, 2, 3}49 fmt.Println(v.Len())50}

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 v := vcs.Vcs{1, 2, 3, 4}4 fmt.Println(v.Len())5}6import (7func main() {8 v := vcs.Vcs{1, 2, 3, 4}9 fmt.Println(v.Len())10}

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 x = vcs.VCS{1, 2, 3}4 fmt.Println(x.Len())5}6import (7func main() {8 x = vcs.VCS{1, 2, 3}9 fmt.Println(x.Len())10}11import (12func main() {13 x = vcs.VCS{1, 2, 3}14 fmt.Println(x.Len())15}16import (17func main() {18 x = vcs.VCS{1, 2, 3}19 fmt.Println(x.Len())20}21import (22func main() {23 x = vcs.VCS{1, 2, 3}24 fmt.Println(x.Len())25}26import (27func main() {28 x = vcs.VCS{1, 2, 3}29 fmt.Println(x.Len())30}31import (32func main() {33 x = vcs.VCS{1, 2, 3}34 fmt.Println(x.Len())35}

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 v := vcs.VCS{1, 2, 3}4 fmt.Println(v.Len())5}6import (7func main() {8 v := vcs.VCS{1, 2, 3}9 fmt.Println(v.Len())10 fmt.Println(v.Len(1))11}12import (13func main() {14 v := vcs.VCS{1, 2, 3}15 fmt.Println(v.Len())16}

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 v = vcs.VCS{1, 2, 3}4 fmt.Println("Length of vcs is ", v.Len())5}6import (7func main() {8 v = vcs.VCS{1, 2, 3}9 fmt.Println("Length of vcs is ", v.Len())10}11import (12func main() {13 v = vcs.VCS{1, 2, 3}14 fmt.Println("Length of vcs is ", v.Len())15}16import (17func main() {18 v = vcs.VCS{1, 2, 3}19 fmt.Println("Length of vcs is ", v.Len())20}21import (22func main() {23 v = vcs.VCS{1, 2, 3}24 fmt.Println("Length of vcs is ", v.Len())25}26import (27func main() {28 v = vcs.VCS{1, 2, 3}29 fmt.Println("Length of vcs is ", v.Len())30}

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println(vcs.Len("Hello World"))4}5We can also import a package using its full path. For example, we can import the vcs package using its full path like this:6import (7$ go list -f '{{.ImportPath}} {{.Dir}}' github.com/username/vcs8We can also import a package using a custom name. For example, we can import the vcs package using the name myvcs like this:9import (

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 win := gwu.NewWindow("main", "GWU Example")4 vp := gwu.NewVerticalPanel()5 win.Add(vp)6 lab := gwu.NewLabel("Label")7 vp.Add(lab)8 btn := gwu.NewButton("Button")9 vp.Add(btn)10 txt := gwu.NewTextBox("Text box")11 vp.Add(txt)12 pwd := gwu.NewPasswordBox("Password box")13 vp.Add(pwd)14 txta := gwu.NewTextArea("Text area")15 vp.Add(txta)16 upl := gwu.NewFileUpload()17 vp.Add(upl)18 dd := gwu.NewDropDown("drop-down")19 dd.Add(gwu.NewOpt("opt1"))20 dd.Add(gwu.NewOpt("opt2"))21 dd.Add(gwu.NewOpt("opt3"))22 vp.Add(dd)23 cb := gwu.NewCheckBox("check box")24 vp.Add(cb)25 rb := gwu.NewRadioButton("radio button")26 vp.Add(rb)27 hp := gwu.NewHorizontalPanel()28 vp.Add(hp)29 lab2 := gwu.NewLabel("Label2")30 hp.Add(lab2)31 btn2 := gwu.NewButton("Button2")32 hp.Add(btn2)33 txt2 := gwu.NewTextBox("Text box2")34 hp.Add(txt2)35 pwd2 := gwu.NewPasswordBox("Password box2")36 hp.Add(pwd2)37 txta2 := gwu.NewTextArea("Text area2")38 hp.Add(txta2)39 upl2 := gwu.NewFileUpload()40 hp.Add(upl2)

Full Screen

Full Screen

Len

Using AI Code Generation

copy

Full Screen

1import "fmt"2import "github.com/GoLang/golang"3func main() {4 vcs = vcs{"1.0"}5 fmt.Println(vcs.Len())6}7import "fmt"8import "github.com/GoLang/golang"9func main() {10 vcs = vcs{"1.0"}11 fmt.Println(vcs.Len())12}13import "fmt"14import "github.com/GoLang/golang"15func main() {16 vcs = vcs{"1.0"}17 fmt.Println(vcs.Len())18}19import "fmt"20import "github.com/GoLang/golang"21func main() {22 vcs = vcs{"1.0"}23 fmt.Println(vcs.Len())24}25import "fmt"26import "github.com/GoLang/golang"27func main() {28 vcs = vcs{"1.0"}29 fmt.Println(vcs.Len())30}31import "fmt"32import "github.com/GoLang/golang"33func main() {34 vcs = vcs{"1.0"}35 fmt.Println(vcs.Len())36}37import "fmt"38import "github.com/GoLang/golang"39func main() {40 vcs = vcs{"1.0"}41 fmt.Println(vcs.Len())42}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful