{"action":"created","comment":{"url":"https://api.github.com/repos/src-d/lookout/pulls/comments/205164038","pull_request_review_id":140379950,"id":205164038,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwNTE2NDAzOA==","diff_hunk":"@@ -0,0 +1,126 @@\n+package console\n+\n+import (\n+\t\"bufio\"\n+\t\"context\"\n+\t\"fmt\"\n+\t\"io\"\n+\t\"strings\"\n+\t\"time\"\n+\n+\t\"github.com/src-d/lookout\"\n+\n+\t\"gopkg.in/src-d/go-git.v4/plumbing\"\n+\t\"gopkg.in/src-d/go-log.v1\"\n+)\n+\n+// Provider is the name\n+const Provider = \"console\"\n+\n+// WatchOptions options to use in the Watcher constructor.\n+type WatchOptions struct {\n+\tReader io.Reader\n+}\n+\n+// Watcher watches for new events in the console\n+type Watcher struct {\n+\to       *WatchOptions\n+\tscanner *bufio.Scanner\n+}\n+\n+// NewWatcher returns a new console watcher\n+func NewWatcher(o *WatchOptions) (*Watcher, error) {\n+\treturn &Watcher{\n+\t\to:       o,\n+\t\tscanner: bufio.NewScanner(o.Reader),\n+\t}, nil\n+}\n+\n+// Watch reads from stdin and calls cb for each new event\n+func (w *Watcher) Watch(ctx context.Context, cb lookout.EventHandler) error {\n+\tlog.With(log.Fields{\"provider\": Provider}).Infof(\"Starting watcher\")\n+\n+\tlines := make(chan string, 1)\n+\tgo func() {\n+\t\tfor w.scanner.Scan() {\n+\t\t\tlines <- w.scanner.Text()\n+\t\t}\n+\t}()\n+\n+\tfor {\n+\t\tselect {\n+\t\tcase <-ctx.Done():\n+\t\t\treturn ctx.Err()\n+\t\tcase line := <-lines:\n+\t\t\tif err := w.handleInput(cb, line); err != nil {\n+\t\t\t\tif lookout.NoErrStopWatcher.Is(err) {\n+\t\t\t\t\treturn nil\n+\t\t\t\t}\n+\n+\t\t\t\treturn err\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+func (w *Watcher) handleInput(cb lookout.EventHandler, line string) error {\n+\tif line == \"\" {\n+\t\treturn nil\n+\t}\n+\n+\tvar cmd, gitURL, fromBranch, fromHash, toBranch, toHash string\n+\t_, err := fmt.Sscanf(line,\n+\t\t\"%s %s %s %s %s %s\",\n+\t\t&cmd, &gitURL, &fromBranch, &fromHash, &toBranch, &toHash)\n+\n+\tif err != nil {\n+\t\tlog.Errorf(err, \"could not process input line %q\", line)\n+\t\treturn nil\n+\t}\n+\n+\tvar event lookout.Event\n+\n+\tcommitRev := lookout.CommitRevision{\n+\t\tBase: lookout.ReferencePointer{\n+\t\t\tInternalRepositoryURL: gitURL,\n+\t\t\tReferenceName:         plumbing.ReferenceName(fmt.Sprintf(\"refs/heads/%s\", fromBranch)),\n+\t\t\tHash:                  fromHash,\n+\t\t},\n+\t\tHead: lookout.ReferencePointer{\n+\t\t\tInternalRepositoryURL: gitURL,\n+\t\t\tReferenceName:         plumbing.ReferenceName(fmt.Sprintf(\"refs/heads/%s\", toBranch)),\n+\t\t\tHash:                  toHash,\n+\t\t},\n+\t}\n+\n+\tswitch strings.ToLower(cmd) {\n+\tcase \"review\":\n+\t\tevent = &lookout.ReviewEvent{\n+\t\t\tProvider:    Provider,\n+\t\t\tInternalID:  \"1\",","path":"provider/console/watcher.go","position":100,"original_position":100,"commit_id":"5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed","original_commit_id":"5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed","user":{"login":"bzz","id":5582506,"node_id":"MDQ6VXNlcjU1ODI1MDY=","avatar_url":"https://avatars3.githubusercontent.com/u/5582506?v=4","gravatar_id":"","url":"https://api.github.com/users/bzz","html_url":"https://github.com/bzz","followers_url":"https://api.github.com/users/bzz/followers","following_url":"https://api.github.com/users/bzz/following{/other_user}","gists_url":"https://api.github.com/users/bzz/gists{/gist_id}","starred_url":"https://api.github.com/users/bzz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bzz/subscriptions","organizations_url":"https://api.github.com/users/bzz/orgs","repos_url":"https://api.github.com/users/bzz/repos","events_url":"https://api.github.com/users/bzz/events{/privacy}","received_events_url":"https://api.github.com/users/bzz/received_events","type":"User","site_admin":false},"body":"Random UUID has very low probability of being repeated and that is something (more or less) that is expected from other providers","created_at":"2018-07-25T15:50:36Z","updated_at":"2018-07-25T15:50:36Z","html_url":"https://github.com/src-d/lookout/pull/57#discussion_r205164038","pull_request_url":"https://api.github.com/repos/src-d/lookout/pulls/57","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/src-d/lookout/pulls/comments/205164038"},"html":{"href":"https://github.com/src-d/lookout/pull/57#discussion_r205164038"},"pull_request":{"href":"https://api.github.com/repos/src-d/lookout/pulls/57"}},"in_reply_to_id":205157840},"pull_request":{"url":"https://api.github.com/repos/src-d/lookout/pulls/57","id":203822824,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAzODIyODI0","html_url":"https://github.com/src-d/lookout/pull/57","diff_url":"https://github.com/src-d/lookout/pull/57.diff","patch_url":"https://github.com/src-d/lookout/pull/57.patch","issue_url":"https://api.github.com/repos/src-d/lookout/issues/57","number":57,"state":"open","locked":false,"title":"Console provider","user":{"login":"carlosms","id":1469173,"node_id":"MDQ6VXNlcjE0NjkxNzM=","avatar_url":"https://avatars0.githubusercontent.com/u/1469173?v=4","gravatar_id":"","url":"https://api.github.com/users/carlosms","html_url":"https://github.com/carlosms","followers_url":"https://api.github.com/users/carlosms/followers","following_url":"https://api.github.com/users/carlosms/following{/other_user}","gists_url":"https://api.github.com/users/carlosms/gists{/gist_id}","starred_url":"https://api.github.com/users/carlosms/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carlosms/subscriptions","organizations_url":"https://api.github.com/users/carlosms/orgs","repos_url":"https://api.github.com/users/carlosms/repos","events_url":"https://api.github.com/users/carlosms/events{/privacy}","received_events_url":"https://api.github.com/users/carlosms/received_events","type":"User","site_admin":false},"body":"Part of #40.\r\n\r\nThis PR adds a new console provider, watcher and poster. It will listen for events in sdtin and output the comments to stdout.\r\n\r\nIt can be run as:\r\n\r\n```bash\r\ngo run cmd/lookout/* serve  --provider console repourl\r\n```\r\n\r\nThe events have to be provided as a line with the format\r\n```\r\nREVIEW/PUSH repoURL baseBranch baseHash headBranch headHash\r\n```\r\nFor example:\r\n```\r\nreview https://github.com/carlosms/lookout.git master 0ac15b52f3ea4e3f22f347904547c3651dc26f5e console-provider 5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed\r\n```\r\n```\r\nreview file:///home/cmartin/go/src/github.com/src-d/lookout master 0ac15b52f3ea4e3f22f347904547c3651dc26f5e console-provider 5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed\r\n```\r\n\r\nThe comments from the dummy analyzer look like this:\r\n```\r\ncmd/lookout/serve.go: The file has increased in 29 lines.\r\ncmd/lookout/serve.go:30: This line exceeded 80 bytes.\r\ncmd/lookout/serve.go:31: This line exceeded 80 bytes.\r\n```\r\n\r\nA few notes:\r\n\r\n- `lookout serve` requires the positional argument of a repo url, that the new provider ignores. I left it as it is because eventually we'll manage the repos we monitor in a different way (conf file or DB).\r\n- The usage is not as clean as with `lookout review`, where you can just give two nice revision names and it would work, because:\r\n  - We don't know if the repo is a local dir, so here we can't use go-git to get the hash of a revision.\r\n  - `serve` uses `LibraryCommitLoader`, whereas `review` uses `StorerCommitLoader`. For this reason we need to provide both the reference name and the hash.\r\n- Right now you can't trigger an analysis with base and head from two different repositories, so you can't compare a fork with its base repo. This is enforced in the data server side, [loader.go#L43](https://github.com/src-d/lookout/blob/master/service/git/loader.go#L43)","created_at":"2018-07-25T12:37:10Z","updated_at":"2018-07-25T15:50:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2370bba70665c32888dc1293d60dc10c0c8112f7","assignee":null,"assignees":[],"requested_reviewers":[{"login":"smacker","id":406916,"node_id":"MDQ6VXNlcjQwNjkxNg==","avatar_url":"https://avatars0.githubusercontent.com/u/406916?v=4","gravatar_id":"","url":"https://api.github.com/users/smacker","html_url":"https://github.com/smacker","followers_url":"https://api.github.com/users/smacker/followers","following_url":"https://api.github.com/users/smacker/following{/other_user}","gists_url":"https://api.github.com/users/smacker/gists{/gist_id}","starred_url":"https://api.github.com/users/smacker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smacker/subscriptions","organizations_url":"https://api.github.com/users/smacker/orgs","repos_url":"https://api.github.com/users/smacker/repos","events_url":"https://api.github.com/users/smacker/events{/privacy}","received_events_url":"https://api.github.com/users/smacker/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/src-d/lookout/pulls/57/commits","review_comments_url":"https://api.github.com/repos/src-d/lookout/pulls/57/comments","review_comment_url":"https://api.github.com/repos/src-d/lookout/pulls/comments{/number}","comments_url":"https://api.github.com/repos/src-d/lookout/issues/57/comments","statuses_url":"https://api.github.com/repos/src-d/lookout/statuses/5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed","head":{"label":"carlosms:console-provider","ref":"console-provider","sha":"5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed","user":{"login":"carlosms","id":1469173,"node_id":"MDQ6VXNlcjE0NjkxNzM=","avatar_url":"https://avatars0.githubusercontent.com/u/1469173?v=4","gravatar_id":"","url":"https://api.github.com/users/carlosms","html_url":"https://github.com/carlosms","followers_url":"https://api.github.com/users/carlosms/followers","following_url":"https://api.github.com/users/carlosms/following{/other_user}","gists_url":"https://api.github.com/users/carlosms/gists{/gist_id}","starred_url":"https://api.github.com/users/carlosms/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carlosms/subscriptions","organizations_url":"https://api.github.com/users/carlosms/orgs","repos_url":"https://api.github.com/users/carlosms/repos","events_url":"https://api.github.com/users/carlosms/events{/privacy}","received_events_url":"https://api.github.com/users/carlosms/received_events","type":"User","site_admin":false},"repo":{"id":141594755,"node_id":"MDEwOlJlcG9zaXRvcnkxNDE1OTQ3NTU=","name":"lookout","full_name":"carlosms/lookout","owner":{"login":"carlosms","id":1469173,"node_id":"MDQ6VXNlcjE0NjkxNzM=","avatar_url":"https://avatars0.githubusercontent.com/u/1469173?v=4","gravatar_id":"","url":"https://api.github.com/users/carlosms","html_url":"https://github.com/carlosms","followers_url":"https://api.github.com/users/carlosms/followers","following_url":"https://api.github.com/users/carlosms/following{/other_user}","gists_url":"https://api.github.com/users/carlosms/gists{/gist_id}","starred_url":"https://api.github.com/users/carlosms/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carlosms/subscriptions","organizations_url":"https://api.github.com/users/carlosms/orgs","repos_url":"https://api.github.com/users/carlosms/repos","events_url":"https://api.github.com/users/carlosms/events{/privacy}","received_events_url":"https://api.github.com/users/carlosms/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/carlosms/lookout","description":"Just a prototype, nothing very relevant.","fork":true,"url":"https://api.github.com/repos/carlosms/lookout","forks_url":"https://api.github.com/repos/carlosms/lookout/forks","keys_url":"https://api.github.com/repos/carlosms/lookout/keys{/key_id}","collaborators_url":"https://api.github.com/repos/carlosms/lookout/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/carlosms/lookout/teams","hooks_url":"https://api.github.com/repos/carlosms/lookout/hooks","issue_events_url":"https://api.github.com/repos/carlosms/lookout/issues/events{/number}","events_url":"https://api.github.com/repos/carlosms/lookout/events","assignees_url":"https://api.github.com/repos/carlosms/lookout/assignees{/user}","branches_url":"https://api.github.com/repos/carlosms/lookout/branches{/branch}","tags_url":"https://api.github.com/repos/carlosms/lookout/tags","blobs_url":"https://api.github.com/repos/carlosms/lookout/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/carlosms/lookout/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/carlosms/lookout/git/refs{/sha}","trees_url":"https://api.github.com/repos/carlosms/lookout/git/trees{/sha}","statuses_url":"https://api.github.com/repos/carlosms/lookout/statuses/{sha}","languages_url":"https://api.github.com/repos/carlosms/lookout/languages","stargazers_url":"https://api.github.com/repos/carlosms/lookout/stargazers","contributors_url":"https://api.github.com/repos/carlosms/lookout/contributors","subscribers_url":"https://api.github.com/repos/carlosms/lookout/subscribers","subscription_url":"https://api.github.com/repos/carlosms/lookout/subscription","commits_url":"https://api.github.com/repos/carlosms/lookout/commits{/sha}","git_commits_url":"https://api.github.com/repos/carlosms/lookout/git/commits{/sha}","comments_url":"https://api.github.com/repos/carlosms/lookout/comments{/number}","issue_comment_url":"https://api.github.com/repos/carlosms/lookout/issues/comments{/number}","contents_url":"https://api.github.com/repos/carlosms/lookout/contents/{+path}","compare_url":"https://api.github.com/repos/carlosms/lookout/compare/{base}...{head}","merges_url":"https://api.github.com/repos/carlosms/lookout/merges","archive_url":"https://api.github.com/repos/carlosms/lookout/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/carlosms/lookout/downloads","issues_url":"https://api.github.com/repos/carlosms/lookout/issues{/number}","pulls_url":"https://api.github.com/repos/carlosms/lookout/pulls{/number}","milestones_url":"https://api.github.com/repos/carlosms/lookout/milestones{/number}","notifications_url":"https://api.github.com/repos/carlosms/lookout/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/carlosms/lookout/labels{/name}","releases_url":"https://api.github.com/repos/carlosms/lookout/releases{/id}","deployments_url":"https://api.github.com/repos/carlosms/lookout/deployments","created_at":"2018-07-19T14:57:03Z","updated_at":"2018-07-25T10:48:08Z","pushed_at":"2018-07-25T12:09:53Z","git_url":"git://github.com/carlosms/lookout.git","ssh_url":"git@github.com:carlosms/lookout.git","clone_url":"https://github.com/carlosms/lookout.git","svn_url":"https://github.com/carlosms/lookout","homepage":"","size":52329,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"agpl-3.0","name":"GNU Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"src-d:master","ref":"master","sha":"0ac15b52f3ea4e3f22f347904547c3651dc26f5e","user":{"login":"src-d","id":15128793,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1MTI4Nzkz","avatar_url":"https://avatars2.githubusercontent.com/u/15128793?v=4","gravatar_id":"","url":"https://api.github.com/users/src-d","html_url":"https://github.com/src-d","followers_url":"https://api.github.com/users/src-d/followers","following_url":"https://api.github.com/users/src-d/following{/other_user}","gists_url":"https://api.github.com/users/src-d/gists{/gist_id}","starred_url":"https://api.github.com/users/src-d/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/src-d/subscriptions","organizations_url":"https://api.github.com/users/src-d/orgs","repos_url":"https://api.github.com/users/src-d/repos","events_url":"https://api.github.com/users/src-d/events{/privacy}","received_events_url":"https://api.github.com/users/src-d/received_events","type":"Organization","site_admin":false},"repo":{"id":136146572,"node_id":"MDEwOlJlcG9zaXRvcnkxMzYxNDY1NzI=","name":"lookout","full_name":"src-d/lookout","owner":{"login":"src-d","id":15128793,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1MTI4Nzkz","avatar_url":"https://avatars2.githubusercontent.com/u/15128793?v=4","gravatar_id":"","url":"https://api.github.com/users/src-d","html_url":"https://github.com/src-d","followers_url":"https://api.github.com/users/src-d/followers","following_url":"https://api.github.com/users/src-d/following{/other_user}","gists_url":"https://api.github.com/users/src-d/gists{/gist_id}","starred_url":"https://api.github.com/users/src-d/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/src-d/subscriptions","organizations_url":"https://api.github.com/users/src-d/orgs","repos_url":"https://api.github.com/users/src-d/repos","events_url":"https://api.github.com/users/src-d/events{/privacy}","received_events_url":"https://api.github.com/users/src-d/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/src-d/lookout","description":"Assisted Code Review","fork":false,"url":"https://api.github.com/repos/src-d/lookout","forks_url":"https://api.github.com/repos/src-d/lookout/forks","keys_url":"https://api.github.com/repos/src-d/lookout/keys{/key_id}","collaborators_url":"https://api.github.com/repos/src-d/lookout/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/src-d/lookout/teams","hooks_url":"https://api.github.com/repos/src-d/lookout/hooks","issue_events_url":"https://api.github.com/repos/src-d/lookout/issues/events{/number}","events_url":"https://api.github.com/repos/src-d/lookout/events","assignees_url":"https://api.github.com/repos/src-d/lookout/assignees{/user}","branches_url":"https://api.github.com/repos/src-d/lookout/branches{/branch}","tags_url":"https://api.github.com/repos/src-d/lookout/tags","blobs_url":"https://api.github.com/repos/src-d/lookout/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/src-d/lookout/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/src-d/lookout/git/refs{/sha}","trees_url":"https://api.github.com/repos/src-d/lookout/git/trees{/sha}","statuses_url":"https://api.github.com/repos/src-d/lookout/statuses/{sha}","languages_url":"https://api.github.com/repos/src-d/lookout/languages","stargazers_url":"https://api.github.com/repos/src-d/lookout/stargazers","contributors_url":"https://api.github.com/repos/src-d/lookout/contributors","subscribers_url":"https://api.github.com/repos/src-d/lookout/subscribers","subscription_url":"https://api.github.com/repos/src-d/lookout/subscription","commits_url":"https://api.github.com/repos/src-d/lookout/commits{/sha}","git_commits_url":"https://api.github.com/repos/src-d/lookout/git/commits{/sha}","comments_url":"https://api.github.com/repos/src-d/lookout/comments{/number}","issue_comment_url":"https://api.github.com/repos/src-d/lookout/issues/comments{/number}","contents_url":"https://api.github.com/repos/src-d/lookout/contents/{+path}","compare_url":"https://api.github.com/repos/src-d/lookout/compare/{base}...{head}","merges_url":"https://api.github.com/repos/src-d/lookout/merges","archive_url":"https://api.github.com/repos/src-d/lookout/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/src-d/lookout/downloads","issues_url":"https://api.github.com/repos/src-d/lookout/issues{/number}","pulls_url":"https://api.github.com/repos/src-d/lookout/pulls{/number}","milestones_url":"https://api.github.com/repos/src-d/lookout/milestones{/number}","notifications_url":"https://api.github.com/repos/src-d/lookout/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/src-d/lookout/labels{/name}","releases_url":"https://api.github.com/repos/src-d/lookout/releases{/id}","deployments_url":"https://api.github.com/repos/src-d/lookout/deployments","created_at":"2018-06-05T08:37:23Z","updated_at":"2018-07-25T15:50:30Z","pushed_at":"2018-07-25T15:50:28Z","git_url":"git://github.com/src-d/lookout.git","ssh_url":"git@github.com:src-d/lookout.git","clone_url":"https://github.com/src-d/lookout.git","svn_url":"https://github.com/src-d/lookout","homepage":"","size":52322,"stargazers_count":4,"watchers_count":4,"language":"Go","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":13,"license":{"key":"agpl-3.0","name":"GNU Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"forks":5,"open_issues":13,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/src-d/lookout/pulls/57"},"html":{"href":"https://github.com/src-d/lookout/pull/57"},"issue":{"href":"https://api.github.com/repos/src-d/lookout/issues/57"},"comments":{"href":"https://api.github.com/repos/src-d/lookout/issues/57/comments"},"review_comments":{"href":"https://api.github.com/repos/src-d/lookout/pulls/57/comments"},"review_comment":{"href":"https://api.github.com/repos/src-d/lookout/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/src-d/lookout/pulls/57/commits"},"statuses":{"href":"https://api.github.com/repos/src-d/lookout/statuses/5ed66cc9ebcc62bed0c58e9b376f4d9baf2122ed"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"bzz"}}