mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
Swarm: need tools to update/manipulate manifests #3498
This commit is contained in:
parent
799caf8289
commit
82ddd30f22
1 changed files with 297 additions and 126 deletions
|
|
@ -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) {
|
|
||||||
log.Fatal(mhash, " is not a valid hash")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !common.IsHexAddress(hash) {
|
if len(args) > 3 {
|
||||||
log.Fatal(hash, " is not a valid hash")
|
ctype = args[3]
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
newMRoot.Entries = append(newMRoot.Entries, entry)
|
ctype = mime.TypeByExtension(filepath.Ext(path))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !foundEntry {
|
newManifest := addEntryToManifest (ctx, mhash, path, hash, ctype)
|
||||||
log.Fatal(path, " Path not present in the Manifest, not setting anything")
|
fmt.Println(newManifest)
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue