github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/swarm/manifest.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:31</date>
    10  //</624342605999640576>
    11  
    12  
    13  //
    14  package main
    15  
    16  import (
    17  	"fmt"
    18  	"os"
    19  	"strings"
    20  
    21  	"github.com/ethereum/go-ethereum/cmd/utils"
    22  	"github.com/ethereum/go-ethereum/swarm/api"
    23  	swarm "github.com/ethereum/go-ethereum/swarm/api/client"
    24  	"gopkg.in/urfave/cli.v1"
    25  )
    26  
    27  //
    28  //最后一个参数new entry hash必须是清单的hash
    29  //
    30  //
    31  func manifestAdd(ctx *cli.Context) {
    32  	args := ctx.Args()
    33  	if len(args) != 3 {
    34  		utils.Fatalf("Need exactly three arguments <MHASH> <path> <HASH>")
    35  	}
    36  
    37  	var (
    38  		mhash = args[0]
    39  		path  = args[1]
    40  		hash  = args[2]
    41  	)
    42  
    43  	bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
    44  	client := swarm.NewClient(bzzapi)
    45  
    46  	m, _, err := client.DownloadManifest(hash)
    47  	if err != nil {
    48  		utils.Fatalf("Error downloading manifest to add: %v", err)
    49  	}
    50  	l := len(m.Entries)
    51  	if l == 0 {
    52  		utils.Fatalf("No entries in manifest %s", hash)
    53  	} else if l > 1 {
    54  		utils.Fatalf("Too many entries in manifest %s", hash)
    55  	}
    56  
    57  	newManifest := addEntryToManifest(client, mhash, path, m.Entries[0])
    58  	fmt.Println(newManifest)
    59  }
    60  
    61  //清单更新将替换给定路径上清单的现有条目。
    62  //最后一个参数new entry hash必须是清单的hash
    63  //只有一个条目,这些元数据将添加到原始清单中。
    64  //成功后,此函数将打印更新清单的哈希。
    65  func manifestUpdate(ctx *cli.Context) {
    66  	args := ctx.Args()
    67  	if len(args) != 3 {
    68  		utils.Fatalf("Need exactly three arguments <MHASH> <path> <HASH>")
    69  	}
    70  
    71  	var (
    72  		mhash = args[0]
    73  		path  = args[1]
    74  		hash  = args[2]
    75  	)
    76  
    77  	bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
    78  	client := swarm.NewClient(bzzapi)
    79  
    80  	m, _, err := client.DownloadManifest(hash)
    81  	if err != nil {
    82  		utils.Fatalf("Error downloading manifest to update: %v", err)
    83  	}
    84  	l := len(m.Entries)
    85  	if l == 0 {
    86  		utils.Fatalf("No entries in manifest %s", hash)
    87  	} else if l > 1 {
    88  		utils.Fatalf("Too many entries in manifest %s", hash)
    89  	}
    90  
    91  	newManifest, _, defaultEntryUpdated := updateEntryInManifest(client, mhash, path, m.Entries[0], true)
    92  	if defaultEntryUpdated {
    93  //
    94  //
    95  //
    96  		fmt.Fprintln(os.Stderr, "Manifest default entry is updated, too")
    97  	}
    98  	fmt.Println(newManifest)
    99  }
   100  
   101  //manifestremove删除给定路径上清单的现有条目。
   102  //成功后,此函数将打印清单的哈希,但该哈希没有
   103  //
   104  func manifestRemove(ctx *cli.Context) {
   105  	args := ctx.Args()
   106  	if len(args) != 2 {
   107  		utils.Fatalf("Need exactly two arguments <MHASH> <path>")
   108  	}
   109  
   110  	var (
   111  		mhash = args[0]
   112  		path  = args[1]
   113  	)
   114  
   115  	bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
   116  	client := swarm.NewClient(bzzapi)
   117  
   118  	newManifest := removeEntryFromManifest(client, mhash, path)
   119  	fmt.Println(newManifest)
   120  }
   121  
   122  func addEntryToManifest(client *swarm.Client, mhash, path string, entry api.ManifestEntry) string {
   123  	var longestPathEntry = api.ManifestEntry{}
   124  
   125  	mroot, isEncrypted, err := client.DownloadManifest(mhash)
   126  	if err != nil {
   127  		utils.Fatalf("Manifest download failed: %v", err)
   128  	}
   129  
   130  //看看我们的道路是否在这张清单中,或者我们需要更深入地挖掘
   131  	for _, e := range mroot.Entries {
   132  		if path == e.Path {
   133  			utils.Fatalf("Path %s already present, not adding anything", path)
   134  		} else {
   135  			if e.ContentType == api.ManifestType {
   136  				prfxlen := strings.HasPrefix(path, e.Path)
   137  				if prfxlen && len(path) > len(longestPathEntry.Path) {
   138  					longestPathEntry = e
   139  				}
   140  			}
   141  		}
   142  	}
   143  
   144  	if longestPathEntry.Path != "" {
   145  //
   146  		newPath := path[len(longestPathEntry.Path):]
   147  		newHash := addEntryToManifest(client, longestPathEntry.Hash, newPath, entry)
   148  
   149  //替换父清单的哈希
   150  		newMRoot := &api.Manifest{}
   151  		for _, e := range mroot.Entries {
   152  			if longestPathEntry.Path == e.Path {
   153  				e.Hash = newHash
   154  			}
   155  			newMRoot.Entries = append(newMRoot.Entries, e)
   156  		}
   157  		mroot = newMRoot
   158  	} else {
   159  //
   160  		entry.Path = path
   161  		mroot.Entries = append(mroot.Entries, entry)
   162  	}
   163  
   164  	newManifestHash, err := client.UploadManifest(mroot, isEncrypted)
   165  	if err != nil {
   166  		utils.Fatalf("Manifest upload failed: %v", err)
   167  	}
   168  	return newManifestHash
   169  }
   170  
   171  //
   172  //
   173  //
   174  //
   175  //
   176  //
   177  func updateEntryInManifest(client *swarm.Client, mhash, path string, entry api.ManifestEntry, isRoot bool) (newManifestHash, oldHash string, defaultEntryUpdated bool) {
   178  	var (
   179  		newEntry         = api.ManifestEntry{}
   180  		longestPathEntry = api.ManifestEntry{}
   181  	)
   182  
   183  	mroot, isEncrypted, err := client.DownloadManifest(mhash)
   184  	if err != nil {
   185  		utils.Fatalf("Manifest download failed: %v", err)
   186  	}
   187  
   188  //看看我们的道路是否在这张清单中,或者我们需要更深入地挖掘
   189  	for _, e := range mroot.Entries {
   190  		if path == e.Path {
   191  			newEntry = e
   192  //
   193  //
   194  			oldHash = e.Hash
   195  		} else {
   196  			if e.ContentType == api.ManifestType {
   197  				prfxlen := strings.HasPrefix(path, e.Path)
   198  				if prfxlen && len(path) > len(longestPathEntry.Path) {
   199  					longestPathEntry = e
   200  				}
   201  			}
   202  		}
   203  	}
   204  
   205  	if longestPathEntry.Path == "" && newEntry.Path == "" {
   206  		utils.Fatalf("Path %s not present in the Manifest, not setting anything", path)
   207  	}
   208  
   209  	if longestPathEntry.Path != "" {
   210  //
   211  		newPath := path[len(longestPathEntry.Path):]
   212  		var newHash string
   213  		newHash, oldHash, _ = updateEntryInManifest(client, longestPathEntry.Hash, newPath, entry, false)
   214  
   215  //替换父清单的哈希
   216  		newMRoot := &api.Manifest{}
   217  		for _, e := range mroot.Entries {
   218  			if longestPathEntry.Path == e.Path {
   219  				e.Hash = newHash
   220  			}
   221  			newMRoot.Entries = append(newMRoot.Entries, e)
   222  
   223  		}
   224  		mroot = newMRoot
   225  	}
   226  
   227  //
   228  //检查是否应更新默认条目
   229  	if newEntry.Path != "" || isRoot {
   230  //替换叶清单的哈希
   231  		newMRoot := &api.Manifest{}
   232  		for _, e := range mroot.Entries {
   233  			if newEntry.Path == e.Path {
   234  				entry.Path = e.Path
   235  				newMRoot.Entries = append(newMRoot.Entries, entry)
   236  			} else if isRoot && e.Path == "" && e.Hash == oldHash {
   237  				entry.Path = e.Path
   238  				newMRoot.Entries = append(newMRoot.Entries, entry)
   239  				defaultEntryUpdated = true
   240  			} else {
   241  				newMRoot.Entries = append(newMRoot.Entries, e)
   242  			}
   243  		}
   244  		mroot = newMRoot
   245  	}
   246  
   247  	newManifestHash, err = client.UploadManifest(mroot, isEncrypted)
   248  	if err != nil {
   249  		utils.Fatalf("Manifest upload failed: %v", err)
   250  	}
   251  	return newManifestHash, oldHash, defaultEntryUpdated
   252  }
   253  
   254  func removeEntryFromManifest(client *swarm.Client, mhash, path string) string {
   255  	var (
   256  		entryToRemove    = api.ManifestEntry{}
   257  		longestPathEntry = api.ManifestEntry{}
   258  	)
   259  
   260  	mroot, isEncrypted, err := client.DownloadManifest(mhash)
   261  	if err != nil {
   262  		utils.Fatalf("Manifest download failed: %v", err)
   263  	}
   264  
   265  //看看我们的道路是否在这张清单中,或者我们需要更深入地挖掘
   266  	for _, entry := range mroot.Entries {
   267  		if path == entry.Path {
   268  			entryToRemove = entry
   269  		} else {
   270  			if entry.ContentType == api.ManifestType {
   271  				prfxlen := strings.HasPrefix(path, entry.Path)
   272  				if prfxlen && len(path) > len(longestPathEntry.Path) {
   273  					longestPathEntry = entry
   274  				}
   275  			}
   276  		}
   277  	}
   278  
   279  	if longestPathEntry.Path == "" && entryToRemove.Path == "" {
   280  		utils.Fatalf("Path %s not present in the Manifest, not removing anything", path)
   281  	}
   282  
   283  	if longestPathEntry.Path != "" {
   284  //
   285  		newPath := path[len(longestPathEntry.Path):]
   286  		newHash := removeEntryFromManifest(client, longestPathEntry.Hash, newPath)
   287  
   288  //替换父清单的哈希
   289  		newMRoot := &api.Manifest{}
   290  		for _, entry := range mroot.Entries {
   291  			if longestPathEntry.Path == entry.Path {
   292  				entry.Hash = newHash
   293  			}
   294  			newMRoot.Entries = append(newMRoot.Entries, entry)
   295  		}
   296  		mroot = newMRoot
   297  	}
   298  
   299  	if entryToRemove.Path != "" {
   300  //删除此清单中的条目
   301  		newMRoot := &api.Manifest{}
   302  		for _, entry := range mroot.Entries {
   303  			if entryToRemove.Path != entry.Path {
   304  				newMRoot.Entries = append(newMRoot.Entries, entry)
   305  			}
   306  		}
   307  		mroot = newMRoot
   308  	}
   309  
   310  	newManifestHash, err := client.UploadManifest(mroot, isEncrypted)
   311  	if err != nil {
   312  		utils.Fatalf("Manifest upload failed: %v", err)
   313  	}
   314  	return newManifestHash
   315  }
   316