Swarm: need tools to update/manipulate manifests #3498

This commit is contained in:
Zahoor Mohamed 2017-01-29 02:19:02 +05:30
parent 799caf8289
commit 82ddd30f22

View file

@ -18,20 +18,20 @@
package main package main
import ( import (
"encoding/json"
"fmt"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
"log" "log"
"mime" "mime"
"path/filepath" "path/filepath"
"strings" "strings"
"fmt"
"encoding/json"
) )
func add(ctx *cli.Context) { func add(ctx *cli.Context) {
args := ctx.Args() args := ctx.Args()
if len(args) < 3 { if len(args) < 3 {
log.Fatal("need atleast three arguments") log.Fatal("need atleast three arguments <MHASH> <path> <HASH> [<content-type>]")
} }
var ( var (
@ -39,134 +39,20 @@ func add(ctx *cli.Context) {
path = args[1] path = args[1]
hash = args[2] hash = args[2]
) ctype string
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), "/")
wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
client = &client{api: bzzapi}
mroot manifest mroot manifest
) )
/* TODO: check for proper hash
if !common.IsHexAddress(mhash) { if len(args) > 3 {
log.Fatal(mhash, " is not a valid hash") ctype = args[3]
} else {
ctype = mime.TypeByExtension(filepath.Ext(path))
} }
if !common.IsHexAddress(hash) { newManifest := addEntryToManifest (ctx, mhash, path, hash, ctype)
log.Fatal(hash, " is not a valid hash") fmt.Println(newManifest)
}
*/
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
}
if !wantManifest { if !wantManifest {
// Print the manifest. This is the only output to stdout. // 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)) fmt.Println(string(mrootJSON))
return return
} }
}
func update(ctx *cli.Context) {
args := ctx.Args()
if len(args) < 3 {
log.Fatal("need atleast three arguments <MHASH> <path> <HASH>")
}
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 <MHASH> <path>")
}
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) newManifestHash, err := client.uploadManifest(mroot)
if err != nil { if err != nil {
log.Fatalln("manifest upload failed:", err) 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
}