func (r *Rule) AttrString(key string) string {
	attr, ok := r.attrs[key]
	if !ok {
		return ""
	}
	str, ok := attr.RHS.(*bzl.StringExpr)
	if !ok {
		return ""
	}
	return str.Value
}

func ( r * Rule ) AttrString ( key string ) string { attr , ok := r . attrs [ key ] if ! ok { return " " } str , ok := attr . RHS . ( * bzl . StringExpr ) if ! ok { return " " } return str . Value }

// AttrString returns the value of the named attribute if it is a scalar string.
// "" is returned if the attribute is not set or is not a string.

AttrString returns the value of the named attribute if it is a scalar string . is returned if the attribute is not set or is not a string .


func (r *Rule) AttrStrings(key string) []string {
	attr, ok := r.attrs[key]
	if !ok {
		return nil
	}
	list, ok := attr.RHS.(*bzl.ListExpr)
	if !ok {
		return nil
	}
	strs := make([]string, 0, len(list.List))
	for _, e := range list.List {
		if str, ok := e.(*bzl.StringExpr); ok {
			strs = append(strs, str.Value)
		}
	}
	return strs
}

func ( r * Rule ) AttrStrings ( key string ) [ ] string { attr , ok := r . attrs [ key ] if ! ok { return nil } list , ok := attr . RHS . ( * bzl . ListExpr ) if ! ok { return nil } strs := make ( [ ] string , 0 , len ( list . List ) ) for _ , e := range list . List { if str , ok := e . ( * bzl . StringExpr ) ; ok { strs = append ( strs , str . Value ) } } return strs }

// AttrStrings returns the string values of an attribute if it is a list.
// nil is returned if the attribute is not set or is not a list. Non-string
// values within the list won't be returned.

AttrStrings returns the string values of an attribute if it is a list . nil is returned if the attribute is not set or is not a list . Non - string values within the list won t be returned .


func (r *Rule) DelAttr(key string) {
	delete(r.attrs, key)
	r.updated = true
}

func ( r * Rule ) DelAttr ( key string ) { delete ( r . attrs , key ) r . updated = true }

// DelAttr removes the named attribute from the rule.

DelAttr removes the named attribute from the rule .


func (r *Rule) SetAttr(key string, value interface{}) {
	rhs := ExprFromValue(value)
	if attr, ok := r.attrs[key]; ok {
		attr.RHS = rhs
	} else {
		r.attrs[key] = &bzl.AssignExpr{
			LHS: &bzl.Ident{Name: key},
			RHS: rhs,
			Op:  "=",
		}
	}
	r.updated = true
}

func ( r * Rule ) SetAttr ( key string , value interface { } ) { rhs := ExprFromValue ( value ) if attr , ok := r . attrs [ key ] ; ok { attr . RHS = rhs } else { r . attrs [ key ] = & bzl . AssignExpr { LHS : & bzl . Ident { Name : key } , RHS : rhs , Op : " " , } } r . updated = true }

// SetAttr adds or replaces the named attribute with an expression produced
// by ExprFromValue.

SetAttr adds or replaces the named attribute with an expression produced by ExprFromValue .


func (r *Rule) PrivateAttrKeys() []string {
	keys := make([]string, 0, len(r.private))
	for k := range r.private {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	return keys
}

func ( r * Rule ) PrivateAttrKeys ( ) [ ] string { keys := make ( [ ] string , 0 , len ( r . private ) ) for k := range r . private { keys = append ( keys , k ) } sort . Strings ( keys ) return keys }

// PrivateAttrKeys returns a sorted list of private attribute names.

PrivateAttrKeys returns a sorted list of private attribute names .


func (r *Rule) SetPrivateAttr(key string, value interface{}) {
	r.private[key] = value
}

func ( r * Rule ) SetPrivateAttr ( key string , value interface { } ) { r . private [ key ] = value }

// SetPrivateAttr associates a value with a key. Unlike SetAttr, this value
// is not converted to a build syntax tree and will not be written to a build
// file.

SetPrivateAttr associates a value with a key . Unlike SetAttr this value is not converted to a build syntax tree and will not be written to a build file .


func (r *Rule) Insert(f *File) {
	// TODO(jayconrod): should rules always be inserted at the end? Should there
	// be some sort order?
	var stmt []bzl.Expr
	if f.function == nil {
		stmt = f.File.Stmt
	} else {
		stmt = f.function.stmt.Body
	}
	r.index = len(stmt)
	r.inserted = true
	f.Rules = append(f.Rules, r)
}

// Insert marks this statement for insertion at the end of the file. Multiple
// statements will be inserted in the order Insert is called.

Insert marks this statement for insertion at the end of the file . Multiple statements will be inserted in the order Insert is called .


func (r *Rule) IsEmpty(info KindInfo) bool {
	if info.NonEmptyAttrs == nil {
		return false
	}
	for k := range info.NonEmptyAttrs {
		if _, ok := r.attrs[k]; ok {
			return false
		}
	}
	return true
}

func ( r * Rule ) IsEmpty ( info KindInfo ) bool { if info . NonEmptyAttrs == nil { return false } for k := range info . NonEmptyAttrs { if _ , ok := r . attrs [ k ] ; ok { return false } } return true }

// IsEmpty returns true when the rule contains none of the attributes in attrs
// for its kind. attrs should contain attributes that make the rule buildable
// like srcs or deps and not descriptive attributes like name or visibility.

IsEmpty returns true when the rule contains none of the attributes in attrs for its kind . attrs should contain attributes that make the rule buildable like srcs or deps and not descriptive attributes like name or visibility .


func CheckInternalVisibility(rel, visibility string) string {
	if i := strings.LastIndex(rel, "/internal/"); i >= 0 {
		visibility = fmt.Sprintf("//%s:__subpackages__", rel[:i])
	} else if strings.HasPrefix(rel, "internal/") {
		visibility = "//:__subpackages__"
	}
	return visibility
}

func CheckInternalVisibility ( rel , visibility string ) string { if i := strings . LastIndex ( rel , " " ) ; i >= 0 { visibility = fmt . Sprintf ( " " , rel [ : i ] ) } else if strings . HasPrefix ( rel , " " ) { visibility = " " } return visibility }

// CheckInternalVisibility overrides the given visibility if the package is
// internal.

CheckInternalVisibility overrides the given visibility if the package is internal .


func New(repo, pkg, name string) Label {
	return Label{Repo: repo, Pkg: pkg, Name: name}
}

func New ( repo , pkg , name string ) Label { return Label { Repo : repo , Pkg : pkg , Name : name } }

// New constructs a new label from components.

New constructs a new label from components .


func (l Label) Rel(repo, pkg string) Label {
	if l.Relative || l.Repo != repo {
		return l
	}
	if l.Pkg == pkg {
		return Label{Name: l.Name, Relative: true}
	}
	return Label{Pkg: l.Pkg, Name: l.Name}
}

func ( l Label ) Rel ( repo , pkg string ) Label { if l . Relative || l . Repo != repo { return l } if l . Pkg == pkg { return Label { Name : l . Name , Relative : true } } return Label { Pkg : l . Pkg , Name : l . Name } }

// Rel attempts to compute a relative label from this label. If this label
// is already relative or is in a different package, this label may be
// returned unchanged.

Rel attempts to compute a relative label from this label . If this label is already relative or is in a different package this label may be returned unchanged .


func (l Label) Equal(other Label) bool {
	return l.Repo == other.Repo &&
		l.Pkg == other.Pkg &&
		l.Name == other.Name &&
		l.Relative == other.Relative
}

func ( l Label ) Equal ( other Label ) bool { return l . Repo == other . Repo && l . Pkg == other . Pkg && l . Name == other . Name && l . Relative == other . Relative }

// Equal returns whether two labels are exactly the same. It does not return
// true for different labels that refer to the same target.

Equal returns whether two labels are exactly the same . It does not return true for different labels that refer to the same target .


func (l Label) Contains(other Label) bool {
	if l.Relative {
		log.Panicf("l must not be relative: %s", l)
	}
	if other.Relative {
		log.Panicf("other must not be relative: %s", other)
	}
	result := l.Repo == other.Repo && pathtools.HasPrefix(other.Pkg, l.Pkg)
	return result
}

func ( l Label ) Contains ( other Label ) bool { if l . Relative { log . Panicf ( " " , l ) } if other . Relative { log . Panicf ( " " , other ) } result := l . Repo == other . Repo && pathtools . HasPrefix ( other . Pkg , l . Pkg ) return result }

// Contains returns whether other is contained by the package of l or a
// sub-package. Neither label may be relative.

Contains returns whether other is contained by the package of l or a sub - package . Neither label may be relative .


func generateFromPath(w io.Writer, rootPath string) error {
	return filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !strings.HasSuffix(path, ".proto") {
			return nil
		}
		relPath, err := filepath.Rel(rootPath, path)
		if err != nil || strings.HasPrefix(relPath, "..") {
			log.Panicf("file %q not in repository rootPath %q", path, rootPath)
		}
		relPath = filepath.ToSlash(relPath)

		if strings.HasPrefix(relPath, "google/api/experimental/") {
			// Special case: these protos need to be built together with protos in
			// google/api. They have the same 'option go_package'. The proto_library
			// rule requires them to be in the same Bazel package, so we don't
			// create a build file in experimental.
			packagePath := "google.golang.org/genproto/googleapis/api"
			protoLabel, goLabel := protoLabels("google/api/x", "api")
			fmt.Fprintf(w, "%s,%s,%s,%s\n", relPath, protoLabel, packagePath, goLabel)
			return nil
		}

		packagePath, packageName, err := loadGoPackage(path)
		if err != nil {
			log.Print(err)
			return nil
		}

		protoLabel, goLabel := protoLabels(relPath, packageName)

		fmt.Fprintf(w, "%s,%s,%s,%s\n", relPath, protoLabel, packagePath, goLabel)
		return nil
	})
}


func shouldCall(rel string, mode Mode, updateRels map[string]bool) bool {
	return mode != UpdateDirsMode || updateRels[rel]
}

func shouldCall ( rel string , mode Mode , updateRels map [ string ] bool ) bool { return mode != UpdateDirsMode || updateRels [ rel ] }

// shouldCall returns true if Walk should call the callback in the
// directory rel.

shouldCall returns true if Walk should call the callback in the directory rel .


func shouldUpdate(rel string, mode Mode, updateParent bool, updateRels map[string]bool) bool {
	return mode == VisitAllUpdateSubdirsMode && updateParent || updateRels[rel]
}

func shouldUpdate ( rel string , mode Mode , updateParent bool , updateRels map [ string ] bool ) bool { return mode == VisitAllUpdateSubdirsMode && updateParent || updateRels [ rel ] }

// shouldUpdate returns true if Walk should pass true to the callback's update
// parameter in the directory rel. This indicates the build file should be
// updated.

shouldUpdate returns true if Walk should pass true to the callback s update parameter in the directory rel . This indicates the build file should be updated .


func shouldVisit(rel string, mode Mode, updateRels map[string]bool) bool {
	if mode != UpdateDirsMode {
		return true
	}
	_, ok := updateRels[rel]
	return ok
}

func shouldVisit ( rel string , mode Mode , updateRels map [ string ] bool ) bool { if mode != UpdateDirsMode { return true } _ , ok := updateRels [ rel ] return ok }

// shouldVisit returns true if Walk should visit the subdirectory rel.

shouldVisit returns true if Walk should visit the subdirectory rel .


func SquashRules(src, dst *Rule, filename string) error {
	if dst.ShouldKeep() {
		return nil
	}

	for key, srcAttr := range src.attrs {
		srcValue := srcAttr.RHS
		if dstAttr, ok := dst.attrs[key]; !ok {
			dst.SetAttr(key, srcValue)
		} else if !ShouldKeep(dstAttr) {
			dstValue := dstAttr.RHS
			if squashedValue, err := squashExprs(srcValue, dstValue); err != nil {
				start, end := dstValue.Span()
				return fmt.Errorf("%s:%d.%d-%d.%d: could not squash expression", filename, start.Line, start.LineRune, end.Line, end.LineRune)
			} else {
				dst.SetAttr(key, squashedValue)
			}
		}
	}
	dst.expr.Comment().Before = append(dst.expr.Comment().Before, src.expr.Comment().Before...)
	dst.expr.Comment().Suffix = append(dst.expr.Comment().Suffix, src.expr.Comment().Suffix...)
	dst.expr.Comment().After = append(dst.expr.Comment().After, src.expr.Comment().After...)
	return nil
}

func SquashRules ( src , dst * Rule , filename string ) error { if dst . ShouldKeep ( ) { return nil } for key , srcAttr := range src . attrs { srcValue := srcAttr . RHS if dstAttr , ok := dst . attrs [ key ] ; ! ok { dst . SetAttr ( key , srcValue ) } else if ! ShouldKeep ( dstAttr ) { dstValue := dstAttr . RHS if squashedValue , err := squashExprs ( srcValue , dstValue ) ; err != nil { start , end := dstValue . Span ( ) return fmt . Errorf ( " " , filename , start . Line , start . LineRune , end . Line , end . LineRune ) } else { dst . SetAttr ( key , squashedValue ) } } } dst . expr . Comment ( ) . Before = append ( dst . expr . Comment ( ) . Before , src . expr . Comment ( ) . Before ... ) dst . expr . Comment ( ) . Suffix = append ( dst . expr . Comment ( ) . Suffix , src . expr . Comment ( ) . Suffix ... ) dst . expr . Comment ( ) . After = append ( dst . expr . Comment ( ) . After , src . expr . Comment ( ) . After ... ) return nil }

// SquashRules copies information from src into dst without discarding
// information in dst. SquashRules detects duplicate elements in lists and
// dictionaries, but it doesn't sort elements after squashing. If squashing
// fails because the expression is not understood, an error is returned,
// and neither rule is modified.

SquashRules copies information from src into dst without discarding information in dst . SquashRules detects duplicate elements in lists and dictionaries but it doesn t sort elements after squashing . If squashing fails because the expression is not understood an error is returned and neither rule is modified .


func runClient() error {
	startTime := time.Now()
	conn, err := net.Dial("unix", *socketPath)
	if err != nil {
		if err := startServer(); err != nil {
			return fmt.Errorf("error starting server: %v", err)
		}
		for retry := 0; retry < 3; retry++ {
			conn, err = net.Dial("unix", *socketPath)
			if err == nil {
				break
			}
			// Wait for server to start listening.
			time.Sleep(1 * time.Second)
		}
		if err != nil {
			return fmt.Errorf("failed to connect to server: %v", err)
		}
	}
	defer conn.Close()

	if _, err := io.Copy(os.Stderr, conn); err != nil {
		log.Print(err)
	}

	elapsedTime := time.Since(startTime)
	log.Printf("ran gazelle in %.3f s", elapsedTime.Seconds())
	return nil
}

func
runClient
(
)
error
{
startTime
:=
time
.
Now
(
)
conn
,
err
:=
net
.
Dial
(
"
"
,
*
socketPath
)
if
err
!=
{
if
err
:=
startServer
(
)
;
err
!=
{
return
fmt
.
Errorf
(
"
"
,
err
)
}
for
retry
:=
0
;
retry
<
3
;
retry
++
{
conn
,
err
=
net
.
Dial
(
"
"
,
*
socketPath
)
if
err
==
{
break
}
// Wait for server to start listening.
time
.
Sleep
(
1
*
time
.
Second
)
}
if
err
!=
{
return
fmt
.
Errorf
(
"
"
,
err
)
}
}
defer
conn
.
Close
(
)
if
_
,
err
:=
io
.
Copy
(
os
.
Stderr
,
conn
)
;
err
!=
{
log
.
Print
(
err
)
}
elapsedTime
:=
time
.
Since
(
startTime
)
log
.
Printf
(
"
"
,
elapsedTime
.
Seconds
(
)
)
return
}

// runClient performs the main work of the client. It attempts to connect
// to the server via a UNIX-domain socket. If the server is not running,
// it starts the server and tries again. The server does all the work, so
// the client just waits for the server to complete, then exits.

runClient performs the main work of the client . It attempts to connect to the server via a UNIX - domain socket . If the server is not running it starts the server and tries again . The server does all the work so the client just waits for the server to complete then exits .


func UpdateRepo(rc *RemoteCache, importPath string) (Repo, error) {
	root, name, err := rc.Root(importPath)
	if err != nil {
		return Repo{}, err
	}
	remote, vcs, err := rc.Remote(root)
	if err != nil {
		return Repo{}, err
	}
	commit, tag, err := rc.Head(remote, vcs)
	if err != nil {
		return Repo{}, err
	}
	repo := Repo{
		Name:     name,
		GoPrefix: root,
		Commit:   commit,
		Tag:      tag,
		Remote:   remote,
		VCS:      vcs,
	}
	return repo, nil
}

func UpdateRepo ( rc * RemoteCache , importPath string ) ( Repo , error ) { root , name , err := rc . Root ( importPath ) if err != nil { return Repo { } , err } remote , vcs , err := rc . Remote ( root ) if err != nil { return Repo { } , err } commit , tag , err := rc . Head ( remote , vcs ) if err != nil { return Repo { } , err } repo := Repo { Name : name , GoPrefix : root , Commit : commit , Tag : tag , Remote : remote , VCS : vcs , } return repo , nil }

// UpdateRepo returns an object describing a repository at the most recent
// commit or version tag.
//
// This function uses RemoteCache to retrieve information about the repository.
// Depending on how the RemoteCache was initialized and used earlier, some
// information may already be locally available. Frequently though, information
// will be fetched over the network, so this function may be slow.

UpdateRepo returns an object describing a repository at the most recent commit or version tag . This function uses RemoteCache to retrieve information about the repository . Depending on how the RemoteCache was initialized and used earlier some information may already be locally available . Frequently though information will be fetched over the network so this function may be slow .


func NewRemoteCache(knownRepos []Repo) (r *RemoteCache, cleanup func() error) {
	r = &RemoteCache{
		RepoRootForImportPath: vcs.RepoRootForImportPath,
		HeadCmd:               defaultHeadCmd,
		root:                  remoteCacheMap{cache: make(map[string]*remoteCacheEntry)},
		remote:                remoteCacheMap{cache: make(map[string]*remoteCacheEntry)},
		head:                  remoteCacheMap{cache: make(map[string]*remoteCacheEntry)},
		mod:                   remoteCacheMap{cache: make(map[string]*remoteCacheEntry)},
	}
	r.ModInfo = func(importPath string) (string, error) {
		return defaultModInfo(r, importPath)
	}
	for _, repo := range knownRepos {
		r.root.cache[repo.GoPrefix] = &remoteCacheEntry{
			value: rootValue{
				root: repo.GoPrefix,
				name: repo.Name,
			},
		}
		if repo.Remote != "" {
			r.remote.cache[repo.GoPrefix] = &remoteCacheEntry{
				value: remoteValue{
					remote: repo.Remote,
					vcs:    repo.VCS,
				},
			}
		}
		r.mod.cache[repo.GoPrefix] = &remoteCacheEntry{
			value: modValue{
				path:  repo.GoPrefix,
				name:  repo.Name,
				known: true,
			},
		}
	}
	return r, r.cleanup
}

func NewRemoteCache ( knownRepos [ ] Repo ) ( r * RemoteCache , cleanup func ( ) error ) { r = & RemoteCache { RepoRootForImportPath : vcs . RepoRootForImportPath , HeadCmd : defaultHeadCmd , root : remoteCacheMap { cache : make ( map [ string ] * remoteCacheEntry ) } , remote : remoteCacheMap { cache : make ( map [ string ] * remoteCacheEntry ) } , head : remoteCacheMap { cache : make ( map [ string ] * remoteCacheEntry ) } , mod : remoteCacheMap { cache : make ( map [ string ] * remoteCacheEntry ) } , } r . ModInfo = func ( importPath string ) ( string , error ) { return defaultModInfo ( r , importPath ) } for _ , repo := range knownRepos { r . root . cache [ repo . GoPrefix ] = & remoteCacheEntry { value : rootValue { root : repo . GoPrefix , name : repo . Name , } , } if repo . Remote != " " { r . remote . cache [ repo . GoPrefix ] = & remoteCacheEntry { value : remoteValue { remote : repo . Remote , vcs : repo . VCS , } , } } r . mod . cache [ repo . GoPrefix ] = & remoteCacheEntry { value : modValue { path : repo . GoPrefix , name : repo . Name , known : true , } , } } return r , r . cleanup }

// NewRemoteCache creates a new RemoteCache with a set of known repositories.
// The Root and Remote methods will return information about repositories listed
// here without accessing the network. However, the Head method will still
// access the network for these repositories to retrieve information about new
// versions.
//
// A cleanup function is also returned. The caller must call this when
// RemoteCache is no longer needed. RemoteCache may write files to a temporary
// directory. This will delete them.

NewRemoteCache creates a new RemoteCache with a set of known repositories . The Root and Remote methods will return information about repositories listed here without accessing the network . However the Head method will still access the network for these repositories to retrieve information about new versions . A cleanup function is also returned . The caller must call this when RemoteCache is no longer needed . RemoteCache may write files to a temporary directory . This will delete them .


func (r *RemoteCache) Remote(root string) (remote, vcs string, err error) {
	v, err := r.remote.ensure(root, func() (interface{}, error) {
		repo, err := r.RepoRootForImportPath(root, false)
		if err != nil {
			return nil, err
		}
		return remoteValue{remote: repo.Repo, vcs: repo.VCS.Cmd}, nil
	})
	if err != nil {
		return "", "", err
	}
	value := v.(remoteValue)
	return value.remote, value.vcs, nil
}

func ( r * RemoteCache ) Remote ( root string ) ( remote , vcs string , err error ) { v , err := r . remote . ensure ( root , func ( ) ( interface { } , error ) { repo , err := r . RepoRootForImportPath ( root , false ) if err != nil { return nil , err } return remoteValue { remote : repo . Repo , vcs : repo . VCS . Cmd } , nil } ) if err != nil { return " " , " " , err } value := v . ( remoteValue ) return value . remote , value . vcs , nil }

// Remote returns the VCS name and the remote URL for a repository with the
// given root import path. This is suitable for creating new repository rules.

Remote returns the VCS name and the remote URL for a repository with the given root import path . This is suitable for creating new repository rules .


func (m *remoteCacheMap) get(key string) (value interface{}, ok bool, err error) {
	m.mu.Lock()
	e, ok := m.cache[key]
	m.mu.Unlock()
	if !ok {
		return nil, ok, nil
	}
	if e.ready != nil {
		<-e.ready
	}
	return e.value, ok, e.err
}

func ( m * remoteCacheMap ) get ( key string ) ( value interface { } , ok bool , err error ) { m . mu . Lock ( ) e , ok := m . cache [ key ] m . mu . Unlock ( ) if ! ok { return nil , ok , nil } if e . ready != nil { <- e . ready } return e . value , ok , e . err }

// get retrieves a value associated with the given key from the cache. ok will
// be true if the key exists in the cache, even if it's in the process of
// being fetched.

get retrieves a value associated with the given key from the cache . ok will be true if the key exists in the cache even if it s in the process of being fetched .


func (m *remoteCacheMap) ensure(key string, load func() (interface{}, error)) (interface{}, error) {
	m.mu.Lock()
	e, ok := m.cache[key]
	if !ok {
		e = &remoteCacheEntry{ready: make(chan struct{})}
		m.cache[key] = e
		m.mu.Unlock()
		e.value, e.err = load()
		close(e.ready)
	} else {
		m.mu.Unlock()
		if e.ready != nil {
			<-e.ready
		}
	}
	return e.value, e.err
}

func ( m * remoteCacheMap ) ensure ( key string , load func ( ) ( interface { } , error ) ) ( interface { } , error ) { m . mu . Lock ( ) e , ok := m . cache [ key ] if ! ok { e = & remoteCacheEntry { ready : make ( chan struct { } ) } m . cache [ key ] = e m . mu . Unlock ( ) e . value , e . err = load ( ) close ( e . ready ) } else { m . mu . Unlock ( ) if e . ready != nil { <- e . ready } } return e . value , e . err }

// ensure retreives a value associated with the given key from the cache. If
// the key does not exist in the cache, the load function will be called,
// and its result will be associated with the key. The load function will not
// be called more than once for any key.

ensure retreives a value associated with the given key from the cache . If the key does not exist in the cache the load function will be called and its result will be associated with the key . The load function will not be called more than once for any key .


func RelBaseName(rel, prefix, root string) string {
	base := path.Base(rel)
	if base == "." || base == "/" {
		base = path.Base(prefix)
	}
	if base == "." || base == "/" {
		base = filepath.Base(root)
	}
	if base == "." || base == "/" {
		base = "root"
	}
	return base
}

func RelBaseName ( rel , prefix , root string ) string { base := path . Base ( rel ) if base == " " || base == " " { base = path . Base ( prefix ) } if base == " " || base == " " { base = filepath . Base ( root ) } if base == " " || base == " " { base = " " } return base }

// RelBaseName returns the base name for rel, a slash-separated path relative
// to the repository root. If rel is empty, RelBaseName returns the base name
// of prefix. If prefix is empty, RelBaseName returns the base name of root,
// the absolute file path of the repository root directory. If that's empty
// to, then RelBaseName returns "root".

RelBaseName returns the base name for rel a slash - separated path relative to the repository root . If rel is empty RelBaseName returns the base name of prefix . If prefix is empty RelBaseName returns the base name of root the absolute file path of the repository root directory . If that s empty to then RelBaseName returns root .


func (c *Config) Clone() *Config {
	cc := *c
	cc.Exts = make(map[string]interface{})
	for k, v := range c.Exts {
		cc.Exts[k] = v
	}
	cc.KindMap = make(map[string]MappedKind)
	for k, v := range c.KindMap {
		cc.KindMap[k] = v
	}
	return &cc
}

func ( c * Config ) Clone ( ) * Config { cc := * c cc . Exts = make ( map [ string ] interface { } ) for k , v := range c . Exts { cc . Exts [ k ] = v } cc . KindMap = make ( map [ string ] MappedKind ) for k , v := range c . KindMap { cc . KindMap [ k ] = v } return & cc }

// Clone creates a copy of the configuration for use in a subdirectory.
// Note that the Exts map is copied, but its contents are not.
// Configurer.Configure should do this, if needed.

Clone creates a copy of the configuration for use in a subdirectory . Note that the Exts map is copied but its contents are not . Configurer . Configure should do this if needed .


func (c *Config) IsValidBuildFileName(name string) bool {
	for _, n := range c.ValidBuildFileNames {
		if name == n {
			return true
		}
	}
	return false
}

func ( c * Config ) IsValidBuildFileName ( name string ) bool { for _ , n := range c . ValidBuildFileNames { if name == n { return true } } return false }

// IsValidBuildFileName returns true if a file with the given base name
// should be treated as a build file.

IsValidBuildFileName returns true if a file with the given base name should be treated as a build file .


func (l tagLine) check(c *config.Config, os, arch string) bool {
	if len(l) == 0 {
		return false
	}
	for _, g := range l {
		if g.check(c, os, arch) {
			return true
		}
	}
	return false
}

func ( l tagLine ) check ( c * config . Config , os , arch string ) bool { if len ( l ) == 0 { return false } for _ , g := range l { if g . check ( c , os , arch ) { return true } } return false }

// check returns true if at least one of the tag groups is satisfied.

check returns true if at least one of the tag groups is satisfied .


func fileNameInfo(path_ string) fileInfo {
	name := filepath.Base(path_)
	var ext ext
	switch path.Ext(name) {
	case ".go":
		ext = goExt
	case ".c", ".cc", ".cpp", ".cxx", ".m", ".mm":
		ext = cExt
	case ".h", ".hh", ".hpp", ".hxx":
		ext = hExt
	case ".s":
		ext = sExt
	case ".S":
		ext = csExt
	case ".proto":
		ext = protoExt
	default:
		ext = unknownExt
	}
	if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") {
		ext = unknownExt
	}

	// Determine test, goos, and goarch. This is intended to match the logic
	// in goodOSArchFile in go/build.
	var isTest bool
	var goos, goarch string
	l := strings.Split(name[:len(name)-len(path.Ext(name))], "_")
	if len(l) >= 2 && l[len(l)-1] == "test" {
		isTest = ext == goExt
		l = l[:len(l)-1]
	}
	switch {
	case len(l) >= 3 && rule.KnownOSSet[l[len(l)-2]] && rule.KnownArchSet[l[len(l)-1]]:
		goos = l[len(l)-2]
		goarch = l[len(l)-1]
	case len(l) >= 2 && rule.KnownOSSet[l[len(l)-1]]:
		goos = l[len(l)-1]
	case len(l) >= 2 && rule.KnownArchSet[l[len(l)-1]]:
		goarch = l[len(l)-1]
	}

	return fileInfo{
		path:   path_,
		name:   name,
		ext:    ext,
		isTest: isTest,
		goos:   goos,
		goarch: goarch,
	}
}

// fileNameInfo returns information that can be inferred from the name of
// a file. It does not read data from the file.

fileNameInfo returns information that can be inferred from the name of a file . It does not read data from the file .


func otherFileInfo(path string) fileInfo {
	info := fileNameInfo(path)
	if info.ext == unknownExt {
		return info
	}

	tags, err := readTags(info.path)
	if err != nil {
		log.Printf("%s: error reading file: %v", info.path, err)
		return info
	}
	info.tags = tags
	return info
}

func otherFileInfo ( path string ) fileInfo { info := fileNameInfo ( path ) if info . ext == unknownExt { return info } tags , err := readTags ( info . path ) if err != nil { log . Printf ( " " , info . path , err ) return info } info . tags = tags return info }

// otherFileInfo returns information about a non-.go file. It will parse
// part of the file to determine build tags. If the file can't be read, an
// error will be logged, and partial information will be returned.

otherFileInfo returns information about a non - . go file . It will parse part of the file to determine build tags . If the file can t be read an error will be logged and partial information will be returned .


func protoFileInfo(path_ string, protoInfo proto.FileInfo) fileInfo {
	info := fileNameInfo(path_)

	// Look for "option go_package".  If there's no / in the package option, then
	// it's just a simple package name, not a full import path.
	for _, opt := range protoInfo.Options {
		if opt.Key != "go_package" {
			continue
		}
		if strings.LastIndexByte(opt.Value, '/') == -1 {
			info.packageName = opt.Value
		} else {
			if i := strings.LastIndexByte(opt.Value, ';'); i != -1 {
				info.importPath = opt.Value[:i]
				info.packageName = opt.Value[i+1:]
			} else {
				info.importPath = opt.Value
				info.packageName = path.Base(opt.Value)
			}
		}
	}

	// Set the Go package name from the proto package name if there was no
	// option go_package.
	if info.packageName == "" && protoInfo.PackageName != "" {
		info.packageName = strings.Replace(protoInfo.PackageName, ".", "_", -1)
	}

	info.imports = protoInfo.Imports
	info.hasServices = protoInfo.HasServices
	return info
}

// protoFileInfo extracts metadata from a proto file. The proto extension
// already "parses" these and stores metadata in proto.FileInfo, so this is
// just processing relevant options.

protoFileInfo extracts metadata from a proto file . The proto extension already parses these and stores metadata in proto . FileInfo so this is just processing relevant options .


func (ix *RuleIndex) AddRule(c *config.Config, r *rule.Rule, f *rule.File) {
	var imps []ImportSpec
	if rslv := ix.mrslv(r, f.Pkg); rslv != nil {
		imps = rslv.Imports(c, r, f)
	}
	// If imps == nil, the rule is not importable. If imps is the empty slice,
	// it may still be importable if it embeds importable libraries.
	if imps == nil {
		return
	}

	record := &ruleRecord{
		rule:       r,
		label:      label.New(c.RepoName, f.Pkg, r.Name()),
		file:       f,
		importedAs: imps,
	}
	if _, ok := ix.labelMap[record.label]; ok {
		log.Printf("multiple rules found with label %s", record.label)
		return
	}
	ix.rules = append(ix.rules, record)
	ix.labelMap[record.label] = record
}

// AddRule adds a rule r to the index. The rule will only be indexed if there
// is a known resolver for the rule's kind and Resolver.Imports returns a
// non-nil slice.
//
// AddRule may only be called before Finish.

AddRule adds a rule r to the index . The rule will only be indexed if there is a known resolver for the rule s kind and Resolver . Imports returns a non - nil slice . AddRule may only be called before Finish .


func (ix *RuleIndex) Finish() {
	for _, r := range ix.rules {
		ix.collectEmbeds(r)
	}
	ix.buildImportIndex()
}

func ( ix * RuleIndex ) Finish ( ) { for _ , r := range ix . rules { ix . collectEmbeds ( r ) } ix . buildImportIndex ( ) }

// Finish constructs the import index and performs any other necessary indexing
// actions after all rules have been added. This step is necessary because
// a rule may be indexed differently based on what rules are added later.
//
// Finish must be called after all AddRule calls and before any
// FindRulesByImport calls.

Finish constructs the import index and performs any other necessary indexing actions after all rules have been added . This step is necessary because a rule may be indexed differently based on what rules are added later . Finish must be called after all AddRule calls and before any FindRulesByImport calls .


func (ix *RuleIndex) buildImportIndex() {
	ix.importMap = make(map[ImportSpec][]*ruleRecord)
	for _, r := range ix.rules {
		if r.embedded {
			continue
		}
		indexed := make(map[ImportSpec]bool)
		for _, imp := range r.importedAs {
			if indexed[imp] {
				continue
			}
			indexed[imp] = true
			ix.importMap[imp] = append(ix.importMap[imp], r)
		}
	}
}

func ( ix * RuleIndex ) buildImportIndex ( ) { ix . importMap = make ( map [ ImportSpec ] [ ] * ruleRecord ) for _ , r := range ix . rules { if r . embedded { continue } indexed := make ( map [ ImportSpec ] bool ) for _ , imp := range r . importedAs { if indexed [ imp ] { continue } indexed [ imp ] = true ix . importMap [ imp ] = append ( ix . importMap [ imp ] , r ) } } }

// buildImportIndex constructs the map used by FindRulesByImport.

buildImportIndex constructs the map used by FindRulesByImport .


func (r FindResult) IsSelfImport(from label.Label) bool {
	if from.Equal(r.Label) {
		return true
	}
	for _, e := range r.Embeds {
		if from.Equal(e) {
			return true
		}
	}
	return false
}

func ( r FindResult ) IsSelfImport ( from label . Label ) bool { if from . Equal ( r . Label ) { return true } for _ , e := range r . Embeds { if from . Equal ( e ) { return true } } return false }

// IsSelfImport returns true if the result's label matches the given label
// or the result's rule transitively embeds the rule with the given label.
// Self imports cause cyclic dependencies, so the caller may want to omit
// the dependency or report an error.

IsSelfImport returns true if the result s label matches the given label or the result s rule transitively embeds the rule with the given label . Self imports cause cyclic dependencies so the caller may want to omit the dependency or report an error .


func applyKindMappings(mappedKinds []config.MappedKind, loads []rule.LoadInfo) []rule.LoadInfo {
	if len(mappedKinds) == 0 {
		return loads
	}

	// Add new RuleInfos or replace existing ones with merged ones.
	mappedLoads := make([]rule.LoadInfo, len(loads))
	copy(mappedLoads, loads)
	for _, mappedKind := range mappedKinds {
		mappedLoads = appendOrMergeKindMapping(mappedLoads, mappedKind)
	}
	return mappedLoads
}

// applyKindMappings returns a copy of LoadInfo that includes c.KindMap.

applyKindMappings returns a copy of LoadInfo that includes c . KindMap .


func appendOrMergeKindMapping(mappedLoads []rule.LoadInfo, mappedKind config.MappedKind) []rule.LoadInfo {
	// If mappedKind.KindLoad already exists in the list, create a merged copy.
	for _, load := range mappedLoads {
		if load.Name == mappedKind.KindLoad {
			load.Symbols = append(load.Symbols, mappedKind.KindName)
			return mappedLoads
		}
	}

	// Add a new LoadInfo.
	return append(mappedLoads, rule.LoadInfo{
		Name:    mappedKind.KindLoad,
		Symbols: []string{mappedKind.KindName},
	})
}

// appendOrMergeKindMapping adds LoadInfo for the given replacement.

appendOrMergeKindMapping adds LoadInfo for the given replacement .


func RuleName(names ...string) string {
	base := "root"
	for _, name := range names {
		notIdent := func(c rune) bool {
			return !('A' <= c && c <= 'Z' ||
				'a' <= c && c <= 'z' ||
				'0' <= c && c <= '9' ||
				c == '_')
		}
		if i := strings.LastIndexFunc(name, notIdent); i >= 0 {
			name = name[i+1:]
		}
		if name != "" {
			base = name
			break
		}
	}
	return base + "_proto"
}

func RuleName ( names ... string ) string { base := " " for _ , name := range names { notIdent := func ( c rune ) bool { return ! ( 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' ) } if i := strings . LastIndexFunc ( name , notIdent ) ; i >= 0 { name = name [ i + 1 : ] } if name != " " { base = name break } } return base + " " }

// RuleName returns a name for a proto_library derived from the given strings.
// For each string, RuleName will look for a non-empty suffix of identifier
// characters and then append "_proto" to that.

RuleName returns a name for a proto_library derived from the given strings . For each string RuleName will look for a non - empty suffix of identifier characters and then append _proto to that .


func buildPackages(pc *ProtoConfig, dir, rel string, protoFiles, genFiles []string) []*Package {
	packageMap := make(map[string]*Package)
	for _, name := range protoFiles {
		info := protoFileInfo(dir, name)
		key := info.PackageName
		if pc.groupOption != "" {
			for _, opt := range info.Options {
				if opt.Key == pc.groupOption {
					key = opt.Value
					break
				}
			}
		}
		if packageMap[key] == nil {
			packageMap[key] = newPackage(info.PackageName)
		}
		packageMap[key].addFile(info)
	}

	switch pc.Mode {
	case DefaultMode:
		pkg, err := selectPackage(dir, rel, packageMap)
		if err != nil {
			log.Print(err)
		}
		if pkg == nil {
			return nil // empty rule created in generateEmpty
		}
		for _, name := range genFiles {
			pkg.addGenFile(dir, name)
		}
		return []*Package{pkg}

	case PackageMode:
		pkgs := make([]*Package, 0, len(packageMap))
		for _, pkg := range packageMap {
			pkgs = append(pkgs, pkg)
		}
		return pkgs

	default:
		return nil
	}
}

func
buildPackages
(
pc
*
ProtoConfig
,
dir
,
rel
string
,
protoFiles
,
genFiles
[
]
string
)
[
]
*
Package
{
packageMap
:=
make
(
map
[
string
]
*
Package
)
for
_
,
name
:=
range
protoFiles
{
info
:=
protoFileInfo
(
dir
,
name
)
key
:=
info
.
PackageName
if
pc
.
groupOption
!=
"
"
{
for
_
,
opt
:=
range
info
.
Options
{
if
opt
.
Key
==
pc
.
groupOption
{
key
=
opt
.
Value
break
}
}
}
if
packageMap
[
key
]
==
{
packageMap
[
key
]
=
newPackage
(
info
.
PackageName
)
}
packageMap
[
key
]
.
addFile
(
info
)
}
switch
pc
.
Mode
{
case
DefaultMode
:
pkg
,
err
:=
selectPackage
(
dir
,
rel
,
packageMap
)
if
err
!=
{
log
.
Print
(
err
)
}
if
pkg
==
{
return
// empty rule created in generateEmpty
}
for
_
,
name
:=
range
genFiles
{
pkg
.
addGenFile
(
dir
,
name
)
}
return
[
]
*
Package
{
pkg
}
case
PackageMode
:
pkgs
:=
make
(
[
]
*
Package
,
0
,
len
(
packageMap
)
)
for
_
,
pkg
:=
range
packageMap
{
pkgs
=
append
(
pkgs
,
pkg
)
}
return
pkgs
default
:
return
}
}

// buildPackage extracts metadata from the .proto files in a directory and
// constructs possibly several packages, then selects a package to generate
// a proto_library rule for.

buildPackage extracts metadata from the . proto files in a directory and constructs possibly several packages then selects a package to generate a proto_library rule for .


func selectPackage(dir, rel string, packageMap map[string]*Package) (*Package, error) {
	if len(packageMap) == 0 {
		return nil, nil
	}
	if len(packageMap) == 1 {
		for _, pkg := range packageMap {
			return pkg, nil
		}
	}
	defaultPackageName := strings.Replace(rel, "/", "_", -1)
	for _, pkg := range packageMap {
		if pkgName := goPackageName(pkg); pkgName != "" && pkgName == defaultPackageName {
			return pkg, nil
		}
	}
	return nil, fmt.Errorf("%s: directory contains multiple proto packages. Gazelle can only generate a proto_library for one package.", dir)
}

func selectPackage ( dir , rel string , packageMap map [ string ] * Package ) ( * Package , error ) { if len ( packageMap ) == 0 { return nil , nil } if len ( packageMap ) == 1 { for _ , pkg := range packageMap { return pkg , nil } } defaultPackageName := strings . Replace ( rel , " " , " " , - 1 ) for _ , pkg := range packageMap { if pkgName := goPackageName ( pkg ) ; pkgName != " " && pkgName == defaultPackageName { return pkg , nil } } return nil , fmt . Errorf ( " " , dir ) }

// selectPackage chooses a package to generate rules for.

selectPackage chooses a package to generate rules for .


func generateProto(pc *ProtoConfig, rel string, pkg *Package, shouldSetVisibility bool) *rule.Rule {
	var name string
	if pc.Mode == DefaultMode {
		name = RuleName(goPackageName(pkg), pc.GoPrefix, rel)
	} else {
		name = RuleName(pkg.Options[pc.groupOption], pkg.Name, rel)
	}
	r := rule.NewRule("proto_library", name)
	srcs := make([]string, 0, len(pkg.Files))
	for f := range pkg.Files {
		srcs = append(srcs, f)
	}
	sort.Strings(srcs)
	if len(srcs) > 0 {
		r.SetAttr("srcs", srcs)
	}
	r.SetPrivateAttr(PackageKey, *pkg)
	imports := make([]string, 0, len(pkg.Imports))
	for i := range pkg.Imports {
		imports = append(imports, i)
	}
	sort.Strings(imports)
	// NOTE: This attribute should not be used outside this extension. It's still
	// convenient for testing though.
	r.SetPrivateAttr(config.GazelleImportsKey, imports)
	for k, v := range pkg.Options {
		r.SetPrivateAttr(k, v)
	}
	if shouldSetVisibility {
		vis := rule.CheckInternalVisibility(rel, "//visibility:public")
		r.SetAttr("visibility", []string{vis})
	}
	if pc.stripImportPrefix != "" {
		r.SetAttr("strip_import_prefix", pc.stripImportPrefix)
	}
	if pc.importPrefix != "" {
		r.SetAttr("import_prefix", pc.importPrefix)
	}
	return r
}

// generateProto creates a new proto_library rule for a package. The rule may
// be empty if there are no sources.

generateProto creates a new proto_library rule for a package . The rule may be empty if there are no sources .


func generateEmpty(f *rule.File, regularFiles, genFiles []string) []*rule.Rule {
	if f == nil {
		return nil
	}
	knownFiles := make(map[string]bool)
	for _, f := range regularFiles {
		knownFiles[f] = true
	}
	for _, f := range genFiles {
		knownFiles[f] = true
	}
	var empty []*rule.Rule
outer:
	for _, r := range f.Rules {
		if r.Kind() != "proto_library" {
			continue
		}
		srcs := r.AttrStrings("srcs")
		if len(srcs) == 0 && r.Attr("srcs") != nil {
			// srcs is not a string list; leave it alone
			continue
		}
		for _, src := range r.AttrStrings("srcs") {
			if knownFiles[src] {
				continue outer
			}
		}
		empty = append(empty, rule.NewRule("proto_library", r.Name()))
	}
	return empty
}

// generateEmpty generates a list of proto_library rules that may be deleted.
// This is generated from existing proto_library rules with srcs lists that
// don't match any static or generated files.

generateEmpty generates a list of proto_library rules that may be deleted . This is generated from existing proto_library rules with srcs lists that don t match any static or generated files .


func ImportRepoRules(filename string, repoCache *RemoteCache) ([]*rule.Rule, error) {
	format := getLockFileFormat(filename)
	if format == unknownFormat {
		return nil, fmt.Errorf(`%s: unrecognized lock file format. Expected "Gopkg.lock", "go.mod", or "Godeps.json"`, filename)
	}
	parser := lockFileParsers[format]
	repos, err := parser(filename, repoCache)
	if err != nil {
		return nil, fmt.Errorf("error parsing %q: %v", filename, err)
	}
	sort.Stable(byName(repos))

	rules := make([]*rule.Rule, 0, len(repos))
	for _, repo := range repos {
		rules = append(rules, GenerateRule(repo))
	}
	return rules, nil
}

// ImportRepoRules reads the lock file of a vendoring tool and returns
// a list of equivalent repository rules that can be merged into a WORKSPACE
// file. The format of the file is inferred from its basename.

ImportRepoRules reads the lock file of a vendoring tool and returns a list of equivalent repository rules that can be merged into a WORKSPACE file . The format of the file is inferred from its basename .


func MergeRules(genRules []*rule.Rule, existingRules map[*rule.File][]string, destFile *rule.File, kinds map[string]rule.KindInfo) []*rule.File {
	sort.Stable(byRuleName(genRules))

	repoMap := make(map[string]*rule.File)
	for file, repoNames := range existingRules {
		if file.Path == destFile.Path && file.MacroName() != "" && file.MacroName() == destFile.MacroName() {
			file = destFile
		}
		for _, name := range repoNames {
			repoMap[name] = file
		}
	}

	rulesByFile := make(map[*rule.File][]*rule.Rule)
	for _, rule := range genRules {
		dest := destFile
		if file, ok := repoMap[rule.Name()]; ok {
			dest = file
		}
		rulesByFile[dest] = append(rulesByFile[dest], rule)
	}

	updatedFiles := make(map[string]*rule.File)
	for f, rules := range rulesByFile {
		merger.MergeFile(f, nil, rules, merger.PreResolve, kinds)
		f.Sync()
		if uf, ok := updatedFiles[f.Path]; ok {
			uf.SyncMacroFile(f)
		} else {
			updatedFiles[f.Path] = f
		}
	}
	files := make([]*rule.File, 0, len(updatedFiles))
	for _, f := range updatedFiles {
		files = append(files, f)
	}
	return files
}

func MergeRules ( genRules [ ] * rule . Rule , existingRules map [ * rule . File ] [ ] string , destFile * rule . File , kinds map [ string ] rule . KindInfo ) [ ] * rule . File { sort . Stable ( byRuleName ( genRules ) ) repoMap := make ( map [ string ] * rule . File ) for file , repoNames := range existingRules { if file . Path == destFile . Path && file . MacroName ( ) != " " && file . MacroName ( ) == destFile . MacroName ( ) { file = destFile } for _ , name := range repoNames { repoMap [ name ] = file } } rulesByFile := make ( map [ * rule . File ] [ ] * rule . Rule ) for _ , rule := range genRules { dest := destFile if file , ok := repoMap [ rule . Name ( ) ] ; ok { dest = file } rulesByFile [ dest ] = append ( rulesByFile [ dest ] , rule ) } updatedFiles := make ( map [ string ] * rule . File ) for f , rules := range rulesByFile { merger . MergeFile ( f , nil , rules , merger . PreResolve , kinds ) f . Sync ( ) if uf , ok := updatedFiles [ f . Path ] ; ok { uf . SyncMacroFile ( f ) } else { updatedFiles [ f . Path ] = f } } files := make ( [ ] * rule . File , 0 , len ( updatedFiles ) ) for _ , f := range updatedFiles { files = append ( files , f ) } return files }

// MergeRules merges a list of generated repo rules with the already defined repo rules,
// and then updates each rule's underlying file. If the generated rule matches an existing
// one, then it inherits the file where the existing rule was defined. If the rule is new then
// its file is set as the destFile parameter. A list of the updated files is returned.

MergeRules merges a list of generated repo rules with the already defined repo rules and then updates each rule s underlying file . If the generated rule matches an existing one then it inherits the file where the existing rule was defined . If the rule is new then its file is set as the destFile parameter . A list of the updated files is returned .


func GenerateRule(repo Repo) *rule.Rule {
	r := rule.NewRule("go_repository", repo.Name)
	if repo.Commit != "" {
		r.SetAttr("commit", repo.Commit)
	}
	if repo.Tag != "" {
		r.SetAttr("tag", repo.Tag)
	}
	r.SetAttr("importpath", repo.GoPrefix)
	if repo.Remote != "" {
		r.SetAttr("remote", repo.Remote)
	}
	if repo.VCS != "" {
		r.SetAttr("vcs", repo.VCS)
	}
	if repo.Version != "" {
		r.SetAttr("version", repo.Version)
	}
	if repo.Sum != "" {
		r.SetAttr("sum", repo.Sum)
	}
	if repo.Replace != "" {
		r.SetAttr("replace", repo.Replace)
	}
	return r
}

func GenerateRule ( repo Repo ) * rule . Rule { r := rule . NewRule ( " " , repo . Name ) if repo . Commit != " " { r . SetAttr ( " " , repo . Commit ) } if repo . Tag != " " { r . SetAttr ( " " , repo . Tag ) } r . SetAttr ( " " , repo . GoPrefix ) if repo . Remote != " " { r . SetAttr ( " " , repo . Remote ) } if repo . VCS != " " { r . SetAttr ( " " , repo . VCS ) } if repo . Version != " " { r . SetAttr ( " " , repo . Version ) } if repo . Sum != " " { r . SetAttr ( " " , repo . Sum ) } if repo . Replace != " " { r . SetAttr ( " " , repo . Replace ) } return r }

// GenerateRule returns a repository rule for the given repository that can
// be written in a WORKSPACE file.

GenerateRule returns a repository rule for the given repository that can be written in a WORKSPACE file .


func FindExternalRepo(repoRoot, name string) (string, error) {
	// See https://docs.bazel.build/versions/master/output_directories.html
	// for documentation on Bazel directory layout.
	// We expect the bazel-out symlink in the workspace root directory to point to
	// <output-base>/execroot/<workspace-name>/bazel-out
	// We expect the external repository to be checked out at
	// <output-base>/external/<name>
	// Note that users can change the prefix for most of the Bazel symlinks with
	// --symlink_prefix, but this does not include bazel-out.
	externalPath := strings.Join([]string{repoRoot, "bazel-out", "..", "..", "..", "external", name}, string(os.PathSeparator))
	cleanPath, err := filepath.EvalSymlinks(externalPath)
	if err != nil {
		return "", err
	}
	st, err := os.Stat(cleanPath)
	if err != nil {
		return "", err
	}
	if !st.IsDir() {
		return "", fmt.Errorf("%s: not a directory", externalPath)
	}
	return cleanPath, nil
}

// FindExternalRepo attempts to locate the directory where Bazel has fetched
// the external repository with the given name. An error is returned if the
// repository directory cannot be located.

FindExternalRepo attempts to locate the directory where Bazel has fetched the external repository with the given name . An error is returned if the repository directory cannot be located .


func ListRepositories(workspace *rule.File) (repos []Repo, repoNamesByFile map[*rule.File][]string, err error) {
	repoNamesByFile = make(map[*rule.File][]string)
	repos, repoNamesByFile[workspace] = getRepos(workspace.Rules)
	for _, d := range workspace.Directives {
		switch d.Key {
		case "repository_macro":
			f, defName, err := parseRepositoryMacroDirective(d.Value)
			if err != nil {
				return nil, nil, err
			}
			f = filepath.Join(filepath.Dir(workspace.Path), filepath.Clean(f))
			macroFile, err := rule.LoadMacroFile(f, "", defName)
			if err != nil {
				return nil, nil, err
			}
			currRepos, names := getRepos(macroFile.Rules)
			repoNamesByFile[macroFile] = names
			repos = append(repos, currRepos...)
		}
	}

	return repos, repoNamesByFile, nil
}

func ListRepositories ( workspace * rule . File ) ( repos [ ] Repo , repoNamesByFile map [ * rule . File ] [ ] string , err error ) { repoNamesByFile = make ( map [ * rule . File ] [ ] string ) repos , repoNamesByFile [ workspace ] = getRepos ( workspace . Rules ) for _ , d := range workspace . Directives { switch d . Key { case " " : f , defName , err := parseRepositoryMacroDirective ( d . Value ) if err != nil { return nil , nil , err } f = filepath . Join ( filepath . Dir ( workspace . Path ) , filepath . Clean ( f ) ) macroFile , err := rule . LoadMacroFile ( f , " " , defName ) if err != nil { return nil , nil , err } currRepos , names := getRepos ( macroFile . Rules ) repoNamesByFile [ macroFile ] = names repos = append ( repos , currRepos ... ) } } return repos , repoNamesByFile , nil }

// ListRepositories extracts metadata about repositories declared in a
// file.

ListRepositories extracts metadata about repositories declared in a file .


func migrateLibraryEmbed(c *config.Config, f *rule.File) {
	for _, r := range f.Rules {
		if !isGoRule(r.Kind()) {
			continue
		}
		libExpr := r.Attr("library")
		if libExpr == nil || rule.ShouldKeep(libExpr) || r.Attr("embed") != nil {
			continue
		}
		r.DelAttr("library")
		r.SetAttr("embed", &bzl.ListExpr{List: []bzl.Expr{libExpr}})
	}
}

func migrateLibraryEmbed ( c * config . Config , f * rule . File ) { for _ , r := range f . Rules { if ! isGoRule ( r . Kind ( ) ) { continue } libExpr := r . Attr ( " " ) if libExpr == nil || rule . ShouldKeep ( libExpr ) || r . Attr ( " " ) != nil { continue } r . DelAttr ( " " ) r . SetAttr ( " " , & bzl . ListExpr { List : [ ] bzl . Expr { libExpr } } ) } }

// migrateLibraryEmbed converts "library" attributes to "embed" attributes,
// preserving comments. This only applies to Go rules, and only if there is
// no keep comment on "library" and no existing "embed" attribute.

migrateLibraryEmbed converts library attributes to embed attributes preserving comments . This only applies to Go rules and only if there is no keep comment on library and no existing embed attribute .


func migrateGrpcCompilers(c *config.Config, f *rule.File) {
	for _, r := range f.Rules {
		if r.Kind() != "go_grpc_library" || r.ShouldKeep() || r.Attr("compilers") != nil {
			continue
		}
		r.SetKind("go_proto_library")
		r.SetAttr("compilers", []string{grpcCompilerLabel})
	}
}

func migrateGrpcCompilers ( c * config . Config , f * rule . File ) { for _ , r := range f . Rules { if r . Kind ( ) != " " || r . ShouldKeep ( ) || r . Attr ( " " ) != nil { continue } r . SetKind ( " " ) r . SetAttr ( " " , [ ] string { grpcCompilerLabel } ) } }

// migrateGrpcCompilers converts "go_grpc_library" rules into "go_proto_library"
// rules with a "compilers" attribute.

migrateGrpcCompilers converts go_grpc_library rules into go_proto_library rules with a compilers attribute .


func squashCgoLibrary(c *config.Config, f *rule.File) {
	// Find the default cgo_library and go_library rules.
	var cgoLibrary, goLibrary *rule.Rule
	for _, r := range f.Rules {
		if r.Kind() == "cgo_library" && r.Name() == "cgo_default_library" && !r.ShouldKeep() {
			if cgoLibrary != nil {
				log.Printf("%s: when fixing existing file, multiple cgo_library rules with default name found", f.Path)
				continue
			}
			cgoLibrary = r
			continue
		}
		if r.Kind() == "go_library" && r.Name() == defaultLibName {
			if goLibrary != nil {
				log.Printf("%s: when fixing existing file, multiple go_library rules with default name referencing cgo_library found", f.Path)
			}
			goLibrary = r
			continue
		}
	}

	if cgoLibrary == nil {
		return
	}
	if !c.ShouldFix {
		log.Printf("%s: cgo_library is deprecated. Run 'gazelle fix' to squash with go_library.", f.Path)
		return
	}

	if goLibrary == nil {
		cgoLibrary.SetKind("go_library")
		cgoLibrary.SetName(defaultLibName)
		cgoLibrary.SetAttr("cgo", true)
		return
	}

	if err := rule.SquashRules(cgoLibrary, goLibrary, f.Path); err != nil {
		log.Print(err)
		return
	}
	goLibrary.DelAttr("embed")
	goLibrary.SetAttr("cgo", true)
	cgoLibrary.Delete()
}

// squashCgoLibrary removes cgo_library rules with the default name and
// merges their attributes with go_library with the default name. If no
// go_library rule exists, a new one will be created.
//
// Note that the library attribute is disregarded, so cgo_library and
// go_library attributes will be squashed even if the cgo_library was unlinked.
// MergeFile will remove unused values and attributes later.

squashCgoLibrary removes cgo_library rules with the default name and merges their attributes with go_library with the default name . If no go_library rule exists a new one will be created . Note that the library attribute is disregarded so cgo_library and go_library attributes will be squashed even if the cgo_library was unlinked . MergeFile will remove unused values and attributes later .


func removeLegacyProto(c *config.Config, f *rule.File) {
	// Don't fix if the proto mode was set to something other than the default.
	if pcMode := getProtoMode(c); pcMode != proto.DefaultMode {
		return
	}

	// Scan for definitions to delete.
	var protoLoads []*rule.Load
	for _, l := range f.Loads {
		if l.Name() == "@io_bazel_rules_go//proto:go_proto_library.bzl" {
			protoLoads = append(protoLoads, l)
		}
	}
	var protoFilegroups, protoRules []*rule.Rule
	for _, r := range f.Rules {
		if r.Kind() == "filegroup" && r.Name() == legacyProtoFilegroupName {
			protoFilegroups = append(protoFilegroups, r)
		}
		if r.Kind() == "go_proto_library" {
			protoRules = append(protoRules, r)
		}
	}
	if len(protoLoads)+len(protoFilegroups) == 0 {
		return
	}
	if !c.ShouldFix {
		log.Printf("%s: go_proto_library.bzl is deprecated. Run 'gazelle fix' to replace old rules.", f.Path)
		return
	}

	// Delete legacy proto loads and filegroups. Only delete go_proto_library
	// rules if we deleted a load.
	for _, l := range protoLoads {
		l.Delete()
	}
	for _, r := range protoFilegroups {
		r.Delete()
	}
	if len(protoLoads) > 0 {
		for _, r := range protoRules {
			r.Delete()
		}
	}
}

// removeLegacyProto removes uses of the old proto rules. It deletes loads
// from go_proto_library.bzl. It deletes proto filegroups. It removes
// go_proto_library attributes which are no longer recognized. New rules
// are generated in place of the deleted rules, but attributes and comments
// are not migrated.

removeLegacyProto removes uses of the old proto rules . It deletes loads from go_proto_library . bzl . It deletes proto filegroups . It removes go_proto_library attributes which are no longer recognized . New rules are generated in place of the deleted rules but attributes and comments are not migrated .


func removeLegacyGazelle(c *config.Config, f *rule.File) {
	for _, l := range f.Loads {
		if l.Name() == "@io_bazel_rules_go//go:def.bzl" && l.Has("gazelle") {
			l.Remove("gazelle")
			if l.IsEmpty() {
				l.Delete()
			}
		}
	}
}

func removeLegacyGazelle ( c * config . Config , f * rule . File ) { for _ , l := range f . Loads { if l . Name ( ) == " " && l . Has ( " " ) { l . Remove ( " " ) if l . IsEmpty ( ) { l . Delete ( ) } } } }

// removeLegacyGazelle removes loads of the "gazelle" macro from
// @io_bazel_rules_go//go:def.bzl. The definition has moved to
// @bazel_gazelle//:def.bzl, and the old one will be deleted soon.

removeLegacyGazelle removes loads of the gazelle macro from


func selectPackage(c *config.Config, dir string, packageMap map[string]*goPackage) (*goPackage, error) {
	buildablePackages := make(map[string]*goPackage)
	for name, pkg := range packageMap {
		if pkg.isBuildable(c) {
			buildablePackages[name] = pkg
		}
	}

	if len(buildablePackages) == 0 {
		return nil, &build.NoGoError{Dir: dir}
	}

	if len(buildablePackages) == 1 {
		for _, pkg := range buildablePackages {
			return pkg, nil
		}
	}

	if pkg, ok := buildablePackages[defaultPackageName(c, dir)]; ok {
		return pkg, nil
	}

	err := &build.MultiplePackageError{Dir: dir}
	for name, pkg := range buildablePackages {
		// Add the first file for each package for the error message.
		// Error() method expects these lists to be the same length. File
		// lists must be non-empty. These lists are only created by
		// buildPackage for packages with .go files present.
		err.Packages = append(err.Packages, name)
		err.Files = append(err.Files, pkg.firstGoFile())
	}
	return nil, err
}

// selectPackages selects one Go packages out of the buildable packages found
// in a directory. If multiple packages are found, it returns the package
// whose name matches the directory if such a package exists.

selectPackages selects one Go packages out of the buildable packages found in a directory . If multiple packages are found it returns the package whose name matches the directory if such a package exists .


func (mr *metaResolver) AddBuiltin(kindName string, resolver resolve.Resolver) {
	mr.builtins[kindName] = resolver
}

func ( mr * metaResolver ) AddBuiltin ( kindName string , resolver resolve . Resolver ) { mr . builtins [ kindName ] = resolver }

// AddBuiltin registers a builtin kind with its info.

AddBuiltin registers a builtin kind with its info .


func (mr *metaResolver) MappedKind(pkgRel string, kind config.MappedKind) {
	mr.mappedKinds[pkgRel] = append(mr.mappedKinds[pkgRel], kind)
}

func ( mr * metaResolver ) MappedKind ( pkgRel string , kind config . MappedKind ) { mr . mappedKinds [ pkgRel ] = append ( mr . mappedKinds [ pkgRel ] , kind ) }

// MappedKind records the fact that the given mapping was applied while
// processing the given package.

MappedKind records the fact that the given mapping was applied while processing the given package .


func (mr metaResolver) Resolver(r *rule.Rule, pkgRel string) resolve.Resolver {
	for _, mappedKind := range mr.mappedKinds[pkgRel] {
		if mappedKind.KindName == r.Kind() {
			return mr.builtins[mappedKind.FromKind]
		}
	}
	return mr.builtins[r.Kind()]
}

func ( mr metaResolver ) Resolver ( r * rule . Rule , pkgRel string ) resolve . Resolver { for _ , mappedKind := range mr . mappedKinds [ pkgRel ] { if mappedKind . KindName == r . Kind ( ) { return mr . builtins [ mappedKind . FromKind ] } } return mr . builtins [ r . Kind ( ) ] }

// Resolver returns a resolver for the given rule and package, and a bool
// indicating whether one was found. Empty string may be passed for pkgRel,
// which results in consulting the builtin kinds only.

Resolver returns a resolver for the given rule and package and a bool indicating whether one was found . Empty string may be passed for pkgRel which results in consulting the builtin kinds only .


func sortExprLabels(e bzl.Expr, _ []bzl.Expr) {
	list, ok := e.(*bzl.ListExpr)
	if !ok || len(list.List) == 0 {
		return
	}

	keys := make([]stringSortKey, len(list.List))
	for i, elem := range list.List {
		s, ok := elem.(*bzl.StringExpr)
		if !ok {
			return // don't sort lists unless all elements are strings
		}
		keys[i] = makeSortKey(i, s)
	}

	before := keys[0].x.Comment().Before
	keys[0].x.Comment().Before = nil
	sort.Sort(byStringExpr(keys))
	keys[0].x.Comment().Before = append(before, keys[0].x.Comment().Before...)
	for i, k := range keys {
		list.List[i] = k.x
	}
}

// sortExprLabels sorts lists of strings using the same order as buildifier.
// Buildifier also sorts string lists, but not those involved with "select"
// expressions. This function is intended to be used with bzl.Walk.

sortExprLabels sorts lists of strings using the same order as buildifier . Buildifier also sorts string lists but not those involved with select expressions . This function is intended to be used with bzl . Walk .


func checkRulesGoVersion(repoRoot string) {
	const message = `Gazelle may not be compatible with this version of rules_go.
Update io_bazel_rules_go to a newer version in your WORKSPACE file.`

	rulesGoPath, err := repo.FindExternalRepo(repoRoot, config.RulesGoRepoName)
	if err != nil {
		return
	}
	defBzlPath := filepath.Join(rulesGoPath, "go", "def.bzl")
	defBzlContent, err := ioutil.ReadFile(defBzlPath)
	if err != nil {
		return
	}
	versionRe := regexp.MustCompile(`(?m)^RULES_GO_VERSION = ['"]([0-9.]*)['"]`)
	match := versionRe.FindSubmatch(defBzlContent)
	if match == nil {
		log.Printf("RULES_GO_VERSION not found in @%s//go:def.bzl.\n%s", config.RulesGoRepoName, message)
		return
	}
	vstr := string(match[1])
	v, err := version.ParseVersion(vstr)
	if err != nil {
		log.Printf("RULES_GO_VERSION %q could not be parsed in @%s//go:def.bzl.\n%s", vstr, config.RulesGoRepoName, message)
	}
	if v.Compare(minimumRulesGoVersion) < 0 {
		log.Printf("Found RULES_GO_VERSION %s. Minimum compatible version is %s.\n%s", v, minimumRulesGoVersion, message)
	}
}

// checkRulesGoVersion checks whether a compatible version of rules_go is
// being used in the workspace. A message will be logged if an incompatible
// version is found.
//
// Note that we can't always determine the version of rules_go in use. Also,
// if we find an incompatible version, we shouldn't bail out since the
// incompatibility may not matter in the current workspace.

checkRulesGoVersion checks whether a compatible version of rules_go is being used in the workspace . A message will be logged if an incompatible version is found . Note that we can t always determine the version of rules_go in use . Also if we find an incompatible version we shouldn t bail out since the incompatibility may not matter in the current workspace .


func (gc *goConfig) preprocessTags() {
	if gc.genericTags == nil {
		gc.genericTags = make(map[string]bool)
	}
	gc.genericTags["gc"] = true
}

func ( gc * goConfig ) preprocessTags ( ) { if gc . genericTags == nil { gc . genericTags = make ( map [ string ] bool ) } gc . genericTags [ " " ] = true }

// preprocessTags adds some tags which are on by default before they are
// used to match files.

preprocessTags adds some tags which are on by default before they are used to match files .


func (gc *goConfig) setBuildTags(tags string) error {
	if tags == "" {
		return nil
	}
	for _, t := range strings.Split(tags, ",") {
		if strings.HasPrefix(t, "!") {
			return fmt.Errorf("build tags can't be negated: %s", t)
		}
		gc.genericTags[t] = true
	}
	return nil
}

func ( gc * goConfig ) setBuildTags ( tags string ) error { if tags == " " { return nil } for _ , t := range strings . Split ( tags , " " ) { if strings . HasPrefix ( t , " " ) { return fmt . Errorf ( " " , t ) } gc . genericTags [ t ] = true } return nil }

// setBuildTags sets genericTags by parsing as a comma separated list. An
// error will be returned for tags that wouldn't be recognized by "go build".
// preprocessTags should be called before this.

setBuildTags sets genericTags by parsing as a comma separated list . An error will be returned for tags that wouldn t be recognized by go build . preprocessTags should be called before this .


func splitValue(value string) []string {
	parts := strings.Split(value, ",")
	values := make([]string, 0, len(parts))
	for _, part := range parts {
		values = append(values, strings.TrimSpace(part))
	}
	return values
}

func splitValue ( value string ) [ ] string { parts := strings . Split ( value , " " ) values := make ( [ ] string , 0 , len ( parts ) ) for _ , part := range parts { values = append ( values , strings . TrimSpace ( part ) ) } return values }

// splitDirective splits a comma-separated directive value into its component
// parts, trimming each of any whitespace characters.

splitDirective splits a comma - separated directive value into its component parts trimming each of any whitespace characters .


func copyGoModToTemp(filename string) (tempDir string, err error) {
	goModOrig, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer goModOrig.Close()

	tempDir, err = ioutil.TempDir("", "gazelle-temp-gomod")
	if err != nil {
		return "", err
	}

	goModCopy, err := os.Create(filepath.Join(tempDir, "go.mod"))
	if err != nil {
		os.Remove(tempDir)
		return "", err
	}
	defer func() {
		if cerr := goModCopy.Close(); err == nil && cerr != nil {
			err = cerr
		}
	}()

	_, err = io.Copy(goModCopy, goModOrig)
	if err != nil {
		os.RemoveAll(tempDir)
		return "", err
	}
	return tempDir, err
}

func copyGoModToTemp ( filename string ) ( tempDir string , err error ) { goModOrig , err := os . Open ( filename ) if err != nil { return " " , err } defer goModOrig . Close ( ) tempDir , err = ioutil . TempDir ( " " , " " ) if err != nil { return " " , err } goModCopy , err := os . Create ( filepath . Join ( tempDir , " " ) ) if err != nil { os . Remove ( tempDir ) return " " , err } defer func ( ) { if cerr := goModCopy . Close ( ) ; err == nil && cerr != nil { err = cerr } } ( ) _ , err = io . Copy ( goModCopy , goModOrig ) if err != nil { os . RemoveAll ( tempDir ) return " " , err } return tempDir , err }

// copyGoModToTemp copies to given go.mod file to a temporary directory.
// go list tends to mutate go.mod files, but gazelle shouldn't do that.

copyGoModToTemp copies to given go . mod file to a temporary directory . go list tends to mutate go . mod files but gazelle shouldn t do that .


func findGoTool() string {
	path := "go" // rely on PATH by default
	if goroot, ok := os.LookupEnv("GOROOT"); ok {
		path = filepath.Join(goroot, "bin", "go")
	}
	if runtime.GOOS == "windows" {
		path += ".exe"
	}
	return path
}

func
findGoTool
(
)
string
{
path
:=
"
"
// rely on PATH by default
if
goroot
,
ok
:=
os
.
LookupEnv
(
"
"
)
;
ok
{
path
=
filepath
.
Join
(
goroot
,
"
"
,
"
"
)
}
if
runtime
.
GOOS
==
"
"
{
path
+=
"
"
}
return
path
}

// findGoTool attempts to locate the go executable. If GOROOT is set, we'll
// prefer the one in there; otherwise, we'll rely on PATH. If the wrapper
// script generated by the gazelle rule is invoked by Bazel, it will set
// GOROOT to the configured SDK. We don't want to rely on the host SDK in
// that situation.

findGoTool attempts to locate the go executable . If GOROOT is set we ll prefer the one in there ; otherwise we ll rely on PATH . If the wrapper script generated by the gazelle rule is invoked by Bazel it will set GOROOT to the configured SDK . We don t want to rely on the host SDK in that situation .


func (pkg *goPackage) isBuildable(c *config.Config) bool {
	return pkg.firstGoFile() != "" || !pkg.proto.sources.isEmpty()
}

func ( pkg * goPackage ) isBuildable ( c * config . Config ) bool { return pkg . firstGoFile ( ) != " " || ! pkg . proto . sources . isEmpty ( ) }

// isBuildable returns true if anything in the package is buildable.
// This is true if the package has Go code that satisfies build constraints
// on any platform or has proto files not in legacy mode.

isBuildable returns true if anything in the package is buildable . This is true if the package has Go code that satisfies build constraints on any platform or has proto files not in legacy mode .


func startServer() error {
	exe, err := os.Executable()
	if err != nil {
		return err
	}
	args := []string{"-server"}
	args = append(args, os.Args[1:]...)
	cmd := exec.Command(exe, args...)
	log.Printf("starting server: %s", strings.Join(cmd.Args, " "))
	if err := cmd.Start(); err != nil {
		return err
	}
	if err := cmd.Process.Release(); err != nil {
		return err
	}
	return nil
}

func startServer ( ) error { exe , err := os . Executable ( ) if err != nil { return err } args := [ ] string { " " } args = append ( args , os . Args [ 1 : ] ... ) cmd := exec . Command ( exe , args ... ) log . Printf ( " " , strings . Join ( cmd . Args , " " ) ) if err := cmd . Start ( ) ; err != nil { return err } if err := cmd . Process . Release ( ) ; err != nil { return err } return nil }

// startServer starts a new server process. This is called by the client.

startServer starts a new server process . This is called by the client .


func watchDir(root string, record func(string)) (cancel func(), err error) {
	w, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}

	dirs, errs := listDirs(root)
	for _, err := range errs {
		log.Print(err)
	}
	gitDir := filepath.Join(root, ".git")
	for _, dir := range dirs {
		if dir == gitDir {
			continue
		}
		if err := w.Add(dir); err != nil {
			log.Print(err)
		}
	}

	done := make(chan struct{})
	go func() {
		for {
			select {
			case ev := <-w.Events:
				if shouldIgnore(ev.Name) {
					continue
				}
				if ev.Op == fsnotify.Create {
					if st, err := os.Lstat(ev.Name); err != nil {
						log.Print(err)
					} else if st.IsDir() {
						dirs, errs := listDirs(ev.Name)
						for _, err := range errs {
							log.Print(err)
						}
						for _, dir := range dirs {
							if err := w.Add(dir); err != nil {
								log.Print(err)
							}
							recordWrite(dir)
						}
					}
				} else {
					recordWrite(filepath.Dir(ev.Name))
				}
			case err := <-w.Errors:
				log.Print(err)
			case <-done:
				if err := w.Close(); err != nil {
					log.Print(err)
				}
				return
			}
		}
	}()
	return func() { close(done) }, nil
}

func watchDir ( root string , record func ( string ) ) ( cancel func ( ) , err error ) { w , err := fsnotify . NewWatcher ( ) if err != nil { return nil , err } dirs , errs := listDirs ( root ) for _ , err := range errs { log . Print ( err ) } gitDir := filepath . Join ( root , " " ) for _ , dir := range dirs { if dir == gitDir { continue } if err := w . Add ( dir ) ; err != nil { log . Print ( err ) } } done := make ( chan struct { } ) go func ( ) { for { select { case ev := <- w . Events : if shouldIgnore ( ev . Name ) { continue } if ev . Op == fsnotify . Create { if st , err := os . Lstat ( ev . Name ) ; err != nil { log . Print ( err ) } else if st . IsDir ( ) { dirs , errs := listDirs ( ev . Name ) for _ , err := range errs { log . Print ( err ) } for _ , dir := range dirs { if err := w . Add ( dir ) ; err != nil { log . Print ( err ) } recordWrite ( dir ) } } } else { recordWrite ( filepath . Dir ( ev . Name ) ) } case err := <- w . Errors : log . Print ( err ) case <- done : if err := w . Close ( ) ; err != nil { log . Print ( err ) } return } } } ( ) return func ( ) { close ( done ) } , nil }

// watchDir listens for file system changes in root and its
// subdirectories. The record function is called with directories whose
// contents have changed. New directories are watched recursively.
// The returned cancel function may be called to stop watching.

watchDir listens for file system changes in root and its subdirectories . The record function is called with directories whose contents have changed . New directories are watched recursively . The returned cancel function may be called to stop watching .


func listDirs(dir string) ([]string, []error) {
	var dirs []string
	var errs []error
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			errs = append(errs, err)
			return nil
		}
		if info.IsDir() {
			dirs = append(dirs, path)
		}
		return nil
	})
	if err != nil {
		errs = append(errs, err)
	}
	return dirs, errs
}

func listDirs ( dir string ) ( [ ] string , [ ] error ) { var dirs [ ] string var errs [ ] error err := filepath . Walk ( dir , func ( path string , info os . FileInfo , err error ) error { if err != nil { errs = append ( errs , err ) return nil } if info . IsDir ( ) { dirs = append ( dirs , path ) } return nil } ) if err != nil { errs = append ( errs , err ) } return dirs , errs }

// listDirs returns a slice containing all the subdirectories under dir,
// including dir itself.

listDirs returns a slice containing all the subdirectories under dir including dir itself .


func shouldIgnore(p string) bool {
	p = strings.TrimPrefix(filepath.ToSlash(p), "./")
	base := path.Base(p)
	return strings.HasPrefix(p, "tools/") || base == ".git" || base == "BUILD" || base == "BUILD.bazel"
}

func shouldIgnore ( p string ) bool { p = strings . TrimPrefix ( filepath . ToSlash ( p ) , " " ) base := path . Base ( p ) return strings . HasPrefix ( p , " " ) || base == " " || base == " " || base == " " }

// shouldIgnore returns whether a write to the given file should be ignored
// because they were caused by gazelle or autogazelle or something unrelated
// to the build.

shouldIgnore returns whether a write to the given file should be ignored because they were caused by gazelle or autogazelle or something unrelated to the build .


func recordWrite(path string) {
	dirSetMutex.Lock()
	defer dirSetMutex.Unlock()
	dirSet[path] = true
}

func recordWrite ( path string ) { dirSetMutex . Lock ( ) defer dirSetMutex . Unlock ( ) dirSet [ path ] = true }

// recordWrite records that a directory has been modified and that its build
// file should be updated the next time gazelle runs.

recordWrite records that a directory has been modified and that its build file should be updated the next time gazelle runs .


func getAndClearWrittenDirs() []string {
	dirSetMutex.Lock()
	defer dirSetMutex.Unlock()
	dirs := make([]string, 0, len(dirSet))
	for d := range dirSet {
		dirs = append(dirs, d)
	}
	dirSet = make(map[string]bool)
	return dirs
}

func getAndClearWrittenDirs ( ) [ ] string { dirSetMutex . Lock ( ) defer dirSetMutex . Unlock ( ) dirs := make ( [ ] string , 0 , len ( dirSet ) ) for d := range dirSet { dirs = append ( dirs , d ) } dirSet = make ( map [ string ] bool ) return dirs }

// getAndClearWrittenDirs retrieves a list of directories that have been
// modified since the last time getAndClearWrittenDirs was called.

getAndClearWrittenDirs retrieves a list of directories that have been modified since the last time getAndClearWrittenDirs was called .


func CombineHandlers(handlers ...http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		for _, handler := range handlers {
			handler(w, req)
		}
	}
}

func CombineHandlers ( handlers ... http . HandlerFunc ) http . HandlerFunc { return func ( w http . ResponseWriter , req * http . Request ) { for _ , handler := range handlers { handler ( w , req ) } } }

//CombineHandler takes variadic list of handlers and produces one handler
//that calls each handler in order.

CombineHandler takes variadic list of handlers and produces one handler that calls each handler in order .


func VerifyContentType(contentType string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		Expect(req.Header.Get("Content-Type")).Should(Equal(contentType))
	}
}

func VerifyContentType ( contentType string ) http . HandlerFunc { return func ( w http . ResponseWriter , req * http . Request ) { Expect ( req . Header . Get ( " " ) ) . Should ( Equal ( contentType ) ) } }

//VerifyContentType returns a handler that verifies that a request has a Content-Type header set to the
//specified value

VerifyContentType returns a handler that verifies that a request has a Content - Type header set to the specified value


func VerifyMimeType(mimeType string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		Expect(strings.Split(req.Header.Get("Content-Type"), ";")[0]).Should(Equal(mimeType))
	}
}

func VerifyMimeType ( mimeType string ) http . HandlerFunc { return func ( w http . ResponseWriter , req * http . Request ) { Expect ( strings . Split ( req . Header . Get ( " " ) , " " ) [ 0 ] ) . Should ( Equal ( mimeType ) ) } }

//VerifyMimeType returns a handler that verifies that a request has a specified mime type set
//in Content-Type header

VerifyMimeType returns a handler that verifies that a request has a specified mime type set in Content - Type header


func VerifyBasicAuth(username string, password string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		auth := req.Header.Get("Authorization")
		Expect(auth).ShouldNot(Equal(""), "Authorization header must be specified")

		decoded, err := base64.StdEncoding.DecodeString(auth[6:])
		Expect(err).ShouldNot(HaveOccurred())

		Expect(string(decoded)).Should(Equal(fmt.Sprintf("%s:%s", username, password)), "Authorization mismatch")
	}
}

func VerifyBasicAuth ( username string , password string ) http . HandlerFunc { return func ( w http . ResponseWriter , req * http . Request ) { auth := req . Header . Get ( " " ) Expect ( auth ) . ShouldNot ( Equal ( " " ) , " " ) decoded , err := base64 . StdEncoding . DecodeString ( auth [ 6 : ] ) Expect ( err ) . ShouldNot ( HaveOccurred ( ) ) Expect ( string ( decoded ) ) . Should ( Equal ( fmt . Sprintf ( " " , username , password ) ) , " " ) } }

//VerifyBasicAuth returns a handler that verifies the request contains a BasicAuth Authorization header
//matching the passed in username and password

VerifyBasicAuth returns a handler that verifies the request contains a BasicAuth Authorization header matching the passed in username and password


func VerifyJSONRepresenting(object interface{}) http.HandlerFunc {
	data, err := json.Marshal(object)
	Expect(err).ShouldNot(HaveOccurred())
	return CombineHandlers(
		VerifyContentType("application/json"),
		VerifyJSON(string(data)),
	)
}

func VerifyJSONRepresenting ( object interface { } ) http . HandlerFunc { data , err := json . Marshal ( object ) Expect ( err ) . ShouldNot ( HaveOccurred ( ) ) return CombineHandlers ( VerifyContentType ( " " ) , VerifyJSON ( string ( data ) ) , ) }

//VerifyJSONRepresenting is similar to VerifyJSON.  Instead of taking a JSON string, however, it
//takes an arbitrary JSON-encodable object and verifies that the requests's body is a JSON representation
//that matches the object

VerifyJSONRepresenting is similar to VerifyJSON . Instead of taking a JSON string however it takes an arbitrary JSON - encodable object and verifies that the requests s body is a JSON representation that matches the object


func VerifyFormKV(key string, values ...string) http.HandlerFunc {
	return VerifyForm(url.Values{key: values})
}

func VerifyFormKV ( key string , values ... string ) http . HandlerFunc { return VerifyForm ( url . Values { key : values } ) }

//VerifyFormKV returns a handler that verifies a request contains a form key with the specified values.
//
//It is a convenience wrapper around `VerifyForm` that lets you avoid having to create a `url.Values` object.

VerifyFormKV returns a handler that verifies a request contains a form key with the specified values . It is a convenience wrapper around VerifyForm that lets you avoid having to create a url . Values object .


func RespondWithProto(statusCode int, message proto.Message, optionalHeader ...http.Header) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		data, err := proto.Marshal(message)
		Expect(err).ShouldNot(HaveOccurred())

		var headers http.Header
		if len(optionalHeader) == 1 {
			headers = optionalHeader[0]
		} else {
			headers = make(http.Header)
		}
		if _, found := headers["Content-Type"]; !found {
			headers["Content-Type"] = []string{"application/x-protobuf"}
		}
		copyHeader(headers, w.Header())

		w.WriteHeader(statusCode)
		w.Write(data)
	}
}

func RespondWithProto ( statusCode int , message proto . Message , optionalHeader ... http . Header ) http . HandlerFunc { return func ( w http . ResponseWriter , req * http . Request ) { data , err := proto . Marshal ( message ) Expect ( err ) . ShouldNot ( HaveOccurred ( ) ) var headers http . Header if len ( optionalHeader ) == 1 { headers = optionalHeader [ 0 ] } else { headers = make ( http . Header ) } if _ , found := headers [ " " ] ; ! found { headers [ " " ] = [ ] string { " " } } copyHeader ( headers , w . Header ( ) ) w . WriteHeader ( statusCode ) w . Write ( data ) } }

//RespondWithProto returns a handler that responds to a request with the specified status code and a body
//containing the protobuf serialization of the provided message.
//
//Also, RespondWithProto can be given an optional http.Header.  The headers defined therein will be added to the response headers.

RespondWithProto returns a handler that responds to a request with the specified status code and a body containing the protobuf serialization of the provided message . Also RespondWithProto can be given an optional http . Header . The headers defined therein will be added to the response headers .


func RegisterFailHandlerWithT(t types.TWithHelper, handler types.GomegaFailHandler) {
	if handler == nil {
		globalFailWrapper = nil
		return
	}

	globalFailWrapper = &types.GomegaFailWrapper{
		Fail:        handler,
		TWithHelper: t,
	}
}

func RegisterFailHandlerWithT ( t types . TWithHelper , handler types . GomegaFailHandler ) { if handler == nil { globalFailWrapper = nil return } globalFailWrapper = & types . GomegaFailWrapper { Fail : handler , TWithHelper : t , } }

// RegisterFailHandlerWithT ensures that the given types.TWithHelper and fail handler
// are used globally.

RegisterFailHandlerWithT ensures that the given types . TWithHelper and fail handler are used globally .


func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
	if globalFailWrapper == nil {
		panic(nilFailHandlerPanic)
	}
	timeoutInterval := defaultEventuallyTimeout
	pollingInterval := defaultEventuallyPollingInterval
	if len(intervals) > 0 {
		timeoutInterval = toDuration(intervals[0])
	}
	if len(intervals) > 1 {
		pollingInterval = toDuration(intervals[1])
	}
	return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, globalFailWrapper, timeoutInterval, pollingInterval, offset)
}

func EventuallyWithOffset ( offset int , actual interface { } , intervals ... interface { } ) AsyncAssertion { if globalFailWrapper == nil { panic ( nilFailHandlerPanic ) } timeoutInterval := defaultEventuallyTimeout pollingInterval := defaultEventuallyPollingInterval if len ( intervals ) > 0 { timeoutInterval = toDuration ( intervals [ 0 ] ) } if len ( intervals ) > 1 { pollingInterval = toDuration ( intervals [ 1 ] ) } return asyncassertion . New ( asyncassertion . AsyncAssertionTypeEventually , actual , globalFailWrapper , timeoutInterval , pollingInterval , offset ) }

// EventuallyWithOffset operates like Eventually but takes an additional
// initial argument to indicate an offset in the call stack.  This is useful when building helper
// functions that contain matchers.  To learn more, read about `ExpectWithOffset`.

EventuallyWithOffset operates like Eventually but takes an additional initial argument to indicate an offset in the call stack . This is useful when building helper functions that contain matchers . To learn more read about ExpectWithOffset .


func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion {
	if globalFailWrapper == nil {
		panic(nilFailHandlerPanic)
	}
	timeoutInterval := defaultConsistentlyDuration
	pollingInterval := defaultConsistentlyPollingInterval
	if len(intervals) > 0 {
		timeoutInterval = toDuration(intervals[0])
	}
	if len(intervals) > 1 {
		pollingInterval = toDuration(intervals[1])
	}
	return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, globalFailWrapper, timeoutInterval, pollingInterval, offset)
}

func ConsistentlyWithOffset ( offset int , actual interface { } , intervals ... interface { } ) AsyncAssertion { if globalFailWrapper == nil { panic ( nilFailHandlerPanic ) } timeoutInterval := defaultConsistentlyDuration pollingInterval := defaultConsistentlyPollingInterval if len ( intervals ) > 0 { timeoutInterval = toDuration ( intervals [ 0 ] ) } if len ( intervals ) > 1 { pollingInterval = toDuration ( intervals [ 1 ] ) } return asyncassertion . New ( asyncassertion . AsyncAssertionTypeConsistently , actual , globalFailWrapper , timeoutInterval , pollingInterval , offset ) }

// ConsistentlyWithOffset operates like Consistnetly but takes an additional
// initial argument to indicate an offset in the call stack. This is useful when building helper
// functions that contain matchers. To learn more, read about `ExpectWithOffset`.

ConsistentlyWithOffset operates like Consistnetly but takes an additional initial argument to indicate an offset in the call stack . This is useful when building helper functions that contain matchers . To learn more read about ExpectWithOffset .


func (g *WithT) Expect(actual interface{}, extra ...interface{}) Assertion {
	return assertion.New(actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), 0, extra...)
}

func ( g * WithT ) Expect ( actual interface { } , extra ... interface { } ) Assertion { return assertion . New ( actual , testingtsupport . BuildTestingTGomegaFailWrapper ( g . t ) , 0 , extra ... ) }

// Expect is used to make assertions. See documentation for Expect.

Expect is used to make assertions . See documentation for Expect .


func (g *WithT) Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion {
	timeoutInterval := defaultEventuallyTimeout
	pollingInterval := defaultEventuallyPollingInterval
	if len(intervals) > 0 {
		timeoutInterval = toDuration(intervals[0])
	}
	if len(intervals) > 1 {
		pollingInterval = toDuration(intervals[1])
	}
	return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, 0)
}

func ( g * WithT ) Eventually ( actual interface { } , intervals ... interface { } ) AsyncAssertion { timeoutInterval := defaultEventuallyTimeout pollingInterval := defaultEventuallyPollingInterval if len ( intervals ) > 0 { timeoutInterval = toDuration ( intervals [ 0 ] ) } if len ( intervals ) > 1 { pollingInterval = toDuration ( intervals [ 1 ] ) } return asyncassertion . New ( asyncassertion . AsyncAssertionTypeEventually , actual , testingtsupport . BuildTestingTGomegaFailWrapper ( g . t ) , timeoutInterval , pollingInterval , 0 ) }

// Eventually is used to make asynchronous assertions. See documentation for Eventually.

Eventually is used to make asynchronous assertions . See documentation for Eventually .


func (g *WithT) Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion {
	timeoutInterval := defaultConsistentlyDuration
	pollingInterval := defaultConsistentlyPollingInterval
	if len(intervals) > 0 {
		timeoutInterval = toDuration(intervals[0])
	}
	if len(intervals) > 1 {
		pollingInterval = toDuration(intervals[1])
	}
	return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, 0)
}

func ( g * WithT ) Consistently ( actual interface { } , intervals ... interface { } ) AsyncAssertion { timeoutInterval := defaultConsistentlyDuration pollingInterval := defaultConsistentlyPollingInterval if len ( intervals ) > 0 { timeoutInterval = toDuration ( intervals [ 0 ] ) } if len ( intervals ) > 1 { pollingInterval = toDuration ( intervals [ 1 ] ) } return asyncassertion . New ( asyncassertion . AsyncAssertionTypeConsistently , actual , testingtsupport . BuildTestingTGomegaFailWrapper ( g . t ) , timeoutInterval , pollingInterval , 0 ) }

// Consistently is used to make asynchronous assertions. See documentation for Consistently.

Consistently is used to make asynchronous assertions . See documentation for Consistently .


func TimeoutCloser(c io.Closer, timeout time.Duration) io.Closer {
	return timeoutReaderWriterCloser{c: c, d: timeout}
}

func TimeoutCloser ( c io . Closer , timeout time . Duration ) io . Closer { return timeoutReaderWriterCloser { c : c , d : timeout } }

// TimeoutCloser returns an io.Closer that wraps the passed-in io.Closer.  If the underlying Closer fails to close within the alloted timeout ErrTimeout is returned.

TimeoutCloser returns an io . Closer that wraps the passed - in io . Closer . If the underlying Closer fails to close within the alloted timeout ErrTimeout is returned .


func TimeoutReader(r io.Reader, timeout time.Duration) io.Reader {
	return timeoutReaderWriterCloser{r: r, d: timeout}
}

func TimeoutReader ( r io . Reader , timeout time . Duration ) io . Reader { return timeoutReaderWriterCloser { r : r , d : timeout } }

// TimeoutReader returns an io.Reader that wraps the passed-in io.Reader.  If the underlying Reader fails to read within the alloted timeout ErrTimeout is returned.

TimeoutReader returns an io . Reader that wraps the passed - in io . Reader . If the underlying Reader fails to read within the alloted timeout ErrTimeout is returned .


func TimeoutWriter(w io.Writer, timeout time.Duration) io.Writer {
	return timeoutReaderWriterCloser{w: w, d: timeout}
}

func TimeoutWriter ( w io . Writer , timeout time . Duration ) io . Writer { return timeoutReaderWriterCloser { w : w , d : timeout } }

// TimeoutWriter returns an io.Writer that wraps the passed-in io.Writer.  If the underlying Writer fails to write within the alloted timeout ErrTimeout is returned.

TimeoutWriter returns an io . Writer that wraps the passed - in io . Writer . If the underlying Writer fails to write within the alloted timeout ErrTimeout is returned .


func Nest(path string, err error) error {
	if ag, ok := err.(AggregateError); ok {
		var errs AggregateError
		for _, e := range ag {
			errs = append(errs, Nest(path, e))
		}
		return errs
	}
	if ne, ok := err.(*NestedError); ok {
		return &NestedError{
			Path: path + ne.Path,
			Err:  ne.Err,
		}
	}
	return &NestedError{
		Path: path,
		Err:  err,
	}
}

func Nest ( path string , err error ) error { if ag , ok := err . ( AggregateError ) ; ok { var errs AggregateError for _ , e := range ag { errs = append ( errs , Nest ( path , e ) ) } return errs } if ne , ok := err . ( * NestedError ) ; ok { return & NestedError { Path : path + ne . Path , Err : ne . Err , } } return & NestedError { Path : path , Err : err , } }

// Create a NestedError with the given path.
// If err is a NestedError, prepend the path to it.
// If err is an AggregateError, recursively Nest each error.

Create a NestedError with the given path . If err is a NestedError prepend the path to it . If err is an AggregateError recursively Nest each error .


func SetMockService(m *MockService) {
	m.Cache = &cache.MockAppCacheService{}
	m.Plan = &app.MockPlanService{}
	m.Platform = &app.MockPlatformService{}
	m.PlatformImage = &image.MockPlatformImageService{}
	m.Team = &auth.MockTeamService{}
	m.UserQuota = &quota.MockQuotaService{}
	m.AppQuota = &quota.MockQuotaService{}
	m.Cluster = &provision.MockClusterService{}
	m.ServiceBroker = &service.MockServiceBrokerService{}
	m.ServiceBrokerCatalogCache = &service.MockServiceBrokerCatalogCacheService{}
	servicemanager.AppCache = m.Cache
	servicemanager.Plan = m.Plan
	servicemanager.Platform = m.Platform
	servicemanager.PlatformImage = m.PlatformImage
	servicemanager.Team = m.Team
	servicemanager.UserQuota = m.UserQuota
	servicemanager.AppQuota = m.AppQuota
	servicemanager.Cluster = m.Cluster
	servicemanager.ServiceBroker = m.ServiceBroker
	servicemanager.ServiceBrokerCatalogCache = m.ServiceBrokerCatalogCache
}

func SetMockService ( m * MockService ) { m . Cache = & cache . MockAppCacheService { } m . Plan = & app . MockPlanService { } m . Platform = & app . MockPlatformService { } m . PlatformImage = & image . MockPlatformImageService { } m . Team = & auth . MockTeamService { } m . UserQuota = & quota . MockQuotaService { } m . AppQuota = & quota . MockQuotaService { } m . Cluster = & provision . MockClusterService { } m . ServiceBroker = & service . MockServiceBrokerService { } m . ServiceBrokerCatalogCache = & service . MockServiceBrokerCatalogCacheService { } servicemanager . AppCache = m . Cache servicemanager . Plan = m . Plan servicemanager . Platform = m . Platform servicemanager . PlatformImage = m . PlatformImage servicemanager . Team = m . Team servicemanager . UserQuota = m . UserQuota servicemanager . AppQuota = m . AppQuota servicemanager . Cluster = m . Cluster servicemanager . ServiceBroker = m . ServiceBroker servicemanager . ServiceBrokerCatalogCache = m . ServiceBrokerCatalogCache }

// SetMockService return a new MockService and set as a servicemanager


func FindMachineByIdOrAddress(id string, address string) (Machine, error) {
	coll, err := collection()
	if err != nil {
		return Machine{}, err
	}
	defer coll.Close()
	var result Machine
	query := bson.M{}
	if id != "" {
		query["_id"] = id
	} else {
		query["address"] = address
	}
	err = coll.Find(query).One(&result)
	if err == mgo.ErrNotFound {
		err = ErrMachineNotFound
	}
	return result, err
}

func FindMachineByIdOrAddress ( id string , address string ) ( Machine , error ) { coll , err := collection ( ) if err != nil { return Machine { } , err } defer coll . Close ( ) var result Machine query := bson . M { } if id != " " { query [ " " ] = id } else { query [ " " ] = address } err = coll . Find ( query ) . One ( & result ) if err == mgo . ErrNotFound { err = ErrMachineNotFound } return result , err }

// Uses id or address, this is only used because previously we didn't have
// iaas-id in node metadata.

Uses id or address this is only used because previously we didn t have iaas - id in node metadata .


func (w *FlushingWriter) Write(data []byte) (written int, err error) {
	w.writeMutex.Lock()
	defer w.writeMutex.Unlock()
	w.wrote = true
	written, err = w.ResponseWriter.Write(data)
	if err != nil {
		return
	}
	if f, ok := w.ResponseWriter.(http.Flusher); ok {
		defer func() {
			if r := recover(); r != nil {
				msg := fmt.Sprintf("Error recovered on flushing writer: %#v", r)
				log.Debugf(msg)
				err = errors.Errorf(msg)
			}
		}()
		f.Flush()
	}
	return
}

func ( w * FlushingWriter ) Write ( data [ ] byte ) ( written int , err error ) { w . writeMutex . Lock ( ) defer w . writeMutex . Unlock ( ) w . wrote = true written , err = w . ResponseWriter . Write ( data ) if err != nil { return } if f , ok := w . ResponseWriter . ( http . Flusher ) ; ok { defer func ( ) { if r := recover ( ) ; r != nil { msg := fmt . Sprintf ( " " , r ) log . Debugf ( msg ) err = errors . Errorf ( msg ) } } ( ) f . Flush ( ) } return }


func (w *FlushingWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	if hijacker, ok := w.ResponseWriter.(http.Hijacker); ok {
		return hijacker.Hijack()
	}
	return nil, nil, errors.New("cannot hijack connection")
}

func ( w * FlushingWriter ) Hijack ( ) ( net . Conn , * bufio . ReadWriter , error ) { if hijacker , ok := w . ResponseWriter . ( http . Hijacker ) ; ok { return hijacker . Hijack ( ) } return nil , nil , errors . New ( " " ) }

// Hijack will hijack the underlying TCP connection, if available in the
// ResponseWriter.

Hijack will hijack the underlying TCP connection if available in the ResponseWriter .


func ListDeploys(filter *Filter, skip, limit int) ([]DeployData, error) {
	appsList, err := List(filter)
	if err != nil {
		return nil, err
	}
	apps := make([]string, len(appsList))
	for i, a := range appsList {
		apps[i] = a.GetName()
	}
	evts, err := event.List(&event.Filter{
		Target:    event.Target{Type: event.TargetTypeApp},
		Raw:       bson.M{"target.value": bson.M{"$in": apps}},
		KindNames: []string{permission.PermAppDeploy.FullName()},
		KindType:  event.KindTypePermission,
		Limit:     limit,
		Skip:      skip,
	})
	if err != nil {
		return nil, err
	}
	validImages, err := findValidImages(appsList...)
	if err != nil {
		return nil, err
	}
	list := make([]DeployData, len(evts))
	for i := range evts {
		list[i] = *eventToDeployData(&evts[i], validImages, false)
	}
	return list, nil
}

func ListDeploys ( filter * Filter , skip , limit int ) ( [ ] DeployData , error ) { appsList , err := List ( filter ) if err != nil { return nil , err } apps := make ( [ ] string , len ( appsList ) ) for i , a := range appsList { apps [ i ] = a . GetName ( ) } evts , err := event . List ( & event . Filter { Target : event . Target { Type : event . TargetTypeApp } , Raw : bson . M { " " : bson . M { " " : apps } } , KindNames : [ ] string { permission . PermAppDeploy . FullName ( ) } , KindType : event . KindTypePermission , Limit : limit , Skip : skip , } ) if err != nil { return nil , err } validImages , err := findValidImages ( appsList ... ) if err != nil { return nil , err } list := make ( [ ] DeployData , len ( evts ) ) for i := range evts { list [ i ] = * eventToDeployData ( & evts [ i ] , validImages , false ) } return list , nil }

// ListDeploys returns the list of deploy that match a given filter.

ListDeploys returns the list of deploy that match a given filter .


func (r *DelayedRouter) AddAll(version, path string, h http.Handler) *mux.Route {
	return r.addRoute(version, path, h, "GET", "POST", "PUT", "DELETE")
}

func ( r * DelayedRouter ) AddAll ( version , path string , h http . Handler ) * mux . Route { return r . addRoute ( version , path , h , " " , " " , " " , " " ) }

// AddAll binds a path to GET, POST, PUT and DELETE methods.

AddAll binds a path to GET POST PUT and DELETE methods .


func samlRequestTimeout(schemeData map[string]string) int {
	p := schemeData["request_timeout"]
	timeout, _ := strconv.Atoi(p)
	return timeout
}

func samlRequestTimeout ( schemeData map [ string ] string ) int { p := schemeData [ " " ] timeout , _ := strconv . Atoi ( p ) return timeout }


func RegisterHandler(path string, method string, h http.Handler) {
	RegisterHandlerVersion("1.0", path, method, h)
}

func RegisterHandler ( path string , method string , h http . Handler ) { RegisterHandlerVersion ( " " , path , method , h ) }

// RegisterHandler inserts a handler on a list of handlers for version 1.0

RegisterHandler inserts a handler on a list of handlers for version 1 . 0