{"action":"created","comment":{"url":"https://api.github.com/repos/ipfs/go-ipfs/pulls/comments/70587372","id":70587372,"diff_hunk":"@@ -185,3 +188,99 @@ func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) {\n \tlog.Debugf(\"ipfs block: got block with key: %q\", b.Key())\n \treturn b, nil\n }\n+\n+var blockRmCmd = &cmds.Command{\n+\tHelptext: cmds.HelpText{\n+\t\tTagline: \"Remove IPFS block(s).\",\n+\t\tShortDescription: `\n+'ipfs block put' is a plumbing command for removing raw ipfs blocks.\n+It takes a list of base58 encoded multihashs to remove.\n+`,\n+\t},\n+\tArguments: []cmds.Argument{\n+\t\tcmds.StringArg(\"hash\", true, true, \"Bash58 encoded multihash of block(s) to remove.\"),\n+\t},\n+\tOptions: []cmds.Option{\n+\t\tcmds.BoolOption(\"ignore-pins\", \"Ignore pins.\").Default(false),\n+\t},\n+\tRun: func(req cmds.Request, res cmds.Response) {\n+\t\tignorePins, _, err := req.Option(\"ignore-pins\").Bool()\n+\t\tif err != nil {\n+\t\t\tres.SetError(err, cmds.ErrNormal)\n+\t\t\treturn\n+\t\t}\n+\t\tn, err := req.InvocContext().GetNode()\n+\t\tif err != nil {\n+\t\t\tres.SetError(err, cmds.ErrNormal)\n+\t\t\treturn\n+\t\t}\n+\t\thashes := req.Arguments()\n+\t\tkeys := make([]key.Key, 0, len(hashes))\n+\t\tfor _, hash := range hashes {\n+\t\t\tk := key.B58KeyDecode(hash)\n+\t\t\tkeys = append(keys, k)\n+\t\t}\n+\t\trdr, wtr := io.Pipe()\n+\t\tgo func() {\n+\t\t\tpinning := n.Pinning\n+\t\t\tif ignorePins {\n+\t\t\t\tpinning = nil\n+\t\t\t}\n+\t\t\terr := rmBlocks(n.Blockstore, pinning, wtr, keys)\n+\t\t\tif err != nil {\n+\t\t\t\twtr.CloseWithError(fmt.Errorf(\"Some blocks not deleted: %s\", err))\n+\t\t\t} else {\n+\t\t\t\twtr.Close()\n+\t\t\t}\n+\t\t}()\n+\t\tres.SetOutput(rdr)\n+\t\treturn\n+\t},\n+\tMarshalers: cmds.MarshalerMap{\n+\t\tcmds.Text: func(res cmds.Response) (io.Reader, error) {\n+\t\t\treturn res.(io.Reader), nil\n+\t\t},\n+\t},\n+}\n+\n+type noopLocker struct{}\n+\n+func (noopLocker) Unlock() {}\n+\n+// pins may be nil\n+func rmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out io.Writer, keys []key.Key) error {\n+\tvar unlocker bs.Unlocker = noopLocker{}\n+\tdefer unlocker.Unlock()","path":"core/commands/block.go","position":85,"original_position":85,"commit_id":"36a6f93aee2a197f0375ab487971b3dcfc42b3a4","original_commit_id":"36a6f93aee2a197f0375ab487971b3dcfc42b3a4","user":{"login":"whyrusleeping","id":1243164,"avatar_url":"https://avatars.githubusercontent.com/u/1243164?v=3","gravatar_id":"","url":"https://api.github.com/users/whyrusleeping","html_url":"https://github.com/whyrusleeping","followers_url":"https://api.github.com/users/whyrusleeping/followers","following_url":"https://api.github.com/users/whyrusleeping/following{/other_user}","gists_url":"https://api.github.com/users/whyrusleeping/gists{/gist_id}","starred_url":"https://api.github.com/users/whyrusleeping/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whyrusleeping/subscriptions","organizations_url":"https://api.github.com/users/whyrusleeping/orgs","repos_url":"https://api.github.com/users/whyrusleeping/repos","events_url":"https://api.github.com/users/whyrusleeping/events{/privacy}","received_events_url":"https://api.github.com/users/whyrusleeping/received_events","type":"User","site_admin":false},"body":"this reference will be bound such that it will always be called on the noop lock, even when the value in the unlocker variable is changed. If you want to do things this way, you will need to capture the variable in a closure:\r\n```\r\ndefer func() {\r\n    unlocker.Unlock()\r\n}()\r\n```","created_at":"2016-07-13T08:53:31Z","updated_at":"2016-07-13T08:53:31Z","html_url":"https://github.com/ipfs/go-ipfs/pull/2962#discussion_r70587372","pull_request_url":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962","_links":{"self":{"href":"https://api.github.com/repos/ipfs/go-ipfs/pulls/comments/70587372"},"html":{"href":"https://github.com/ipfs/go-ipfs/pull/2962#discussion_r70587372"},"pull_request":{"href":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962"}}},"pull_request":{"url":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962","id":76884442,"html_url":"https://github.com/ipfs/go-ipfs/pull/2962","diff_url":"https://github.com/ipfs/go-ipfs/pull/2962.diff","patch_url":"https://github.com/ipfs/go-ipfs/pull/2962.patch","issue_url":"https://api.github.com/repos/ipfs/go-ipfs/issues/2962","number":2962,"state":"open","locked":false,"title":"[WIP] Add \"ipfs block rm\" command.","user":{"login":"kevina","id":1271492,"avatar_url":"https://avatars.githubusercontent.com/u/1271492?v=3","gravatar_id":"","url":"https://api.github.com/users/kevina","html_url":"https://github.com/kevina","followers_url":"https://api.github.com/users/kevina/followers","following_url":"https://api.github.com/users/kevina/following{/other_user}","gists_url":"https://api.github.com/users/kevina/gists{/gist_id}","starred_url":"https://api.github.com/users/kevina/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kevina/subscriptions","organizations_url":"https://api.github.com/users/kevina/orgs","repos_url":"https://api.github.com/users/kevina/repos","events_url":"https://api.github.com/users/kevina/events{/privacy}","received_events_url":"https://api.github.com/users/kevina/received_events","type":"User","site_admin":false},"body":"This is a basic implementation for #2914.\r\n\r\nIt accepts multiple blocks to remove, however that does not provide any performance benifit just yet as it calls `pins.IsPinned()` for each block, which traverses every recursive pin to check for indirect pins.  This operation costs is O(P*N) where P is the number of pinned blocks and N is the number of blocks to be removed.  With a little effort this can be brought down to O(P) by checking for multiple pins at once.\r\n\r\nSince the pin check is expensive it provides an option to ignore pins.  Removing a pinned block will break any command that checks for pins.  Right now if this happens recovering from the situation is very difficult.  At very least a command should be provided to list any broken or missing pins.  An additional optional command can be provided to attempt to repair recursive pins.\r\n\r\nTODO:\r\n- [ ] Provide command to check for multiple pins at once\r\n- [ ] Provide a `ipfs pin verify` command to list broken or missing pins\r\n\r\nOptional:\r\n- [ ] Provide a command to repair pins (I already wrote similar code in #2634)\r\n\r\n","created_at":"2016-07-10T21:44:04Z","updated_at":"2016-07-13T08:53:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e339f938ce3a4b1cc2933ecae3ec6a8aeb27c687","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962/commits","review_comments_url":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962/comments","review_comment_url":"https://api.github.com/repos/ipfs/go-ipfs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ipfs/go-ipfs/issues/2962/comments","statuses_url":"https://api.github.com/repos/ipfs/go-ipfs/statuses/36a6f93aee2a197f0375ab487971b3dcfc42b3a4","head":{"label":"ipfs:kevina/block-rm","ref":"kevina/block-rm","sha":"36a6f93aee2a197f0375ab487971b3dcfc42b3a4","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":21233191,"name":"go-ipfs","full_name":"ipfs/go-ipfs","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/go-ipfs","description":"IPFS implementation in go","fork":false,"url":"https://api.github.com/repos/ipfs/go-ipfs","forks_url":"https://api.github.com/repos/ipfs/go-ipfs/forks","keys_url":"https://api.github.com/repos/ipfs/go-ipfs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/go-ipfs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/go-ipfs/teams","hooks_url":"https://api.github.com/repos/ipfs/go-ipfs/hooks","issue_events_url":"https://api.github.com/repos/ipfs/go-ipfs/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/go-ipfs/events","assignees_url":"https://api.github.com/repos/ipfs/go-ipfs/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/go-ipfs/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/go-ipfs/tags","blobs_url":"https://api.github.com/repos/ipfs/go-ipfs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/go-ipfs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/go-ipfs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/go-ipfs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/go-ipfs/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/go-ipfs/languages","stargazers_url":"https://api.github.com/repos/ipfs/go-ipfs/stargazers","contributors_url":"https://api.github.com/repos/ipfs/go-ipfs/contributors","subscribers_url":"https://api.github.com/repos/ipfs/go-ipfs/subscribers","subscription_url":"https://api.github.com/repos/ipfs/go-ipfs/subscription","commits_url":"https://api.github.com/repos/ipfs/go-ipfs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/go-ipfs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/go-ipfs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/go-ipfs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/go-ipfs/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/go-ipfs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/go-ipfs/merges","archive_url":"https://api.github.com/repos/ipfs/go-ipfs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/go-ipfs/downloads","issues_url":"https://api.github.com/repos/ipfs/go-ipfs/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/go-ipfs/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/go-ipfs/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/go-ipfs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/go-ipfs/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/go-ipfs/releases{/id}","deployments_url":"https://api.github.com/repos/ipfs/go-ipfs/deployments","created_at":"2014-06-26T08:14:34Z","updated_at":"2016-07-12T22:25:52Z","pushed_at":"2016-07-12T12:06:37Z","git_url":"git://github.com/ipfs/go-ipfs.git","ssh_url":"git@github.com:ipfs/go-ipfs.git","clone_url":"https://github.com/ipfs/go-ipfs.git","svn_url":"https://github.com/ipfs/go-ipfs","homepage":"https://github.com/ipfs/ipfs","size":34106,"stargazers_count":2034,"watchers_count":2034,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":329,"mirror_url":null,"open_issues_count":532,"forks":329,"open_issues":532,"watchers":2034,"default_branch":"master"}},"base":{"label":"ipfs:master","ref":"master","sha":"4e67003f5ad1fb4973b7d38ab9122a7ebe0b8d4e","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":21233191,"name":"go-ipfs","full_name":"ipfs/go-ipfs","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/go-ipfs","description":"IPFS implementation in go","fork":false,"url":"https://api.github.com/repos/ipfs/go-ipfs","forks_url":"https://api.github.com/repos/ipfs/go-ipfs/forks","keys_url":"https://api.github.com/repos/ipfs/go-ipfs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/go-ipfs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/go-ipfs/teams","hooks_url":"https://api.github.com/repos/ipfs/go-ipfs/hooks","issue_events_url":"https://api.github.com/repos/ipfs/go-ipfs/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/go-ipfs/events","assignees_url":"https://api.github.com/repos/ipfs/go-ipfs/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/go-ipfs/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/go-ipfs/tags","blobs_url":"https://api.github.com/repos/ipfs/go-ipfs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/go-ipfs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/go-ipfs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/go-ipfs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/go-ipfs/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/go-ipfs/languages","stargazers_url":"https://api.github.com/repos/ipfs/go-ipfs/stargazers","contributors_url":"https://api.github.com/repos/ipfs/go-ipfs/contributors","subscribers_url":"https://api.github.com/repos/ipfs/go-ipfs/subscribers","subscription_url":"https://api.github.com/repos/ipfs/go-ipfs/subscription","commits_url":"https://api.github.com/repos/ipfs/go-ipfs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/go-ipfs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/go-ipfs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/go-ipfs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/go-ipfs/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/go-ipfs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/go-ipfs/merges","archive_url":"https://api.github.com/repos/ipfs/go-ipfs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/go-ipfs/downloads","issues_url":"https://api.github.com/repos/ipfs/go-ipfs/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/go-ipfs/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/go-ipfs/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/go-ipfs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/go-ipfs/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/go-ipfs/releases{/id}","deployments_url":"https://api.github.com/repos/ipfs/go-ipfs/deployments","created_at":"2014-06-26T08:14:34Z","updated_at":"2016-07-12T22:25:52Z","pushed_at":"2016-07-12T12:06:37Z","git_url":"git://github.com/ipfs/go-ipfs.git","ssh_url":"git@github.com:ipfs/go-ipfs.git","clone_url":"https://github.com/ipfs/go-ipfs.git","svn_url":"https://github.com/ipfs/go-ipfs","homepage":"https://github.com/ipfs/ipfs","size":34106,"stargazers_count":2034,"watchers_count":2034,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":329,"mirror_url":null,"open_issues_count":532,"forks":329,"open_issues":532,"watchers":2034,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962"},"html":{"href":"https://github.com/ipfs/go-ipfs/pull/2962"},"issue":{"href":"https://api.github.com/repos/ipfs/go-ipfs/issues/2962"},"comments":{"href":"https://api.github.com/repos/ipfs/go-ipfs/issues/2962/comments"},"review_comments":{"href":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962/comments"},"review_comment":{"href":"https://api.github.com/repos/ipfs/go-ipfs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ipfs/go-ipfs/pulls/2962/commits"},"statuses":{"href":"https://api.github.com/repos/ipfs/go-ipfs/statuses/36a6f93aee2a197f0375ab487971b3dcfc42b3a4"}}}}
{"actor":{"display_login":"whyrusleeping"}}