{"action":"created","comment":{"url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/comments/167912611","pull_request_review_id":96192655,"id":167912611,"diff_hunk":"@@ -415,3 +422,38 @@ func excludedForSubdir(excluded []string, subdir string) []string {\n \t}\n \treturn filtered\n }\n+\n+type symlinkResolver struct {\n+\troot    string\n+\tvisited []string\n+}\n+\n+// Decide if symlink dir/base should be followed.\n+func (r *symlinkResolver) follow(dir, base string) bool {\n+\tif dir == r.root && strings.HasPrefix(base, \"bazel-\") {\n+\t\t// Links such as bazel-<workspace>, bazel-out, bazel-genfiles are created by\n+\t\t// Bazel to point to internal build directories.\n+\t\treturn false\n+\t}\n+\t// See if the symlink points to a tree that has been already visited.\n+\tfullpath := filepath.Join(dir, base)\n+\tdest, err := os.Readlink(fullpath)\n+\tif err != nil {\n+\t\tlog.Printf(\"readlink %v: %v\", fullpath, err)\n+\t\treturn false\n+\t}\n+\tdest = filepath.Join(dir, dest)\n+\tfor _, p := range r.visited {","path":"internal/packages/walk.go","position":52,"original_position":52,"commit_id":"d998a9750d41b1a09d9243506b5cd230545c24bf","original_commit_id":"d998a9750d41b1a09d9243506b5cd230545c24bf","user":{"login":"jayconrod","id":164791,"avatar_url":"https://avatars3.githubusercontent.com/u/164791?v=4","gravatar_id":"","url":"https://api.github.com/users/jayconrod","html_url":"https://github.com/jayconrod","followers_url":"https://api.github.com/users/jayconrod/followers","following_url":"https://api.github.com/users/jayconrod/following{/other_user}","gists_url":"https://api.github.com/users/jayconrod/gists{/gist_id}","starred_url":"https://api.github.com/users/jayconrod/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jayconrod/subscriptions","organizations_url":"https://api.github.com/users/jayconrod/orgs","repos_url":"https://api.github.com/users/jayconrod/repos","events_url":"https://api.github.com/users/jayconrod/events{/privacy}","received_events_url":"https://api.github.com/users/jayconrod/received_events","type":"User","site_admin":false},"body":"Use `pathutils.HasPrefix(dest, r.root)` to check whether the link is inside the workspace. `pathutils` is an internal package that is aware of path components. `r.root` will already be a canonical path.\r\n\r\nTo check whether a directory has been visited, it would be faster to use a `map` (since we won't need to check prefixes anymore).","created_at":"2018-02-13T16:04:27Z","updated_at":"2018-02-13T16:12:47Z","html_url":"https://github.com/bazelbuild/bazel-gazelle/pull/116#discussion_r167912611","pull_request_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/comments/167912611"},"html":{"href":"https://github.com/bazelbuild/bazel-gazelle/pull/116#discussion_r167912611"},"pull_request":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116"}}},"pull_request":{"url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116","id":166996174,"html_url":"https://github.com/bazelbuild/bazel-gazelle/pull/116","diff_url":"https://github.com/bazelbuild/bazel-gazelle/pull/116.diff","patch_url":"https://github.com/bazelbuild/bazel-gazelle/pull/116.patch","issue_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues/116","number":116,"state":"open","locked":false,"title":"Add -follow_symlinks flag","user":{"login":"yasushi-saito","id":546227,"avatar_url":"https://avatars2.githubusercontent.com/u/546227?v=4","gravatar_id":"","url":"https://api.github.com/users/yasushi-saito","html_url":"https://github.com/yasushi-saito","followers_url":"https://api.github.com/users/yasushi-saito/followers","following_url":"https://api.github.com/users/yasushi-saito/following{/other_user}","gists_url":"https://api.github.com/users/yasushi-saito/gists{/gist_id}","starred_url":"https://api.github.com/users/yasushi-saito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yasushi-saito/subscriptions","organizations_url":"https://api.github.com/users/yasushi-saito/orgs","repos_url":"https://api.github.com/users/yasushi-saito/repos","events_url":"https://api.github.com/users/yasushi-saito/events{/privacy}","received_events_url":"https://api.github.com/users/yasushi-saito/received_events","type":"User","site_admin":false},"body":"This flag defines a comma-separated list of globs. Bazel will descend into\r\nsymlinks that match the globs.\r\n\r\nBazel itself follows symlinks, except for those to build directories (bazel-bin,\r\netc). This change allows repositories that uses symlinks to work more properly.","created_at":"2018-02-04T05:43:50Z","updated_at":"2018-02-13T16:12:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"22bda131f41d775df580ffccf327d6fd86b4e315","assignee":null,"assignees":[],"requested_reviewers":[{"login":"ianthehat","id":858832,"avatar_url":"https://avatars0.githubusercontent.com/u/858832?v=4","gravatar_id":"","url":"https://api.github.com/users/ianthehat","html_url":"https://github.com/ianthehat","followers_url":"https://api.github.com/users/ianthehat/followers","following_url":"https://api.github.com/users/ianthehat/following{/other_user}","gists_url":"https://api.github.com/users/ianthehat/gists{/gist_id}","starred_url":"https://api.github.com/users/ianthehat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ianthehat/subscriptions","organizations_url":"https://api.github.com/users/ianthehat/orgs","repos_url":"https://api.github.com/users/ianthehat/repos","events_url":"https://api.github.com/users/ianthehat/events{/privacy}","received_events_url":"https://api.github.com/users/ianthehat/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116/commits","review_comments_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116/comments","review_comment_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues/116/comments","statuses_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/statuses/d998a9750d41b1a09d9243506b5cd230545c24bf","head":{"label":"yasushi-saito:symlinks","ref":"symlinks","sha":"d998a9750d41b1a09d9243506b5cd230545c24bf","user":{"login":"yasushi-saito","id":546227,"avatar_url":"https://avatars2.githubusercontent.com/u/546227?v=4","gravatar_id":"","url":"https://api.github.com/users/yasushi-saito","html_url":"https://github.com/yasushi-saito","followers_url":"https://api.github.com/users/yasushi-saito/followers","following_url":"https://api.github.com/users/yasushi-saito/following{/other_user}","gists_url":"https://api.github.com/users/yasushi-saito/gists{/gist_id}","starred_url":"https://api.github.com/users/yasushi-saito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yasushi-saito/subscriptions","organizations_url":"https://api.github.com/users/yasushi-saito/orgs","repos_url":"https://api.github.com/users/yasushi-saito/repos","events_url":"https://api.github.com/users/yasushi-saito/events{/privacy}","received_events_url":"https://api.github.com/users/yasushi-saito/received_events","type":"User","site_admin":false},"repo":{"id":120148909,"name":"bazel-gazelle","full_name":"yasushi-saito/bazel-gazelle","owner":{"login":"yasushi-saito","id":546227,"avatar_url":"https://avatars2.githubusercontent.com/u/546227?v=4","gravatar_id":"","url":"https://api.github.com/users/yasushi-saito","html_url":"https://github.com/yasushi-saito","followers_url":"https://api.github.com/users/yasushi-saito/followers","following_url":"https://api.github.com/users/yasushi-saito/following{/other_user}","gists_url":"https://api.github.com/users/yasushi-saito/gists{/gist_id}","starred_url":"https://api.github.com/users/yasushi-saito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yasushi-saito/subscriptions","organizations_url":"https://api.github.com/users/yasushi-saito/orgs","repos_url":"https://api.github.com/users/yasushi-saito/repos","events_url":"https://api.github.com/users/yasushi-saito/events{/privacy}","received_events_url":"https://api.github.com/users/yasushi-saito/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/yasushi-saito/bazel-gazelle","description":"Gazelle is a Bazel build file generator for Go projects.","fork":true,"url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle","forks_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/forks","keys_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/teams","hooks_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/hooks","issue_events_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/issues/events{/number}","events_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/events","assignees_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/assignees{/user}","branches_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/branches{/branch}","tags_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/tags","blobs_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/git/refs{/sha}","trees_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/statuses/{sha}","languages_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/languages","stargazers_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/stargazers","contributors_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/contributors","subscribers_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/subscribers","subscription_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/subscription","commits_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/commits{/sha}","git_commits_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/git/commits{/sha}","comments_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/comments{/number}","issue_comment_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/issues/comments{/number}","contents_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/contents/{+path}","compare_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/merges","archive_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/downloads","issues_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/issues{/number}","pulls_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/pulls{/number}","milestones_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/milestones{/number}","notifications_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/labels{/name}","releases_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/releases{/id}","deployments_url":"https://api.github.com/repos/yasushi-saito/bazel-gazelle/deployments","created_at":"2018-02-04T02:37:53Z","updated_at":"2018-02-04T02:37:55Z","pushed_at":"2018-02-12T19:42:13Z","git_url":"git://github.com/yasushi-saito/bazel-gazelle.git","ssh_url":"git@github.com:yasushi-saito/bazel-gazelle.git","clone_url":"https://github.com/yasushi-saito/bazel-gazelle.git","svn_url":"https://github.com/yasushi-saito/bazel-gazelle","homepage":"","size":384,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"bazelbuild:master","ref":"master","sha":"7d4dba6bdf57b96eb30e57bff2cd432acc285e73","user":{"login":"bazelbuild","id":11684617,"avatar_url":"https://avatars1.githubusercontent.com/u/11684617?v=4","gravatar_id":"","url":"https://api.github.com/users/bazelbuild","html_url":"https://github.com/bazelbuild","followers_url":"https://api.github.com/users/bazelbuild/followers","following_url":"https://api.github.com/users/bazelbuild/following{/other_user}","gists_url":"https://api.github.com/users/bazelbuild/gists{/gist_id}","starred_url":"https://api.github.com/users/bazelbuild/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bazelbuild/subscriptions","organizations_url":"https://api.github.com/users/bazelbuild/orgs","repos_url":"https://api.github.com/users/bazelbuild/repos","events_url":"https://api.github.com/users/bazelbuild/events{/privacy}","received_events_url":"https://api.github.com/users/bazelbuild/received_events","type":"Organization","site_admin":false},"repo":{"id":112655189,"name":"bazel-gazelle","full_name":"bazelbuild/bazel-gazelle","owner":{"login":"bazelbuild","id":11684617,"avatar_url":"https://avatars1.githubusercontent.com/u/11684617?v=4","gravatar_id":"","url":"https://api.github.com/users/bazelbuild","html_url":"https://github.com/bazelbuild","followers_url":"https://api.github.com/users/bazelbuild/followers","following_url":"https://api.github.com/users/bazelbuild/following{/other_user}","gists_url":"https://api.github.com/users/bazelbuild/gists{/gist_id}","starred_url":"https://api.github.com/users/bazelbuild/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bazelbuild/subscriptions","organizations_url":"https://api.github.com/users/bazelbuild/orgs","repos_url":"https://api.github.com/users/bazelbuild/repos","events_url":"https://api.github.com/users/bazelbuild/events{/privacy}","received_events_url":"https://api.github.com/users/bazelbuild/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/bazelbuild/bazel-gazelle","description":"Gazelle is a Bazel build file generator for Go projects.","fork":false,"url":"https://api.github.com/repos/bazelbuild/bazel-gazelle","forks_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/forks","keys_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/teams","hooks_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/hooks","issue_events_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues/events{/number}","events_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/events","assignees_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/assignees{/user}","branches_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/branches{/branch}","tags_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/tags","blobs_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/git/refs{/sha}","trees_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/statuses/{sha}","languages_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/languages","stargazers_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/stargazers","contributors_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/contributors","subscribers_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/subscribers","subscription_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/subscription","commits_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/commits{/sha}","git_commits_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/git/commits{/sha}","comments_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/comments{/number}","issue_comment_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues/comments{/number}","contents_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/contents/{+path}","compare_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/merges","archive_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/downloads","issues_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues{/number}","pulls_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls{/number}","milestones_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/milestones{/number}","notifications_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/labels{/name}","releases_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/releases{/id}","deployments_url":"https://api.github.com/repos/bazelbuild/bazel-gazelle/deployments","created_at":"2017-11-30T20:08:09Z","updated_at":"2018-02-12T10:38:45Z","pushed_at":"2018-02-12T19:42:14Z","git_url":"git://github.com/bazelbuild/bazel-gazelle.git","ssh_url":"git@github.com:bazelbuild/bazel-gazelle.git","clone_url":"https://github.com/bazelbuild/bazel-gazelle.git","svn_url":"https://github.com/bazelbuild/bazel-gazelle","homepage":"","size":398,"stargazers_count":33,"watchers_count":33,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":13,"mirror_url":null,"archived":false,"open_issues_count":40,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":13,"open_issues":40,"watchers":33,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116"},"html":{"href":"https://github.com/bazelbuild/bazel-gazelle/pull/116"},"issue":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues/116"},"comments":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/issues/116/comments"},"review_comments":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116/comments"},"review_comment":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/pulls/116/commits"},"statuses":{"href":"https://api.github.com/repos/bazelbuild/bazel-gazelle/statuses/d998a9750d41b1a09d9243506b5cd230545c24bf"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"jayconrod"}}