github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/cmd/swarm/manifest.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum 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-ethereum 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-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Command MANIFEST update 18 package main 19 20 import ( 21 "gopkg.in/urfave/cli.v1" 22 "log" 23 "mime" 24 "path/filepath" 25 "strings" 26 "fmt" 27 "encoding/json" 28 ) 29 30 func add(ctx *cli.Context) { 31 32 args := ctx.Args() 33 if len(args) < 3 { 34 log.Fatal("need atleast three arguments <MHASH> <path> <HASH> [<content-type>]") 35 } 36 37 var ( 38 mhash = args[0] 39 path = args[1] 40 hash = args[2] 41 42 ctype string 43 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 44 mroot manifest 45 ) 46 47 48 if len(args) > 3 { 49 ctype = args[3] 50 } else { 51 ctype = mime.TypeByExtension(filepath.Ext(path)) 52 } 53 54 newManifest := addEntryToManifest (ctx, mhash, path, hash, ctype) 55 fmt.Println(newManifest) 56 57 if !wantManifest { 58 // Print the manifest. This is the only output to stdout. 59 mrootJSON, _ := json.MarshalIndent(mroot, "", " ") 60 fmt.Println(string(mrootJSON)) 61 return 62 } 63 } 64 65 func update(ctx *cli.Context) { 66 67 args := ctx.Args() 68 if len(args) < 3 { 69 log.Fatal("need atleast three arguments <MHASH> <path> <HASH>") 70 } 71 72 var ( 73 mhash = args[0] 74 path = args[1] 75 hash = args[2] 76 77 ctype string 78 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 79 mroot manifest 80 ) 81 if len(args) > 3 { 82 ctype = args[3] 83 } else { 84 ctype = mime.TypeByExtension(filepath.Ext(path)) 85 } 86 87 newManifest := updateEntryInManifest (ctx, mhash, path, hash, ctype) 88 fmt.Println(newManifest) 89 90 if !wantManifest { 91 // Print the manifest. This is the only output to stdout. 92 mrootJSON, _ := json.MarshalIndent(mroot, "", " ") 93 fmt.Println(string(mrootJSON)) 94 return 95 } 96 } 97 98 func remove(ctx *cli.Context) { 99 args := ctx.Args() 100 if len(args) < 2 { 101 log.Fatal("need atleast two arguments <MHASH> <path>") 102 } 103 104 var ( 105 mhash = args[0] 106 path = args[1] 107 108 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 109 mroot manifest 110 ) 111 112 newManifest := removeEntryFromManifest (ctx, mhash, path) 113 fmt.Println(newManifest) 114 115 if !wantManifest { 116 // Print the manifest. This is the only output to stdout. 117 mrootJSON, _ := json.MarshalIndent(mroot, "", " ") 118 fmt.Println(string(mrootJSON)) 119 return 120 } 121 } 122 123 func addEntryToManifest(ctx *cli.Context, mhash , path, hash , ctype string) string { 124 125 var ( 126 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 127 client = &client{api: bzzapi} 128 longestPathEntry = manifestEntry{ 129 Path: "", 130 Hash: "", 131 ContentType: "", 132 } 133 ) 134 135 mroot, err := client.downloadManifest(mhash) 136 if err != nil { 137 log.Fatalln("manifest download failed:", err) 138 } 139 140 //TODO: check if the "hash" to add is valid and present in swarm 141 _, err = client.downloadManifest(hash) 142 if err != nil { 143 log.Fatalln("hash to add is not present:", err) 144 } 145 146 147 // See if we path is in this Manifest or do we have to dig deeper 148 for _, entry := range mroot.Entries { 149 if path == entry.Path { 150 log.Fatal(path, "Already present, not adding anything") 151 }else { 152 if entry.ContentType == "application/bzz-manifest+json" { 153 prfxlen := strings.HasPrefix(path, entry.Path) 154 if prfxlen && len(path) > len(longestPathEntry.Path) { 155 longestPathEntry = entry 156 } 157 } 158 } 159 } 160 161 if longestPathEntry.Path != "" { 162 // Load the child Manifest add the entry there 163 newPath := path[len(longestPathEntry.Path):] 164 newHash := addEntryToManifest (ctx, longestPathEntry.Hash, newPath, hash, ctype) 165 166 // Replace the hash for parent Manifests 167 newMRoot := manifest{} 168 for _, entry := range mroot.Entries { 169 if longestPathEntry.Path == entry.Path { 170 entry.Hash = newHash 171 } 172 newMRoot.Entries = append(newMRoot.Entries, entry) 173 } 174 mroot = newMRoot 175 } else { 176 // Add the entry in the leaf Manifest 177 newEntry := manifestEntry{ 178 Path: path, 179 Hash: hash, 180 ContentType: ctype, 181 } 182 mroot.Entries = append(mroot.Entries, newEntry) 183 } 184 185 186 newManifestHash, err := client.uploadManifest(mroot) 187 if err != nil { 188 log.Fatalln("manifest upload failed:", err) 189 } 190 return newManifestHash 191 192 193 194 } 195 196 func updateEntryInManifest(ctx *cli.Context, mhash , path, hash , ctype string) string { 197 198 var ( 199 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 200 client = &client{api: bzzapi} 201 newEntry = manifestEntry{ 202 Path: "", 203 Hash: "", 204 ContentType: "", 205 } 206 longestPathEntry = manifestEntry{ 207 Path: "", 208 Hash: "", 209 ContentType: "", 210 } 211 ) 212 213 mroot, err := client.downloadManifest(mhash) 214 if err != nil { 215 log.Fatalln("manifest download failed:", err) 216 } 217 218 //TODO: check if the "hash" with which to update is valid and present in swarm 219 220 221 // See if we path is in this Manifest or do we have to dig deeper 222 for _, entry := range mroot.Entries { 223 if path == entry.Path { 224 newEntry = entry 225 }else { 226 if entry.ContentType == "application/bzz-manifest+json" { 227 prfxlen := strings.HasPrefix(path, entry.Path) 228 if prfxlen && len(path) > len(longestPathEntry.Path) { 229 longestPathEntry = entry 230 } 231 } 232 } 233 } 234 235 if longestPathEntry.Path == "" && newEntry.Path == "" { 236 log.Fatal(path, " Path not present in the Manifest, not setting anything") 237 } 238 239 if longestPathEntry.Path != "" { 240 // Load the child Manifest add the entry there 241 newPath := path[len(longestPathEntry.Path):] 242 newHash := updateEntryInManifest (ctx, longestPathEntry.Hash, newPath, hash, ctype) 243 244 // Replace the hash for parent Manifests 245 newMRoot := manifest{} 246 for _, entry := range mroot.Entries { 247 if longestPathEntry.Path == entry.Path { 248 entry.Hash = newHash 249 } 250 newMRoot.Entries = append(newMRoot.Entries, entry) 251 252 } 253 mroot = newMRoot 254 } 255 256 if newEntry.Path != "" { 257 // Replace the hash for leaf Manifest 258 newMRoot := manifest{} 259 for _, entry := range mroot.Entries { 260 if newEntry.Path == entry.Path { 261 myEntry := manifestEntry{ 262 Path: entry.Path, 263 Hash: hash, 264 ContentType: ctype, 265 } 266 newMRoot.Entries = append(newMRoot.Entries, myEntry) 267 } else { 268 newMRoot.Entries = append(newMRoot.Entries, entry) 269 } 270 } 271 mroot = newMRoot 272 } 273 274 275 newManifestHash, err := client.uploadManifest(mroot) 276 if err != nil { 277 log.Fatalln("manifest upload failed:", err) 278 } 279 return newManifestHash 280 } 281 282 func removeEntryFromManifest(ctx *cli.Context, mhash , path string) string { 283 284 var ( 285 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 286 client = &client{api: bzzapi} 287 entryToRemove = manifestEntry{ 288 Path: "", 289 Hash: "", 290 ContentType: "", 291 } 292 longestPathEntry = manifestEntry{ 293 Path: "", 294 Hash: "", 295 ContentType: "", 296 } 297 ) 298 299 mroot, err := client.downloadManifest(mhash) 300 if err != nil { 301 log.Fatalln("manifest download failed:", err) 302 } 303 304 305 306 // See if we path is in this Manifest or do we have to dig deeper 307 for _, entry := range mroot.Entries { 308 if path == entry.Path { 309 entryToRemove = entry 310 }else { 311 if entry.ContentType == "application/bzz-manifest+json" { 312 prfxlen := strings.HasPrefix(path, entry.Path) 313 if prfxlen && len(path) > len(longestPathEntry.Path) { 314 longestPathEntry = entry 315 } 316 } 317 } 318 } 319 320 if longestPathEntry.Path == "" && entryToRemove.Path == "" { 321 log.Fatal(path, "Path not present in the Manifest, not removing anything") 322 } 323 324 if longestPathEntry.Path != "" { 325 // Load the child Manifest remove the entry there 326 newPath := path[len(longestPathEntry.Path):] 327 newHash := removeEntryFromManifest (ctx, longestPathEntry.Hash, newPath) 328 329 // Replace the hash for parent Manifests 330 newMRoot := manifest{} 331 for _, entry := range mroot.Entries { 332 if longestPathEntry.Path == entry.Path { 333 entry.Hash = newHash 334 } 335 newMRoot.Entries = append(newMRoot.Entries, entry) 336 } 337 mroot = newMRoot 338 } 339 340 if entryToRemove.Path != "" { 341 // remove the entry in this Manifest 342 newMRoot := manifest{} 343 for _, entry := range mroot.Entries { 344 if entryToRemove.Path != entry.Path { 345 newMRoot.Entries = append(newMRoot.Entries, entry) 346 } 347 } 348 mroot = newMRoot 349 } 350 351 352 newManifestHash, err := client.uploadManifest(mroot) 353 if err != nil { 354 log.Fatalln("manifest upload failed:", err) 355 } 356 return newManifestHash 357 358 359 } 360