gitlab.nesad.fit.vutbr.cz/blended/libblended@v0.0.0-20221202124402-2bee159339df/ipfs/link.go (about)

     1  package ipfs
     2  
     3  import (
     4  	"path/filepath"
     5  	"strings"
     6  )
     7  
     8  func (c *IpfsClient) Link(path string, name string, ipfsHash string) (string, error) {
     9  	// check if the file exists
    10  	_, err := c.Stat(ipfsHash)
    11  	if err != nil {
    12  		return "", err
    13  	}
    14  
    15  	// unpin old IPFS hash
    16  	oldHash := strings.SplitN(path, "/", 2)[0]
    17  	err = c.Shell.Unpin(oldHash)
    18  	if err != nil {
    19  		return "", err
    20  	}
    21  
    22  	newHash, err := c.patchLink(path, name, ipfsHash)
    23  	if err != nil {
    24  		return "", err
    25  	}
    26  
    27  	err = c.Shell.Pin(path)
    28  	if err != nil {
    29  		return "", err
    30  	}
    31  
    32  	return newHash, nil
    33  }
    34  
    35  func (c *IpfsClient) patchLink(root string, linkName string, linkHash string) (string, error) {
    36  	var rmLink struct {
    37  		Hash string
    38  	}
    39  
    40  	ctx, cancel := c.getContext()
    41  	err := c.Shell.Request("object/patch/add-link", root, linkName, linkHash).
    42  		Option("create", true).
    43  		Exec(ctx, &rmLink)
    44  	cancel()
    45  	return rmLink.Hash, err
    46  }
    47  
    48  // this function recursive patches link.
    49  // example: we have IPFS directory structure consisting of multiple subfolders /a/b/c/d/e
    50  // if e changed its hash, we need to patch link d->e to point to new hash of e
    51  // than we need to patch link c->d to points to new d that points to new e and so on...
    52  func (c *IpfsClient) recursivePatchLink(path string, name string, hash string) (string, error) {
    53  	//  Dir returns "." when path is empty
    54  	if path == "." {
    55  		return hash, nil
    56  	} else {
    57  		// update link to point to new hash
    58  		newHash, err := c.patchLink(filepath.ToSlash(path), name, hash)
    59  		if err != nil {
    60  			return "", err
    61  		}
    62  
    63  		pathWithoutLastElement := filepath.Dir(path)
    64  		lastName := filepath.Base(path)
    65  
    66  		return c.recursivePatchLink(pathWithoutLastElement, lastName, newHash)
    67  	}
    68  }
    69  
    70  func (c *IpfsClient) removeLink(hash string, linkName string) (string, error) {
    71  	var rmLink struct {
    72  		Hash string
    73  	}
    74  
    75  	ctx, cancel := c.getContext()
    76  	err := c.Shell.Request("object/patch/rm-link", hash, linkName).
    77  		Exec(ctx, &rmLink)
    78  	cancel()
    79  
    80  	if err != nil {
    81  		return "", err
    82  	}
    83  	return rmLink.Hash, err
    84  }