From 82ddd30f22d0b55ff9751598d3da444dd3803ccf Mon Sep 17 00:00:00 2001 From: Zahoor Mohamed Date: Sun, 29 Jan 2017 02:19:02 +0530 Subject: [PATCH] Swarm: need tools to update/manipulate manifests #3498 --- cmd/swarm/manifest.go | 423 +++++++++++++++++++++++++++++------------- 1 file changed, 297 insertions(+), 126 deletions(-) diff --git a/cmd/swarm/manifest.go b/cmd/swarm/manifest.go index e8a7a1d393..094f7f960a 100644 --- a/cmd/swarm/manifest.go +++ b/cmd/swarm/manifest.go @@ -18,20 +18,20 @@ package main import ( - "encoding/json" - "fmt" "gopkg.in/urfave/cli.v1" "log" "mime" "path/filepath" "strings" + "fmt" + "encoding/json" ) func add(ctx *cli.Context) { args := ctx.Args() if len(args) < 3 { - log.Fatal("need atleast three arguments") + log.Fatal("need atleast three arguments []") } var ( @@ -39,134 +39,20 @@ func add(ctx *cli.Context) { path = args[1] hash = args[2] - ) - - updateManifest (ctx, mhash, "add", path, hash) -} - -func update(ctx *cli.Context) { - - args := ctx.Args() - if len(args) < 3 { - log.Fatal("need atleast three arguments") - } - - var ( - mhash = args[0] - path = args[1] - hash = args[2] - - ) - - updateManifest (ctx, mhash, "update", path, hash) -} - -func remove(ctx *cli.Context) { - args := ctx.Args() - if len(args) < 2 { - log.Fatal("need atleast two arguments") - } - - var ( - mhash = args[0] - path = args[1] - - ) - - updateManifest (ctx, mhash, "remove", path, "") -} - - -func updateManifest(ctx *cli.Context, mhash , subcmd, path, hash string) { - - var ( - bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") + ctype string wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) - client = &client{api: bzzapi} mroot manifest ) - /* TODO: check for proper hash - if !common.IsHexAddress(mhash) { - log.Fatal(mhash, " is not a valid hash") + + if len(args) > 3 { + ctype = args[3] + } else { + ctype = mime.TypeByExtension(filepath.Ext(path)) } - if !common.IsHexAddress(hash) { - log.Fatal(hash, " is not a valid hash") - } - */ - - mroot, err := client.downloadManifest(mhash) - if err != nil { - log.Fatalln("manifest download failed:", err) - } - - switch subcmd { - - case "add": - for _, entry := range mroot.Entries { - if path == entry.Path { - log.Fatal(path, "Already present, not adding anything") - } - } - - newEntry := manifestEntry{ - Path: path, - Hash: hash, - ContentType: mime.TypeByExtension(filepath.Ext(path)), - } - mroot.Entries = append(mroot.Entries, newEntry) - break - - case "update": - foundEntry := bool(false) - newMRoot := manifest{} - for _, entry := range mroot.Entries { - if path == entry.Path { - newEntry := manifestEntry{ - Path: entry.Path, - Hash: hash, - ContentType: entry.ContentType, - } - foundEntry = true - newMRoot.Entries = append(newMRoot.Entries, newEntry) - } else { - newMRoot.Entries = append(newMRoot.Entries, entry) - } - } - - if !foundEntry { - log.Fatal(path, " Path not present in the Manifest, not setting anything") - } - - mroot = newMRoot - break - - case "remove": - - foundEntry := bool(false) - newMRoot := manifest{} - for _, entry := range mroot.Entries { - if path != entry.Path { - newEntry := manifestEntry{ - Path: entry.Path, - Hash: entry.Hash, - ContentType: entry.ContentType, - } - newMRoot.Entries = append(newMRoot.Entries, newEntry) - } else { - foundEntry = true - } - } - - if !foundEntry { - log.Fatal(path, "Path not present in the Manifest, not removing anything") - } - - mroot = newMRoot - break - - } + newManifest := addEntryToManifest (ctx, mhash, path, hash, ctype) + fmt.Println(newManifest) if !wantManifest { // Print the manifest. This is the only output to stdout. @@ -174,11 +60,296 @@ func updateManifest(ctx *cli.Context, mhash , subcmd, path, hash string) { fmt.Println(string(mrootJSON)) return } +} + +func update(ctx *cli.Context) { + + args := ctx.Args() + if len(args) < 3 { + log.Fatal("need atleast three arguments ") + } + + var ( + mhash = args[0] + path = args[1] + hash = args[2] + + ctype string + wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) + mroot 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) + + if !wantManifest { + // Print the manifest. This is the only output to stdout. + mrootJSON, _ := json.MarshalIndent(mroot, "", " ") + fmt.Println(string(mrootJSON)) + return + } +} + +func remove(ctx *cli.Context) { + args := ctx.Args() + if len(args) < 2 { + log.Fatal("need atleast two arguments ") + } + + var ( + mhash = args[0] + path = args[1] + + wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) + mroot manifest + ) + + newManifest := removeEntryFromManifest (ctx, mhash, path) + 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 addEntryToManifest(ctx *cli.Context, mhash , path, hash , ctype string) string { + + var ( + bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") + client = &client{api: bzzapi} + longestPathEntry = manifestEntry{ + Path: "", + Hash: "", + ContentType: "", + } + ) + + mroot, err := client.downloadManifest(mhash) + if err != nil { + log.Fatalln("manifest download failed:", err) + } + + //TODO: check if the "hash" to add 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 { + log.Fatal(path, "Already present, not adding anything") + }else { + if entry.ContentType == "application/bzz-manifest+json" { + prfxlen := strings.HasPrefix(path, entry.Path) + if prfxlen && len(path) > len(longestPathEntry.Path) { + longestPathEntry = entry + } + } + } + } + + if longestPathEntry.Path != "" { + // Load the child Manifest add the entry there + newPath := path[len(longestPathEntry.Path):] + newHash := addEntryToManifest (ctx, longestPathEntry.Hash, newPath, hash, ctype) + + // Replace the hash for parent Manifests + newMRoot := manifest{} + for _, entry := range mroot.Entries { + if longestPathEntry.Path == entry.Path { + entry.Hash = newHash + } + newMRoot.Entries = append(newMRoot.Entries, entry) + } + mroot = newMRoot + } else { + // Add the entry in the leaf Manifest + newEntry := manifestEntry{ + Path: path, + Hash: hash, + ContentType: ctype, + } + mroot.Entries = append(mroot.Entries, newEntry) + } + newManifestHash, err := client.uploadManifest(mroot) if err != nil { log.Fatalln("manifest upload failed:", err) } - fmt.Println(newManifestHash) + return newManifestHash + + } + +func updateEntryInManifest(ctx *cli.Context, mhash , path, hash , ctype string) string { + + var ( + bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") + client = &client{api: bzzapi} + newEntry = manifestEntry{ + Path: "", + Hash: "", + ContentType: "", + } + longestPathEntry = manifestEntry{ + Path: "", + Hash: "", + ContentType: "", + } + ) + + mroot, err := client.downloadManifest(mhash) + if err != nil { + log.Fatalln("manifest download failed:", 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 + }else { + if entry.ContentType == "application/bzz-manifest+json" { + prfxlen := strings.HasPrefix(path, entry.Path) + if prfxlen && len(path) > len(longestPathEntry.Path) { + longestPathEntry = entry + } + } + } + } + + if longestPathEntry.Path == "" && newEntry.Path == "" { + log.Fatal(path, " Path not present in the Manifest, not setting anything") + } + + if longestPathEntry.Path != "" { + // Load the child Manifest add the entry there + newPath := path[len(longestPathEntry.Path):] + newHash := addEntryToManifest (ctx, longestPathEntry.Hash, newPath, hash, ctype) + + // Replace the hash for parent Manifests + newMRoot := manifest{} + for _, entry := range mroot.Entries { + if longestPathEntry.Path == entry.Path { + entry.Hash = newHash + } + newMRoot.Entries = append(newMRoot.Entries, entry) + + } + mroot = newMRoot + } + + if newEntry.Path != "" { + // Replace the hash for leaf Manifest + newMRoot := manifest{} + for _, entry := range mroot.Entries { + if newEntry.Path == entry.Path { + myEntry := manifestEntry{ + Path: entry.Path, + Hash: hash, + ContentType: ctype, + } + newMRoot.Entries = append(newMRoot.Entries, myEntry) + } else { + newMRoot.Entries = append(newMRoot.Entries, entry) + } + } + mroot = newMRoot + } + + + newManifestHash, err := client.uploadManifest(mroot) + if err != nil { + log.Fatalln("manifest upload failed:", err) + } + return newManifestHash +} + +func removeEntryFromManifest(ctx *cli.Context, mhash , path string) string { + + var ( + bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") + client = &client{api: bzzapi} + entryToRemove = manifestEntry{ + Path: "", + Hash: "", + ContentType: "", + } + longestPathEntry = manifestEntry{ + Path: "", + Hash: "", + ContentType: "", + } + ) + + mroot, err := client.downloadManifest(mhash) + if err != nil { + log.Fatalln("manifest download failed:", 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 { + entryToRemove = entry + }else { + if entry.ContentType == "application/bzz-manifest+json" { + prfxlen := strings.HasPrefix(path, entry.Path) + if prfxlen && len(path) > len(longestPathEntry.Path) { + longestPathEntry = entry + } + } + } + } + + if longestPathEntry.Path == "" && entryToRemove.Path == "" { + log.Fatal(path, "Path not present in the Manifest, not removing anything") + } + + if longestPathEntry.Path != "" { + // Load the child Manifest remove the entry there + newPath := path[len(longestPathEntry.Path):] + newHash := removeEntryFromManifest (ctx, longestPathEntry.Hash, newPath) + + // Replace the hash for parent Manifests + newMRoot := manifest{} + for _, entry := range mroot.Entries { + if longestPathEntry.Path == entry.Path { + entry.Hash = newHash + } + newMRoot.Entries = append(newMRoot.Entries, entry) + } + mroot = newMRoot + } + + if entryToRemove.Path != "" { + // remove the entry in this Manifest + newMRoot := manifest{} + for _, entry := range mroot.Entries { + if entryToRemove.Path != entry.Path { + newMRoot.Entries = append(newMRoot.Entries, entry) + } + } + mroot = newMRoot + } + + + newManifestHash, err := client.uploadManifest(mroot) + if err != nil { + log.Fatalln("manifest upload failed:", err) + } + return newManifestHash + + +} +