github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/cmd/swarm/manifest.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of go-wtc. 3 // 4 // go-wtc is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-wtc is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-wtc. If not, see <http://www.gnu.org/licenses/>. 16 17 // Command MANIFEST update 18 package main 19 20 import ( 21 "encoding/json" 22 "fmt" 23 "mime" 24 "path/filepath" 25 "strings" 26 27 "github.com/wtc/go-wtc/cmd/utils" 28 "github.com/wtc/go-wtc/swarm/api" 29 swarm "github.com/wtc/go-wtc/swarm/api/client" 30 "gopkg.in/urfave/cli.v1" 31 ) 32 33 func add(ctx *cli.Context) { 34 args := ctx.Args() 35 if len(args) < 3 { 36 utils.Fatalf("Need atleast three arguments <MHASH> <path> <HASH> [<content-type>]") 37 } 38 39 var ( 40 mhash = args[0] 41 path = args[1] 42 hash = args[2] 43 44 ctype string 45 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 46 mroot api.Manifest 47 ) 48 49 if len(args) > 3 { 50 ctype = args[3] 51 } else { 52 ctype = mime.TypeByExtension(filepath.Ext(path)) 53 } 54 55 newManifest := addEntryToManifest(ctx, mhash, path, hash, ctype) 56 fmt.Println(newManifest) 57 58 if !wantManifest { 59 // Print the manifest. This is the only output to stdout. 60 mrootJSON, _ := json.MarshalIndent(mroot, "", " ") 61 fmt.Println(string(mrootJSON)) 62 return 63 } 64 } 65 66 func update(ctx *cli.Context) { 67 68 args := ctx.Args() 69 if len(args) < 3 { 70 utils.Fatalf("Need atleast three arguments <MHASH> <path> <HASH>") 71 } 72 73 var ( 74 mhash = args[0] 75 path = args[1] 76 hash = args[2] 77 78 ctype string 79 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 80 mroot api.Manifest 81 ) 82 if len(args) > 3 { 83 ctype = args[3] 84 } else { 85 ctype = mime.TypeByExtension(filepath.Ext(path)) 86 } 87 88 newManifest := updateEntryInManifest(ctx, mhash, path, hash, ctype) 89 fmt.Println(newManifest) 90 91 if !wantManifest { 92 // Print the manifest. This is the only output to stdout. 93 mrootJSON, _ := json.MarshalIndent(mroot, "", " ") 94 fmt.Println(string(mrootJSON)) 95 return 96 } 97 } 98 99 func remove(ctx *cli.Context) { 100 args := ctx.Args() 101 if len(args) < 2 { 102 utils.Fatalf("Need atleast two arguments <MHASH> <path>") 103 } 104 105 var ( 106 mhash = args[0] 107 path = args[1] 108 109 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 110 mroot api.Manifest 111 ) 112 113 newManifest := removeEntryFromManifest(ctx, mhash, path) 114 fmt.Println(newManifest) 115 116 if !wantManifest { 117 // Print the manifest. This is the only output to stdout. 118 mrootJSON, _ := json.MarshalIndent(mroot, "", " ") 119 fmt.Println(string(mrootJSON)) 120 return 121 } 122 } 123 124 func addEntryToManifest(ctx *cli.Context, mhash, path, hash, ctype string) string { 125 126 var ( 127 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 128 client = swarm.NewClient(bzzapi) 129 longestPathEntry = api.ManifestEntry{} 130 ) 131 132 mroot, err := client.DownloadManifest(mhash) 133 if err != nil { 134 utils.Fatalf("Manifest download failed: %v", err) 135 } 136 137 //TODO: check if the "hash" to add is valid and present in swarm 138 _, err = client.DownloadManifest(hash) 139 if err != nil { 140 utils.Fatalf("Hash to add is not present: %v", err) 141 } 142 143 // See if we path is in this Manifest or do we have to dig deeper 144 for _, entry := range mroot.Entries { 145 if path == entry.Path { 146 utils.Fatalf("Path %s already present, not adding anything", path) 147 } else { 148 if entry.ContentType == "application/bzz-manifest+json" { 149 prfxlen := strings.HasPrefix(path, entry.Path) 150 if prfxlen && len(path) > len(longestPathEntry.Path) { 151 longestPathEntry = entry 152 } 153 } 154 } 155 } 156 157 if longestPathEntry.Path != "" { 158 // Load the child Manifest add the entry there 159 newPath := path[len(longestPathEntry.Path):] 160 newHash := addEntryToManifest(ctx, longestPathEntry.Hash, newPath, hash, ctype) 161 162 // Replace the hash for parent Manifests 163 newMRoot := &api.Manifest{} 164 for _, entry := range mroot.Entries { 165 if longestPathEntry.Path == entry.Path { 166 entry.Hash = newHash 167 } 168 newMRoot.Entries = append(newMRoot.Entries, entry) 169 } 170 mroot = newMRoot 171 } else { 172 // Add the entry in the leaf Manifest 173 newEntry := api.ManifestEntry{ 174 Hash: hash, 175 Path: path, 176 ContentType: ctype, 177 } 178 mroot.Entries = append(mroot.Entries, newEntry) 179 } 180 181 newManifestHash, err := client.UploadManifest(mroot) 182 if err != nil { 183 utils.Fatalf("Manifest upload failed: %v", err) 184 } 185 return newManifestHash 186 187 } 188 189 func updateEntryInManifest(ctx *cli.Context, mhash, path, hash, ctype string) string { 190 191 var ( 192 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 193 client = swarm.NewClient(bzzapi) 194 newEntry = api.ManifestEntry{} 195 longestPathEntry = api.ManifestEntry{} 196 ) 197 198 mroot, err := client.DownloadManifest(mhash) 199 if err != nil { 200 utils.Fatalf("Manifest download failed: %v", err) 201 } 202 203 //TODO: check if the "hash" with which to update is valid and present in swarm 204 205 // See if we path is in this Manifest or do we have to dig deeper 206 for _, entry := range mroot.Entries { 207 if path == entry.Path { 208 newEntry = entry 209 } else { 210 if entry.ContentType == "application/bzz-manifest+json" { 211 prfxlen := strings.HasPrefix(path, entry.Path) 212 if prfxlen && len(path) > len(longestPathEntry.Path) { 213 longestPathEntry = entry 214 } 215 } 216 } 217 } 218 219 if longestPathEntry.Path == "" && newEntry.Path == "" { 220 utils.Fatalf("Path %s not present in the Manifest, not setting anything", path) 221 } 222 223 if longestPathEntry.Path != "" { 224 // Load the child Manifest add the entry there 225 newPath := path[len(longestPathEntry.Path):] 226 newHash := updateEntryInManifest(ctx, longestPathEntry.Hash, newPath, hash, ctype) 227 228 // Replace the hash for parent Manifests 229 newMRoot := &api.Manifest{} 230 for _, entry := range mroot.Entries { 231 if longestPathEntry.Path == entry.Path { 232 entry.Hash = newHash 233 } 234 newMRoot.Entries = append(newMRoot.Entries, entry) 235 236 } 237 mroot = newMRoot 238 } 239 240 if newEntry.Path != "" { 241 // Replace the hash for leaf Manifest 242 newMRoot := &api.Manifest{} 243 for _, entry := range mroot.Entries { 244 if newEntry.Path == entry.Path { 245 myEntry := api.ManifestEntry{ 246 Hash: hash, 247 Path: entry.Path, 248 ContentType: ctype, 249 } 250 newMRoot.Entries = append(newMRoot.Entries, myEntry) 251 } else { 252 newMRoot.Entries = append(newMRoot.Entries, entry) 253 } 254 } 255 mroot = newMRoot 256 } 257 258 newManifestHash, err := client.UploadManifest(mroot) 259 if err != nil { 260 utils.Fatalf("Manifest upload failed: %v", err) 261 } 262 return newManifestHash 263 } 264 265 func removeEntryFromManifest(ctx *cli.Context, mhash, path string) string { 266 267 var ( 268 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 269 client = swarm.NewClient(bzzapi) 270 entryToRemove = api.ManifestEntry{} 271 longestPathEntry = api.ManifestEntry{} 272 ) 273 274 mroot, err := client.DownloadManifest(mhash) 275 if err != nil { 276 utils.Fatalf("Manifest download failed: %v", err) 277 } 278 279 // See if we path is in this Manifest or do we have to dig deeper 280 for _, entry := range mroot.Entries { 281 if path == entry.Path { 282 entryToRemove = entry 283 } else { 284 if entry.ContentType == "application/bzz-manifest+json" { 285 prfxlen := strings.HasPrefix(path, entry.Path) 286 if prfxlen && len(path) > len(longestPathEntry.Path) { 287 longestPathEntry = entry 288 } 289 } 290 } 291 } 292 293 if longestPathEntry.Path == "" && entryToRemove.Path == "" { 294 utils.Fatalf("Path %s not present in the Manifest, not removing anything", path) 295 } 296 297 if longestPathEntry.Path != "" { 298 // Load the child Manifest remove the entry there 299 newPath := path[len(longestPathEntry.Path):] 300 newHash := removeEntryFromManifest(ctx, longestPathEntry.Hash, newPath) 301 302 // Replace the hash for parent Manifests 303 newMRoot := &api.Manifest{} 304 for _, entry := range mroot.Entries { 305 if longestPathEntry.Path == entry.Path { 306 entry.Hash = newHash 307 } 308 newMRoot.Entries = append(newMRoot.Entries, entry) 309 } 310 mroot = newMRoot 311 } 312 313 if entryToRemove.Path != "" { 314 // remove the entry in this Manifest 315 newMRoot := &api.Manifest{} 316 for _, entry := range mroot.Entries { 317 if entryToRemove.Path != entry.Path { 318 newMRoot.Entries = append(newMRoot.Entries, entry) 319 } 320 } 321 mroot = newMRoot 322 } 323 324 newManifestHash, err := client.UploadManifest(mroot) 325 if err != nil { 326 utils.Fatalf("Manifest upload failed: %v", err) 327 } 328 return newManifestHash 329 }