X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/64c74f24fcdfbbef0e08b72c09d85c53390ca3b3..9a1056497d7b7ad18769336489d3a6822547b65a:/sdk/go/arvados/fs_project.go diff --git a/sdk/go/arvados/fs_project.go b/sdk/go/arvados/fs_project.go index 92995510c7..380fb9c6d5 100644 --- a/sdk/go/arvados/fs_project.go +++ b/sdk/go/arvados/fs_project.go @@ -6,7 +6,6 @@ package arvados import ( "log" - "os" "strings" ) @@ -30,19 +29,34 @@ func (fs *customFileSystem) projectsLoadOne(parent inode, uuid, name string) (in } var contents CollectionList - err = fs.RequestAndDecode(&contents, "GET", "arvados/v1/groups/"+uuid+"/contents", nil, ResourceListParams{ - Count: "none", - Filters: []Filter{ - {"name", "=", name}, - {"uuid", "is_a", []string{"arvados#collection", "arvados#group"}}, - {"groups.group_class", "=", "project"}, - }, - }) - if err != nil { - return nil, err + for _, subst := range []string{"/", fs.forwardSlashNameSubstitution} { + contents = CollectionList{} + err = fs.RequestAndDecode(&contents, "GET", "arvados/v1/groups/"+uuid+"/contents", nil, ResourceListParams{ + Count: "none", + Filters: []Filter{ + {"name", "=", strings.Replace(name, subst, "/", -1)}, + {"uuid", "is_a", []string{"arvados#collection", "arvados#group"}}, + {"groups.group_class", "=", "project"}, + }, + }) + if err != nil { + return nil, err + } + if len(contents.Items) > 0 || fs.forwardSlashNameSubstitution == "/" || fs.forwardSlashNameSubstitution == "" || !strings.Contains(name, fs.forwardSlashNameSubstitution) { + break + } + // If the requested name contains the configured "/" + // replacement string and didn't match a + // project/collection exactly, we'll try again with + // "/" in its place, so a lookup of a munged name + // works regardless of whether the directory listing + // has been populated with escaped names. + // + // Note this doesn't handle items whose names contain + // both "/" and the substitution string. } if len(contents.Items) == 0 { - return nil, os.ErrNotExist + return nil, nil } coll := contents.Items[0] @@ -53,7 +67,7 @@ func (fs *customFileSystem) projectsLoadOne(parent inode, uuid, name string) (in } else if strings.Contains(coll.UUID, "-4zz18-") { return deferredCollectionFS(fs, parent, coll), nil } else { - log.Printf("projectnode: unrecognized UUID in response: %q", coll.UUID) + log.Printf("group contents: unrecognized UUID in response: %q", coll.UUID) return nil, ErrInvalidArgument } } @@ -66,52 +80,57 @@ func (fs *customFileSystem) projectsLoadAll(parent inode, uuid string) ([]inode, var inodes []inode - // Note: the "filters" slice's backing array might be reused - // by append(filters,...) below. This isn't goroutine safe, - // but all accesses are in the same goroutine, so it's OK. - filters := []Filter{{"owner_uuid", "=", uuid}} - params := ResourceListParams{ - Count: "none", - Filters: filters, - Order: "uuid", - } - for { - var resp CollectionList - err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/collections", nil, params) - if err != nil { - return nil, err + // When #17424 is resolved, remove the outer loop here and use + // []string{"arvados#collection", "arvados#group"} directly as the uuid + // filter. + for _, class := range []string{"arvados#collection", "arvados#group"} { + // Note: the "filters" slice's backing array might be reused + // by append(filters,...) below. This isn't goroutine safe, + // but all accesses are in the same goroutine, so it's OK. + filters := []Filter{ + {"uuid", "is_a", class}, } - if len(resp.Items) == 0 { - break + if class == "arvados#group" { + filters = append(filters, Filter{"group_class", "=", "project"}) } - for _, i := range resp.Items { - coll := i - if !permittedName(coll.Name) { - continue - } - inodes = append(inodes, deferredCollectionFS(fs, parent, coll)) - } - params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID}) - } - filters = append(filters, Filter{"group_class", "=", "project"}) - params.Filters = filters - for { - var resp GroupList - err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/groups", nil, params) - if err != nil { - return nil, err + params := ResourceListParams{ + Count: "none", + Filters: filters, + Order: "uuid", } - if len(resp.Items) == 0 { - break - } - for _, group := range resp.Items { - if !permittedName(group.Name) { - continue + + for { + // The groups content endpoint returns Collection and Group (project) + // objects. This function only accesses the UUID and Name field. Both + // collections and groups have those fields, so it is easier to just treat + // the ObjectList that comes back as a CollectionList. + var resp CollectionList + err = fs.RequestAndDecode(&resp, "GET", "arvados/v1/groups/"+uuid+"/contents", nil, params) + if err != nil { + return nil, err + } + if len(resp.Items) == 0 { + break + } + for _, i := range resp.Items { + if fs.forwardSlashNameSubstitution != "" { + i.Name = strings.Replace(i.Name, "/", fs.forwardSlashNameSubstitution, -1) + } + if !permittedName(i.Name) { + continue + } + if strings.Contains(i.UUID, "-j7d0g-") { + inodes = append(inodes, fs.newProjectNode(parent, i.Name, i.UUID)) + } else if strings.Contains(i.UUID, "-4zz18-") { + inodes = append(inodes, deferredCollectionFS(fs, parent, i)) + } else { + log.Printf("group contents: unrecognized UUID in response: %q", i.UUID) + return nil, ErrInvalidArgument + } } - inodes = append(inodes, fs.newProjectNode(parent, group.Name, group.UUID)) + params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID}) } - params.Filters = append(filters, Filter{"uuid", ">", resp.Items[len(resp.Items)-1].UUID}) } return inodes, nil }