@@ -94,9 +94,28 @@ func (b *Bucket) ExpandPathURL(pathElements ...interface{}) *url.URL {
94
94
// enclosed by the provided path. Note that there's currently no way to get a
95
95
// path that ends in '/'.
96
96
func (b * Bucket ) ExpandListURL (pathElements ... interface {}) * url.URL {
97
+ return buildURL (map [string ]string {
98
+ // GCS api doesn't like preceding '/', so remove it.
99
+ "prefix" : strings .TrimPrefix (joinStringsAndInts (pathElements ... ), "/" ),
100
+ })
101
+ }
102
+
103
+ // ExpandListDirURL produces the URL for a list API query which will list directories
104
+ // enclosed by the provided path. Note that there's currently no way to get a
105
+ // path that ends in '/'.
106
+ func (b * Bucket ) ExpandListDirURL (pathElements ... interface {}) * url.URL {
107
+ return buildURL (map [string ]string {
108
+ // GCS api doesn't like preceding '/', so remove it.
109
+ "prefix" : strings .TrimPrefix (joinStringsAndInts (pathElements ... )+ "/" , "/" ),
110
+ "delimiter" : "/" ,
111
+ })
112
+ }
113
+
114
+ func (b * Bucket ) buildUrl (parameters map [string ]string ) * url.URL {
97
115
q := url.Values {}
98
- // GCS api doesn't like preceding '/', so remove it.
99
- q .Set ("prefix" , strings .TrimPrefix (joinStringsAndInts (pathElements ... ), "/" ))
116
+ for key , value := range parameters {
117
+ q .Set (key , value )
118
+ }
100
119
return & url.URL {
101
120
Scheme : b .scheme ,
102
121
Host : b .listHost ,
@@ -109,31 +128,58 @@ func (b *Bucket) ExpandListURL(pathElements ...interface{}) *url.URL {
109
128
// The returned file name included the complete path from bucket root
110
129
func (b * Bucket ) List (pathElements ... interface {}) ([]string , error ) {
111
130
listURL := b .ExpandListURL (pathElements ... )
112
- res , err := getResponseWithRetry (listURL .String ())
131
+ data , err := queryURL (listURL .String ())
132
+ if err != nil {
133
+ return nil , err
134
+ }
135
+ var ret []string
136
+ if _ , ok := data ["items" ]; ! ok {
137
+ glog .Warningf ("No matching files were found (from: %v)" , listURL .String ())
138
+ return ret , nil
139
+ }
140
+ for _ , item := range data ["items" ].([]interface {}) {
141
+ ret = append (ret , (item .(map [string ]interface {})["name" ]).(string ))
142
+ }
143
+ return ret , nil
144
+ }
145
+
146
+ // ListDirs returns a list of all directories inside the given path.
147
+ // The returned direcotry name included the complete path from bucket root
148
+ func (b * Bucket ) ListDirs (pathElements ... interface {}) ([]string , error ) {
149
+ listURL := b .ExpandListDirURL (pathElements ... )
150
+ data , err := queryURL (listURL .String ())
151
+ if err != nil {
152
+ return nil , err
153
+ }
154
+ var ret []string
155
+ if _ , ok := data ["prefixes" ]; ! ok {
156
+ glog .Warningf ("No matching dirs were found (from: %v)" , listURL .String ())
157
+ return ret , nil
158
+ }
159
+ for _ , item := range data ["prefixes" ].([]interface {}) {
160
+ ret = append (ret , item .(string ))
161
+ }
162
+ return ret , nil
163
+ }
164
+
165
+ func queryURL (url string ) (map [string ]interface {}, error ) {
166
+ res , err := getResponseWithRetry (url )
113
167
if err != nil {
114
- return nil , fmt .Errorf ("Failed to GET %v: %v" , listURL , err )
168
+ return nil , fmt .Errorf ("Failed to GET %v: %v" , url , err )
115
169
}
116
170
if res .StatusCode != http .StatusOK {
117
- return nil , fmt .Errorf ("Got a non-success response %v while listing %v" , res .StatusCode , listURL . String () )
171
+ return nil , fmt .Errorf ("Got a non-success response %v while listing %v" , res .StatusCode , url )
118
172
}
119
173
body , err := ioutil .ReadAll (res .Body )
120
174
if err != nil {
121
- return nil , fmt .Errorf ("Failed to read the response for %v: %v" , listURL . String () , err )
175
+ return nil , fmt .Errorf ("Failed to read the response for %v: %v" , url , err )
122
176
}
123
177
var data map [string ]interface {}
124
178
err = json .Unmarshal (body , & data )
125
179
if err != nil {
126
180
return nil , fmt .Errorf ("Failed to unmarshal %v: %v" , string (body ), err )
127
181
}
128
- var ret []string
129
- if _ , ok := data ["items" ]; ! ok {
130
- glog .Warningf ("No matching files were found (from: %v)" , listURL .String ())
131
- return ret , nil
132
- }
133
- for _ , item := range data ["items" ].([]interface {}) {
134
- ret = append (ret , (item .(map [string ]interface {})["name" ]).(string ))
135
- }
136
- return ret , nil
182
+ return data , nil
137
183
}
138
184
139
185
func joinStringsAndInts (pathElements ... interface {}) string {
0 commit comments