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  }