diff --git a/bzz/api.go b/bzz/api.go index d9fd7a6d7a..f2a026ab9d 100644 --- a/bzz/api.go +++ b/bzz/api.go @@ -237,7 +237,7 @@ func (self *Api) Upload(lpath string) (string, error) { if errors[i] != nil { return "", errors[i] } - entry.Path = entry.Path[start:] + entry.Path = regularSlashes(entry.Path[start:]) trie.addEntry(entry) } @@ -315,7 +315,7 @@ func (self *Api) getPath(uri string) (reader SectionReader, mimeType string, sta trie, err := loadManifest(self.dpa, key) if err != nil { - dpaLogger.Debugf("Swarm: loadManifest error: %v", err) + dpaLogger.Debugf("Swarm: loadManifestTrie error: %v", err) return } diff --git a/bzz/manifest.go b/bzz/manifest.go index 015716201e..7057386046 100644 --- a/bzz/manifest.go +++ b/bzz/manifest.go @@ -220,7 +220,7 @@ func (self *manifestTrie) findPrefixOf(path string) (entry *manifestTrieEntry, p b := byte(path[0]) entry = self.entries[b] if entry == nil { - return nil, 0 + return self.entries[256], 0 } epl := len(entry.Path) dpaLogger.Debugf("path = %v entry.Path = %v epl = %v", path, entry.Path, epl) @@ -243,33 +243,27 @@ func (self *manifestTrie) findPrefixOf(path string) (entry *manifestTrieEntry, p return } -func (self *manifestTrie) getEntryNLS(path string) (entry *manifestTrieEntry, pos int) { - entry, pos = self.findPrefixOf(path) - if entry != nil { - for (pos < len(path)) && (path[pos] == '/') { - pos++ - } - if (pos < len(path)) && (pos > 0) && (path[pos-1] != '/') { - return nil, 0 +// file system manifest always contains regularized paths +// no leading or trailing slashes, only single slashes inside +func regularSlashes(path string) (res string) { + for i := 0; i < len(path); i++ { + if (path[i] != '/') || ((i > 0) && (path[i-1] != '/')) { + res = res + path[i:i+1] } } + if (len(res) > 0) && (res[len(res)-1] == '/') { + res = res[:len(res)-1] + } + //fmt.Printf("%v -> %v\n", path, res) return } -func (self *manifestTrie) getEntry(path string) (entry *manifestTrieEntry, pos int) { - var slash string - for { - entry, pos = self.getEntryNLS(slash + path) - dpaLogger.Debugf("getEntryNLS(%s) pos=%v", slash+path, pos) - if pos < len(slash) { - dpaLogger.Debugf("Path '%s' on manifest not found.", path) - return nil, 0 - } - if entry != nil { - pos -= len(slash) - dpaLogger.Debugf("Swarm: '%s' matches '%s'.", path, entry.Path) - return - } - slash = slash + "/" +func (self *manifestTrie) getEntry(spath string) (entry *manifestTrieEntry, fullpath string) { + path := regularSlashes(spath) + var pos int + entry, pos = self.findPrefixOf(path) + if (pos > 0) && (pos < len(path)) && (path[pos] != '/') { + return nil, "" } + return entry, path[:pos] } diff --git a/bzz/manifest_test.go b/bzz/manifest_test.go index 07ed8bc2fa..2bc6422eec 100644 --- a/bzz/manifest_test.go +++ b/bzz/manifest_test.go @@ -28,38 +28,29 @@ func testGetEntry(t *testing.T, path, match string, paths ...string) *manifestTr } func checkEntry(t *testing.T, path, match string, trie *manifestTrie) { - entry, _ := trie.getEntry(path) + entry, fullpath := trie.getEntry(path) if match == "-" && entry != nil { - t.Errorf("expected no match for '%s', got '%s'", path, entry.Path) + t.Errorf("expected no match for '%s', got '%s'", path, fullpath) } else if entry == nil { - t.Errorf("expected entry '%s' to match '%s', got no match", match, path) - } else if entry.Path != match { - t.Errorf("incorrect entry retrieved for '%s'. expected path '%v', got '%s'", path, match, entry.Path) + if match != "-" { + t.Errorf("expected entry '%s' to match '%s', got no match", match, path) + } + } else if fullpath != match { + t.Errorf("incorrect entry retrieved for '%s'. expected path '%v', got '%s'", path, match, fullpath) } } func TestGetEntry(t *testing.T) { + // file system manifest always contains regularized paths testGetEntry(t, "a", "a", "a") testGetEntry(t, "b", "-", "a") - testGetEntry(t, "/a", "/a", "/a") - testGetEntry(t, "/a", "///a", "///a") - testGetEntry(t, "/a", "a", "a") + testGetEntry(t, "/a//", "a", "a") // fallback - testGetEntry(t, "/a", "/", "/") - testGetEntry(t, "a", "/", "/") testGetEntry(t, "/a", "", "") + testGetEntry(t, "/a/b", "a/b", "a/b") // longest/deepest math - testGetEntry(t, "a/b", "a/b", "a///", "a/b") - // trailing slash - testGetEntry(t, "", "", "/", "") - testGetEntry(t, "/", "/", "/", "") - testGetEntry(t, "a", "a", "a", "a/") - testGetEntry(t, "a/", "a/", "a/", "a") - // prefix match - testGetEntry(t, "a", "a", "a", "ab") - testGetEntry(t, "ab", "", "a", "") - testGetEntry(t, "a", "a", "a", "ab") - testGetEntry(t, "a/b", "a", "a", "ab") + testGetEntry(t, "a/b", "a/b", "a", "a/b", "a/bb", "a/b/c") + testGetEntry(t, "//a//b//", "a/b", "a", "a/b", "a/bb", "a/b/c") } func TestDeleteEntry(t *testing.T) {