// Resursively add a directory to IPFS and return the root hash func AddDirectory(ctx commands.Context, fpath string) (string, error) { _, root := path.Split(fpath) args := []string{"add", "-r", fpath} req, cmd, err := NewRequest(ctx, args) if err != nil { return "", err } res := commands.NewResponse(req) cmd.PreRun(req) cmd.Run(req, res) var rootHash string for r := range res.Output().(<-chan interface{}) { if r.(*coreunix.AddedObject).Name == root { rootHash = r.(*coreunix.AddedObject).Hash } } cmd.PostRun(req, res) if res.Error() != nil { return "", res.Error() } if rootHash == "" { return "", addErr } return rootHash, nil }
// Recursively un-pin a directory given it's hash. // This will allow it to be garbage collected. func UnPinDir(ctx commands.Context, rootHash string) error { args := []string{"pin", "rm", rootHash} req, cmd, err := NewRequest(ctx, args) if err != nil { return err } res := commands.NewResponse(req) cmd.Run(req, res) if res.Error() != nil { return res.Error() } return nil }
func ConnectedPeers(ctx commands.Context) ([]string, error) { args := []string{"swarm", "peers"} req, cmd, err := NewRequest(ctx, args) if err != nil { return nil, err } res := commands.NewResponse(req) cmd.Run(req, res) if res.Error() != nil { return nil, res.Error() } return res.Output().([]string), nil }
// Publish a signed IPNS record to our Peer ID func Publish(ctx commands.Context, hash string) (string, error) { args := []string{"name", "publish", hash} req, cmd, err := NewRequest(ctx, args) if err != nil { return "", err } res := commands.NewResponse(req) cmd.Run(req, res) resp := res.Output() returnedVal := resp.(*coreCmds.IpnsEntry).Value if res.Error() != nil { return "", res.Error() } if returnedVal != hash { return "", pubErr } log.Infof("Published %s to IPNS", hash) return returnedVal, nil }
// Fetch data from IPFS given the hash func Cat(ctx commands.Context, hash string) ([]byte, error) { args := []string{"cat", hash} req, cmd, err := NewRequest(ctx, args) if err != nil { return nil, err } res := commands.NewResponse(req) cmd.Run(req, res) if res.Error() != nil { return nil, res.Error() } resp := res.Output() reader := resp.(io.Reader) b := make([]byte, res.Length()) _, err = reader.Read(b) if err != nil { return nil, err } return b, nil }
func AddFile(ctx commands.Context, fpath string) (string, error) { args := []string{"add", fpath} req, cmd, err := NewRequest(ctx, args) if err != nil { return "", err } res := commands.NewResponse(req) cmd.PreRun(req) cmd.Run(req, res) var fileHash string for r := range res.Output().(<-chan interface{}) { fileHash = r.(*coreunix.AddedObject).Hash } cmd.PostRun(req, res) if res.Error() != nil { return "", res.Error() } if fileHash == "" { return "", addErr } return fileHash, nil }
// getResponse decodes a http.Response to create a cmds.Response func getResponse(httpRes *http.Response, req cmds.Request) (cmds.Response, error) { var err error res := cmds.NewResponse(req) contentType := httpRes.Header.Get(contentTypeHeader) contentType = strings.Split(contentType, ";")[0] lengthHeader := httpRes.Header.Get(extraContentLengthHeader) if len(lengthHeader) > 0 { length, err := strconv.ParseUint(lengthHeader, 10, 64) if err != nil { return nil, err } res.SetLength(length) } rr := &httpResponseReader{httpRes} res.SetCloser(rr) if contentType != applicationJson { // for all non json output types, just stream back the output res.SetOutput(rr) return res, nil } else if len(httpRes.Header.Get(channelHeader)) > 0 { // if output is coming from a channel, decode each chunk outChan := make(chan interface{}) go readStreamedJson(req, rr, outChan) res.SetOutput((<-chan interface{})(outChan)) return res, nil } dec := json.NewDecoder(rr) // If we ran into an error if httpRes.StatusCode >= http.StatusBadRequest { e := cmds.Error{} switch { case httpRes.StatusCode == http.StatusNotFound: // handle 404s e.Message = "Command not found." e.Code = cmds.ErrClient case contentType == plainText: // handle non-marshalled errors mes, err := ioutil.ReadAll(rr) if err != nil { return nil, err } e.Message = string(mes) e.Code = cmds.ErrNormal default: // handle marshalled errors err = dec.Decode(&e) if err != nil { return nil, err } } res.SetError(e, e.Code) return res, nil } outputType := reflect.TypeOf(req.Command().Type) v, err := decodeTypedVal(outputType, dec) if err != nil && err != io.EOF { return nil, err } res.SetOutput(v) return res, nil }
// getResponse decodes a http.Response to create a cmds.Response func getResponse(httpRes *http.Response, req cmds.Request) (cmds.Response, error) { var err error res := cmds.NewResponse(req) contentType := httpRes.Header.Get(contentTypeHeader) contentType = strings.Split(contentType, ";")[0] lengthHeader := httpRes.Header.Get(contentLengthHeader) if len(lengthHeader) > 0 { length, err := strconv.ParseUint(lengthHeader, 10, 64) if err != nil { return nil, err } res.SetLength(length) } if len(httpRes.Header.Get(streamHeader)) > 0 { // if output is a stream, we can just use the body reader res.SetOutput(httpRes.Body) return res, nil } else if len(httpRes.Header.Get(channelHeader)) > 0 { // if output is coming from a channel, decode each chunk outChan := make(chan interface{}) go func() { dec := json.NewDecoder(httpRes.Body) outputType := reflect.TypeOf(req.Command().Type) ctx := req.Context().Context for { var v interface{} var err error if outputType != nil { v = reflect.New(outputType).Interface() err = dec.Decode(v) } else { err = dec.Decode(&v) } if err != nil && err != io.EOF { fmt.Println(err.Error()) return } select { case <-ctx.Done(): close(outChan) return default: } if err == io.EOF { close(outChan) return } outChan <- v } }() res.SetOutput((<-chan interface{})(outChan)) return res, nil } dec := json.NewDecoder(httpRes.Body) if httpRes.StatusCode >= http.StatusBadRequest { e := cmds.Error{} if httpRes.StatusCode == http.StatusNotFound { // handle 404s e.Message = "Command not found." e.Code = cmds.ErrClient } else if contentType == "text/plain" { // handle non-marshalled errors buf := bytes.NewBuffer(nil) io.Copy(buf, httpRes.Body) e.Message = string(buf.Bytes()) e.Code = cmds.ErrNormal } else { // handle marshalled errors err = dec.Decode(&e) if err != nil { return nil, err } } res.SetError(e, e.Code) } else { outputType := reflect.TypeOf(req.Command().Type) var v interface{} if outputType != nil { v = reflect.New(outputType).Interface() err = dec.Decode(v) } else { err = dec.Decode(&v) } if err != nil && err != io.EOF { return nil, err } if v != nil { res.SetOutput(v) } } return res, nil }