gitlab.nesad.fit.vutbr.cz/blended/libblended@v0.0.0-20221202124402-2bee159339df/ipfs/utils.go (about) 1 package ipfs 2 3 import ( 4 "context" 5 shell "github.com/ipfs/go-ipfs-api" 6 files "github.com/ipfs/go-ipfs-files" 7 "path/filepath" 8 "strings" 9 "time" 10 ) 11 12 type IpfsStat struct { 13 BlockSize int 14 CumulativeSize int 15 DataSize int 16 Hash string 17 LinksSize int 18 NumLinks int 19 Type string 20 } 21 22 func (stat IpfsStat) GetType() int { 23 if stat.Type == "directory" { 24 return shell.TDirectory 25 } else if stat.Type == "file" { 26 return shell.TFile 27 } 28 29 return shell.TRaw 30 } 31 32 func (c *IpfsClient) Stat(hash string) (*IpfsStat, error) { 33 var stat IpfsStat 34 ctx, cancel := c.getContext() 35 err := c.Shell.Request("files/stat", "/ipfs/"+hash). 36 Exec(ctx, &stat) 37 cancel() 38 39 if err != nil { 40 return nil, err 41 } 42 43 return &stat, err 44 } 45 46 func (c *IpfsClient) Move(ipfsRoot string, path string, ipfsObject string) (string, error) { 47 // if there is no path where we want to move ipfs object, return only original ipfs object hash 48 if path == "" { 49 return ipfsObject, nil 50 } 51 52 // save empty object to IPFS because we want to add link to it later 53 emptyFolder, err := c.CreateEmptyFolder() 54 if err != nil { 55 return "", err 56 } 57 58 // if there is no ipfsRoot, create directories in empty object 59 if ipfsRoot == "" { 60 ipfsRoot = emptyFolder 61 } 62 63 links := strings.Split(path, "/") 64 createdPath := "" 65 for _, link := range links[:len(links)-1] { 66 hasLink, err := c.hasLink(c.JoinPaths(ipfsRoot, createdPath), link) 67 if err != nil { 68 return "", err 69 } 70 if !hasLink { 71 ipfsRoot, err = c.recursivePatchLink(c.JoinPaths(ipfsRoot, createdPath), link, emptyFolder) 72 if err != nil { 73 return "", err 74 } 75 } 76 createdPath = c.JoinPaths(createdPath, link) 77 } 78 79 result, err := c.recursivePatchLink(c.JoinPaths(ipfsRoot, createdPath), links[len(links)-1], ipfsObject) 80 if err != nil { 81 return "", err 82 } 83 84 return result, nil 85 } 86 87 func (c *IpfsClient) hasLink(ipfsHash string, link string) (bool, error) { 88 links, err := c.Ls(ipfsHash) 89 if err != nil { 90 return false, err 91 } 92 93 for _, v := range links { 94 if v.Name == link { 95 return true, nil 96 } 97 } 98 99 return false, nil 100 } 101 102 func (c *IpfsClient) CreateEmptyFolder() (string, error) { 103 slf := files.NewSliceDirectory([]files.DirEntry{ 104 files.FileEntry("", 105 files.NewSliceDirectory([]files.DirEntry{})), 106 }) 107 108 reader := files.NewMultiFileReader(slf, true) 109 var addEvent ipfsAddEvent 110 111 ctx, cancel := c.getContext() 112 err := c.Shell.Request("add"). 113 Option("pin", false). 114 Body(reader). 115 Exec(ctx, &addEvent) 116 cancel() 117 118 if err != nil { 119 return "", err 120 } 121 122 return addEvent.Hash, nil 123 } 124 125 func (c *IpfsClient) JoinPaths(paths ...string) string { 126 return filepath.ToSlash(filepath.Join(paths...)) 127 } 128 129 func (c *IpfsClient) IsUp() bool { 130 ver := struct { 131 Version string 132 Commit string 133 }{} 134 135 ctx, cancel := c.getContext() 136 err := c.Shell.Request("version").Exec(ctx, &ver) 137 cancel() // releases resources if request completes before timeout elapses 138 return err == nil 139 } 140 141 func (c *IpfsClient) getContext() (context.Context, context.CancelFunc) { 142 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 143 return ctx, cancel 144 }