github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/cmd/swarm/manifest.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Command  MANIFEST update
    18  package main
    19  
    20  import (
    21  	"gopkg.in/urfave/cli.v1"
    22  	"log"
    23  	"mime"
    24  	"path/filepath"
    25  	"strings"
    26  	"fmt"
    27  	"encoding/json"
    28  )
    29  
    30  func add(ctx *cli.Context) {
    31  
    32  	args := ctx.Args()
    33  	if len(args) < 3 {
    34  		log.Fatal("need atleast three arguments <MHASH> <path> <HASH> [<content-type>]")
    35  	}
    36  
    37  	var (
    38  		mhash  = args[0]
    39  		path   = args[1]
    40  		hash   = args[2]
    41  
    42  		ctype  string
    43  		wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
    44  		mroot  manifest
    45  	)
    46  
    47  
    48  	if len(args) > 3 {
    49  		ctype = args[3]
    50  	} else {
    51  		ctype = mime.TypeByExtension(filepath.Ext(path))
    52  	}
    53  
    54  	newManifest := addEntryToManifest (ctx, mhash, path, hash, ctype)
    55  	fmt.Println(newManifest)
    56  
    57  	if !wantManifest {
    58  		// Print the manifest. This is the only output to stdout.
    59  		mrootJSON, _ := json.MarshalIndent(mroot, "", "  ")
    60  		fmt.Println(string(mrootJSON))
    61  		return
    62  	}
    63  }
    64  
    65  func update(ctx *cli.Context) {
    66  
    67  	args := ctx.Args()
    68  	if len(args) < 3 {
    69  		log.Fatal("need atleast three arguments <MHASH> <path> <HASH>")
    70  	}
    71  
    72  	var (
    73  		mhash  = args[0]
    74  		path   = args[1]
    75  		hash   = args[2]
    76  
    77  		ctype  string
    78  		wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
    79  		mroot  manifest
    80  	)
    81  	if len(args) > 3 {
    82  		ctype = args[3]
    83  	} else {
    84  		ctype = mime.TypeByExtension(filepath.Ext(path))
    85  	}
    86  
    87  	newManifest := updateEntryInManifest (ctx, mhash, path, hash, ctype)
    88  	fmt.Println(newManifest)
    89  
    90  	if !wantManifest {
    91  		// Print the manifest. This is the only output to stdout.
    92  		mrootJSON, _ := json.MarshalIndent(mroot, "", "  ")
    93  		fmt.Println(string(mrootJSON))
    94  		return
    95  	}
    96  }
    97  
    98  func remove(ctx *cli.Context) {
    99  	args := ctx.Args()
   100  	if len(args) < 2 {
   101  		log.Fatal("need atleast two arguments <MHASH> <path>")
   102  	}
   103  
   104  	var (
   105  		mhash  = args[0]
   106  		path   = args[1]
   107  
   108  		wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
   109  		mroot  manifest
   110  	)
   111  
   112  	newManifest := removeEntryFromManifest (ctx, mhash, path)
   113  	fmt.Println(newManifest)
   114  
   115  	if !wantManifest {
   116  		// Print the manifest. This is the only output to stdout.
   117  		mrootJSON, _ := json.MarshalIndent(mroot, "", "  ")
   118  		fmt.Println(string(mrootJSON))
   119  		return
   120  	}
   121  }
   122  
   123  func addEntryToManifest(ctx *cli.Context, mhash , path, hash , ctype string)  string {
   124  
   125  	var (
   126  		bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   127  		client = &client{api: bzzapi}
   128  		longestPathEntry = manifestEntry{
   129  			Path:        "",
   130  			Hash:        "",
   131  			ContentType:  "",
   132  		}
   133  	)
   134  
   135  	mroot, err := client.downloadManifest(mhash)
   136  	if err != nil {
   137  		log.Fatalln("manifest download failed:", err)
   138  	}
   139  
   140  	//TODO: check if the "hash" to add is valid and present in swarm
   141  	_, err = client.downloadManifest(hash)
   142  	if err != nil {
   143  		log.Fatalln("hash to add is not present:", err)
   144  	}
   145  
   146  
   147  	// See if we path is in this Manifest or do we have to dig deeper
   148  	for _, entry := range mroot.Entries {
   149  		if path == entry.Path {
   150  			log.Fatal(path, "Already present, not adding anything")
   151  		}else {
   152  			if entry.ContentType == "application/bzz-manifest+json" {
   153  				prfxlen := strings.HasPrefix(path, entry.Path)
   154  				if prfxlen && len(path) > len(longestPathEntry.Path) {
   155  					longestPathEntry = entry
   156  				}
   157  			}
   158  		}
   159  	}
   160  
   161  	if longestPathEntry.Path != "" {
   162  		// Load the child Manifest add the entry there
   163  		newPath := path[len(longestPathEntry.Path):]
   164  		newHash := addEntryToManifest (ctx, longestPathEntry.Hash, newPath, hash, ctype)
   165  
   166  		// Replace the hash for parent Manifests
   167  		newMRoot := manifest{}
   168  		for _, entry := range mroot.Entries {
   169  			if longestPathEntry.Path == entry.Path {
   170  				entry.Hash = newHash
   171  			}
   172  			newMRoot.Entries = append(newMRoot.Entries, entry)
   173  		}
   174  		mroot = newMRoot
   175  	} else {
   176  		// Add the entry in the leaf Manifest
   177  		newEntry := manifestEntry{
   178  			Path:        path,
   179  			Hash:        hash,
   180  			ContentType: ctype,
   181  		}
   182  		mroot.Entries = append(mroot.Entries, newEntry)
   183  	}
   184  
   185  
   186  	newManifestHash, err := client.uploadManifest(mroot)
   187  	if err != nil {
   188  		log.Fatalln("manifest upload failed:", err)
   189  	}
   190  	return newManifestHash
   191  
   192  
   193  
   194  }
   195  
   196  func updateEntryInManifest(ctx *cli.Context, mhash , path, hash , ctype string) string {
   197  
   198  	var (
   199  		bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   200  		client = &client{api: bzzapi}
   201  		newEntry = manifestEntry{
   202  			Path:        "",
   203  			Hash:        "",
   204  			ContentType:  "",
   205  		}
   206  		longestPathEntry = manifestEntry{
   207  			Path:        "",
   208  			Hash:        "",
   209  			ContentType:  "",
   210  		}
   211  	)
   212  
   213  	mroot, err := client.downloadManifest(mhash)
   214  	if err != nil {
   215  		log.Fatalln("manifest download failed:", err)
   216  	}
   217  
   218  	//TODO: check if the "hash" with which to update is valid and present in swarm
   219  
   220  
   221  	// See if we path is in this Manifest or do we have to dig deeper
   222  	for _, entry := range mroot.Entries {
   223  		if path == entry.Path {
   224  			newEntry = entry
   225  		}else {
   226  			if entry.ContentType == "application/bzz-manifest+json" {
   227  				prfxlen := strings.HasPrefix(path, entry.Path)
   228  				if prfxlen && len(path) > len(longestPathEntry.Path) {
   229  					longestPathEntry = entry
   230  				}
   231  			}
   232  		}
   233  	}
   234  
   235  	if longestPathEntry.Path == "" && newEntry.Path == "" {
   236  		log.Fatal(path, " Path not present in the Manifest, not setting anything")
   237  	}
   238  
   239  	if longestPathEntry.Path != "" {
   240  		// Load the child Manifest add the entry there
   241  		newPath := path[len(longestPathEntry.Path):]
   242  		newHash := updateEntryInManifest (ctx, longestPathEntry.Hash, newPath, hash, ctype)
   243  
   244  		// Replace the hash for parent Manifests
   245  		newMRoot := manifest{}
   246  		for _, entry := range mroot.Entries {
   247  			if longestPathEntry.Path == entry.Path {
   248  				entry.Hash = newHash
   249  			}
   250  			newMRoot.Entries = append(newMRoot.Entries, entry)
   251  
   252  		}
   253  		mroot = newMRoot
   254  	}
   255  
   256  	if newEntry.Path != "" {
   257  		// Replace the hash for leaf Manifest
   258  		newMRoot := manifest{}
   259  		for _, entry := range mroot.Entries {
   260  			if newEntry.Path == entry.Path {
   261  				myEntry := manifestEntry{
   262  					Path:        entry.Path,
   263  					Hash:        hash,
   264  					ContentType: ctype,
   265  				}
   266  				newMRoot.Entries = append(newMRoot.Entries, myEntry)
   267  			} else {
   268  				newMRoot.Entries = append(newMRoot.Entries, entry)
   269  			}
   270  		}
   271  		mroot = newMRoot
   272  	}
   273  
   274  
   275  	newManifestHash, err := client.uploadManifest(mroot)
   276  	if err != nil {
   277  		log.Fatalln("manifest upload failed:", err)
   278  	}
   279  	return newManifestHash
   280  }
   281  
   282  func removeEntryFromManifest(ctx *cli.Context, mhash , path string) string {
   283  
   284  	var (
   285  		bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   286  		client = &client{api: bzzapi}
   287  		entryToRemove = manifestEntry{
   288  			Path:        "",
   289  			Hash:        "",
   290  			ContentType:  "",
   291  		}
   292  		longestPathEntry = manifestEntry{
   293  			Path:        "",
   294  			Hash:        "",
   295  			ContentType:  "",
   296  		}
   297  	)
   298  
   299  	mroot, err := client.downloadManifest(mhash)
   300  	if err != nil {
   301  		log.Fatalln("manifest download failed:", err)
   302  	}
   303  
   304  
   305  
   306  	// See if we path is in this Manifest or do we have to dig deeper
   307  	for _, entry := range mroot.Entries {
   308  		if path == entry.Path {
   309  			entryToRemove = entry
   310  		}else {
   311  			if entry.ContentType == "application/bzz-manifest+json" {
   312  				prfxlen := strings.HasPrefix(path, entry.Path)
   313  				if prfxlen && len(path) > len(longestPathEntry.Path) {
   314  					longestPathEntry = entry
   315  				}
   316  			}
   317  		}
   318  	}
   319  
   320  	if longestPathEntry.Path == "" && entryToRemove.Path == "" {
   321  		log.Fatal(path, "Path not present in the Manifest, not removing anything")
   322  	}
   323  
   324  	if longestPathEntry.Path != "" {
   325  		// Load the child Manifest remove the entry there
   326  		newPath := path[len(longestPathEntry.Path):]
   327  		newHash := removeEntryFromManifest (ctx, longestPathEntry.Hash, newPath)
   328  
   329  		// Replace the hash for parent Manifests
   330  		newMRoot := manifest{}
   331  		for _, entry := range mroot.Entries {
   332  			if longestPathEntry.Path == entry.Path {
   333  				entry.Hash = newHash
   334  			}
   335  			newMRoot.Entries = append(newMRoot.Entries, entry)
   336  		}
   337  		mroot = newMRoot
   338  	}
   339  
   340  	if entryToRemove.Path != "" {
   341  		// remove the entry in this Manifest
   342  		newMRoot := manifest{}
   343  		for _, entry := range mroot.Entries {
   344  			if entryToRemove.Path != entry.Path {
   345  				newMRoot.Entries = append(newMRoot.Entries, entry)
   346  			}
   347  		}
   348  		mroot = newMRoot
   349  	}
   350  
   351  
   352  	newManifestHash, err := client.uploadManifest(mroot)
   353  	if err != nil {
   354  		log.Fatalln("manifest upload failed:", err)
   355  	}
   356  	return newManifestHash
   357  
   358  
   359  }
   360