aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/swarm/manifest.go
diff options
context:
space:
mode:
authorJanoš Guljaš <janos@users.noreply.github.com>2018-08-10 22:12:55 +0800
committerBalint Gabor <balint.g@gmail.com>2018-08-10 22:12:55 +0800
commit6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36 (patch)
tree3bcd5ab444bd7486a9011656c85baeee00216286 /cmd/swarm/manifest.go
parent3ec5dda4d2dd0dec6d5bd465752f30e8f6ce208c (diff)
downloadgo-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.tar
go-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.tar.gz
go-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.tar.bz2
go-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.tar.lz
go-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.tar.xz
go-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.tar.zst
go-tangerine-6d1e292eefa70b5cb76cd03ff61fc6c4550d7c36.zip
Manifest cli fix and upload defaultpath only once (#17375)
* cmd/swarm: fix manifest subcommands and add tests * cmd/swarm: manifest update: update default entry for non-encrypted uploads * swarm/api: upload defaultpath file only once * swarm/api/client: improve UploadDirectory default path handling * cmd/swarm: support absolute and relative default path values * cmd/swarm: fix a typo in test * cmd/swarm: check encrypted uploads in manifest update tests
Diffstat (limited to 'cmd/swarm/manifest.go')
-rw-r--r--cmd/swarm/manifest.go234
1 files changed, 111 insertions, 123 deletions
diff --git a/cmd/swarm/manifest.go b/cmd/swarm/manifest.go
index 82166edf6..0216ffc1d 100644
--- a/cmd/swarm/manifest.go
+++ b/cmd/swarm/manifest.go
@@ -18,10 +18,8 @@
package main
import (
- "encoding/json"
"fmt"
- "mime"
- "path/filepath"
+ "os"
"strings"
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -30,127 +28,118 @@ import (
"gopkg.in/urfave/cli.v1"
)
-const bzzManifestJSON = "application/bzz-manifest+json"
-
-func add(ctx *cli.Context) {
+// manifestAdd adds a new entry to the manifest at the given path.
+// New entry hash, the last argument, must be the hash of a manifest
+// with only one entry, which meta-data will be added to the original manifest.
+// On success, this function will print new (updated) manifest's hash.
+func manifestAdd(ctx *cli.Context) {
args := ctx.Args()
- if len(args) < 3 {
- utils.Fatalf("Need at least three arguments <MHASH> <path> <HASH> [<content-type>]")
+ if len(args) != 3 {
+ utils.Fatalf("Need exactly three arguments <MHASH> <path> <HASH>")
}
var (
mhash = args[0]
path = args[1]
hash = args[2]
-
- ctype string
- wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
- mroot api.Manifest
)
- if len(args) > 3 {
- ctype = args[3]
- } else {
- ctype = mime.TypeByExtension(filepath.Ext(path))
+ bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
+ client := swarm.NewClient(bzzapi)
+
+ m, _, err := client.DownloadManifest(hash)
+ if err != nil {
+ utils.Fatalf("Error downloading manifest to add: %v", err)
+ }
+ l := len(m.Entries)
+ if l == 0 {
+ utils.Fatalf("No entries in manifest %s", hash)
+ } else if l > 1 {
+ utils.Fatalf("Too many entries in manifest %s", hash)
}
- newManifest := addEntryToManifest(ctx, mhash, path, hash, ctype)
+ newManifest := addEntryToManifest(client, mhash, path, m.Entries[0])
fmt.Println(newManifest)
-
- if !wantManifest {
- // Print the manifest. This is the only output to stdout.
- mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
- fmt.Println(string(mrootJSON))
- return
- }
}
-func update(ctx *cli.Context) {
-
+// manifestUpdate replaces an existing entry of the manifest at the given path.
+// New entry hash, the last argument, must be the hash of a manifest
+// with only one entry, which meta-data will be added to the original manifest.
+// On success, this function will print hash of the updated manifest.
+func manifestUpdate(ctx *cli.Context) {
args := ctx.Args()
- if len(args) < 3 {
- utils.Fatalf("Need at least three arguments <MHASH> <path> <HASH>")
+ if len(args) != 3 {
+ utils.Fatalf("Need exactly three arguments <MHASH> <path> <HASH>")
}
var (
mhash = args[0]
path = args[1]
hash = args[2]
-
- ctype string
- wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
- mroot api.Manifest
)
- if len(args) > 3 {
- ctype = args[3]
- } else {
- ctype = mime.TypeByExtension(filepath.Ext(path))
- }
- newManifest := updateEntryInManifest(ctx, mhash, path, hash, ctype)
- fmt.Println(newManifest)
+ bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
+ client := swarm.NewClient(bzzapi)
- if !wantManifest {
- // Print the manifest. This is the only output to stdout.
- mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
- fmt.Println(string(mrootJSON))
- return
+ m, _, err := client.DownloadManifest(hash)
+ if err != nil {
+ utils.Fatalf("Error downloading manifest to update: %v", err)
+ }
+ l := len(m.Entries)
+ if l == 0 {
+ utils.Fatalf("No entries in manifest %s", hash)
+ } else if l > 1 {
+ utils.Fatalf("Too many entries in manifest %s", hash)
}
+
+ newManifest, _, defaultEntryUpdated := updateEntryInManifest(client, mhash, path, m.Entries[0], true)
+ if defaultEntryUpdated {
+ // Print informational message to stderr
+ // allowing the user to get the new manifest hash from stdout
+ // without the need to parse the complete output.
+ fmt.Fprintln(os.Stderr, "Manifest default entry is updated, too")
+ }
+ fmt.Println(newManifest)
}
-func remove(ctx *cli.Context) {
+// manifestRemove removes an existing entry of the manifest at the given path.
+// On success, this function will print hash of the manifest which does not
+// contain the path.
+func manifestRemove(ctx *cli.Context) {
args := ctx.Args()
- if len(args) < 2 {
- utils.Fatalf("Need at least two arguments <MHASH> <path>")
+ if len(args) != 2 {
+ utils.Fatalf("Need exactly two arguments <MHASH> <path>")
}
var (
mhash = args[0]
path = args[1]
-
- wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
- mroot api.Manifest
)
- newManifest := removeEntryFromManifest(ctx, mhash, path)
- fmt.Println(newManifest)
+ bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
+ client := swarm.NewClient(bzzapi)
- if !wantManifest {
- // Print the manifest. This is the only output to stdout.
- mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
- fmt.Println(string(mrootJSON))
- return
- }
+ newManifest := removeEntryFromManifest(client, mhash, path)
+ fmt.Println(newManifest)
}
-func addEntryToManifest(ctx *cli.Context, mhash, path, hash, ctype string) string {
-
- var (
- bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
- client = swarm.NewClient(bzzapi)
- longestPathEntry = api.ManifestEntry{}
- )
+func addEntryToManifest(client *swarm.Client, mhash, path string, entry api.ManifestEntry) string {
+ var longestPathEntry = api.ManifestEntry{}
mroot, isEncrypted, err := client.DownloadManifest(mhash)
if err != nil {
utils.Fatalf("Manifest download failed: %v", err)
}
- //TODO: check if the "hash" to add is valid and present in swarm
- _, _, err = client.DownloadManifest(hash)
- if err != nil {
- utils.Fatalf("Hash to add is not present: %v", err)
- }
-
// See if we path is in this Manifest or do we have to dig deeper
- for _, entry := range mroot.Entries {
- if path == entry.Path {
+ for _, e := range mroot.Entries {
+ if path == e.Path {
utils.Fatalf("Path %s already present, not adding anything", path)
} else {
- if entry.ContentType == bzzManifestJSON {
- prfxlen := strings.HasPrefix(path, entry.Path)
+ if e.ContentType == api.ManifestType {
+ prfxlen := strings.HasPrefix(path, e.Path)
if prfxlen && len(path) > len(longestPathEntry.Path) {
- longestPathEntry = entry
+ longestPathEntry = e
}
}
}
@@ -159,25 +148,21 @@ func addEntryToManifest(ctx *cli.Context, mhash, path, hash, ctype string) strin
if longestPathEntry.Path != "" {
// Load the child Manifest add the entry there
newPath := path[len(longestPathEntry.Path):]
- newHash := addEntryToManifest(ctx, longestPathEntry.Hash, newPath, hash, ctype)
+ newHash := addEntryToManifest(client, longestPathEntry.Hash, newPath, entry)
// Replace the hash for parent Manifests
newMRoot := &api.Manifest{}
- for _, entry := range mroot.Entries {
- if longestPathEntry.Path == entry.Path {
- entry.Hash = newHash
+ for _, e := range mroot.Entries {
+ if longestPathEntry.Path == e.Path {
+ e.Hash = newHash
}
- newMRoot.Entries = append(newMRoot.Entries, entry)
+ newMRoot.Entries = append(newMRoot.Entries, e)
}
mroot = newMRoot
} else {
// Add the entry in the leaf Manifest
- newEntry := api.ManifestEntry{
- Hash: hash,
- Path: path,
- ContentType: ctype,
- }
- mroot.Entries = append(mroot.Entries, newEntry)
+ entry.Path = path
+ mroot.Entries = append(mroot.Entries, entry)
}
newManifestHash, err := client.UploadManifest(mroot, isEncrypted)
@@ -185,14 +170,16 @@ func addEntryToManifest(ctx *cli.Context, mhash, path, hash, ctype string) strin
utils.Fatalf("Manifest upload failed: %v", err)
}
return newManifestHash
-
}
-func updateEntryInManifest(ctx *cli.Context, mhash, path, hash, ctype string) string {
-
+// updateEntryInManifest updates an existing entry o path with a new one in the manifest with provided mhash
+// finding the path recursively through all nested manifests. Argument isRoot is used for default
+// entry update detection. If the updated entry has the same hash as the default entry, then the
+// default entry in root manifest will be updated too.
+// Returned values are the new manifest hash, hash of the entry that was replaced by the new entry and
+// a a bool that is true if default entry is updated.
+func updateEntryInManifest(client *swarm.Client, mhash, path string, entry api.ManifestEntry, isRoot bool) (newManifestHash, oldHash string, defaultEntryUpdated bool) {
var (
- bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
- client = swarm.NewClient(bzzapi)
newEntry = api.ManifestEntry{}
longestPathEntry = api.ManifestEntry{}
)
@@ -202,17 +189,18 @@ func updateEntryInManifest(ctx *cli.Context, mhash, path, hash, ctype string) st
utils.Fatalf("Manifest download failed: %v", err)
}
- //TODO: check if the "hash" with which to update is valid and present in swarm
-
// See if we path is in this Manifest or do we have to dig deeper
- for _, entry := range mroot.Entries {
- if path == entry.Path {
- newEntry = entry
+ for _, e := range mroot.Entries {
+ if path == e.Path {
+ newEntry = e
+ // keep the reference of the hash of the entry that should be replaced
+ // for default entry detection
+ oldHash = e.Hash
} else {
- if entry.ContentType == bzzManifestJSON {
- prfxlen := strings.HasPrefix(path, entry.Path)
+ if e.ContentType == api.ManifestType {
+ prfxlen := strings.HasPrefix(path, e.Path)
if prfxlen && len(path) > len(longestPathEntry.Path) {
- longestPathEntry = entry
+ longestPathEntry = e
}
}
}
@@ -225,50 +213,50 @@ func updateEntryInManifest(ctx *cli.Context, mhash, path, hash, ctype string) st
if longestPathEntry.Path != "" {
// Load the child Manifest add the entry there
newPath := path[len(longestPathEntry.Path):]
- newHash := updateEntryInManifest(ctx, longestPathEntry.Hash, newPath, hash, ctype)
+ var newHash string
+ newHash, oldHash, _ = updateEntryInManifest(client, longestPathEntry.Hash, newPath, entry, false)
// Replace the hash for parent Manifests
newMRoot := &api.Manifest{}
- for _, entry := range mroot.Entries {
- if longestPathEntry.Path == entry.Path {
- entry.Hash = newHash
+ for _, e := range mroot.Entries {
+ if longestPathEntry.Path == e.Path {
+ e.Hash = newHash
}
- newMRoot.Entries = append(newMRoot.Entries, entry)
+ newMRoot.Entries = append(newMRoot.Entries, e)
}
mroot = newMRoot
}
- if newEntry.Path != "" {
+ // update the manifest if the new entry is found and
+ // check if default entry should be updated
+ if newEntry.Path != "" || isRoot {
// Replace the hash for leaf Manifest
newMRoot := &api.Manifest{}
- for _, entry := range mroot.Entries {
- if newEntry.Path == entry.Path {
- myEntry := api.ManifestEntry{
- Hash: hash,
- Path: entry.Path,
- ContentType: ctype,
- }
- newMRoot.Entries = append(newMRoot.Entries, myEntry)
- } else {
+ for _, e := range mroot.Entries {
+ if newEntry.Path == e.Path {
+ entry.Path = e.Path
newMRoot.Entries = append(newMRoot.Entries, entry)
+ } else if isRoot && e.Path == "" && e.Hash == oldHash {
+ entry.Path = e.Path
+ newMRoot.Entries = append(newMRoot.Entries, entry)
+ defaultEntryUpdated = true
+ } else {
+ newMRoot.Entries = append(newMRoot.Entries, e)
}
}
mroot = newMRoot
}
- newManifestHash, err := client.UploadManifest(mroot, isEncrypted)
+ newManifestHash, err = client.UploadManifest(mroot, isEncrypted)
if err != nil {
utils.Fatalf("Manifest upload failed: %v", err)
}
- return newManifestHash
+ return newManifestHash, oldHash, defaultEntryUpdated
}
-func removeEntryFromManifest(ctx *cli.Context, mhash, path string) string {
-
+func removeEntryFromManifest(client *swarm.Client, mhash, path string) string {
var (
- bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
- client = swarm.NewClient(bzzapi)
entryToRemove = api.ManifestEntry{}
longestPathEntry = api.ManifestEntry{}
)
@@ -283,7 +271,7 @@ func removeEntryFromManifest(ctx *cli.Context, mhash, path string) string {
if path == entry.Path {
entryToRemove = entry
} else {
- if entry.ContentType == bzzManifestJSON {
+ if entry.ContentType == api.ManifestType {
prfxlen := strings.HasPrefix(path, entry.Path)
if prfxlen && len(path) > len(longestPathEntry.Path) {
longestPathEntry = entry
@@ -299,7 +287,7 @@ func removeEntryFromManifest(ctx *cli.Context, mhash, path string) string {
if longestPathEntry.Path != "" {
// Load the child Manifest remove the entry there
newPath := path[len(longestPathEntry.Path):]
- newHash := removeEntryFromManifest(ctx, longestPathEntry.Hash, newPath)
+ newHash := removeEntryFromManifest(client, longestPathEntry.Hash, newPath)
// Replace the hash for parent Manifests
newMRoot := &api.Manifest{}