Skip to content

Commit 8724413

Browse files
authored
Merge pull request #310 from ScottSuarez/support-generation
Add support for gcs object generations
2 parents bcfc71c + 5bb6635 commit 8724413

File tree

2 files changed

+63
-9
lines changed

2 files changed

+63
-9
lines changed

get_gcs.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/url"
77
"os"
88
"path/filepath"
9+
"strconv"
910
"strings"
1011

1112
"cloud.google.com/go/storage"
@@ -22,7 +23,7 @@ func (g *GCSGetter) ClientMode(u *url.URL) (ClientMode, error) {
2223
ctx := g.Context()
2324

2425
// Parse URL
25-
bucket, object, err := g.parseURL(u)
26+
bucket, object, _, err := g.parseURL(u)
2627
if err != nil {
2728
return 0, err
2829
}
@@ -59,7 +60,7 @@ func (g *GCSGetter) Get(dst string, u *url.URL) error {
5960
ctx := g.Context()
6061

6162
// Parse URL
62-
bucket, object, err := g.parseURL(u)
63+
bucket, object, _, err := g.parseURL(u)
6364
if err != nil {
6465
return err
6566
}
@@ -105,7 +106,7 @@ func (g *GCSGetter) Get(dst string, u *url.URL) error {
105106
}
106107
objDst = filepath.Join(dst, objDst)
107108
// Download the matching object.
108-
err = g.getObject(ctx, client, objDst, bucket, obj.Name)
109+
err = g.getObject(ctx, client, objDst, bucket, obj.Name, "")
109110
if err != nil {
110111
return err
111112
}
@@ -118,7 +119,7 @@ func (g *GCSGetter) GetFile(dst string, u *url.URL) error {
118119
ctx := g.Context()
119120

120121
// Parse URL
121-
bucket, object, err := g.parseURL(u)
122+
bucket, object, fragment, err := g.parseURL(u)
122123
if err != nil {
123124
return err
124125
}
@@ -127,11 +128,21 @@ func (g *GCSGetter) GetFile(dst string, u *url.URL) error {
127128
if err != nil {
128129
return err
129130
}
130-
return g.getObject(ctx, client, dst, bucket, object)
131+
return g.getObject(ctx, client, dst, bucket, object, fragment)
131132
}
132133

133-
func (g *GCSGetter) getObject(ctx context.Context, client *storage.Client, dst, bucket, object string) error {
134-
rc, err := client.Bucket(bucket).Object(object).NewReader(ctx)
134+
func (g *GCSGetter) getObject(ctx context.Context, client *storage.Client, dst, bucket, object, fragment string) error {
135+
var rc *storage.Reader
136+
var err error
137+
if fragment != "" {
138+
generation, err := strconv.ParseInt(fragment, 10, 64)
139+
if err != nil {
140+
return err
141+
}
142+
rc, err = client.Bucket(bucket).Object(object).Generation(generation).NewReader(ctx)
143+
} else {
144+
rc, err = client.Bucket(bucket).Object(object).NewReader(ctx)
145+
}
135146
if err != nil {
136147
return err
137148
}
@@ -145,7 +156,7 @@ func (g *GCSGetter) getObject(ctx context.Context, client *storage.Client, dst,
145156
return copyReader(dst, rc, 0666, g.client.umask())
146157
}
147158

148-
func (g *GCSGetter) parseURL(u *url.URL) (bucket, path string, err error) {
159+
func (g *GCSGetter) parseURL(u *url.URL) (bucket, path, fragment string, err error) {
149160
if strings.Contains(u.Host, "googleapis.com") {
150161
hostParts := strings.Split(u.Host, ".")
151162
if len(hostParts) != 3 {
@@ -160,6 +171,7 @@ func (g *GCSGetter) parseURL(u *url.URL) (bucket, path string, err error) {
160171
}
161172
bucket = pathParts[3]
162173
path = pathParts[4]
174+
fragment = u.Fragment
163175
}
164176
return
165177
}

get_gcs_test.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package getter
22

33
import (
4+
"io/ioutil"
45
"net/url"
56
"os"
67
"path/filepath"
@@ -88,6 +89,47 @@ func TestGCSGetter_GetFile(t *testing.T) {
8889
assertContents(t, dst, "# Main\n")
8990
}
9091

92+
func TestGCSGetter_GetGenerationFile(t *testing.T) {
93+
defer initGCPCredentials(t)()
94+
95+
g := new(GCSGetter)
96+
dst := tempTestFile(t)
97+
defer os.RemoveAll(filepath.Dir(dst))
98+
99+
// Download
100+
err := g.GetFile(
101+
dst, testURL("https://www.googleapis.com/storage/v1/go-getter-testcase-data/DO_NOT_DELETE/generation_test.txt#1614317688843055"))
102+
if err != nil {
103+
t.Fatalf("err: %s", err)
104+
}
105+
106+
// Verify contents are valid for this generation
107+
content, err := ioutil.ReadFile(dst)
108+
if err != nil {
109+
t.Fatalf("err: %s", err)
110+
}
111+
if string(content) != "a" {
112+
t.Fatalf("expected file contents from generation to be `a` but got `%s`", content)
113+
}
114+
115+
// Download
116+
err = g.GetFile(
117+
dst, testURL("https://www.googleapis.com/storage/v1/go-getter-testcase-data/DO_NOT_DELETE/generation_test.txt#1614317705239142"))
118+
if err != nil {
119+
t.Fatalf("err: %s", err)
120+
}
121+
122+
// Verify contents are valid for this generation
123+
content, err = ioutil.ReadFile(dst)
124+
if err != nil {
125+
t.Fatalf("err: %s", err)
126+
}
127+
if string(content) != "b" {
128+
t.Fatalf("expected file contents from generation to be `b` but got `%s`", content)
129+
}
130+
131+
}
132+
91133
func TestGCSGetter_GetFile_notfound(t *testing.T) {
92134
g := new(GCSGetter)
93135
dst := tempTestFile(t)
@@ -180,7 +222,7 @@ func TestGCSGetter_Url(t *testing.T) {
180222
t.Fatalf("expected forced protocol to be gcs")
181223
}
182224

183-
bucket, path, err := g.parseURL(u)
225+
bucket, path, _, err := g.parseURL(u)
184226

185227
if err != nil {
186228
t.Fatalf("err: %s", err)

0 commit comments

Comments
 (0)